diff --git a/config.yaml b/config.yaml index d7234e2..8ad6aa3 100644 --- a/config.yaml +++ b/config.yaml @@ -1,5 +1,23 @@ options: + profile: + type: string + default: default + description: | + SDN controller profile to configure OpenDayLight for; supported values include + + cisco-vpp: Cisco VPP for OpenStack + openvswitch-odl: Open vSwitch OpenDayLight for OpenStack + + Only a single profile is supported at any one time. install-url: type: string default: "https://nexus.opendaylight.org/content/groups/public/org/opendaylight/integration/distribution-karaf/0.2.2-Helium-SR2/distribution-karaf-0.2.2-Helium-SR2.tar.gz" - description: Install binaries location + description: Web addressable location of OpenDayLight binaries to install + http-proxy: + type: string + default: + description: Proxy to use for http connections for OpenDayLight + https-proxy: + type: string + default: + description: Proxy to use for https connections for OpenDayLight diff --git a/hooks/odl_controller_hooks.py b/hooks/odl_controller_hooks.py index c25cbef..a3ee1ad 100755 --- a/hooks/odl_controller_hooks.py +++ b/hooks/odl_controller_hooks.py @@ -12,34 +12,43 @@ from charmhelpers.core.hookenv import ( UnregisteredHookError, config, log, - relation_set + relation_set, + relation_ids, ) from charmhelpers.core.host import ( adduser, mkdir, restart_on_change, - service_restart, service_start ) from charmhelpers.fetch import apt_install, install_remote -from odl_controller_utils import write_mvn_config +from odl_controller_utils import write_mvn_config, process_odl_cmds +from odl_controller_utils import PROFILES -PACKAGES = [ "default-jre-headless", "python-jinja2" ] +PACKAGES = ["default-jre-headless", "python-jinja2"] hooks = Hooks() config = config() + @hooks.hook("config-changed") @restart_on_change({"/home/opendaylight/.m2/settings.xml": ["odl-controller"]}) def config_changed(): + process_odl_cmds(PROFILES[config['profile']]) + for r_id in relation_ids('controller-api'): + controller_api_joined(r_id) write_mvn_config() + @hooks.hook("controller-api-relation-joined") -def controller_api_joined(): - relation_set(port=8181, username="admin", password="admin") +def controller_api_joined(r_id=None): + relation_set(relation_id=r_id, + port=PROFILES[config['profile']]['port'], + username="admin", password="admin") + @hooks.hook() def install(): @@ -51,21 +60,20 @@ def install(): install_remote(install_url, dest="/opt") filename = re.sub("^.*/", "", urlparse.urlparse(install_url)[2]) name = re.sub("\.tar\.gz$|\.tar$|\.gz$|\.zip$", "", filename) - os.symlink(name, "/opt/opendaylight-karaf") + if not os.path.exists("/opt/opendaylight-karaf"): + os.symlink(name, "/opt/opendaylight-karaf") shutil.copy("files/odl-controller.conf", "/etc/init") adduser("opendaylight", system_user=True) - mkdir("/home/opendaylight", owner="opendaylight", group="opendaylight", perms=0755) + mkdir("/home/opendaylight", owner="opendaylight", group="opendaylight", + perms=0755) check_call(["chown", "-R", "opendaylight:opendaylight", "/opt/" + name]) - mkdir("/var/log/opendaylight", owner="opendaylight", group="opendaylight", perms=0755) + mkdir("/var/log/opendaylight", owner="opendaylight", group="opendaylight", + perms=0755) # install features write_mvn_config() service_start("odl-controller") - check_call(["/opt/opendaylight-karaf/bin/client", "-r", "61", - "feature:install", "odl-base-all", "odl-aaa-authn", - "odl-restconf", "odl-nsf-all", "odl-adsal-northbound", - "odl-mdsal-apidocs", "odl-ovsdb-openstack", - "odl-ovsdb-northbound", "odl-dlux-core"]) + def main(): try: @@ -73,10 +81,12 @@ def main(): except UnregisteredHookError as e: log("Unknown hook {} - skipping.".format(e)) + @hooks.hook("ovsdb-manager-relation-joined") def ovsdb_manager_joined(): relation_set(port=6640, protocol="tcp") + @hooks.hook("upgrade-charm") def upgrade_charm(): pass diff --git a/hooks/odl_controller_utils.py b/hooks/odl_controller_utils.py index 8f3eefa..8a98f49 100644 --- a/hooks/odl_controller_utils.py +++ b/hooks/odl_controller_utils.py @@ -1,7 +1,34 @@ +import subprocess from os import environ import urlparse from charmhelpers.core.templating import render +from charmhelpers.core.hookenv import config + + +PROFILES = { + 'cisco-vpp': { + 'feature:install': ['cosc-cvpn-ovs-rest', + 'odl-netconf-connector-all'], + 'log:set': { + 'TRACE': ['cosc-cvpn-ovs-rest', + 'odl-netconf-connector-all'], + }, + 'port': 8181 + }, + 'openvswitch-odl': { + 'feature:install': ["odl-base-all", "odl-aaa-authn", + "odl-restconf", "odl-nsf-all", + "odl-adsal-northbound", + "odl-mdsal-apidocs", + "odl-ovsdb-openstack", + "odl-ovsdb-northbound", + "odl-dlux-core"], + 'port': 8080 + } +} +PROFILES['default'] = PROFILES['openvswitch-odl'] + def mvn_ctx(): ctx = {} @@ -9,11 +36,19 @@ def mvn_ctx(): ctx.update(mvn_proxy_ctx("https")) return ctx + def mvn_proxy_ctx(protocol): ctx = {} + proxy = config('%s-proxy' % protocol) key = protocol + "_proxy" - if key in environ: + if proxy: + url = urlparse.urlparse(proxy) + elif key in environ: url = urlparse.urlparse(environ[key]) + else: + url = None + + if url: hostname = url.hostname if hostname: ctx[key] = True @@ -32,7 +67,45 @@ def mvn_proxy_ctx(protocol): ctx[protocol + "_noproxy"] = no_proxy return ctx + def write_mvn_config(): ctx = mvn_ctx() render("settings.xml", "/home/opendaylight/.m2/settings.xml", ctx, "opendaylight", "opendaylight", 0400) + + +def run_odl(cmds, host="localhost", port=8101, retries=20): + run_cmd = ["/opt/opendaylight-karaf/bin/client", "-r", str(retries), + "-h", host, "-a", str(port)] + run_cmd.extend(cmds) + output = subprocess.check_output(run_cmd) + return output + + +def installed_features(): + installed = [] + out = run_odl(["feature:list"]) + for line in out.split("\n"): + columns = line.split("|") + if len(columns) > 2: + install_flag = columns[2].replace(" ", "") + if install_flag == "x": + installed.append(columns[0].replace(" ", "")) + return installed + + +def filter_installed(features): + installed = installed_features() + whitelist = [feature for feature in features if feature not in installed] + return whitelist + + +def process_odl_cmds(odl_cmds): + features = filter_installed(odl_cmds.get("feature:install", [])) + if features: + run_odl(["feature:install"] + features) + logging = odl_cmds.get("log:set") + if logging: + for log_level in logging.keys(): + for target in logging[log_level]: + run_odl(["log:set", log_level, target])