def create_ip_cert_links(ssl_dir, custom_hostname_link=None): """Create symlinks for SAN records :param ssl_dir: str Directory to create symlinks in :param custom_hostname_link: str Additional link to be created """ hostname = get_hostname(unit_get('private-address')) hostname_cert = os.path.join( ssl_dir, 'cert_{}'.format(hostname)) hostname_key = os.path.join( ssl_dir, 'key_{}'.format(hostname)) # Add links to hostname cert, used if os-hostname vars not set for net_type in [INTERNAL, ADMIN, PUBLIC]: try: addr = resolve_address(endpoint_type=net_type) cert = os.path.join(ssl_dir, 'cert_{}'.format(addr)) key = os.path.join(ssl_dir, 'key_{}'.format(addr)) if os.path.isfile(hostname_cert) and not os.path.isfile(cert): os.symlink(hostname_cert, cert) os.symlink(hostname_key, key) except NoNetworkBinding: log("Skipping creating cert symlink for ip in {} space, no " "local address found".format(net_type), WARNING) if custom_hostname_link: custom_cert = os.path.join( ssl_dir, 'cert_{}'.format(custom_hostname_link)) custom_key = os.path.join( ssl_dir, 'key_{}'.format(custom_hostname_link)) if os.path.isfile(hostname_cert) and not os.path.isfile(custom_cert): os.symlink(hostname_cert, custom_cert) os.symlink(hostname_key, custom_key)
def get_certificate_sans(bindings=None): """Get all possible IP addresses for certificate SANs. """ _sans = [unit_get('private-address')] if bindings: # Add default API bindings to bindings list bindings = set(bindings + get_default_api_bindings()) else: # Use default API bindings bindings = get_default_api_bindings() for binding in bindings: # Check for config override try: net_config = config(ADDRESS_MAP[binding]['config']) except KeyError: # There is no configuration network for this binding name net_config = None # Using resolve_address is likely redundant. Keeping it here in # case there is an edge case it handles. net_addr = resolve_address(endpoint_type=binding) ip = get_relation_ip(binding, cidr_network=net_config) _sans = _sans + [net_addr, ip] vip = get_vip_in_network(resolve_network_cidr(ip)) if vip: _sans.append(vip) return set(_sans)
def __call__(self): ctxt = {} servers = [] try: for rid in relation_ids('memcache'): for rel in relations_for_id(rid): priv_addr = rel['private-address'] # Format it as IPv6 address if needed priv_addr = format_ipv6_addr(priv_addr) or priv_addr servers.append("%s:%s" % (priv_addr, rel['port'])) except Exception as ex: log("Could not get memcache servers: %s" % (ex), level='WARNING') servers = [] ctxt['memcached_servers'] = ','.join(servers) # Configure nova-novncproxy https if nova-api is using https. if https(): cn = resolve_address(endpoint_type=INTERNAL) if cn: cert_filename = 'cert_{}'.format(cn) key_filename = 'key_{}'.format(cn) else: cert_filename = 'cert' key_filename = 'key' ssl_dir = '/etc/apache2/ssl/nova' cert = os.path.join(ssl_dir, cert_filename) key = os.path.join(ssl_dir, key_filename) if os.path.exists(cert) and os.path.exists(key): ctxt['ssl_cert'] = cert ctxt['ssl_key'] = key return ctxt
def __call__(self): ctxt = super(NovaConfigContext, self).__call__() ctxt['scheduler_default_filters'] = ( hookenv.config('scheduler-default-filters')) if hookenv.config('pci-alias'): aliases = json.loads(hookenv.config('pci-alias')) if isinstance(aliases, list): ctxt['pci_aliases'] = [ json.dumps(x, sort_keys=True) for x in aliases ] else: ctxt['pci_alias'] = json.dumps(aliases, sort_keys=True) ctxt['disk_allocation_ratio'] = hookenv.config('disk-allocation-ratio') ctxt['cpu_allocation_ratio'] = hookenv.config('cpu-allocation-ratio') ctxt['ram_allocation_ratio'] = hookenv.config('ram-allocation-ratio') addr = ch_ip.resolve_address(ch_ip.INTERNAL) ctxt['host_ip'] = ch_network_ip.format_ipv6_addr(addr) or addr ctxt['quota_instances'] = hookenv.config('quota-instances') ctxt['quota_cores'] = hookenv.config('quota-cores') ctxt['quota_ram'] = hookenv.config('quota-ram') ctxt['quota_metadata_items'] = hookenv.config('quota-metadata-items') ctxt['quota_injected_files'] = hookenv.config('quota-injected-files') ctxt['quota_injected_file_content_bytes'] = hookenv.config( 'quota-injected-file-size') ctxt['quota_injected_file_path_length'] = hookenv.config( 'quota-injected-path-size') ctxt['quota_key_pairs'] = hookenv.config('quota-key-pairs') ctxt['quota_server_groups'] = hookenv.config('quota-server-groups') ctxt['quota_server_group_members'] = hookenv.config( 'quota-server-group-members') return ctxt
def get_certificate_request(json_encode=True): """Generate a certificatee requests based on the network confioguration """ req = CertRequest(json_encode=json_encode) req.add_hostname_cn() # Add os-hostname entries for net_type in [INTERNAL, ADMIN, PUBLIC]: net_config = config(ADDRESS_MAP[net_type]['override']) try: net_addr = resolve_address(endpoint_type=net_type) ip = network_get_primary_address(ADDRESS_MAP[net_type]['binding']) addresses = [net_addr, ip] vip = get_vip_in_network(resolve_network_cidr(ip)) if vip: addresses.append(vip) if net_config: req.add_entry(net_type, net_config, addresses) else: # There is network address with no corresponding hostname. # Add the ip to the hostname cert to allow for this. req.add_hostname_cn_ip(addresses) except NoNetworkBinding: log( "Skipping request for certificate for ip in {} space, no " "local address found".format(net_type), WARNING) return req.get_request()
def test_resolve_address_default_clustered(self): self.is_clustered.return_value = True self.test_config.set('vip', '10.5.3.1') self.assertEquals(ip.resolve_address(), '10.5.3.1') self.config.assert_has_calls( [call('vip'), call('os-public-network')])
def create_ip_cert_links(ssl_dir, custom_hostname_link=None): """Create symlinks for SAN records :param ssl_dir: str Directory to create symlinks in :param custom_hostname_link: str Additional link to be created """ hostname = get_hostname(unit_get('private-address')) hostname_cert = os.path.join(ssl_dir, 'cert_{}'.format(hostname)) hostname_key = os.path.join(ssl_dir, 'key_{}'.format(hostname)) # Add links to hostname cert, used if os-hostname vars not set for net_type in [INTERNAL, ADMIN, PUBLIC]: try: addr = resolve_address(endpoint_type=net_type) cert = os.path.join(ssl_dir, 'cert_{}'.format(addr)) key = os.path.join(ssl_dir, 'key_{}'.format(addr)) if os.path.isfile(hostname_cert) and not os.path.isfile(cert): os.symlink(hostname_cert, cert) os.symlink(hostname_key, key) except NoNetworkBinding: log( "Skipping creating cert symlink for ip in {} space, no " "local address found".format(net_type), WARNING) if custom_hostname_link: custom_cert = os.path.join(ssl_dir, 'cert_{}'.format(custom_hostname_link)) custom_key = os.path.join(ssl_dir, 'key_{}'.format(custom_hostname_link)) if os.path.isfile(hostname_cert) and not os.path.isfile(custom_cert): os.symlink(hostname_cert, custom_cert) os.symlink(hostname_key, custom_key)
def get_certificate_request(json_encode=True): """Generate a certificatee requests based on the network confioguration """ req = CertRequest(json_encode=json_encode) req.add_hostname_cn() # Add os-hostname entries for net_type in [INTERNAL, ADMIN, PUBLIC]: net_config = config(ADDRESS_MAP[net_type]['override']) try: net_addr = resolve_address(endpoint_type=net_type) ip = network_get_primary_address( ADDRESS_MAP[net_type]['binding']) addresses = [net_addr, ip] vip = get_vip_in_network(resolve_network_cidr(ip)) if vip: addresses.append(vip) if net_config: req.add_entry( net_type, net_config, addresses) else: # There is network address with no corresponding hostname. # Add the ip to the hostname cert to allow for this. req.add_hostname_cn_ip(addresses) except NoNetworkBinding: log("Skipping request for certificate for ip in {} space, no " "local address found".format(net_type), WARNING) return req.get_request()
def websso_trusted_dashboard_changed(): """ Provide L7 endpoint details for the dashboard and also handle any config changes that may affect those. """ relations = relation_ids('websso-trusted-dashboard') if not relations: return # TODO: check for vault relation in order to determine url scheme tls_configured = (relation_ids('certificates') or config('ssl-key') or config('enforce-ssl')) scheme = 'https://' if tls_configured else 'http://' hostname = resolve_address(endpoint_type=PUBLIC, override=True) # urljoin needs a base url to be '/'-terminated contrary to the joined path webroot = config('webroot') if not webroot.endswith('/'): webroot += '/' path = urllib.parse.urljoin(webroot, "auth/websso/") # provide trusted dashboard URL details for rid in relations: relation_set(relation_id=rid, relation_settings={ "scheme": scheme, "hostname": hostname, "path": path, })
def __call__(self): ctxt = super(NovaConfigContext, self).__call__() ctxt['scheduler_default_filters'] = config('scheduler-default-filters') ctxt['cpu_allocation_ratio'] = config('cpu-allocation-ratio') ctxt['ram_allocation_ratio'] = config('ram-allocation-ratio') addr = resolve_address(INTERNAL) ctxt['host_ip'] = format_ipv6_addr(addr) or addr return ctxt
def test_resolve_address_default_internal(self): self.is_clustered.return_value = False self.unit_get.return_value = 'unit1' self.get_address_in_network.return_value = 'unit1' self.assertEquals(ip.resolve_address(ip.INTERNAL), 'unit1') self.unit_get.assert_called_with('private-address') calls = [call('os-internal-network'), call('prefer-ipv6')] self.config.assert_has_calls(calls)
def test_resolve_address_default(self): self.is_clustered.return_value = False self.unit_get.return_value = 'unit1' self.get_address_in_network.return_value = 'unit1' self.assertEquals(ip.resolve_address(), 'unit1') self.unit_get.assert_called_with('public-address') calls = [call('os-public-network'), call('prefer-ipv6')] self.config.assert_has_calls(calls) self.get_address_in_network.assert_called_with(None, 'unit1')
def configure_ceph_exporter_relation(target): config = hookenv.config() if data_changed('target.config', config): try: hostname = hookenv.network_get_primary_address('target').decode( "utf-8") except NotImplementedError: hostname = resolve_address(endpoint_type=INTERNAL) target.configure(hostname=hostname, port=config.get('port')) hookenv.status_set('active', 'Ready')
def canonical_url(): """Returns the correct HTTP URL to this host given the state of HTTPS configuration and hacluster. """ scheme = 'http' if https(): scheme = 'https' addr = resolve_address(INTERNAL) return '%s://%s' % (scheme, format_ipv6_addr(addr) or addr)
def __call__(self): if NeutronAPIContext()()['enable_dvr'] or \ config('enable-local-dhcp-and-metadata'): ctxt = { 'shared_secret': get_shared_secret(), 'local_ip': resolve_address(), } else: ctxt = {} return ctxt
def __call__(self): ip_addr = ch_ip.resolve_address(endpoint_type=ch_ip.PUBLIC) ip_addr = ch_network_ip.format_ipv6_addr(ip_addr) or ip_addr ctxt = { 'enable_serial_console': str(hookenv.config('enable-serial-console')).lower(), 'serial_console_base_url': 'ws://{}:6083/'.format(ip_addr) } return ctxt
def admin_relation_changed(relation_id=None): # TODO: fixup relation_data = { 'service_hostname': resolve_address(ADMIN), 'service_port': config('service-port'), 'service_username': config('admin-user'), 'service_tenant_name': config('admin-role'), 'service_region': config('region'), } relation_data['service_password'] = get_admin_passwd() relation_set(relation_id=relation_id, **relation_data)
def test_resolve_address_public_not_clustered(self): self.is_clustered.return_value = False self.test_config.set('os-public-network', '192.168.20.0/24') self.unit_get.return_value = 'unit1' self.get_address_in_network.return_value = '192.168.20.1' self.assertEquals(ip.resolve_address(), '192.168.20.1') self.unit_get.assert_called_with('public-address') calls = [call('os-public-network'), call('prefer-ipv6')] self.config.assert_has_calls(calls) self.get_address_in_network.assert_called_with('192.168.20.0/24', 'unit1')
def test_resolve_address_network_get(self): self.is_clustered.return_value = False self.unit_get.return_value = 'unit1' self.network_get_primary_address.side_effect = None self.network_get_primary_address.return_value = '10.5.60.1' self.assertEqual(ip.resolve_address(), '10.5.60.1') self.unit_get.assert_called_with('public-address') calls = [call('os-public-network'), call('prefer-ipv6')] self.config.assert_has_calls(calls) self.network_get_primary_address.assert_called_with('public')
def test_resolve_address_network_get_clustered(self): self.is_clustered.return_value = True self.test_config.set('vip', '10.5.60.20 192.168.1.20') self.network_get_primary_address.side_effect = None self.network_get_primary_address.return_value = '10.5.60.1' self.resolve_network_cidr.return_value = '10.5.60.1/24' self.assertEqual(ip.resolve_address(), '10.5.60.20') calls = [call('os-public-hostname'), call('vip'), call('os-public-network')] self.config.assert_has_calls(calls) self.network_get_primary_address.assert_called_with('public')
def admin_relation_changed(relation_id=None): # TODO: fixup relation_data = { "service_hostname": resolve_address(ADMIN), "service_port": config("service-port"), "service_username": config("admin-user"), "service_tenant_name": config("admin-role"), "service_region": config("region"), "service_protocol": "https" if https() else "http", } relation_data["service_password"] = get_admin_passwd() relation_set(relation_id=relation_id, **relation_data)
def get_certificate_request(json_encode=True, bindings=None): """Generate a certificate requests based on the network configuration :param json_encode: Encode request in JSON or not. Used for setting directly on a relation. :type json_encode: boolean :param bindings: List of bindings to check in addition to default api bindings. :type bindings: list of strings :returns: CertRequest request as dictionary or JSON string. :rtype: Union[dict, json] """ if bindings: # Add default API bindings to bindings list bindings = set(bindings + get_default_api_bindings()) else: # Use default API bindings bindings = get_default_api_bindings() req = CertRequest(json_encode=json_encode) req.add_hostname_cn() # Add os-hostname entries _sans = get_certificate_sans() # Handle specific hostnames per binding for binding in bindings: hostname_override = config(ADDRESS_MAP[binding]['override']) try: net_addr = resolve_address(endpoint_type=binding) ip = network_get_primary_address(ADDRESS_MAP[binding]['binding']) addresses = [net_addr, ip] vip = get_vip_in_network(resolve_network_cidr(ip)) if vip: addresses.append(vip) # Add hostname certificate request if hostname_override: req.add_entry(binding, hostname_override, addresses) # Remove hostname specific addresses from _sans for addr in addresses: try: _sans.remove(addr) except (ValueError, KeyError): pass except NoNetworkBinding: log( "Skipping request for certificate for ip in {} space, no " "local address found".format(binding), WARNING) # Gurantee all SANs are covered # These are network addresses with no corresponding hostname. # Add the ips to the hostname cert to allow for this. req.add_hostname_cn_ip(_sans) return req.get_request()
def __call__(self): ''' Grab cert and key from configuraton for SSL config ''' ctxt = {'http_port': 70, 'https_port': 433} if config('enforce-ssl'): # NOTE(dosaboy): if ssl is not configured we shouldn't allow this if all(get_cert()): ctxt['ssl_addr'] = resolve_address() else: log( "Enforce ssl redirect requested but ssl not configured - " "skipping redirect", level=WARNING) return ctxt
def __call__(self): ctxt = {} if (hookenv.config('console-ssl-cert') and hookenv.config('console-ssl-key') and hookenv.config('console-access-protocol')): ssl_dir = '/etc/nova/ssl/' if not os.path.exists(ssl_dir): hookenv.log('Creating %s.' % ssl_dir, level=hookenv.DEBUG) os.mkdir(ssl_dir) cert_path = os.path.join(ssl_dir, 'nova_cert.pem') decode_ssl_cert = base64.b64decode( hookenv.config('console-ssl-cert')) key_path = os.path.join(ssl_dir, 'nova_key.pem') decode_ssl_key = base64.b64decode( hookenv.config('console-ssl-key')) with open(cert_path, 'wb') as fh: fh.write(decode_ssl_cert) with open(key_path, 'wb') as fh: fh.write(decode_ssl_key) ctxt['ssl_only'] = True ctxt['ssl_cert'] = cert_path ctxt['ssl_key'] = key_path if ch_cluster.is_clustered(): ip_addr = ch_ip.resolve_address(endpoint_type=ch_ip.PUBLIC) else: ip_addr = hookenv.unit_get('private-address') ip_addr = ch_network_ip.format_ipv6_addr(ip_addr) or ip_addr _proto = hookenv.config('console-access-protocol') url = "https://%s:%s%s" % ( ip_addr, common.console_attributes('proxy-port', proto=_proto), common.console_attributes('proxy-page', proto=_proto)) if _proto == 'novnc': ctxt['novncproxy_base_url'] = url elif _proto == 'spice': ctxt['html5proxy_base_url'] = url return ctxt
def console_settings(): rel_settings = {} proto = common.console_attributes('protocol') if not proto: return {} rel_settings['console_keymap'] = hookenv.config('console-keymap') rel_settings['console_access_protocol'] = proto console_ssl = False if (hookenv.config('console-ssl-cert') and hookenv.config('console-ssl-key')): console_ssl = True if hookenv.config('console-proxy-ip') == 'local': if console_ssl: address = ch_ip.resolve_address(endpoint_type=ch_ip.PUBLIC) address = ch_network_ip.format_ipv6_addr(address) or address proxy_base_addr = 'https://%s' % address else: # canonical_url will only return 'https:' if API SSL are enabled. proxy_base_addr = ch_ip.canonical_url(CONFIGS, ch_ip.PUBLIC) else: if console_ssl or ch_cluster.https(): schema = "https" else: schema = "http" proxy_base_addr = ("{}://{}" .format(schema, hookenv.config('console-proxy-ip'))) if proto == 'vnc': protocols = ['novnc', 'xvpvnc'] else: protocols = [proto] for _proto in protocols: rel_settings['console_proxy_{}_address'.format(_proto)] = \ "{}:{}{}".format( proxy_base_addr, common.console_attributes('proxy-port', proto=_proto), common.console_attributes('proxy-page', proto=_proto)) rel_settings['console_proxy_%s_host' % (_proto)] = \ urlparse(proxy_base_addr).hostname rel_settings['console_proxy_%s_port' % (_proto)] = \ common.console_attributes('proxy-port', proto=_proto) return rel_settings
def console_settings(): rel_settings = {} proto = console_attributes('protocol') if not proto: return {} rel_settings['console_keymap'] = config('console-keymap') rel_settings['console_access_protocol'] = proto console_ssl = False if config('console-ssl-cert') and config('console-ssl-key'): console_ssl = True if config('console-proxy-ip') == 'local': if console_ssl: address = resolve_address(endpoint_type=PUBLIC) address = format_ipv6_addr(address) or address proxy_base_addr = 'https://%s' % address else: # canonical_url will only return 'https:' if API SSL are enabled. proxy_base_addr = canonical_url(CONFIGS, PUBLIC) else: if console_ssl or https(): schema = "https" else: schema = "http" proxy_base_addr = "%s://%s" % (schema, config('console-proxy-ip')) if proto == 'vnc': protocols = ['novnc', 'xvpvnc'] else: protocols = [proto] for _proto in protocols: rel_settings['console_proxy_%s_address' % (_proto)] = \ "%s:%s%s" % (proxy_base_addr, console_attributes('proxy-port', proto=_proto), console_attributes('proxy-page', proto=_proto)) rel_settings['console_proxy_%s_host' % (_proto)] = \ urlparse(proxy_base_addr).hostname rel_settings['console_proxy_%s_port' % (_proto)] = \ console_attributes('proxy-port', proto=_proto) return rel_settings
def __call__(self): ctxt = super(NovaConfigContext, self).__call__() ctxt['scheduler_default_filters'] = ( hookenv.config('scheduler-default-filters')) if hookenv.config('pci-alias'): aliases = json.loads(hookenv.config('pci-alias')) if isinstance(aliases, list): ctxt['pci_aliases'] = [ json.dumps(x, sort_keys=True) for x in aliases ] else: ctxt['pci_alias'] = json.dumps(aliases, sort_keys=True) ctxt['disk_allocation_ratio'] = hookenv.config('disk-allocation-ratio') ctxt['cpu_allocation_ratio'] = hookenv.config('cpu-allocation-ratio') ctxt['ram_allocation_ratio'] = hookenv.config('ram-allocation-ratio') addr = ch_ip.resolve_address(ch_ip.INTERNAL) ctxt['host_ip'] = ch_network_ip.format_ipv6_addr(addr) or addr return ctxt
def __call__(self): ctxt = super(NovaConfigContext, self).__call__() ctxt['scheduler_default_filters'] = ( hookenv.config('scheduler-default-filters') or ','.join(default_enabled_filters())) if hookenv.config('pci-alias'): aliases = json.loads(hookenv.config('pci-alias')) if isinstance(aliases, list): ctxt['pci_aliases'] = [json.dumps(x, sort_keys=True) for x in aliases] else: ctxt['pci_alias'] = json.dumps(aliases, sort_keys=True) ctxt['disk_allocation_ratio'] = hookenv.config('disk-allocation-ratio') ctxt['cpu_allocation_ratio'] = hookenv.config('cpu-allocation-ratio') ctxt['ram_allocation_ratio'] = hookenv.config('ram-allocation-ratio') ctxt['enable_new_services'] = hookenv.config('enable-new-services') addr = ch_ip.resolve_address(ch_ip.INTERNAL) ctxt['host_ip'] = ch_network_ip.format_ipv6_addr(addr) or addr ctxt['quota_instances'] = hookenv.config('quota-instances') ctxt['quota_cores'] = hookenv.config('quota-cores') ctxt['quota_ram'] = hookenv.config('quota-ram') ctxt['quota_metadata_items'] = hookenv.config('quota-metadata-items') ctxt['quota_injected_files'] = hookenv.config('quota-injected-files') ctxt['quota_injected_file_content_bytes'] = hookenv.config( 'quota-injected-file-size') ctxt['quota_injected_file_path_length'] = hookenv.config( 'quota-injected-path-size') ctxt['quota_key_pairs'] = hookenv.config('quota-key-pairs') ctxt['quota_server_groups'] = hookenv.config('quota-server-groups') ctxt['quota_server_group_members'] = hookenv.config( 'quota-server-group-members') ctxt['quota_count_usage_from_placement'] = hookenv.config( 'quota-count-usage-from-placement') ctxt['console_access_protocol'] = hookenv.config( 'console-access-protocol') ctxt['console_access_port'] = hookenv.config('console-access-port') ctxt['scheduler_host_subset_size'] = hookenv.config( 'scheduler-host-subset-size') ctxt['unique_server_names'] = hookenv.config('unique-server-names') ctxt['skip_hosts_with_build_failures'] = hookenv.config( 'skip-hosts-with-build-failures') return ctxt
def update_keystone_fid_service_provider(relation_id=None): if relation_ids('certificates'): tls_enabled = True else: tls_enabled = (config('ssl_cert') is not None and config('ssl_key') is not None) # NOTE: thedac Use resolve_address which checks host name, VIP and # network bindings. Use PUBLIC for now. Possible TODO make this # configurable? hostname = resolve_address(endpoint_type=PUBLIC, override=True) # reactive endpoints implementation on the other side, hence # json-encoded values fid_settings = { 'hostname': json.dumps(hostname), 'port': json.dumps(config('service-port')), 'tls-enabled': json.dumps(tls_enabled), } relation_set(relation_id=relation_id, relation_settings=fid_settings)
def __call__(self): ctxt = {} for rid in relation_ids('cloud-compute'): for unit in related_units(rid): rel = {'rid': rid, 'unit': unit} proto = relation_get('console_access_protocol', **rel) if not proto: # only bother with units that have a proto set. continue ctxt['console_keymap'] = relation_get('console_keymap', **rel) ctxt['console_access_protocol'] = proto ctxt['console_vnc_type'] = True if 'vnc' in proto else False if proto == 'vnc': ctxt = dict(ctxt, **self.get_console_info('xvpvnc', **rel)) ctxt = dict(ctxt, **self.get_console_info('novnc', **rel)) else: ctxt = dict(ctxt, **self.get_console_info(proto, **rel)) break ctxt['console_listen_addr'] = resolve_address(endpoint_type=INTERNAL) return ctxt
def __call__(self): ctxt = {} # Configure nova-novncproxy https if nova-api is using https. if ch_cluster.https(): cn = ch_ip.resolve_address(endpoint_type=ch_ip.INTERNAL) if cn: cert_filename = 'cert_{}'.format(cn) key_filename = 'key_{}'.format(cn) else: cert_filename = 'cert' key_filename = 'key' ssl_dir = '/etc/apache2/ssl/nova' cert = os.path.join(ssl_dir, cert_filename) key = os.path.join(ssl_dir, key_filename) if os.path.exists(cert) and os.path.exists(key): ctxt['ssl_cert'] = cert ctxt['ssl_key'] = key return ctxt
def admin_relation_changed(relation_id=None): # TODO: fixup if expect_ha() and not is_clustered(): log("Expected to be HA but no hacluster relation yet", level=INFO) return relation_data = { 'service_hostname': resolve_address(ADMIN), 'service_port': config('service-port'), 'service_username': config('admin-user'), 'service_tenant_name': config('admin-role'), 'service_region': config('region'), 'service_protocol': 'https' if https() else 'http', 'api_version': get_api_version(), } if relation_data['api_version'] > 2: relation_data['service_user_domain_name'] = ADMIN_DOMAIN relation_data['service_project_domain_name'] = ADMIN_DOMAIN relation_data['service_project_name'] = ADMIN_PROJECT relation_data['service_password'] = get_admin_passwd() relation_set(relation_id=relation_id, **relation_data)
def __call__(self): if isinstance(self.external_ports, six.string_types): self.external_ports = [self.external_ports] if not self.external_ports or not https(): return {} self.configure_ca() self.enable_modules() ctxt = { 'namespace': self.service_namespace, 'endpoints': [], 'ext_ports': [] } cns = self.canonical_names() if cns: for cn in cns: self.configure_cert(cn) else: # Expect cert/key provided in config (currently assumed that ca # uses ip for cn) cn = resolve_address(endpoint_type=INTERNAL) self.configure_cert(cn) addresses = self.get_network_addresses() for address, endpoint in sorted(set(addresses)): for api_port in self.external_ports: ext_port = determine_apache_port(api_port, singlenode_mode=True) int_port = determine_api_port(api_port, singlenode_mode=True) portmap = (address, endpoint, int(ext_port), int(int_port)) ctxt['endpoints'].append(portmap) ctxt['ext_ports'].append(int(ext_port)) ctxt['ext_ports'] = sorted(list(set(ctxt['ext_ports']))) return ctxt
def websso_trusted_dashboard_changed(): """ Provide L7 endpoint details for the dashboard and also handle any config changes that may affect those. """ relations = relation_ids('websso-trusted-dashboard') if not relations: return # TODO: check for vault relation in order to determine url scheme tls_configured = (relation_ids('certificates') or config('ssl-key') or config('enforce-ssl')) scheme = 'https://' if tls_configured else 'http://' hostname = resolve_address(endpoint_type=PUBLIC, override=True) path = "{}/auth/websso/".format(config('webroot')) # provide trusted dashboard URL details for rid in relations: relation_set(relation_id=rid, relation_settings={ "scheme": scheme, "hostname": hostname, "path": path, })
def __call__(self): ctxt = super(NovaConfigContext, self).__call__() ctxt['scheduler_default_filters'] = ( hookenv.config('scheduler-default-filters') or ','.join(default_enabled_filters())) if hookenv.config('pci-alias'): aliases = json.loads(hookenv.config('pci-alias')) if isinstance(aliases, list): ctxt['pci_aliases'] = [json.dumps(x, sort_keys=True) for x in aliases] else: ctxt['pci_alias'] = json.dumps(aliases, sort_keys=True) ctxt['disk_allocation_ratio'] = hookenv.config('disk-allocation-ratio') ctxt['cpu_allocation_ratio'] = hookenv.config('cpu-allocation-ratio') ctxt['ram_allocation_ratio'] = hookenv.config('ram-allocation-ratio') ctxt['enable_new_services'] = hookenv.config('enable-new-services') addr = ch_ip.resolve_address(ch_ip.INTERNAL) ctxt['host_ip'] = ch_network_ip.format_ipv6_addr(addr) or addr ctxt['quota_instances'] = hookenv.config('quota-instances') ctxt['quota_cores'] = hookenv.config('quota-cores') ctxt['quota_ram'] = hookenv.config('quota-ram') ctxt['quota_metadata_items'] = hookenv.config('quota-metadata-items') ctxt['quota_injected_files'] = hookenv.config('quota-injected-files') ctxt['quota_injected_file_content_bytes'] = hookenv.config( 'quota-injected-file-size') ctxt['quota_injected_file_path_length'] = hookenv.config( 'quota-injected-path-size') ctxt['quota_key_pairs'] = hookenv.config('quota-key-pairs') ctxt['quota_server_groups'] = hookenv.config('quota-server-groups') ctxt['quota_server_group_members'] = hookenv.config( 'quota-server-group-members') ctxt['console_access_protocol'] = hookenv.config( 'console-access-protocol') ctxt['console_access_port'] = hookenv.config('console-access-port') return ctxt
def __call__(self): if isinstance(self.external_ports, six.string_types): self.external_ports = [self.external_ports] if not self.external_ports or not https(): return {} self.configure_ca() self.enable_modules() ctxt = {'namespace': self.service_namespace, 'endpoints': [], 'ext_ports': []} cns = self.canonical_names() if cns: for cn in cns: self.configure_cert(cn) else: # Expect cert/key provided in config (currently assumed that ca # uses ip for cn) cn = resolve_address(endpoint_type=INTERNAL) self.configure_cert(cn) addresses = self.get_network_addresses() for address, endpoint in sorted(set(addresses)): for api_port in self.external_ports: ext_port = determine_apache_port(api_port, singlenode_mode=True) int_port = determine_api_port(api_port, singlenode_mode=True) portmap = (address, endpoint, int(ext_port), int(int_port)) ctxt['endpoints'].append(portmap) ctxt['ext_ports'].append(int(ext_port)) ctxt['ext_ports'] = sorted(list(set(ctxt['ext_ports']))) return ctxt
def update_hacluster_dns_ha(service, relation_data, crm_ocf='ocf:maas:dns'): """ Configure DNS-HA resources based on provided configuration @param service: Name of the service being configured @param relation_data: Pointer to dictionary of relation data. @param crm_ocf: Corosync Open Cluster Framework resource agent to use for DNS HA """ # Validate the charm environment for DNS HA assert_charm_supports_dns_ha() settings = ['os-admin-hostname', 'os-internal-hostname', 'os-public-hostname', 'os-access-hostname'] # Check which DNS settings are set and update dictionaries hostname_group = [] for setting in settings: hostname = config(setting) if hostname is None: log('DNS HA: Hostname setting {} is None. Ignoring.' ''.format(setting), DEBUG) continue m = re.search('os-(.+?)-hostname', setting) if m: endpoint_type = m.group(1) # resolve_address's ADDRESS_MAP uses 'int' not 'internal' if endpoint_type == 'internal': endpoint_type = 'int' else: msg = ('Unexpected DNS hostname setting: {}. ' 'Cannot determine endpoint_type name' ''.format(setting)) status_set('blocked', msg) raise DNSHAException(msg) hostname_key = 'res_{}_{}_hostname'.format(service, endpoint_type) if hostname_key in hostname_group: log('DNS HA: Resource {}: {} already exists in ' 'hostname group - skipping'.format(hostname_key, hostname), DEBUG) continue hostname_group.append(hostname_key) relation_data['resources'][hostname_key] = crm_ocf relation_data['resource_params'][hostname_key] = ( 'params fqdn="{}" ip_address="{}"' .format(hostname, resolve_address(endpoint_type=endpoint_type, override=False))) if len(hostname_group) >= 1: log('DNS HA: Hostname group is set with {} as members. ' 'Informing the ha relation'.format(' '.join(hostname_group)), DEBUG) relation_data['groups'] = { 'grp_{}_hostnames'.format(service): ' '.join(hostname_group) } else: msg = 'DNS HA: Hostname group has no members.' status_set('blocked', msg) raise DNSHAException(msg)
def update_dns_ha_resource_params(resources, resource_params, relation_id=None, crm_ocf='ocf:maas:dns'): """ Check for os-*-hostname settings and update resource dictionaries for the HA relation. @param resources: Pointer to dictionary of resources. Usually instantiated in ha_joined(). @param resource_params: Pointer to dictionary of resource parameters. Usually instantiated in ha_joined() @param relation_id: Relation ID of the ha relation @param crm_ocf: Corosync Open Cluster Framework resource agent to use for DNS HA """ # Validate the charm environment for DNS HA assert_charm_supports_dns_ha() settings = ['os-admin-hostname', 'os-internal-hostname', 'os-public-hostname', 'os-access-hostname'] # Check which DNS settings are set and update dictionaries hostname_group = [] for setting in settings: hostname = config(setting) if hostname is None: log('DNS HA: Hostname setting {} is None. Ignoring.' ''.format(setting), DEBUG) continue m = re.search('os-(.+?)-hostname', setting) if m: networkspace = m.group(1) else: msg = ('Unexpected DNS hostname setting: {}. ' 'Cannot determine network space name' ''.format(setting)) status_set('blocked', msg) raise DNSHAException(msg) hostname_key = 'res_{}_{}_hostname'.format(charm_name(), networkspace) if hostname_key in hostname_group: log('DNS HA: Resource {}: {} already exists in ' 'hostname group - skipping'.format(hostname_key, hostname), DEBUG) continue hostname_group.append(hostname_key) resources[hostname_key] = crm_ocf resource_params[hostname_key] = ( 'params fqdn="{}" ip_address="{}" ' ''.format(hostname, resolve_address(endpoint_type=networkspace, override=False))) if len(hostname_group) >= 1: log('DNS HA: Hostname group is set with {} as members. ' 'Informing the ha relation'.format(' '.join(hostname_group)), DEBUG) relation_set(relation_id=relation_id, groups={ 'grp_{}_hostnames'.format(charm_name()): ' '.join(hostname_group)}) else: msg = 'DNS HA: Hostname group has no members.' status_set('blocked', msg) raise DNSHAException(msg)