class JujuClientTest(unittest.TestCase):
    def setUp(self):
        self.c = JujuClient(url=JUJU_URL)

    def tearDown(self):
        self.c.close()

    def test_login(self):
        self.c.login(JUJU_PASS)
        self.assertTrue(self.c.is_connected)
class JujuApiTest(unittest.TestCase):
    def setUp(self):
        self.c = JujuClient(url=JUJU_URL)
        self.c.login(JUJU_PASS)

    def tearDown(self):
        self.c.close()

    def test_info(self):
        ret = self.c.info()
        self.assertTrue(ret)
Exemple #3
0
    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()
Exemple #4
0
class CommandRunner(ListBox):
    def __init__(self):
        self._contents = SimpleListWalker([])
        ListBox.__init__(self, self._contents)
        self.client = JujuClient()

    def add_machine(self, constraints=None):
        """ Add a machine with optional constraints

        :param dict constraints: (optional) machine specs
        """
        log.debug("adding machine with constraints={}".format(constraints))
        out = self.client.add_machine(constraints)
        return out

    def add_unit(self, service_name, machine_id=None, count=1):
        """ Add a unit with optional machine id

        :param str service_name: name of charm
        :param int machine_id: (optional) id of machine to deploy to
        :param int count: (optional) number of units to add
        """
        out = self.client.add_unit(service_name, machine_id, count)
        return out
Exemple #5
0
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()
#!/usr/bin/env python

import os
import sys
sys.path.insert(0, '../cloudinstall')
from cloudinstall.juju.client import JujuClient
from pprint import pprint
import json
import time

JUJU_PASS = os.environ['JUJU_PASS'] if os.environ['JUJU_PASS'] else randomString()
JUJU_URL = os.environ['JUJU_URL'] if os.environ['JUJU_URL'] else 'wss://juju-bootstrap.master:17070/'

if __name__ == '__main__':
    ws = JujuClient(JUJU_URL)
    ws.login(JUJU_PASS)
    ws.info()
    ws.close()
 def setUp(self):
     self.c = JujuClient(url=JUJU_URL)
     self.c.login(JUJU_PASS)
 def setUp(self):
     self.c = JujuClient(url=JUJU_URL)
Exemple #10
0
 def __init__(self):
     self._contents = SimpleListWalker([])
     ListBox.__init__(self, self._contents)
     self.client = JujuClient()