| from git import Repo as gitrepo |
| from shutil import rmtree |
| |
| import os |
| import subprocess |
| |
| from charmhelpers.core import host |
| from charmhelpers.core import hookenv |
| from charmhelpers.core import templating |
| from charmhelpers.core.unitdata import kv |
| from charmhelpers.core.hookenv import ( |
| config, |
| log, |
| open_port, |
| status_set, |
| ) |
| |
| from charmhelpers.core.host import ( |
| chownr, |
| ) |
| |
| from charms.reactive import ( |
| when, |
| when_not, |
| set_state, |
| is_state, |
| ) |
| |
| kvdb = kv() |
| |
| INSTALL_PATH = '/opt/openmano' |
| USER = 'openmanod' |
| |
| |
| @when('openmano.installed', 'openmano.available') |
| def openmano_available(openmano): |
| # TODO make this configurable via charm config |
| openmano.configure(port=9090) |
| |
| |
| @when('openvim-controller.available', |
| 'db.available', |
| 'db.installed', |
| 'openmano.installed', |
| 'openmano.running', |
| ) |
| def openvim_available(openvim, db): |
| for service in openvim.services(): |
| for endpoint in service['hosts']: |
| host = endpoint['hostname'] |
| port = endpoint['port'] |
| user = endpoint['user'] |
| |
| openvim_uri = '{}:{}'.format(host, port) |
| if kvdb.get('openvim_uri') == openvim_uri: |
| return |
| |
| # TODO: encapsulate the logic in create-datacenter.sh into python |
| try: |
| cmd = './scripts/create-datacenter.sh {} {} {} {}'.format( |
| host, port, user, kvdb.get('openmano-tenant')) |
| out, err = _run(cmd) |
| except subprocess.CalledProcessError as e: |
| # Ignore the error if the datacenter already exists. |
| if e.returncode != 153: |
| raise |
| |
| kvdb.set('openvim_uri', openvim_uri) |
| if not is_state('db.available'): |
| status_set('waiting', 'Waiting for database') |
| break |
| break |
| |
| |
| @when('openmano.installed', |
| 'db.installed', |
| 'openvim-controller.available') |
| @when_not('openmano.running') |
| def start(*args): |
| # TODO: if the service fails to start, we should raise an error to the op |
| # Right now, it sets the state as running and the charm dies. Because |
| # service-openmano returns 0 when it fails. |
| cmd = "/home/{}/bin/service-openmano start".format(USER) |
| out, err = _run(cmd) |
| |
| if not kvdb.get('openmano-tenant'): |
| out, err = _run('./scripts/create-tenant.sh') |
| kvdb.set('openmano-tenant', out.strip()) |
| |
| status_set( |
| 'active', |
| 'Up on {host}:{port}'.format( |
| host=hookenv.unit_public_ip(), |
| port='9090')) |
| |
| set_state('openmano.running') |
| |
| |
| @when('db.available', 'openmano.installed') |
| @when_not('db.installed') |
| def setup_db(db): |
| """Setup the database |
| |
| """ |
| db_uri = 'mysql://{}:{}@{}:{}/{}'.format( |
| db.user(), |
| db.password(), |
| db.host(), |
| db.port(), |
| db.database(), |
| ) |
| |
| if kvdb.get('db_uri') == db_uri: |
| # We're already configured |
| return |
| |
| status_set('maintenance', 'Initializing database') |
| |
| try: |
| # HACK: use a packed version of init_mano_db until bug https://osm.etsi.org/bugzilla/show_bug.cgi?id=56 is fixed |
| # cmd = "{}/database_utils/init_mano_db.sh --createdb ".format(kvdb.get('repo')) |
| cmd = "./scripts//init_mano_db.sh --createdb " |
| cmd += "-u {} -p{} -h {} -d {} -P {}".format( |
| db.user(), |
| db.password(), |
| db.host(), |
| db.database(), |
| db.port(), |
| ) |
| output, err = _run(cmd) |
| except subprocess.CalledProcessError: |
| # Eat this. init_mano_db.sh will return error code 1 on success |
| pass |
| |
| context = { |
| 'user': db.user(), |
| 'password': db.password(), |
| 'host': db.host(), |
| 'database': db.database(), |
| 'port': db.port(), |
| } |
| templating.render( |
| 'openmanod.cfg', |
| os.path.join(kvdb.get('repo'), 'openmanod.cfg'), |
| context, |
| owner=USER, |
| group=USER, |
| ) |
| kvdb.set('db_uri', db_uri) |
| |
| status_set('active', 'Database installed.') |
| set_state('db.installed') |
| |
| |
| @when_not('openvim-controller.available') |
| def need_openvim(): |
| status_set('waiting', 'Waiting for OpenVIM') |
| |
| |
| @when_not('db.available') |
| def need_db(): |
| status_set('waiting', 'Waiting for database') |
| |
| |
| @when_not('db.available') |
| @when_not('openvim-controller.available') |
| def need_everything(): |
| status_set('waiting', 'Waiting for database and OpenVIM') |
| |
| |
| @when_not('openmano.installed') |
| def install_layer_openmano(): |
| status_set('maintenance', 'Installing') |
| |
| cfg = config() |
| |
| # TODO change user home |
| # XXX security issue! |
| host.adduser(USER, password=USER) |
| |
| if os.path.isdir(INSTALL_PATH): |
| rmtree(INSTALL_PATH) |
| |
| gitrepo.clone_from( |
| cfg['repository'], |
| INSTALL_PATH, |
| branch=cfg['branch'], |
| ) |
| |
| chownr( |
| INSTALL_PATH, |
| owner=USER, |
| group=USER, |
| follow_links=False, |
| chowntopdir=True |
| ) |
| |
| os.mkdir(os.path.join(INSTALL_PATH, 'logs')) |
| chownr(INSTALL_PATH, USER, USER) |
| kvdb.set('repo', INSTALL_PATH) |
| |
| os.mkdir('/home/{}/bin'.format(USER)) |
| |
| os.symlink( |
| "{}/openmano".format(INSTALL_PATH), |
| "/home/{}/bin/openmano".format(USER)) |
| os.symlink( |
| "{}/scripts/openmano-report.sh".format(INSTALL_PATH), |
| "/home/{}/bin/openmano-report.sh".format(USER)) |
| os.symlink( |
| "{}/scripts/service-openmano.sh".format(INSTALL_PATH), |
| "/home/{}/bin/service-openmano".format(USER)) |
| |
| open_port(9090) |
| set_state('openmano.installed') |
| |
| |
| def _run(cmd, env=None): |
| if isinstance(cmd, str): |
| cmd = cmd.split() if ' ' in cmd else [cmd] |
| |
| log(cmd) |
| p = subprocess.Popen(cmd, |
| env=env, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
| stdout, stderr = p.communicate() |
| retcode = p.poll() |
| if retcode > 0: |
| raise subprocess.CalledProcessError( |
| returncode=retcode, |
| cmd=cmd, |
| output=stderr.decode("utf-8").strip()) |
| return (stdout.decode('utf-8'), stderr.decode('utf-8')) |