def neutron_api_joined(rel_id=None):
    apt_install(NEUTRON_API_PACKAGES, fatal=True)
    try:
        cmd = [
            "dpkg-query", "-f", "${Version}\\n", "-W",
            "neutron-plugin-contrail"
        ]
        version = check_output(cmd).decode("UTF-8").rstrip()
        application_version_set(version)
        # save version for future using
        version = version.split('-')[0].split('.')
        m = int(version[0])
        r = int(version[1]) if len(version) > 1 else 0
        a = int(version[2]) if len(version) > 2 else 0
        config["version"] = (m * 1e4) + (r * 1e2) + a
        config.save()
    except CalledProcessError as e:
        log("Couldn't detect installed application version: " + str(e))

    # create plugin config
    base = "neutron_plugin_contrail.plugins.opencontrail"
    plugin = base + ".contrail_plugin.NeutronPluginContrailCoreV2"
    service_plugins = base + ".loadbalancer.v2.plugin.LoadBalancerPluginV2"
    extensions = [
        "/usr/lib/python2.7/dist-packages/neutron_plugin_contrail/extensions",
        "/usr/lib/python2.7/dist-packages/neutron_lbaas/extensions"
    ]
    conf = {
        "neutron-api": {
            "/etc/neutron/neutron.conf": {
                "sections": {
                    "DEFAULT": [("api_extensions_path", ":".join(extensions))]
                }
            }
        }
    }
    settings = {
        "neutron-plugin": "contrail",
        "core-plugin": plugin,
        "neutron-plugin-config":
        "/etc/neutron/plugins/opencontrail/ContrailPlugin.ini",
        "service-plugins": service_plugins,
        "quota-driver": base + ".quota.driver.QuotaDriver",
        "subordinate_configuration": json.dumps(conf),
    }
    auth_mode = config.get("auth_mode", "cloud-admin")
    if auth_mode == "rbac":
        settings["extra_middleware"] = [{
            "name": "user_token",
            "type": "filter",
            "config": {
                "paste.filter_factory":
                base + ".neutron_middleware:token_factory"
            }
        }]
    relation_set(relation_id=rel_id, relation_settings=settings)

    # if this hook raised after contrail-controller we need
    # to overwrite default config file after installation
    write_configs()
def contrail_controller_changed():
    data = relation_get()

    def _update_config(key, data_key):
        if data_key in data:
            val = data[data_key]
            if val is not None:
                config[key] = val
            else:
                config.pop(key, None)

    _update_config("auth_info", "auth-info")
    _update_config("ssl_ca", "ssl-ca")
    _update_config("api_vip", "api-vip")
    _update_config("api_ip", "private-address")
    _update_config("api_port", "port")
    config.save()
    write_configs()

    status_set("active", "Unit is ready")

    # auth_info can affect endpoints
    changed = update_service_ips()
    if changed and is_leader():
        data = _get_orchestrator_info()
        for rid in relation_ids("contrail-controller"):
            relation_set(relation_id=rid, **data)
def neutron_api_joined(rel_id=None):
    version = utils.get_openstack_version_codename('neutron')
    utils.deploy_openstack_code(
        "contrail-openstack-neutron-init", "neutron",
        {"OPENSTACK_VERSION": utils.PACKAGE_CODENAMES['neutron'][version]})

    # create plugin config
    contrail_version = common_utils.get_contrail_version()
    plugin_path = utils.get_component_sys_paths("neutron")
    base = "neutron_plugin_contrail.plugins.opencontrail"
    plugin = base + ".contrail_plugin.NeutronPluginContrailCoreV2"
    # pass just separator to prevent setting of default list
    service_plugins = "contrail-timestamp,"
    if contrail_version >= 1909:
        service_plugins += "contrail-trunk,"
    if contrail_version >= 2005 and version > 12:
        service_plugins += "contrail-tags,"
    if version < 15:
        service_plugins += base + ".loadbalancer.v2.plugin.LoadBalancerPluginV2,"
    contrail_plugin_extension = plugin_path + "/neutron_plugin_contrail/extensions"
    neutron_lbaas_extensions = plugin_path + "/neutron_lbaas/extensions"
    extensions = [contrail_plugin_extension, neutron_lbaas_extensions]
    conf = {
        "neutron-api": {
            "/etc/neutron/neutron.conf": {
                "sections": {
                    "DEFAULT": [("api_extensions_path", ":".join(extensions))]
                }
            }
        }
    }
    settings = {
        "neutron-plugin": "contrail",
        "core-plugin": plugin,
        "neutron-plugin-config":
        "/etc/neutron/plugins/opencontrail/ContrailPlugin.ini",
        "service-plugins": service_plugins,
        "quota-driver": base + ".quota.driver.QuotaDriver",
        "subordinate_configuration": json.dumps(conf),
    }
    auth_mode = config.get("auth_mode", "cloud-admin")
    if auth_mode == "rbac":
        settings["extra_middleware"] = [{
            "name": "user_token",
            "type": "filter",
            "config": {
                "paste.filter_factory":
                base + ".neutron_middleware:token_factory"
            }
        }]
    relation_set(relation_id=rel_id, relation_settings=settings)

    # if this hook raised after contrail-controller we need
    # to overwrite default config file after installation
    utils.write_configs()
def contrail_cotroller_departed():
    units = [unit for rid in relation_ids("contrail-controller")
                  for unit in related_units(rid)]
    if units:
        return

    keys = ["auth_info", "api_vip", "api_ip", "api_port", "auth_mode"]
    for key in keys:
        config.pop(key, None)
    config.save()
    write_configs()
    status_set("blocked", "Missing relation to contrail-controller")
def upgrade_charm():
    _rebuild_config_from_controller_relation()
    config.save()
    utils.write_configs()
    _update_status()

    if is_leader():
        utils.update_service_ips()
    # apply information to base charms
    _notify_nova()
    _notify_neutron()
    _notify_heat()
    _notify_controller()
def contrail_controller_changed():
    _rebuild_config_from_controller_relation()
    config.save()
    utils.write_configs()
    _update_status()

    # apply information to base charms
    _notify_nova()
    _notify_neutron()
    _notify_heat()

    # auth_info can affect endpoints
    if is_leader() and utils.update_service_ips():
        _notify_controller()
def contrail_controller_changed():
    data = relation_get()

    def _update_config(key, data_key):
        if data_key in data:
            val = data[data_key]
            if val is not None:
                config[key] = val
            else:
                config.pop(key, None)
        else:
            config.pop(key, None)

    _update_config("auth_info", "auth-info")
    _update_config("auth_mode", "auth-mode")
    _update_config("controller_ips", "controller_ips")

    info = data.get("agents-info")
    if not info:
        config["dpdk"] = False
        log("DPDK for current host is False. agents-info is not provided.")
    else:
        ip = unit_private_ip()
        value = json.loads(info).get(ip, False)
        if not isinstance(value, bool):
            value = yaml.load(value)
        config["dpdk"] = value
        log("DPDK for host {ip} is {dpdk}".format(ip=ip, dpdk=value))

    config.save()
    utils.write_configs()

    # apply information to base charms
    _notify_nova()
    _notify_neutron()
    _notify_heat()

    status_set("active", "Unit is ready")

    # auth_info can affect endpoints
    if is_leader():
        changed = utils.update_service_ips()
        if changed:
            _notify_controller()
def neutron_api_joined():
    _notify_neutron(rid=relation_id())

    # if this hook raised after contrail-controller we need
    # to overwrite default config file after installation
    utils.write_configs()
def contrail_cotroller_departed():
    _rebuild_config_from_controller_relation()
    config.save()
    utils.write_configs()
    _update_status()