aboutsummaryrefslogtreecommitdiffstats
path: root/contrail-openstack/hooks/contrail_openstack_utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'contrail-openstack/hooks/contrail_openstack_utils.py')
-rw-r--r--contrail-openstack/hooks/contrail_openstack_utils.py168
1 files changed, 168 insertions, 0 deletions
diff --git a/contrail-openstack/hooks/contrail_openstack_utils.py b/contrail-openstack/hooks/contrail_openstack_utils.py
new file mode 100644
index 0000000..25f57a0
--- /dev/null
+++ b/contrail-openstack/hooks/contrail_openstack_utils.py
@@ -0,0 +1,168 @@
+import apt_pkg
+from base64 import b64decode
+import json
+import os
+import requests
+from six.moves.urllib.parse import urlparse
+from socket import gethostbyname
+
+from charmhelpers.core.hookenv import (
+ config,
+ log,
+ WARNING,
+ ERROR,
+ relation_ids,
+ related_units,
+)
+from charmhelpers.core.host import (
+ write_file,
+)
+from charmhelpers.core.templating import render
+
+apt_pkg.init()
+config = config()
+
+
+def update_service_ips():
+ try:
+ endpoints = _get_endpoints()
+ except Exception as e:
+ log("Couldn't detect services ips: " + str(e),
+ level=WARNING)
+ return False
+
+ changed = {}
+
+ def _check_key(key):
+ val = endpoints.get(key)
+ if val and val != config.get(key):
+ config[key] = val
+ changed[key] = val
+
+ _check_key("compute_service_ip")
+ _check_key("image_service_ip")
+ _check_key("network_service_ip")
+ if changed:
+ config.save()
+ return True
+
+ return False
+
+
+def _get_endpoints():
+ auth_info = config.get("auth_info")
+ if auth_info:
+ auth_info = json.loads(auth_info)
+ if not auth_info or not auth_info.get("keystone_ip"):
+ raise Exception("auth_info is not ready.")
+
+ api_ver = int(auth_info["keystone_api_version"])
+ if api_ver == 2:
+ req_data = {
+ "auth": {
+ "tenantName": auth_info["keystone_admin_tenant"],
+ "passwordCredentials": {
+ "username": auth_info["keystone_admin_user"],
+ "password": auth_info["keystone_admin_password"]}}}
+ else:
+ req_data = {
+ "auth": {
+ "identity": {
+ "methods": ["password"],
+ "password": {
+ "user": {
+ "name": auth_info["keystone_admin_user"],
+ "domain": {"id": "default"},
+ "password": auth_info["keystone_admin_password"]
+ }
+ }
+ }
+ }
+ }
+
+ url = "{proto}://{ip}:{port}/{tokens}".format(
+ proto=auth_info["keystone_protocol"],
+ ip=auth_info["keystone_ip"],
+ port=auth_info["keystone_public_port"],
+ tokens=auth_info["keystone_api_tokens"])
+ r = requests.post(url, headers={'Content-type': 'application/json'},
+ data=json.dumps(req_data), verify=False)
+ content = json.loads(r.content)
+ result = dict()
+ catalog = (content["access"]["serviceCatalog"] if api_ver == 2 else
+ content["token"]["catalog"])
+ for service in catalog:
+ if api_ver == 2:
+ # NOTE: 0 means first region. do we need to search for region?
+ url = service["endpoints"][0]["publicURL"]
+ else:
+ for endpoint in service["endpoints"]:
+ if endpoint["interface"] == "public":
+ url = endpoint["url"]
+ break
+ host = gethostbyname(urlparse(url).hostname)
+ result[service["type"] + "_service_ip"] = host
+ return result
+
+
+def write_configs():
+ # don't need to write any configs for nova. only for neutron.
+
+ units = [unit for rid in relation_ids("neutron-api")
+ for unit in related_units(rid)]
+ if not units:
+ return
+
+ ctx = _get_context()
+
+ # store files in standard path
+ ca_path = "/etc/contrail/ssl/certs/ca-cert.pem"
+ ssl_ca = ctx["ssl_ca"]
+ _save_file(ca_path, ssl_ca)
+ ctx["ssl_ca_path"] = ca_path
+
+ render("ContrailPlugin.ini",
+ "/etc/neutron/plugins/opencontrail/ContrailPlugin.ini",
+ ctx, "root", "neutron", 0o440)
+
+
+def _get_context():
+ ctx = {}
+
+ ip = config.get("api_vip")
+ if not ip:
+ ip = config.get("api_ip")
+ ctx["api_server"] = ip
+ ctx["api_port"] = config.get("api_port")
+
+ ssl_ca = _decode_cert("ssl_ca")
+ ctx["ssl_ca"] = ssl_ca
+ ctx["ssl_enabled"] = (ssl_ca is not None and len(ssl_ca) > 0)
+ log("CTX: " + str(ctx))
+
+ auth_info = config.get("auth_info")
+ if auth_info:
+ ctx.update(json.loads(auth_info))
+ return ctx
+
+
+def _decode_cert(key):
+ val = config.get(key)
+ if not val:
+ return None
+ try:
+ return b64decode(val)
+ except Exception as e:
+ log("Couldn't decode certificate from config['{}']: {}".format(
+ key, str(e)), level=ERROR)
+ return None
+
+
+def _save_file(path, data):
+ if data:
+ fdir = os.path.dirname(path)
+ if not os.path.exists(fdir):
+ os.makedirs(fdir)
+ write_file(path, data, perms=0o444)
+ elif os.path.exists(path):
+ os.remove(path)