From fe4e9a4ca7028aa877fdd3895225a67b026aea11 Mon Sep 17 00:00:00 2001
From: Devan Goodwin <dgoodwin@redhat.com>
Date: Thu, 5 Nov 2015 08:35:53 -0400
Subject: Upgrade improvements

- Push config dir logic out of module and use host variables instead.
- Backup master config with ansible utility.
- Add error handling for the upgrade config module.
- Add verbose option to installer.
- Return details on what we changed when upgrading config.
- Cleanup use of first master.
- Don't install upgrade rpms to check what version we'll upgrade to.
---
 .../upgrades/library/openshift_upgrade_config.py   | 53 +++++++--------
 playbooks/adhoc/upgrades/upgrade.yml               | 78 +++++++++-------------
 2 files changed, 56 insertions(+), 75 deletions(-)

(limited to 'playbooks')

diff --git a/playbooks/adhoc/upgrades/library/openshift_upgrade_config.py b/playbooks/adhoc/upgrades/library/openshift_upgrade_config.py
index 60f4fd8b8..0894efa52 100755
--- a/playbooks/adhoc/upgrades/library/openshift_upgrade_config.py
+++ b/playbooks/adhoc/upgrades/library/openshift_upgrade_config.py
@@ -5,11 +5,8 @@
 """Ansible module for modifying OpenShift configs during an upgrade"""
 
 import os
-import shutil
 import yaml
 
-from datetime import datetime
-
 DOCUMENTATION = '''
 ---
 module: openshift_upgrade_config
@@ -20,21 +17,14 @@ requirements: [ ]
 EXAMPLES = '''
 '''
 
-def get_cfg_dir():
-    """Return the correct config directory to use."""
-    cfg_path = '/etc/origin/'
-    if not os.path.exists(cfg_path):
-        cfg_path = '/etc/openshift/'
-    return cfg_path
-
 
-def upgrade_master_3_0_to_3_1(backup):
+def upgrade_master_3_0_to_3_1(module, config_base, backup):
     """Main upgrade method for 3.0 to 3.1."""
-    changed = False
+    changes = []
 
     # Facts do not get transferred to the hosts where custom modules run,
     # need to make some assumptions here.
-    master_config = os.path.join(get_cfg_dir(), 'master/master-config.yaml')
+    master_config = os.path.join(config_base, 'master/master-config.yaml')
 
     master_cfg_file = open(master_config, 'r')
     config = yaml.safe_load(master_cfg_file.read())
@@ -45,6 +35,7 @@ def upgrade_master_3_0_to_3_1(backup):
         'v1beta3' in config['apiLevels']:
         config['apiLevels'].remove('v1beta3')
         changed = True
+        changes.append("master-config.yaml: removed v1beta3 from apiLevels")
     if 'apiLevels' in config['kubernetesMasterConfig'] and \
         'v1beta3' in config['kubernetesMasterConfig']['apiLevels']:
         config['kubernetesMasterConfig']['apiLevels'].remove('v1beta3')
@@ -57,27 +48,26 @@ def upgrade_master_3_0_to_3_1(backup):
 #            'certFile': 'master.proxy-client.crt',
 #            'keyFile': 'master.proxy-client.key'
 #       }
+#        changes.append("master-config.yaml: added proxyClientInfo")
 
-    if changed:
+    if len(changes) > 0:
         if backup:
-            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
-            basedir = os.path.split(master_config)[0]
-            backup_file = os.path.join(basedir, 'master-config.yaml.bak-%s'
-                                       % timestamp)
-            shutil.copyfile(master_config, backup_file)
+            # TODO: Check success:
+            module.backup_local(master_config)
+
         # Write the modified config:
         out_file = open(master_config, 'w')
         out_file.write(yaml.safe_dump(config, default_flow_style=False))
         out_file.close()
 
-    return changed
+    return changes
 
 
-def upgrade_master(from_version, to_version, backup):
+def upgrade_master(module, config_base, from_version, to_version, backup):
     """Upgrade entry point."""
     if from_version == '3.0':
         if to_version == '3.1':
-            return upgrade_master_3_0_to_3_1(backup)
+            return upgrade_master_3_0_to_3_1(module, config_base, backup)
 
 
 def main():
@@ -89,6 +79,7 @@ def main():
 
     module = AnsibleModule(
         argument_spec=dict(
+            config_base=dict(required=True),
             from_version=dict(required=True, choices=['3.0']),
             to_version=dict(required=True, choices=['3.1']),
             role=dict(required=True, choices=['master']),
@@ -101,12 +92,18 @@ def main():
     to_version = module.params['to_version']
     role = module.params['role']
     backup = module.params['backup']
-
-    changed = False
-    if role == 'master':
-        changed = upgrade_master(from_version, to_version, backup)
-
-    return module.exit_json(changed=changed)
+    config_base = module.params['config_base']
+
+    try:
+        changes = []
+        if role == 'master':
+            changes = upgrade_master(module, config_base, from_version,
+                to_version, backup)
+
+        changed = len(changes) > 0
+        return module.exit_json(changed=changed, changes=changes)
+    except Exception, e:
+        return module.fail_json(msg=str(e))
 
 # ignore pylint errors related to the module_utils import
 # pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import
diff --git a/playbooks/adhoc/upgrades/upgrade.yml b/playbooks/adhoc/upgrades/upgrade.yml
index 09f991b1d..c113c7ab2 100644
--- a/playbooks/adhoc/upgrades/upgrade.yml
+++ b/playbooks/adhoc/upgrades/upgrade.yml
@@ -1,4 +1,12 @@
 ---
+- name: Verify upgrade can proceed
+  hosts: masters
+  tasks:
+  # Checking the global deployment type rather than host facts, this is about
+  # what the user is requesting.
+    - fail: msg="Deployment type enterprise not supported for upgrade"
+      when: deployment_type == "enterprise"
+
 - name: Update deployment type
   hosts: OSEv3
   roles:
@@ -9,14 +17,6 @@
       local_facts:
         deployment_type: "{{ deployment_type }}"
 
-- name: Verify upgrade can proceed
-  hosts: masters
-  tasks:
-  # Checking the global deployment type rather than host facts, this is about
-  # what the user is requesting.
-    - fail: msg="Deployment type enterprise not supported for upgrade"
-      when: deployment_type == "enterprise"
-
 - name: Backup etcd
   hosts: masters
   vars:
@@ -52,48 +52,35 @@
   - name: Display location of etcd backup
     debug: msg="Etcd backup created in {{ openshift.common.data_dir }}/etcd-backup-{{ timestamp }}"
 
-- name: Upgrade base package on masters
-  hosts: masters
-  roles:
-  - openshift_facts
-  vars:
-    openshift_version: "{{ openshift_pkg_version | default('') }}"
-  tasks:
-    - name: Upgrade base package
-      yum: pkg={{ openshift.common.service_type }}{{ openshift_version  }} state=latest
-
-- name: Evaluate oo_first_master
-  hosts: localhost
-  vars:
-    g_masters_group: "{{ 'masters' }}"
-  tasks:
-    - name: Evaluate oo_first_master
-      add_host:
-        name: "{{ groups[g_masters_group][0] }}"
-        groups: oo_first_master
-        ansible_ssh_user: "{{ g_ssh_user | default(omit) }}"
-        ansible_sudo: "{{ g_sudo | default(omit) }}"
-      when: g_masters_group in groups and (groups[g_masters_group] | length) > 0
-
-# TODO: ideally we would check the new version, without installing it. (some
-# kind of yum repoquery? would need to handle openshift -> atomic-openshift
-# package rename)
 - name: Perform upgrade version checking
-  hosts: oo_first_master
+  hosts: masters[0]
   tasks:
-    - name: Determine new version
+    - name: Determine available version
+      shell: >
+        yum list available {{ openshift.common.service_type }} | tail -n 1 | cut -f 2 -d " " | cut -f 1 -d "-"
+      register: _new_version
+    - debug: var=_new_version
+    # The above check will return nothing if the package is already installed,
+    # and we may be re-running upgrade due to a failure.
+    - name: Determine installed version
       command: >
         rpm -q --queryformat '%{version}' {{ openshift.common.service_type }}
       register: _new_version
+      when: _new_version.stdout == ""
+    # Fail if we still don't know:
+    - debug: var=_new_version
+    - name: Verify upgrade version
+      fail: Unable to determine upgrade version for {{ openshift.common.service_type }}
+      when: _new_version.stdout == ""
 
 - name: Ensure AOS 3.0.2 or Origin 1.0.6
-  hosts: oo_first_master
+  hosts: masters[0]
   tasks:
     fail: This playbook requires Origin 1.0.6 or Atomic OpenShift 3.0.2 or later
     when: _new_version.stdout | version_compare('1.0.6','<') or ( _new_version.stdout | version_compare('3.0','>=' and _new_version.stdout | version_compare('3.0.2','<') )
 
 - name: Verify upgrade can proceed
-  hosts: oo_first_master
+  hosts: masters[0]
   tasks:
   # Checking the global deployment type rather than host facts, this is about
   # what the user is requesting.
@@ -107,13 +94,10 @@
   tasks:
     - name: Upgrade to latest available kernel
       yum: pkg=kernel state=latest
-    - name: display just the deployment_type variable for the current host
-      debug:
-        var: hostvars[inventory_hostname]
     - name: Upgrade master packages
       command: yum update -y {{ openshift.common.service_type }}-master{{ openshift_version }}
     - name: Upgrade master configuration.
-      openshift_upgrade_config: from_version=3.0 to_version=3.1 role=master
+      openshift_upgrade_config: from_version=3.0 to_version=3.1 role=master config_base={{ hostvars[inventory_hostname].openshift.common.config_base }}
     - name: Restart master services
       service: name="{{ openshift.common.service_type}}-master" state=restarted
 
@@ -130,7 +114,7 @@
       service: name="{{ openshift.common.service_type }}-node" state=restarted
 
 - name: Update cluster policy
-  hosts: oo_first_master
+  hosts: masters[0]
   tasks:
     - name: oadm policy reconcile-cluster-roles --confirm
       command: >
@@ -138,7 +122,7 @@
         policy reconcile-cluster-roles --confirm
 
 - name: Update cluster policy bindings
-  hosts: oo_first_master
+  hosts: masters[0]
   tasks:
     - name: oadm policy reconcile-cluster-role-bindings --confirm
       command: >
@@ -151,7 +135,7 @@
       when: ( _new_version.stdout | version_compare('1.0.6', '>') and _new_version.stdout | version_compare('3.0','<') ) or _new_version.stdout | version_compare('3.0.2','>')
 
 - name: Upgrade default router
-  hosts: oo_first_master
+  hosts: masters[0]
   vars:
     - router_image: "{{ openshift.master.registry_url | replace( '${component}', 'haproxy-router' ) | replace ( '${version}', 'v' + _new_version.stdout ) }}"
     - oc_cmd: "{{ openshift.common.client_binary }} --config={{ openshift.common.config_base }}/master/admin.kubeconfig"
@@ -189,7 +173,7 @@
         '{"spec":{"template":{"spec":{"containers":[{"name":"router","image":"{{ router_image }}"}]}}}}'
 
 - name: Upgrade default
-  hosts: oo_first_master
+  hosts: masters[0]
   vars:
     - registry_image: "{{  openshift.master.registry_url | replace( '${component}', 'docker-registry' )  | replace ( '${version}', 'v' + _new_version.stdout  ) }}"
     - oc_cmd: "{{ openshift.common.client_binary }} --config={{ openshift.common.config_base }}/master/admin.kubeconfig"
@@ -207,7 +191,7 @@
         '{"spec":{"template":{"spec":{"containers":[{"name":"registry","image":"{{ registry_image }}"}]}}}}'
 
 - name: Update image streams and templates
-  hosts: oo_first_master
+  hosts: masters[0]
   vars:
     openshift_examples_import_command: "update"
     openshift_deployment_type: "{{ deployment_type }}"
-- 
cgit v1.2.3