From 2623277acee6020939019c12076e189717396632 Mon Sep 17 00:00:00 2001 From: David Ames Date: Fri, 10 Aug 2018 07:55:17 -0700 Subject: [PATCH] Series Upgrade Implement the series-upgrade feature allowing to move between Ubuntu series. Change-Id: Iea24af291b3d9d5b7771f35c2374e8d7e9b655c3 --- hooks/charmhelpers/contrib/openstack/utils.py | 68 ++++++++++++++++++- hooks/cinder_hooks.py | 24 +++++++ hooks/post-series-upgrade | 1 + hooks/pre-series-upgrade | 1 + 4 files changed, 91 insertions(+), 3 deletions(-) create mode 120000 hooks/post-series-upgrade create mode 120000 hooks/pre-series-upgrade diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/hooks/charmhelpers/contrib/openstack/utils.py index 0180e555..bce5b593 100644 --- a/hooks/charmhelpers/contrib/openstack/utils.py +++ b/hooks/charmhelpers/contrib/openstack/utils.py @@ -186,7 +186,7 @@ SWIFT_CODENAMES = OrderedDict([ ('queens', ['2.16.0', '2.17.0']), ('rocky', - ['2.18.0']), + ['2.18.0', '2.19.0']), ]) # >= Liberty version->codename mapping @@ -831,12 +831,25 @@ def _ows_check_if_paused(services=None, ports=None): """Check if the unit is supposed to be paused, and if so check that the services/ports (if passed) are actually stopped/not being listened to. - if the unit isn't supposed to be paused, just return None, None + If the unit isn't supposed to be paused, just return None, None + + If the unit is performing a series upgrade, return a message indicating + this. @param services: OPTIONAL services spec or list of service names. @param ports: OPTIONAL list of port numbers. @returns state, message or None, None """ + if is_unit_upgrading_set(): + state, message = check_actually_paused(services=services, + ports=ports) + if state is None: + # we're paused okay, so set maintenance and return + state = "blocked" + message = ("Ready for do-release-upgrade and reboot. " + "Set complete when finished.") + return state, message + if is_unit_paused_set(): state, message = check_actually_paused(services=services, ports=ports) @@ -1339,7 +1352,7 @@ def pause_unit(assess_status_func, services=None, ports=None, message = assess_status_func() if message: messages.append(message) - if messages: + if messages and not is_unit_upgrading_set(): raise Exception("Couldn't pause: {}".format("; ".join(messages))) @@ -1689,3 +1702,52 @@ def install_os_snaps(snaps, refresh=False): snap_install(snap, _ensure_flag(snaps[snap]['channel']), _ensure_flag(snaps[snap]['mode'])) + + +def set_unit_upgrading(): + """Set the unit to a upgrading state in the local kv() store. + """ + with unitdata.HookData()() as t: + kv = t[0] + kv.set('unit-upgrading', True) + + +def clear_unit_upgrading(): + """Clear the unit from a upgrading state in the local kv() store + """ + with unitdata.HookData()() as t: + kv = t[0] + kv.set('unit-upgrading', False) + + +def is_unit_upgrading_set(): + """Return the state of the kv().get('unit-upgrading'). + + To help with units that don't have HookData() (testing) + if it excepts, return False + """ + try: + with unitdata.HookData()() as t: + kv = t[0] + # transform something truth-y into a Boolean. + return not(not(kv.get('unit-upgrading'))) + except Exception: + return False + + +def series_upgrade_prepare(pause_unit_helper=None, configs=None): + """ Run common series upgrade prepare tasks.""" + set_unit_upgrading() + if pause_unit_helper and configs: + if not is_unit_paused_set(): + pause_unit_helper(configs) + + +def series_upgrade_complete(resume_unit_helper=None, configs=None): + """ Run common series upgrade complete tasks.""" + clear_unit_paused() + clear_unit_upgrading() + if configs: + configs.write_all() + if resume_unit_helper: + resume_unit_helper(configs) diff --git a/hooks/cinder_hooks.py b/hooks/cinder_hooks.py index b75e360e..523df997 100755 --- a/hooks/cinder_hooks.py +++ b/hooks/cinder_hooks.py @@ -44,6 +44,8 @@ from cinder_utils import ( filesystem_mounted, assess_status, scrub_old_style_ceph, + pause_unit_helper, + resume_unit_helper, ) from cinder_contexts import ceph_config_file @@ -85,6 +87,8 @@ from charmhelpers.contrib.openstack.utils import ( is_unit_paused_set, pausable_restart_on_change as restart_on_change, CompareOpenStackReleases, + series_upgrade_prepare, + series_upgrade_complete, ) from charmhelpers.contrib.storage.linux.ceph import ( @@ -154,6 +158,12 @@ def install(): @restart_on_change(restart_map(), stopstart=True) @harden() def config_changed(): + # if we are paused, delay doing any config changed hooks. + # It is forced on the resume. + if is_unit_paused_set(): + log("Unit is pause or upgrading. Skipping config_changed", "WARN") + return + conf = config() if conf['prefer-ipv6']: @@ -633,6 +643,20 @@ def certs_changed(relation_id=None, unit=None): configure_https() +@hooks.hook('pre-series-upgrade') +def pre_series_upgrade(): + log("Running prepare series upgrade hook", "INFO") + series_upgrade_prepare( + pause_unit_helper, CONFIGS) + + +@hooks.hook('post-series-upgrade') +def post_series_upgrade(): + log("Running complete series upgrade hook", "INFO") + series_upgrade_complete( + resume_unit_helper, CONFIGS) + + if __name__ == '__main__': try: hooks.execute(sys.argv) diff --git a/hooks/post-series-upgrade b/hooks/post-series-upgrade new file mode 120000 index 00000000..6dcd0084 --- /dev/null +++ b/hooks/post-series-upgrade @@ -0,0 +1 @@ +cinder_hooks.py \ No newline at end of file diff --git a/hooks/pre-series-upgrade b/hooks/pre-series-upgrade new file mode 120000 index 00000000..6dcd0084 --- /dev/null +++ b/hooks/pre-series-upgrade @@ -0,0 +1 @@ +cinder_hooks.py \ No newline at end of file