diff --git a/adapters.py b/adapters.py index 8e6ad35..b423cd7 100644 --- a/adapters.py +++ b/adapters.py @@ -18,6 +18,7 @@ from __future__ import absolute_import from ops.framework import Object +# Adapted from charms_openstack.adapters class OpenStackOperRelationAdapter(object): """ Base adapter class for all OpenStack related adapters. @@ -72,6 +73,7 @@ class OpenStackOperRelationAdapter(object): self.relation, name)))(name)) +# Adapted from charms_openstack.adapters class ConfigurationAdapter(object): """ Configuration Adapter which provides python based access @@ -97,6 +99,7 @@ class ConfigurationAdapter(object): setattr(self, k, v) +# Adapted from charms_openstack.adapters class OpenStackRelationAdapters(Object): """ Base adapters class for OpenStack Charms, used to aggregate diff --git a/ops_openstack.py b/ops_openstack.py index d3c76ea..fe158df 100644 --- a/ops_openstack.py +++ b/ops_openstack.py @@ -2,6 +2,7 @@ from ops.charm import CharmBase from ops.framework import ( StoredState, ) +import ops.model from charmhelpers.fetch import ( apt_install, @@ -16,6 +17,27 @@ from ops.model import ( ) import charmhelpers.contrib.openstack.utils as os_utils import logging +import copy + +# Stolen from charms.ceph +UCA_CODENAME_MAP = { + 'icehouse': 'firefly', + 'juno': 'firefly', + 'kilo': 'hammer', + 'liberty': 'hammer', + 'mitaka': 'jewel', + 'newton': 'jewel', + 'ocata': 'jewel', + 'pike': 'luminous', + 'queens': 'luminous', + 'rocky': 'mimic', + 'stein': 'mimic', + 'train': 'nautilus', + 'ussuri': 'octopus', +} + + +_releases = {} logger = logging.getLogger() class OSBaseCharm(CharmBase): @@ -89,3 +111,82 @@ class OSBaseCharm(CharmBase): charm_func=None) self.state.is_paused = False self.update_status() + + +def charm_class(cls): + _releases[cls.release] = {'deb': cls} + +# Adapted from charms_openstack.charm.core +def get_charm_class(release=None, package_type='deb', all_releases=None, + *args, **kwargs): + """Get an instance of the charm based on the release (or use the + default if release is None). + + OS releases are in alphabetical order, so it looks for the first release + that is provided if release is None, otherwise it finds the release that is + before or equal to the release passed. + + Note that it passes args and kwargs to the class __init__() method. + + :param release: lc string representing release wanted. + :param package_type: string representing the package type required + :returns: BaseOpenStackCharm() derived class according to cls.releases + """ + if not all_releases: + all_releases = os_utils.OPENSTACK_RELEASES + if len(_releases.keys()) == 0: + raise RuntimeError( + "No derived BaseOpenStackCharm() classes registered") + # Note that this relies on OS releases being in alphabetical order + known_releases = sorted(_releases.keys()) + cls = None + if release is None: + # take the latest version of the charm if no release is passed. + cls = _releases[known_releases[-1]][package_type] + else: + # check that the release is a valid release + if release not in all_releases: + raise RuntimeError( + "Release {} is not a known OpenStack release?".format(release)) + release_index = all_releases.index(release) + if (release_index < + all_releases.index(known_releases[0])): + raise RuntimeError( + "Release {} is not supported by this charm. Earliest support " + "is {} release".format(release, known_releases[0])) + else: + # try to find the release that is supported. + for known_release in reversed(known_releases): + if (release_index >= + all_releases.index(known_release) and + package_type in _releases[known_release]): + cls = _releases[known_release][package_type] + break + if cls is None: + raise RuntimeError("Release {} is not supported".format(release)) + return cls + +# Adapted from charms_openstack.charm.core +def get_charm_instance(release=None, package_type='deb', all_releases=None, + *args, **kwargs): + return get_charm_class( + release=release, + package_type=package_type, + all_releases=all_releases, + *args, **kwargs)(release=release, *args, **kwargs) + +def get_charm_class_for_release(): + _origin = None + current_model = ops.model.ModelBackend() + config = current_model.config_get() + if 'source' in config: + _origin = config['source'] + elif 'openstack-origin' in config: + _origin = config['openstack-origin'] + else: + _origin = 'distro' + target_releae = os_utils.get_os_codename_install_source(_origin) + # Check for a cepch charm match first: + ceph_release = UCA_CODENAME_MAP[target_releae] + releases = sorted(list(set(UCA_CODENAME_MAP.values()))) + return get_charm_class(release=ceph_release, all_releases=releases)