Revert "Removing deprecated/unused/outdated code"
[osm/RO.git] / charms / layers / openmano / reactive / layer_openmano.py
diff --git a/charms/layers/openmano/reactive/layer_openmano.py b/charms/layers/openmano/reactive/layer_openmano.py
new file mode 100644 (file)
index 0000000..2320e91
--- /dev/null
@@ -0,0 +1,234 @@
+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'))