def ha_relation_changed(): clustered = utils.relation_get("clustered") if clustered and cluster.is_leader(LEADER_RES): utils.juju_log("INFO", "Cluster configured, notifying other services") # Tell all related services to start using the VIP for r_id in utils.relation_ids("shared-db"): utils.relation_set(rid=r_id, db_host=utils.config_get("vip"))
def ssh_authorized_peers(peer_interface, user, group=None, ensure_local_user=False): """ Main setup function, should be called from both peer -changed and -joined hooks with the same parameters. """ if ensure_local_user: ensure_user(user, group) priv_key, pub_key = get_keypair(user) hook = os.path.basename(sys.argv[0]) if hook == '%s-relation-joined' % peer_interface: utils.relation_set(ssh_pub_key=pub_key) print 'joined' elif hook == '%s-relation-changed' % peer_interface: hosts = [] keys = [] for r_id in utils.relation_ids(peer_interface): for unit in utils.relation_list(r_id): settings = utils.relation_get_dict(relation_id=r_id, remote_unit=unit) if 'ssh_pub_key' in settings: keys.append(settings['ssh_pub_key']) hosts.append(settings['private-address']) else: utils.juju_log('INFO', 'ssh_authorized_peers(): ssh_pub_key '\ 'missing for unit %s, skipping.' % unit) write_authorized_keys(user, keys) write_known_hosts(user, hosts) authed_hosts = ':'.join(hosts) utils.relation_set(ssh_authorized_hosts=authed_hosts)
def cluster_joined(): unison.ssh_authorized_peers(user=rabbit.SSH_USER, group='rabbit', peer_interface='cluster', ensure_local_user=True) if utils.is_relation_made('ha'): utils.juju_log('INFO', 'hacluster relation is present, skipping native ' 'rabbitmq cluster config.') return l_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1] r_unit_no = os.getenv('JUJU_REMOTE_UNIT').split('/')[1] if l_unit_no > r_unit_no: utils.juju_log('INFO', 'cluster_joined: Relation greater.') return rabbit.COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie' if not os.path.isfile(rabbit.COOKIE_PATH): utils.juju_log('ERROR', 'erlang cookie missing from %s' % rabbit.COOKIE_PATH) return cookie = open(rabbit.COOKIE_PATH, 'r').read().strip() # add parent host to the relation local_hostname = subprocess.check_output(['hostname']).strip() utils.relation_set(cookie=cookie, host=local_hostname)
def ha_relation_changed(): clustered = utils.relation_get('clustered') if (clustered and cluster.is_leader(LEADER_RES)): utils.juju_log('INFO', 'Cluster configured, notifying other services') # Tell all related services to start using the VIP for r_id in utils.relation_ids('shared-db'): utils.relation_set(rid=r_id, db_host=utils.config_get('vip'))
def db_joined(): relation_data = { "database": config["database"], "username": config["database-user"], "hostname": config["hostname"] } utils.relation_set(**relation_data)
def cluster_joined(): unison.ssh_authorized_peers(user=rabbit.SSH_USER, group='rabbit', peer_interface='cluster', ensure_local_user=True) if utils.is_relation_made('ha'): utils.juju_log( 'INFO', 'hacluster relation is present, skipping native ' 'rabbitmq cluster config.') return l_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1] r_unit_no = os.getenv('JUJU_REMOTE_UNIT').split('/')[1] if l_unit_no > r_unit_no: utils.juju_log('INFO', 'cluster_joined: Relation greater.') return rabbit.COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie' if not os.path.isfile(rabbit.COOKIE_PATH): utils.juju_log('ERROR', 'erlang cookie missing from %s' % rabbit.COOKIE_PATH) return cookie = open(rabbit.COOKIE_PATH, 'r').read().strip() # add parent host to the relation local_hostname = subprocess.check_output(['hostname']).strip() utils.relation_set(cookie=cookie, host=local_hostname)
def ha_relation_joined(): # Obtain the config values necessary for the cluster config. These # include multicast port and interface to bind to. corosync_bindiface = config['ha-bindiface'] corosync_mcastport = config['ha-mcastport'] vip = config['vip'] vip_cidr = config['vip_cidr'] vip_iface = config['vip_iface'] # Obtain resources resources = { 'res_ks_vip': 'ocf:heartbeat:IPaddr2', 'res_ks_haproxy': 'lsb:haproxy' } resource_params = { 'res_ks_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % \ (vip, vip_cidr, vip_iface), 'res_ks_haproxy': 'op monitor interval="5s"' } init_services = { 'res_ks_haproxy': 'haproxy' } clones = { 'cl_ks_haproxy': 'res_ks_haproxy' } utils.relation_set(init_services=init_services, corosync_bindiface=corosync_bindiface, corosync_mcastport=corosync_mcastport, resources=resources, resource_params=resource_params, clones=clones)
def ha_relation_joined(): vip = utils.config_get('vip') vip_iface = utils.config_get('vip_iface') vip_cidr = utils.config_get('vip_cidr') corosync_bindiface = utils.config_get('ha-bindiface') corosync_mcastport = utils.config_get('ha-mcastport') if None in [vip, vip_cidr, vip_iface]: utils.juju_log('WARNING', 'Insufficient VIP information to configure cluster') sys.exit(1) # Starting configuring resources. init_services = {'res_mysqld': 'mysql'} # If the 'ha' relation has been made *before* the 'ceph' relation, # it doesn't make sense to make it until after the 'ceph' relation is made if not utils.is_relation_made('ceph', 'auth'): utils.juju_log('INFO', '*ceph* relation does not exist. ' 'Not sending *ha* relation data yet') return else: utils.juju_log('INFO', '*ceph* relation exists. Sending *ha* relation data') block_storage = 'ceph' resources = { 'res_mysql_rbd': 'ocf:ceph:rbd', 'res_mysql_fs': 'ocf:heartbeat:Filesystem', 'res_mysql_vip': 'ocf:heartbeat:IPaddr2', 'res_mysqld': 'upstart:mysql'} rbd_name = utils.config_get('rbd-name') resource_params = { 'res_mysql_rbd': 'params name="%s" pool="%s" user="******" ' 'secret="%s"' % (rbd_name, POOL_NAME, SERVICE_NAME, ceph.keyfile_path(SERVICE_NAME)), 'res_mysql_fs': 'params device="/dev/rbd/%s/%s" directory="%s" ' 'fstype="ext4" op start start-delay="10s"' % (POOL_NAME, rbd_name, DATA_SRC_DST), 'res_mysql_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % (vip, vip_cidr, vip_iface), 'res_mysqld': 'op start start-delay="5s" op monitor interval="5s"'} groups = { 'grp_mysql': 'res_mysql_rbd res_mysql_fs res_mysql_vip res_mysqld'} for rel_id in utils.relation_ids('ha'): utils.relation_set(rid=rel_id, block_storage=block_storage, corosync_bindiface=corosync_bindiface, corosync_mcastport=corosync_mcastport, resources=resources, resource_params=resource_params, init_services=init_services, groups=groups)
def ha_relation_joined(): vip = utils.config_get("vip") vip_iface = utils.config_get("vip_iface") vip_cidr = utils.config_get("vip_cidr") corosync_bindiface = utils.config_get("ha-bindiface") corosync_mcastport = utils.config_get("ha-mcastport") if None in [vip, vip_cidr, vip_iface]: utils.juju_log("WARNING", "Insufficient VIP information to configure cluster") sys.exit(1) # Starting configuring resources. init_services = {"res_mysqld": "mysql"} # If the 'ha' relation has been made *before* the 'ceph' relation, # it doesn't make sense to make it until after the 'ceph' relation is made if not utils.is_relation_made("ceph", "auth"): utils.juju_log("INFO", "*ceph* relation does not exist. " "Not sending *ha* relation data yet") return else: utils.juju_log("INFO", "*ceph* relation exists. Sending *ha* relation data") block_storage = "ceph" resources = { "res_mysql_rbd": "ocf:ceph:rbd", "res_mysql_fs": "ocf:heartbeat:Filesystem", "res_mysql_vip": "ocf:heartbeat:IPaddr2", "res_mysqld": "upstart:mysql", } rbd_name = utils.config_get("rbd-name") resource_params = { "res_mysql_rbd": 'params name="%s" pool="%s" user="******" ' 'secret="%s"' % (rbd_name, POOL_NAME, SERVICE_NAME, ceph.keyfile_path(SERVICE_NAME)), "res_mysql_fs": 'params device="/dev/rbd/%s/%s" directory="%s" ' 'fstype="ext4" op start start-delay="10s"' % (POOL_NAME, rbd_name, DATA_SRC_DST), "res_mysql_vip": 'params ip="%s" cidr_netmask="%s" nic="%s"' % (vip, vip_cidr, vip_iface), "res_mysqld": 'op start start-delay="5s" op monitor interval="5s"', } groups = {"grp_mysql": "res_mysql_rbd res_mysql_fs res_mysql_vip res_mysqld"} for rel_id in utils.relation_ids("ha"): utils.relation_set( rid=rel_id, block_storage=block_storage, corosync_bindiface=corosync_bindiface, corosync_mcastport=corosync_mcastport, resources=resources, resource_params=resource_params, init_services=init_services, groups=groups, )
def amqp_changed(relation_id=None, remote_unit=None): if not cluster.eligible_leader('res_rabbitmq_vip'): msg = 'amqp_changed(): Deferring amqp_changed to eligible_leader.' utils.juju_log('INFO', msg) return relation_settings = {} settings = hookenv.relation_get(rid=relation_id, unit=remote_unit) singleset = set([ 'username', 'vhost' ]) if singleset.issubset(settings): if None in [settings['username'], settings['vhost']]: utils.juju_log('INFO', 'amqp_changed(): Relation not ready.') return relation_settings['password'] = configure_amqp(username=settings['username'], vhost=settings['vhost']) else: queues = {} for k, v in settings.iteritems(): amqp = k.split('_')[0] x = '_'.join(k.split('_')[1:]) if amqp not in queues: queues[amqp] = {} queues[amqp][x] = v relation_settings = {} for amqp in queues: if singleset.issubset(queues[amqp]): relation_settings['_'.join([amqp, 'password'])] = configure_amqp(queues[amqp]['username'], queues[amqp]['vhost']) relation_settings['hostname'] = utils.unit_get('private-address') if cluster.is_clustered(): relation_settings['clustered'] = 'true' if utils.is_relation_made('ha'): # active/passive settings relation_settings['vip'] = utils.config_get('vip') if relation_id: relation_settings['rid'] = relation_id utils.relation_set(**relation_settings) # sync new creds to all peers rabbit.synchronize_service_credentials()
def ha_relation_changed(): relation_data = utils.relation_get_dict() if ('clustered' in relation_data and cluster.is_leader(CLUSTER_RES)): utils.juju_log('INFO', 'Cluster configured, notifying other services' ' and updating keystone endpoint configuration') # Update keystone endpoint to point at VIP ensure_initial_admin(config) # Tell all related services to start using # the VIP and haproxy ports instead for r_id in utils.relation_ids('identity-service'): utils.relation_set(rid=r_id, auth_host=config['vip'], service_host=config['vip'])
def amqp_changed(relation_id=None, remote_unit=None): if not cluster.eligible_leader('res_rabbitmq_vip'): msg = 'amqp_changed(): Deferring amqp_changed to eligible_leader.' utils.juju_log('INFO', msg) return relation_settings = {} settings = hookenv.relation_get(rid=relation_id, unit=remote_unit) singleset = set(['username', 'vhost']) if singleset.issubset(settings): if None in [settings['username'], settings['vhost']]: utils.juju_log('INFO', 'amqp_changed(): Relation not ready.') return relation_settings['password'] = configure_amqp( username=settings['username'], vhost=settings['vhost']) else: queues = {} for k, v in settings.iteritems(): amqp = k.split('_')[0] x = '_'.join(k.split('_')[1:]) if amqp not in queues: queues[amqp] = {} queues[amqp][x] = v relation_settings = {} for amqp in queues: if singleset.issubset(queues[amqp]): relation_settings['_'.join([amqp, 'password'])] = configure_amqp( queues[amqp]['username'], queues[amqp]['vhost']) relation_settings['hostname'] = utils.unit_get('private-address') if cluster.is_clustered(): relation_settings['clustered'] = 'true' if utils.is_relation_made('ha'): # active/passive settings relation_settings['vip'] = utils.config_get('vip') if relation_id: relation_settings['rid'] = relation_id utils.relation_set(**relation_settings) # sync new creds to all peers rabbit.synchronize_service_credentials()
def cluster_joined(): if utils.is_relation_made('ha'): utils.juju_log('INFO', 'hacluster relation is present, skipping native '\ 'rabbitmq cluster config.') return l_unit_no = os.getenv('JUJU_UNIT_NAME').split('/')[1] r_unit_no = os.getenv('JUJU_REMOTE_UNIT').split('/')[1] if l_unit_no > r_unit_no: utils.juju_log('INFO', 'cluster_joined: Relation greater.') return rabbit.COOKIE_PATH = '/var/lib/rabbitmq/.erlang.cookie' if not os.path.isfile(rabbit.COOKIE_PATH): utils.juju_log('ERROR', 'erlang cookie missing from %s' %\ rabbit.COOKIE_PATH) cookie = open(rabbit.COOKIE_PATH, 'r').read().strip() local_hostname = subprocess.check_output(['hostname']).strip() utils.relation_set(cookie=cookie, host=local_hostname)
def amqp_changed(relation_id=None, remote_unit=None): if not cluster.eligible_leader('res_rabbitmq_vip'): msg = 'amqp_changed(): Deferring amqp_changed to eligible_leader.' utils.juju_log('INFO', msg) return rabbit_user = utils.relation_get('username', rid=relation_id, unit=remote_unit) vhost = utils.relation_get('vhost', rid=relation_id, unit=remote_unit) if None in [rabbit_user, vhost]: utils.juju_log('INFO', 'amqp_changed(): Relation not ready.') return password_file = os.path.join(RABBIT_DIR, '%s.passwd' % rabbit_user) if os.path.exists(password_file): password = open(password_file).read().strip() else: cmd = ['pwgen', '64', '1'] password = subprocess.check_output(cmd).strip() with open(password_file, 'wb') as out: out.write(password) rabbit.create_vhost(vhost) rabbit.create_user(rabbit_user, password) rabbit.grant_permissions(rabbit_user, vhost) rabbit_hostname = utils.unit_get('private-address') relation_settings = { 'password': password, 'hostname': rabbit_hostname } if cluster.is_clustered(): relation_settings['clustered'] = 'true' relation_settings['vip'] = utils.config_get('vip') if relation_id: relation_settings['rid'] = relation_id utils.relation_set(**relation_settings)
def identity_changed(relation_id=None, remote_unit=None): """ A service has advertised its API endpoints, create an entry in the service catalog. Optionally allow this hook to be re-fired for an existing relation+unit, for context see see db_changed(). """ if not cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Deferring identity_changed() to service leader.') return settings = utils.relation_get_dict(relation_id=relation_id, remote_unit=remote_unit) # the minimum settings needed per endpoint single = set(['service', 'region', 'public_url', 'admin_url', 'internal_url']) if single.issubset(settings): # other end of relation advertised only one endpoint if 'None' in [v for k, v in settings.iteritems()]: # Some backend services advertise no endpoint but require a # hook execution to update auth strategy. relation_data = {} # Check if clustered and use vip + haproxy ports if so if cluster.is_clustered(): relation_data["auth_host"] = config['vip'] relation_data["service_host"] = config['vip'] else: relation_data["auth_host"] = config['hostname'] relation_data["service_host"] = config['hostname'] relation_data["auth_port"] = config['admin-port'] relation_data["service_port"] = config['service-port'] if config['https-service-endpoints'] in ['True', 'true']: # Pass CA cert as client will need it to # verify https connections ca = get_ca(user=SSH_USER) ca_bundle = ca.get_ca_bundle() relation_data['https_keystone'] = 'True' relation_data['ca_cert'] = b64encode(ca_bundle) if relation_id: relation_data['rid'] = relation_id # Allow the remote service to request creation of any additional # roles. Currently used by Horizon for role in get_requested_roles(settings): utils.juju_log('INFO', "Creating requested role: %s" % role) create_role(role) utils.relation_set(**relation_data) return else: ensure_valid_service(settings['service']) add_endpoint(region=settings['region'], service=settings['service'], publicurl=settings['public_url'], adminurl=settings['admin_url'], internalurl=settings['internal_url']) service_username = settings['service'] https_cn = urlparse.urlparse(settings['internal_url']) https_cn = https_cn.hostname else: # assemble multiple endpoints from relation data. service name # should be prepended to setting name, ie: # realtion-set ec2_service=$foo ec2_region=$foo ec2_public_url=$foo # relation-set nova_service=$foo nova_region=$foo nova_public_url=$foo # Results in a dict that looks like: # { 'ec2': { # 'service': $foo # 'region': $foo # 'public_url': $foo # } # 'nova': { # 'service': $foo # 'region': $foo # 'public_url': $foo # } # } endpoints = {} for k, v in settings.iteritems(): ep = k.split('_')[0] x = '_'.join(k.split('_')[1:]) if ep not in endpoints: endpoints[ep] = {} endpoints[ep][x] = v services = [] https_cn = None for ep in endpoints: # weed out any unrelated relation stuff Juju might have added # by ensuring each possible endpiont has appropriate fields # ['service', 'region', 'public_url', 'admin_url', 'internal_url'] if single.issubset(endpoints[ep]): ep = endpoints[ep] ensure_valid_service(ep['service']) add_endpoint(region=ep['region'], service=ep['service'], publicurl=ep['public_url'], adminurl=ep['admin_url'], internalurl=ep['internal_url']) services.append(ep['service']) if not https_cn: https_cn = urlparse.urlparse(ep['internal_url']) https_cn = https_cn.hostname service_username = '******'.join(services) if 'None' in [v for k, v in settings.iteritems()]: return if not service_username: return token = get_admin_token() utils.juju_log('INFO', "Creating service credentials for '%s'" % service_username) service_password = get_service_password(service_username) create_user(service_username, service_password, config['service-tenant']) grant_role(service_username, config['admin-role'], config['service-tenant']) # Allow the remote service to request creation of any additional roles. # Currently used by Swift and Ceilometer. for role in get_requested_roles(settings): utils.juju_log('INFO', "Creating requested role: %s" % role) create_role(role, service_username, config['service-tenant']) # As of https://review.openstack.org/#change,4675, all nodes hosting # an endpoint(s) needs a service username and password assigned to # the service tenant and granted admin role. # note: config['service-tenant'] is created in utils.ensure_initial_admin() # we return a token, information about our API endpoints, and the generated # service credentials relation_data = { "admin_token": token, "service_host": config["hostname"], "service_port": config["service-port"], "auth_host": config["hostname"], "auth_port": config["admin-port"], "service_username": service_username, "service_password": service_password, "service_tenant": config['service-tenant'], "https_keystone": "False", "ssl_cert": "", "ssl_key": "", "ca_cert": "" } if relation_id: relation_data['rid'] = relation_id # Check if clustered and use vip + haproxy ports if so if cluster.is_clustered(): relation_data["auth_host"] = config['vip'] relation_data["service_host"] = config['vip'] # generate or get a new cert/key for service if set to manage certs. if config['https-service-endpoints'] in ['True', 'true']: ca = get_ca(user=SSH_USER) cert, key = ca.get_cert_and_key(common_name=https_cn) ca_bundle = ca.get_ca_bundle() relation_data['ssl_cert'] = b64encode(cert) relation_data['ssl_key'] = b64encode(key) relation_data['ca_cert'] = b64encode(ca_bundle) relation_data['https_keystone'] = 'True' unison.sync_to_peers(peer_interface='cluster', paths=[SSL_DIR], user=SSH_USER, verbose=True) utils.relation_set(**relation_data) synchronize_service_credentials()
def ensure_valid_service(service): if service not in valid_services.keys(): utils.juju_log('WARNING', "Invalid service requested: '%s'" % service) utils.relation_set(admin_token=-1) return
def ha_relation_joined(): vip = utils.config_get('vip') vip_iface = utils.config_get('vip_iface') vip_cidr = utils.config_get('vip_cidr') corosync_bindiface = utils.config_get('ha-bindiface') corosync_mcastport = utils.config_get('ha-mcastport') if None in [vip, vip_cidr, vip_iface]: utils.juju_log('WARNING', 'Insufficient VIP information to configure cluster') sys.exit(1) # Starting configuring resources. init_services = { 'res_mysqld': 'mysql', } # If the 'ha' relation has been made *before* the 'ceph' relation, # it doesn't make sense to make it until after the 'ceph' relation is made if not utils.is_relation_made('ceph', 'auth'): utils.juju_log( 'INFO', '*ceph* relation does not exist. ' 'Not sending *ha* relation data yet') return else: utils.juju_log('INFO', '*ceph* relation exists. Sending *ha* relation data') block_storage = 'ceph' resources = { 'res_mysql_rbd': 'ocf:ceph:rbd', 'res_mysql_fs': 'ocf:heartbeat:Filesystem', 'res_mysql_vip': 'ocf:heartbeat:IPaddr2', 'res_mysqld': 'upstart:mysql', } rbd_name = utils.config_get('rbd-name') resource_params = { 'res_mysql_rbd': 'params name="%s" pool="%s" user="******" ' 'secret="%s"' % \ (rbd_name, POOL_NAME, SERVICE_NAME, ceph.keyfile_path(SERVICE_NAME)), 'res_mysql_fs': 'params device="/dev/rbd/%s/%s" directory="%s" ' 'fstype="ext4" op start start-delay="10s"' % \ (POOL_NAME, rbd_name, DATA_SRC_DST), 'res_mysql_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % \ (vip, vip_cidr, vip_iface), 'res_mysqld': 'op start start-delay="5s" op monitor interval="5s"', } groups = { 'grp_mysql': 'res_mysql_rbd res_mysql_fs res_mysql_vip res_mysqld', } for rel_id in utils.relation_ids('ha'): utils.relation_set(rid=rel_id, block_storage=block_storage, corosync_bindiface=corosync_bindiface, corosync_mcastport=corosync_mcastport, resources=resources, resource_params=resource_params, init_services=init_services, groups=groups)
def shared_db_changed(): def get_allowed_units(database, username): allowed_units = set() for relid in hookenv.relation_ids('shared-db'): for unit in hookenv.related_units(relid): attr = "%s_%s" % (database, 'hostname') hosts = hookenv.relation_get(attribute=attr, unit=unit, rid=relid) if not hosts: hosts = [hookenv.relation_get(attribute='private-address', unit=unit, rid=relid)] else: # hostname can be json-encoded list of hostnames try: hosts = json.loads(hosts) except ValueError: pass if not isinstance(hosts, list): hosts = [hosts] if hosts: for host in hosts: utils.juju_log('INFO', "Checking host '%s' grant" % (host)) if grant_exists(database, username, host): if unit not in allowed_units: allowed_units.add(unit) else: utils.juju_log('INFO', "No hosts found for grant check") return allowed_units def configure_db(hostname, database, username): passwd_file = "/var/lib/mysql/mysql-{}.passwd".format(username) if hostname != local_hostname: try: remote_ip = socket.gethostbyname(hostname) except Exception: # socket.gethostbyname doesn't support ipv6 remote_ip = hostname else: remote_ip = '127.0.0.1' if not os.path.exists(passwd_file): password = pwgen() with open(passwd_file, 'w') as pfile: pfile.write(password) os.chmod(pfile.name, 0600) else: with open(passwd_file) as pfile: password = pfile.read().strip() if not database_exists(database): create_database(database) if not grant_exists(database, username, remote_ip): create_grant(database, username, remote_ip, password) return password if not cluster.eligible_leader(LEADER_RES): utils.juju_log('INFO', 'MySQL service is peered, bailing shared-db relation' ' as this service unit is not the leader') return if utils.config_get('prefer-ipv6'): local_hostname = get_ipv6_addr(exc_list=[utils.config_get('vip')])[0] else: local_hostname = utils.unit_get('private-address') settings = relation_get() singleset = set([ 'database', 'username', 'hostname']) if singleset.issubset(settings): # Process a single database configuration hostname = settings['hostname'] database = settings['database'] username = settings['username'] # Hostname can be json-encoded list of hostnames try: hostname = json.loads(hostname) except ValueError: pass if isinstance(hostname, list): for host in hostname: password = configure_db(host, database, username) else: password = configure_db(hostname, database, username) allowed_units = " ".join(unit_sorted(get_allowed_units(database, username))) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname, password=password, allowed_units=allowed_units) else: utils.relation_set(db_host=utils.config_get("vip"), password=password, allowed_units=allowed_units) 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 return_data = {} for db in databases: if singleset.issubset(databases[db]): database = databases[db]['database'] hostname = databases[db]['hostname'] username = databases[db]['username'] try: hostname = json.loads(hostname) except ValueError: hostname = hostname if isinstance(hostname, list): for host in hostname: password = configure_db(host, database, username) else: password = configure_db(hostname, database, username) return_data['_'.join([db, 'password'])] = password allowed_units = unit_sorted(get_allowed_units(database, username)) return_data['_'.join([db, 'allowed_units'])] = \ " ".join(allowed_units) if len(return_data) > 0: utils.relation_set(**return_data) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname) else: utils.relation_set(db_host=utils.config_get("vip"))
def shared_db_changed(): def configure_db(hostname, database, username): passwd_file = "/var/lib/mysql/mysql-{}.passwd"\ .format(username) if hostname != local_hostname: remote_ip = socket.gethostbyname(hostname) else: remote_ip = '127.0.0.1' if not os.path.exists(passwd_file): password = pwgen() with open(passwd_file, 'w') as pfile: pfile.write(password) else: with open(passwd_file) as pfile: password = pfile.read().strip() if not database_exists(database): create_database(database) if not grant_exists(database, username, remote_ip): create_grant(database, username, remote_ip, password) return password if not cluster.eligible_leader(LEADER_RES): utils.juju_log( 'INFO', 'MySQL service is peered, bailing shared-db relation' ' as this service unit is not the leader') return settings = relation_get() local_hostname = utils.unit_get('private-address') singleset = set(['database', 'username', 'hostname']) if singleset.issubset(settings): # Process a single database configuration password = configure_db(settings['hostname'], settings['database'], settings['username']) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname, password=password) else: utils.relation_set(db_host=utils.config_get("vip"), 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 return_data = {} for db in databases: if singleset.issubset(databases[db]): return_data['_'.join([db, 'password'])] = \ configure_db(databases[db]['hostname'], databases[db]['database'], databases[db]['username']) if len(return_data) > 0: utils.relation_set(**return_data) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname) else: utils.relation_set(db_host=utils.config_get("vip"))
def shared_db_changed(): if not cluster.eligible_leader(LEADER_RES): utils.juju_log( 'INFO', 'MySQL service is peered, bailing shared-db relation' ' as this service unit is not the leader') return if utils.config_get('prefer-ipv6'): local_hostname = get_ipv6_addr(exc_list=[utils.config_get('vip')])[0] else: local_hostname = utils.unit_get('private-address') settings = relation_get() singleset = set(['database', 'username', 'hostname']) db_helper = get_db_helper() if singleset.issubset(settings): # Process a single database configuration hostname = settings['hostname'] database = settings['database'] username = settings['username'] # Hostname can be json-encoded list of hostnames try: hostname = json.loads(hostname) except ValueError: hostname = [hostname] for host in hostname: password = db_helper.configure_db(host, database, username) allowed_units = db_helper.get_allowed_units(database, username) allowed_units = unit_sorted(allowed_units) allowed_units = ' '.join(allowed_units) if cluster.is_clustered(): db_host = utils.config_get("vip") else: db_host = local_hostname utils.relation_set(db_host=db_host, password=password, allowed_units=allowed_units) 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 return_data = {} for db in databases: if singleset.issubset(databases[db]): database = databases[db]['database'] hostname = databases[db]['hostname'] username = databases[db]['username'] try: # Can be json-encoded list of hostnames hostname = json.loads(hostname) except ValueError: # Otherwise expected to be single hostname hostname = [hostname] for host in hostname: password = db_helper.configure_db(host, database, username) a_units = db_helper.get_allowed_units(database, username) a_units = ' '.join(unit_sorted(a_units)) return_data['%s_allowed_units' % (db)] = a_units return_data['%s_password' % (db)] = password if len(return_data) > 0: utils.relation_set(**return_data) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname) else: utils.relation_set(db_host=utils.config_get("vip"))
def shared_db_changed(): if not cluster.eligible_leader(LEADER_RES): utils.juju_log('INFO', 'MySQL service is peered, bailing shared-db relation' ' as this service unit is not the leader') return if utils.config_get('prefer-ipv6'): local_hostname = get_ipv6_addr(exc_list=[utils.config_get('vip')])[0] else: local_hostname = utils.unit_get('private-address') settings = relation_get() singleset = set([ 'database', 'username', 'hostname']) db_helper = get_db_helper() if singleset.issubset(settings): # Process a single database configuration hostname = settings['hostname'] database = settings['database'] username = settings['username'] # Hostname can be json-encoded list of hostnames try: hostname = json.loads(hostname) except ValueError: hostname = [hostname] for host in hostname: password = db_helper.configure_db(host, database, username) allowed_units = db_helper.get_allowed_units(database, username) allowed_units = unit_sorted(allowed_units) allowed_units = ' '.join(allowed_units) if cluster.is_clustered(): db_host = utils.config_get("vip") else: db_host = local_hostname utils.relation_set(db_host=db_host, password=password, allowed_units=allowed_units) 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 return_data = {} for db in databases: if singleset.issubset(databases[db]): database = databases[db]['database'] hostname = databases[db]['hostname'] username = databases[db]['username'] try: # Can be json-encoded list of hostnames hostname = json.loads(hostname) except ValueError: # Otherwise expected to be single hostname hostname = [hostname] for host in hostname: password = db_helper.configure_db(host, database, username) a_units = db_helper.get_allowed_units(database, username) a_units = ' '.join(unit_sorted(a_units)) return_data['%s_allowed_units' % (db)] = a_units return_data['%s_password' % (db)] = password if len(return_data) > 0: utils.relation_set(**return_data) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname) else: utils.relation_set(db_host=utils.config_get("vip"))
def shared_db_changed(): def configure_db(hostname, database, username): passwd_file = "/var/lib/mysql/mysql-{}.passwd"\ .format(username) if hostname != local_hostname: remote_ip = socket.gethostbyname(hostname) else: remote_ip = '127.0.0.1' if not os.path.exists(passwd_file): password = pwgen() with open(passwd_file, 'w') as pfile: pfile.write(password) else: with open(passwd_file) as pfile: password = pfile.read().strip() if not database_exists(database): create_database(database) if not grant_exists(database, username, remote_ip): create_grant(database, username, remote_ip, password) return password if not cluster.eligible_leader(LEADER_RES): utils.juju_log('INFO', 'MySQL service is peered, bailing shared-db relation' ' as this service unit is not the leader') return settings = relation_get() local_hostname = utils.unit_get('private-address') singleset = set([ 'database', 'username', 'hostname' ]) if singleset.issubset(settings): # Process a single database configuration password = configure_db(settings['hostname'], settings['database'], settings['username']) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname, password=password) else: utils.relation_set(db_host=utils.config_get("vip"), 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 return_data = {} for db in databases: if singleset.issubset(databases[db]): return_data['_'.join([db, 'password'])] = \ configure_db(databases[db]['hostname'], databases[db]['database'], databases[db]['username']) if len(return_data) > 0: utils.relation_set(**return_data) if not cluster.is_clustered(): utils.relation_set(db_host=local_hostname) else: utils.relation_set(db_host=utils.config_get("vip"))
def ha_joined(): corosync_bindiface = utils.config_get('ha-bindiface') corosync_mcastport = utils.config_get('ha-mcastport') vip = utils.config_get('vip') vip_iface = utils.config_get('vip_iface') vip_cidr = utils.config_get('vip_cidr') rbd_name = utils.config_get('rbd-name') if None in [corosync_bindiface, corosync_mcastport, vip, vip_iface, vip_cidr, rbd_name]: utils.juju_log('ERROR', 'Insufficient configuration data to ' 'configure hacluster.') sys.exit(1) if not utils.is_relation_made('ceph', 'auth'): utils.juju_log('INFO', 'ha_joined: No ceph relation yet, deferring.') return name = '%s@localhost' % SERVICE_NAME if rabbit.get_node_name() != name: utils.juju_log('INFO', 'Stopping rabbitmq-server.') utils.stop('rabbitmq-server') rabbit.set_node_name('%s@localhost' % SERVICE_NAME) else: utils.juju_log('INFO', 'Node name already set to %s.' % name) relation_settings = {} relation_settings['corosync_bindiface'] = corosync_bindiface relation_settings['corosync_mcastport'] = corosync_mcastport relation_settings['resources'] = { 'res_rabbitmq_rbd': 'ocf:ceph:rbd', 'res_rabbitmq_fs': 'ocf:heartbeat:Filesystem', 'res_rabbitmq_vip': 'ocf:heartbeat:IPaddr2', 'res_rabbitmq-server': 'lsb:rabbitmq-server', } relation_settings['resource_params'] = { 'res_rabbitmq_rbd': 'params name="%s" pool="%s" user="******" ' 'secret="%s"' % (rbd_name, POOL_NAME, SERVICE_NAME, ceph.keyfile_path(SERVICE_NAME)), 'res_rabbitmq_fs': 'params device="/dev/rbd/%s/%s" directory="%s" ' 'fstype="ext4" op start start-delay="10s"' % (POOL_NAME, rbd_name, RABBIT_DIR), 'res_rabbitmq_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % (vip, vip_cidr, vip_iface), 'res_rabbitmq-server': 'op start start-delay="5s" ' 'op monitor interval="5s"', } relation_settings['groups'] = { 'grp_rabbitmq': 'res_rabbitmq_rbd res_rabbitmq_fs res_rabbitmq_vip ' 'res_rabbitmq-server', } for rel_id in utils.relation_ids('ha'): utils.relation_set(rid=rel_id, **relation_settings) env_vars = { 'OPENSTACK_PORT_EPMD': 4369, 'OPENSTACK_PORT_MCASTPORT': utils.config_get('ha-mcastport'), } openstack.save_script_rc(**env_vars)
def ha_joined(): corosync_bindiface = utils.config_get('ha-bindiface') corosync_mcastport = utils.config_get('ha-mcastport') vip = utils.config_get('vip') vip_iface = utils.config_get('vip_iface') vip_cidr = utils.config_get('vip_cidr') rbd_name = utils.config_get('rbd-name') if None in [ corosync_bindiface, corosync_mcastport, vip, vip_iface, vip_cidr, rbd_name ]: utils.juju_log( 'ERROR', 'Insufficient configuration data to ' 'configure hacluster.') sys.exit(1) if not utils.is_relation_made('ceph', 'auth'): utils.juju_log('INFO', 'ha_joined: No ceph relation yet, deferring.') return name = '%s@localhost' % SERVICE_NAME if rabbit.get_node_name() != name: utils.juju_log('INFO', 'Stopping rabbitmq-server.') utils.stop('rabbitmq-server') rabbit.set_node_name('%s@localhost' % SERVICE_NAME) else: utils.juju_log('INFO', 'Node name already set to %s.' % name) relation_settings = {} relation_settings['corosync_bindiface'] = corosync_bindiface relation_settings['corosync_mcastport'] = corosync_mcastport relation_settings['resources'] = { 'res_rabbitmq_rbd': 'ocf:ceph:rbd', 'res_rabbitmq_fs': 'ocf:heartbeat:Filesystem', 'res_rabbitmq_vip': 'ocf:heartbeat:IPaddr2', 'res_rabbitmq-server': 'lsb:rabbitmq-server', } relation_settings['resource_params'] = { 'res_rabbitmq_rbd': 'params name="%s" pool="%s" user="******" ' 'secret="%s"' % (rbd_name, POOL_NAME, SERVICE_NAME, ceph.keyfile_path(SERVICE_NAME)), 'res_rabbitmq_fs': 'params device="/dev/rbd/%s/%s" directory="%s" ' 'fstype="ext4" op start start-delay="10s"' % (POOL_NAME, rbd_name, RABBIT_DIR), 'res_rabbitmq_vip': 'params ip="%s" cidr_netmask="%s" nic="%s"' % (vip, vip_cidr, vip_iface), 'res_rabbitmq-server': 'op start start-delay="5s" ' 'op monitor interval="5s"', } relation_settings['groups'] = { 'grp_rabbitmq': 'res_rabbitmq_rbd res_rabbitmq_fs res_rabbitmq_vip ' 'res_rabbitmq-server', } for rel_id in utils.relation_ids('ha'): utils.relation_set(rid=rel_id, **relation_settings) env_vars = { 'OPENSTACK_PORT_EPMD': 4369, 'OPENSTACK_PORT_MCASTPORT': utils.config_get('ha-mcastport'), } openstack.save_script_rc(**env_vars)