class CharmBase: """ Base charm class """ charm_name = None display_name = None related = [] isolate = False constraints = None deploy_priority = sys.maxsize allow_multi_units = False optional = False def __init__(self, juju_state=None, machine=None): """ initialize :param state: :class:JujuState :param machine: :class:Machine """ self.charm_path = None self.exposed = False self.juju_state = juju_state assert isinstance(self.juju_state, JujuState) self.machine = machine self.client = JujuClient() @property def is_single(self): return pegasus.SINGLE_SYSTEM @property def is_multi(self): return pegasus.MULTI_SYSTEM def openstack_password(self): PASSWORD_FILE = expanduser('~/.cloud-install/openstack.passwd') try: with open(PASSWORD_FILE) as f: OPENSTACK_PASSWORD = f.read().strip() except IOError: OPENSTACK_PASSWORD = '******' return OPENSTACK_PASSWORD def is_related(self, charm, relations): """ test for existence of charm relation :param str charm: charm to verify :param list relations: related charms :returns: True if existing relation found, False otherwise :rtype: bool """ try: list(filter(lambda r: charm in r.charms, relations))[0] return True except IndexError: return False @classmethod def name(class_): """ Return charm name :returns: name of charm :rtype: lowercase str """ if class_.charm_name: return class_.charm_name return class_.__name__.lower() def setup(self, _id=None): """ Deploy charm and configuration options The default should be sufficient but if more functionality is needed this should be overridden. """ kwds = {} kwds['machine_id'] = _id if self.charm_name in CHARM_CONFIG: kwds['configfile'] = CHARM_CONFIG_FILENAME if self.isolate: kwds['machine_id'] = None kwds['instances'] = 1 kwds['constraints'] = self.constraints self.client.deploy(self.charm_name, kwds) else: self.client.deploy(self.charm_name, kwds) def set_relations(self): """ Setup charm relations Override in charm specific. """ if len(self.related) > 0: services = self.juju_state.service(self.charm_name) for charm in self.related: try: if not self.is_related(charm, services.relations) \ and len(list(services.relations)) != 0: self.client.add_relation(self.charm_name, charm) except: log.exception("Ignoring exception in set_relations.") log.debug("No relations " "found for {c}".format(c=self.charm_name)) def post_proc(self): """ Perform any post processing i.e. setting configuration variables for a charm Override in charm classes """ pass def __repr__(self): return self.name()
class CharmBase: """ Base charm class """ charm_name = None display_name = None related = [] isolate = False constraints = None deploy_priority = sys.maxsize display_priority = DisplayPriorities.Core allow_multi_units = False optional = False disabled = False machine_id = False def __init__(self, juju_state=None, machine=None): """ initialize :param state: :class:JujuState :param machine: :class:Machine """ self.charm_path = None self.exposed = False self.juju_state = juju_state assert isinstance(self.juju_state, JujuState) self.machine = machine self.client = JujuClient() @property def tmpl_path(self): """ template path """ return "/usr/share/cloud-installer/templates" @property def cfg_path(self): """ top level configuration path """ return path.expanduser('~/.cloud-install') @property def is_single(self): return pegasus.SINGLE_SYSTEM @property def is_multi(self): return pegasus.MULTI_SYSTEM def openstack_password(self): PASSWORD_FILE = path.join(self.cfg_path, 'openstack.passwd') try: with open(PASSWORD_FILE) as f: OPENSTACK_PASSWORD = f.read().strip() except IOError: OPENSTACK_PASSWORD = '******' return OPENSTACK_PASSWORD def _openstack_env(self, user, password, tenant, auth_url): """ setup openstack environment vars """ return """export OS_USERNAME={user} export OS_PASSWORD={password} export OS_TENANT_NAME={tenant} export OS_AUTH_URL=http://{auth_url}:5000/v2.0 export OS_REGION_NAME=RegionOne """.format( user=user, password=password, tenant=tenant, auth_url=auth_url) def _openstack_env_save(self, user, data): """ sets up environment file user """ try: with open(self._openstack_env_path(user), 'w') as f: f.write(data) except IOError as e: log.error("Unable to write admin environment variables." "(Result: {e})".format(e=e)) def _openstack_env_path(self, user): """ path to openstack environment file """ fname = "openstack-{u}-rc".format(u=user) return path.join(self.cfg_path, fname) def is_related(self, charm, relations): """ test for existence of charm relation :param str charm: charm to verify :param list relations: related charms :returns: True if existing relation found, False otherwise :rtype: bool """ try: list(filter(lambda r: charm in r.charms, relations))[0] return True except IndexError: return False @classmethod def name(class_): """ Return charm name :returns: name of charm :rtype: lowercase str """ if class_.charm_name: return class_.charm_name return class_.__name__.lower() def setup(self): """ Deploy charm and configuration options The default should be sufficient but if more functionality is needed this should be overridden. """ kwds = {} kwds['machine_id'] = self.machine_id if self.charm_name in CHARM_CONFIG: kwds['configfile'] = CHARM_CONFIG_FILENAME if self.isolate: kwds['machine_id'] = None kwds['instances'] = 1 kwds['constraints'] = self.constraints self.client.deploy(self.charm_name, kwds) else: self.client.deploy(self.charm_name, kwds) def set_relations(self): """ Setup charm relations Override in charm specific. """ if len(self.related) > 0: services = self.juju_state.service(self.charm_name) for charm in self.related: if not self.is_related(charm, services.relations): err = self.client.add_relation(self.charm_name, charm) if err: log.error("Relation not ready for " "{c}, requeueing.".format(c=self.charm_name)) return True return False def post_proc(self): """ Perform any post processing i.e. setting configuration variables for a charm Override in charm classes """ pass def wait_for_agent(self, svc_name=None): """ Waits for service agent to be reachable :rtype: Unit() :returns: unit if ready """ if not svc_name: svc_name = self.charm_name log.debug("Checking availability for {c}.".format(c=svc_name)) juju, _ = pegasus.poll_state() svc = juju.service(svc_name) unit = svc.unit(svc_name) if unit.agent_state == "started": return unit return False def _pubkey(self): """ return ssh pub key """ return path.expanduser('~/.ssh/id_rsa.pub') def __repr__(self): return self.name()