def get_db_host(client_hostname): """Get address of local database host. If an access-network has been configured, expect selected address to be on that network. If none can be found, revert to primary address. If vip(s) are configured, chooses first available. """ vips = config('vip').split() if config('vip') else [] access_network = config('access-network') if access_network: client_ip = get_host_ip(client_hostname) if is_address_in_network(access_network, client_ip): if is_clustered(): for vip in vips: if is_address_in_network(access_network, vip): return vip log("Unable to identify a VIP in the access-network '%s'" % (access_network), level=WARNING) else: return get_address_in_network(access_network) else: log("Client address '%s' not in access-network '%s'" % (client_ip, access_network), level=WARNING) if is_clustered() and vips: return vips[0] # NOTE on private network if config('prefer-ipv6'): return get_ipv6_addr(exc_list=vips)[0] return unit_get('private-address')
def render_config(clustered=False, hosts=[]): if not os.path.exists(os.path.dirname(resolve_cnf_file())): os.makedirs(os.path.dirname(resolve_cnf_file())) context = { 'cluster_name': 'juju_cluster', 'private_address': get_host_ip(), 'clustered': clustered, 'cluster_hosts': ",".join(hosts), 'sst_method': config('sst-method'), 'sst_password': config('sst-password'), 'innodb_file_per_table': config('innodb-file-per-table'), 'table_open_cache': config('table-open-cache'), 'lp1366997_workaround': config('lp1366997-workaround'), } if config('prefer-ipv6'): # NOTE(hopem): this is a kludge to get percona working with ipv6. # See lp 1380747 for more info. This is intended as a stop gap until # percona package is fixed to support ipv6. context['bind_address'] = '::' context['wsrep_provider_options'] = 'gmcast.listen_addr=tcp://:::4567;' context['ipv6'] = True else: context['ipv6'] = False context.update(PerconaClusterHelper().parse_config()) render(os.path.basename(resolve_cnf_file()), resolve_cnf_file(), context, perms=0o444)
def get_db_host(client_hostname, interface='shared-db'): """Get address of local database host. If an access-network has been configured, expect selected address to be on that network. If none can be found, revert to primary address. If network spaces are supported (Juju >= 2.0), use network-get to retrieve the network binding for the interface. If vip(s) are configured, chooses first available. """ vips = config('vip').split() if config('vip') else [] dns_ha = config('dns-ha') access_network = config('access-network') client_ip = get_host_ip(client_hostname) if is_clustered() and dns_ha: log("Using DNS HA hostname: {}".format(config('os-access-hostname'))) return config('os-access-hostname') elif access_network: if is_address_in_network(access_network, client_ip): if is_clustered(): for vip in vips: if is_address_in_network(access_network, vip): return vip log("Unable to identify a VIP in the access-network '%s'" % (access_network), level=WARNING) else: return get_address_in_network(access_network) else: log("Client address '%s' not in access-network '%s'" % (client_ip, access_network), level=WARNING) else: try: # NOTE(jamespage) # Try to use network spaces to resolve binding for # interface, and to resolve the VIP associated with # the binding if provided. interface_binding = network_get_primary_address(interface) if is_clustered() and vips: interface_cidr = resolve_network_cidr(interface_binding) for vip in vips: if is_address_in_network(interface_cidr, vip): return vip return interface_binding except NotImplementedError: # NOTE(jamespage): skip - fallback to previous behaviour pass if is_clustered() and vips: return vips[0] # NOTE on private network if config('prefer-ipv6'): return get_ipv6_addr(exc_list=vips)[0] return unit_get('private-address')
def get_db_host(client_hostname, interface='shared-db'): """Get address of local database host. If an access-network has been configured, expect selected address to be on that network. If none can be found, revert to primary address. If network spaces are supported (Juju >= 2.0), use network-get to retrieve the network binding for the interface. If vip(s) are configured, chooses first available. """ vips = config('vip').split() if config('vip') else [] access_network = config('access-network') client_ip = get_host_ip(client_hostname) if access_network: if is_address_in_network(access_network, client_ip): if is_clustered(): for vip in vips: if is_address_in_network(access_network, vip): return vip log("Unable to identify a VIP in the access-network '%s'" % (access_network), level=WARNING) else: return get_address_in_network(access_network) else: log("Client address '%s' not in access-network '%s'" % (client_ip, access_network), level=WARNING) else: try: # NOTE(jamespage) # Try to use network spaces to resolve binding for # interface, and to resolve the VIP associated with # the binding if provided. interface_binding = network_get_primary_address(interface) if is_clustered() and vips: interface_cidr = resolve_network_cidr(interface_binding) for vip in vips: if is_address_in_network(interface_cidr, vip): return vip return interface_binding except NotImplementedError: # NOTE(jamespage): skip - fallback to previous behaviour pass if is_clustered() and vips: return vips[0] # NOTE on private network if config('prefer-ipv6'): return get_ipv6_addr(exc_list=vips)[0] return unit_get('private-address')
def shared_db_changed(relation_id=None, unit=None): if not seeded(): log("Percona cluster not yet bootstrapped - deferring shared-db rel " "until bootstrapped", DEBUG) return if not is_elected_leader(DC_RESOURCE_NAME): # NOTE(jamespage): relation level data candidate log('Service is peered, clearing shared-db relation ' 'as this service unit is not the leader') relation_clear(relation_id) # Each unit needs to set the db information otherwise if the unit # with the info dies the settings die with it Bug# 1355848 if is_relation_made('cluster'): for rel_id in relation_ids('shared-db'): peerdb_settings = \ peer_retrieve_by_prefix(rel_id, exc_list=['hostname']) passwords = [key for key in peerdb_settings.keys() if 'password' in key.lower()] if len(passwords) > 0: relation_set(relation_id=rel_id, **peerdb_settings) return settings = relation_get(unit=unit, rid=relation_id) access_network = config('access-network') db_helper = get_db_helper() peer_store_and_set(relation_id=relation_id, relation_settings={'access-network': access_network}) singleset = set(['database', 'username', 'hostname']) if singleset.issubset(settings): # Process a single database configuration hostname = settings['hostname'] database = settings['database'] username = settings['username'] normalized_address = get_host_ip(hostname) if access_network and not is_address_in_network(access_network, normalized_address): # NOTE: for configurations using access-network, only setup # database access if remote unit has presented a # hostname or ip address thats within the configured # network cidr log("Host '%s' not in access-network '%s' - ignoring" % (normalized_address, access_network), level=INFO) return # NOTE: do this before querying access grants password = configure_db_for_hosts(hostname, database, username, db_helper) allowed_units = db_helper.get_allowed_units(database, username, relation_id=relation_id) allowed_units = unit_sorted(allowed_units) allowed_units = ' '.join(allowed_units) relation_set(relation_id=relation_id, allowed_units=allowed_units) db_host = get_db_host(hostname) peer_store_and_set(relation_id=relation_id, db_host=db_host, password=password) else: # Process multiple database setup requests. # from incoming relation data: # nova_database=xxx nova_username=xxx nova_hostname=xxx # quantum_database=xxx quantum_username=xxx quantum_hostname=xxx # create # { # "nova": { # "username": xxx, # "database": xxx, # "hostname": xxx # }, # "quantum": { # "username": xxx, # "database": xxx, # "hostname": xxx # } # } # databases = {} for k, v in settings.iteritems(): db = k.split('_')[0] x = '_'.join(k.split('_')[1:]) if db not in databases: databases[db] = {} databases[db][x] = v allowed_units = {} return_data = {} for db in databases: if singleset.issubset(databases[db]): database = databases[db]['database'] hostname = databases[db]['hostname'] username = databases[db]['username'] normalized_address = get_host_ip(hostname) if (access_network and not is_address_in_network(access_network, normalized_address)): # NOTE: for configurations using access-network, # only setup database access if remote unit # has presented a hostname or ip address # thats within the configured network cidr return # NOTE: do this before querying access grants password = configure_db_for_hosts(hostname, database, username, db_helper) a_units = db_helper.get_allowed_units(database, username, relation_id=relation_id) a_units = ' '.join(unit_sorted(a_units)) allowed_units['%s_allowed_units' % (db)] = a_units return_data['%s_password' % (db)] = password db_host = get_db_host(hostname) if allowed_units: relation_set(relation_id=relation_id, **allowed_units) else: log("No allowed_units - not setting relation settings", level=DEBUG) if return_data: peer_store_and_set(relation_id=relation_id, db_host=db_host, **return_data) else: log("No return data - not setting relation settings", level=DEBUG)