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)
def identity_admin_changed(): ip = relation_get("service_hostname") if ip: api_version = int(relation_get("api_version")) api_suffix = 'v2.0' if api_version == 2 else 'v3' api_tokens = 'v2.0/tokens' if api_version == 2 else 'v3/auth/tokens' auth_info = { "keystone_protocol": relation_get("service_protocol"), "keystone_ip": ip, "keystone_public_port": relation_get("service_port"), "keystone_admin_user": relation_get("service_username"), "keystone_admin_password": relation_get("service_password"), "keystone_admin_tenant": relation_get("service_tenant_name"), "keystone_region": relation_get("service_region"), "keystone_api_version": api_version, "keystone_api_suffix": api_suffix, "keystone_api_tokens": api_tokens, # next three field are only for api_version = 3 "keystone_user_domain_name": relation_get("service_user_domain_name"), "keystone_project_domain_name": relation_get("service_project_domain_name"), "keystone_project_name": relation_get("service_project_name"), } auth_info = json.dumps(auth_info) config["auth_info"] = auth_info else: config.pop("auth_info", None) update_relations() update_status()
def tls_changed(module, rel_data): if not rel_data: # departed case cert = key = ca = None else: # changed case unitname = local_unit().replace('/', '_') cert_name = '{0}.server.cert'.format(unitname) key_name = '{0}.server.key'.format(unitname) cert = rel_data.get(cert_name) key = rel_data.get(key_name) ca = rel_data.get('ca') if not cert or not key or not ca: log("tls-certificates client's relation data is not fully available. Rel data: {}".format(rel_data)) cert = key = ca = None changed = update_certificates(module, cert, key, ca) if not changed: log("Certificates were not changed.") return False log("Certificates have been changed. Rewrite configs and rerun services.") if cert is not None and len(cert) > 0: config["ssl_enabled"] = True config["ca_cert"] = ca else: config["ssl_enabled"] = False config.pop("ca_cert", None) config.save() return True
def contrail_controller_departed(): # while we have at least one openstack/kubernetes unit on the remote end # then we can suggest that orchestrator is still defined agents_present = False issu_present = False for rid in relation_ids("contrail-controller"): for unit in related_units(rid): utype = relation_get('unit-type', unit, rid) if utype == "openstack" or utype == "kubernetes": agents_present = True if utype == "issu": issu_present = True changed = False if not agents_present and "orchestrator_info" in config: config.pop("orchestrator_info", None) changed = True if not issu_present and config.get("maintenance") == 'issu': # TODO: finish ISSU process config.pop("maintenance", None) config.pop("issu_controller_ips", None) config.pop("issu_controller_data_ips", None) config.pop("issu_analytics_ips", None) changed = True if changed: update_northbound_relations() update_southbound_relations()
def contrail_analyticsdb_departed(): units = [ unit for rid in relation_ids("contrail-analyticsdb") for unit in related_units(rid) ] if not units: config.pop("analyticsdb_ips", None) utils.update_charm_status()
def _update_config(data, key, data_key): if data_key in data: changed = config.get(key) != data[data_key] config[key] = data[data_key] else: changed = key in config config.pop(key, None) return changed
def contrail_analyticsdb_departed(): units = [ unit for rid in relation_ids("contrail-analyticsdb") for unit in related_units(rid) ] if not units: config.pop("db_user", None) config.pop("db_password", None) update_charm_status()
def contrail_controller_changed(): data = relation_get() if "orchestrator-info" in data: config["orchestrator_info"] = data["orchestrator-info"] else: config.pop("orchestrator_info", None) config.save() utils.update_charm_status(import_cluster=True)
def contrail_analytics_departed(): units = [unit for rid in relation_ids("contrail-analytics") for unit in related_units(rid)] if not units: for key in ["auth_info", "auth_mode", "orchestrator_info", "rabbitmq_hosts"]: config.pop(key, None) config.save() utils.update_charm_status() _notify_proxy_services()
def contrail_auth_departed(): units = [unit for rid in relation_ids("contrail-auth") for unit in related_units(rid)] if units: return config.pop("auth_info", None) update_northbound_relations() update_southbound_relations() utils.update_charm_status()
def contrail_auth_changed(): auth_info = relation_get("auth-info") if auth_info is not None: config["auth_info"] = auth_info else: config.pop("auth_info", None) update_northbound_relations() update_southbound_relations() utils.update_charm_status()
def _value_changed(rel_data, rel_key, cfg_key): if rel_key not in rel_data: # data is absent in relation. it means that remote charm doesn't # send it due to lack of information return value = rel_data[rel_key] if value is not None and value != config.get(cfg_key): config[cfg_key] = value elif value is None and config.get(cfg_key) is not None: config.pop(cfg_key, None)
def identity_admin_departed(): count = 0 for rid in relation_ids("identity-admin"): count += len(related_units(rid)) if count > 0: return config.pop("auth_info", None) update_relations() update_status()
def analyticsdb_departed(): count = 0 for rid in relation_ids("contrail-analyticsdb"): for unit in related_units(rid): if relation_get("unit-type", unit, rid) == "controller": count += 1 if count == 0: for key in ["auth_info", "orchestrator_info"]: config.pop(key, None) utils.update_charm_status()
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(): # NOTE: old image can not be deleted if container is running. # TODO: so think about killing the container # clear cached version of image config.pop("version_with_build", None) config.pop("version", None) config.save() # NOTE: this hook can be fired when either resource changed or charm code # changed. so if code was changed then we may need to update config update_charm_status()
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", "orchestrator_info", "analytics-server"] for key in keys: config.pop(key, None) utils.update_charm_status() status_set("blocked", "Missing relation to contrail-controller")
def analyticsdb_departed(): units = [unit for rid in relation_ids("contrail-controller") for unit in related_units(rid)] if not units: for key in ["auth_info", "orchestrator_info", "ssl_enabled"]: config.pop(key, None) if is_container_launched(CONTAINER_NAME): status_set( "blocked", "Container is present but cloud orchestrator was disappeared." " Please kill container by yourself or restore" " cloud orchestrator.") update_charm_status()
def contrail_issu_relation_changed(): rel_data = relation_get() if "orchestrator-info" in rel_data: config["orchestrator_info"] = rel_data["orchestrator-info"] else: config.pop("orchestrator_info", None) config.save() update_northbound_relations() utils.update_charm_status() issu_data = dict() for name in ["rabbitmq_connection_details", "cassandra_connection_details", "zookeeper_connection_details"]: issu_data.update(common_utils.json_loads(rel_data.get(name), dict())) utils.update_issu_state(issu_data)
def contrail_controller_changed(): data = relation_get() log("RelData: " + str(data)) def _update_config(key, data_key): if data_key in data: config[key] = data[data_key] else: config.pop(key, None) _update_config("analytics_servers", "analytics-server") _update_config("analyticsdb_enabled", "analyticsdb_enabled") _update_config("auth_info", "auth-info") _update_config("orchestrator_info", "orchestrator-info") _update_config("controller_ips", "controller_ips") _update_config("controller_data_ips", "controller_data_ips") _update_config("issu_controller_ips", "issu_controller_ips") _update_config("issu_controller_data_ips", "issu_controller_data_ips") _update_config("issu_analytics_ips", "issu_analytics_ips") maintenance = None if "maintenance" in data: maintenance = "issu" if "ziu" in data or "ziu_done" in data: maintenance = "ziu" if maintenance: config["maintenance"] = maintenance else: config.pop("maintenance", None) info = common_utils.json_loads(data.get("agents-info"), dict()) k8s_info = info.get("k8s_info") if k8s_info: ip = unit_private_ip() for cluster in k8s_info: kubernetes_workers = k8s_info[cluster].get("kubernetes_workers", []) if kubernetes_workers and ip in kubernetes_workers: config["pod_subnets"] = k8s_info[cluster].get("pod_subnets") break if "controller_data_ips" in data: settings = {"vhost-address": utils.get_vhost_ip()} for rid in relation_ids("agent-cluster"): relation_set(relation_id=rid, relation_settings=settings) utils.update_ziu("controller-changed") utils.update_charm_status()
def contrail_controller_departed(): # while we have at least one openstack unit on the remote end # then we can suggest that orchestrator is still openstack for rid in relation_ids("contrail-controller"): for unit in related_units(rid): utype = relation_get('unit-type', unit, rid) if utype == "openstack": return config.pop("orchestrator_info", None) if is_leader(): update_northbound_relations() if is_container_launched(CONTAINER_NAME): status_set( "blocked", "Container is present but cloud orchestrator was disappeared. " "Please kill container by yourself or restore cloud orchestrator.")
def contrail_controller_departed(): if not remote_unit().startswith("contrail-openstack-compute"): return units = [ unit for rid in relation_ids("contrail-openstack-compute") for unit in related_units(rid) ] if units: return config.pop("orchestrator_info", None) if is_leader(): update_northbound_relations() if is_container_launched(CONTAINER_NAME): status_set( "blocked", "Container is present but cloud orchestrator was disappeared. " "Please kill container by yourself or restore cloud orchestrator.")
def contrail_analytics_departed(): units = [ unit for rid in relation_ids("contrail-controller") for unit in related_units(rid) ] if not units: for key in [ "auth_info", "auth_mode", "orchestrator_info", "ssl_ca", "ssl_cert", "ssl_key", "rabbitmq_vhost", "rabbitmq_user", "rabbitmq_password" ]: config.pop(key, None) if is_container_launched(CONTAINER_NAME): status_set( "blocked", "Container is present but cloud orchestrator was disappeared." " Please kill container by yourself or restore cloud orchestrator." ) update_charm_status()
def _rebuild_config_from_controller_relation(): items = dict() def _update_item(data, key, data_key): val = data.get(data_key) if val is not None: items[key] = val ip = unit_private_ip() units = [(rid, unit) for rid in relation_ids("contrail-controller") for unit in related_units(rid)] # add relation info as last item to override outdated data units.append((None, None)) for rid, unit in units: data = relation_get(attribute=None, unit=unit, rid=rid) if data is None: continue _update_item(data, "auth_info", "auth-info") _update_item(data, "auth_mode", "auth-mode") _update_item(data, "controller_ips", "controller_ips") info = data.get("agents-info") if not info: items["dpdk"] = False else: value = json.loads(info).get(ip, False) if not isinstance(value, bool): value = yaml.load(value) items["dpdk"] = value if not items.get("dpdk"): log("DPDK for current host is False. agents-info is not provided.") else: log("DPDK for host {ip} is {dpdk}".format(ip=ip, dpdk=value)) for key in ["auth_info", "auth_mode", "controller_ips", "dpdk"]: if key in items: config[key] = items[key] else: config.pop(key, None)
def contrail_controller_changed(): data = relation_get() log("RelData: " + str(data)) def _update_config(key, data_key): if data_key in data: config[key] = data[data_key] else: config.pop(key, None) _update_config("analytics_servers", "analytics-server") _update_config("auth_info", "auth-info") _update_config("orchestrator_info", "orchestrator-info") _update_config("controller_ips", "controller_ips") _update_config("controller_data_ips", "controller_data_ips") _update_config("issu_controller_ips", "issu_controller_ips") _update_config("issu_controller_data_ips", "issu_controller_data_ips") _update_config("issu_analytics_ips", "issu_analytics_ips") if "controller_data_ips" in data: settings = {"vhost-address": utils.get_vhost_ip()} for rid in relation_ids("agent-cluster"): relation_set(relation_id=rid, relation_settings=settings) maintenance = None if "maintenance" in data: maintenance = "issu" if "ziu" in data or "ziu_done" in data: maintenance = "ziu" if maintenance: config["maintenance"] = maintenance else: config.pop("maintenance", None) config.save() utils.update_ziu("controller-changed") utils.update_charm_status()
def contrail_controller_departed(): changed = _rebuild_orchestrator_info() issu_present = False for rid in relation_ids("contrail-controller"): for unit in related_units(rid): utype = relation_get('unit-type', unit, rid) if utype == "issu": issu_present = True if not issu_present and config.get("maintenance") == 'issu': # TODO: finish ISSU process config.pop("maintenance", None) config.pop("issu_controller_ips", None) config.pop("issu_controller_data_ips", None) config.pop("issu_analytics_ips", None) changed = True if changed: update_northbound_relations() update_southbound_relations()
def config_set(key, value): if value is not None: config[key] = value else: config.pop(key, None) config.save()
def _update_config(key, data_key): if data_key in data: config[key] = data[data_key] else: config.pop(key, None)
def amqp_departed(): config.pop("rabbit-hostname", None) config.pop("rabbit-password", None) config.save() utils.update_charm_status()