def config_changed(): unison.ensure_user(user=SSH_USER, group='keystone') execute("chmod -R g+wrx /var/lib/keystone/") # Determine whether or not we should do an upgrade, based on the # the version offered in keyston-release. available = get_os_codename_install_source(config['openstack-origin']) installed = get_os_codename_package('keystone') if (available and get_os_version_codename(available) > \ get_os_version_codename(installed)): # TODO: fixup this call to work like utils.install() do_openstack_upgrade(config['openstack-origin'], ' '.join(packages)) # Ensure keystone group permissions execute("chmod -R g+wrx /var/lib/keystone/") env_vars = {'OPENSTACK_SERVICE_KEYSTONE': 'keystone', 'OPENSTACK_PORT_ADMIN': cluster.determine_api_port( config['admin-port']), 'OPENSTACK_PORT_PUBLIC': cluster.determine_api_port( config['service-port'])} save_script_rc(**env_vars) set_admin_token(config['admin-token']) if cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Cluster leader - ensuring endpoint configuration' ' is up to date') ensure_initial_admin(config) update_config_block('logger_root', level=config['log-level'], file='/etc/keystone/logging.conf') if get_os_version_package('keystone') >= '2013.1': # PKI introduced in Grizzly configure_pki_tokens(config) if config_dirty(): utils.restart('keystone') if cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Firing identity_changed hook' ' for all related services.') # HTTPS may have been set - so fire all identity relations # again for r_id in utils.relation_ids('identity-service'): for unit in utils.relation_list(r_id): identity_changed(relation_id=r_id, remote_unit=unit)
def config_changed(): unison.ensure_user(user=rabbit.SSH_USER, group='rabbit') ensure_unison_rabbit_permissions() if utils.config_get('management_plugin') is True: rabbit.enable_plugin(MAN_PLUGIN) utils.open_port(55672) else: # rabbit.disable_plugin(MAN_PLUGIN) utils.close_port(55672) if utils.config_get('ssl_enabled') is True: ssl_key = utils.config_get('ssl_key') ssl_cert = utils.config_get('ssl_cert') ssl_port = utils.config_get('ssl_port') if None in [ssl_key, ssl_cert, ssl_port]: utils.juju_log('ERROR', 'Please provide ssl_key, ssl_cert and ssl_port' ' config when enabling SSL support') sys.exit(1) else: rabbit.enable_ssl(ssl_key, ssl_cert, ssl_port) utils.open_port(ssl_port) else: if os.path.exists(rabbit.RABBITMQ_CONF): os.remove(rabbit.RABBITMQ_CONF) utils.close_port(utils.config_get('ssl_port')) if cluster.eligible_leader('res_rabbitmq_vip'): utils.restart('rabbitmq-server') update_nrpe_checks()
def ceph_changed(): utils.juju_log('INFO', 'Start Ceph Relation Changed') auth = utils.relation_get('auth') key = utils.relation_get('key') if None in [auth, key]: utils.juju_log('INFO', 'Missing key or auth in relation') sys.exit(0) ceph.configure(service=SERVICE_NAME, key=key, auth=auth) if cluster.eligible_leader('res_rabbitmq_vip'): rbd_img = utils.config_get('rbd-name') rbd_size = utils.config_get('rbd-size') sizemb = int(rbd_size.split('G')[0]) * 1024 blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img) ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME, rbd_img=rbd_img, sizemb=sizemb, fstype='ext4', mount_point=RABBIT_DIR, blk_device=blk_device, system_services=['rabbitmq-server']) else: utils.juju_log('INFO', 'This is not the peer leader. Not configuring RBD.') utils.juju_log('INFO', 'Stopping rabbitmq-server.') utils.stop('rabbitmq-server') # If 'ha' relation has been made before the 'ceph' relation # it is important to make sure the ha-relation data is being # sent. if utils.is_relation_made('ha'): utils.juju_log('INFO', '*ha* relation exists. Triggering ha_joined()') ha_joined() else: utils.juju_log('INFO', '*ha* relation does not exist.') utils.juju_log('INFO', 'Finish Ceph Relation Changed')
def config_changed(): unison.ensure_user(user=rabbit.SSH_USER, group='rabbit') ensure_unison_rabbit_permissions() if utils.config_get('management_plugin') is True: rabbit.enable_plugin(MAN_PLUGIN) utils.open_port(55672) else: # rabbit.disable_plugin(MAN_PLUGIN) utils.close_port(55672) if utils.config_get('ssl_enabled') is True: ssl_key = utils.config_get('ssl_key') ssl_cert = utils.config_get('ssl_cert') ssl_port = utils.config_get('ssl_port') if None in [ssl_key, ssl_cert, ssl_port]: utils.juju_log( 'ERROR', 'Please provide ssl_key, ssl_cert and ssl_port' ' config when enabling SSL support') sys.exit(1) else: rabbit.enable_ssl(ssl_key, ssl_cert, ssl_port) utils.open_port(ssl_port) else: if os.path.exists(rabbit.RABBITMQ_CONF): os.remove(rabbit.RABBITMQ_CONF) utils.close_port(utils.config_get('ssl_port')) if cluster.eligible_leader('res_rabbitmq_vip'): utils.restart('rabbitmq-server') update_nrpe_checks()
def upgrade_charm(): # Ensure all required packages are installed utils.install(*packages) cluster_changed() if cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Cluster leader - ensuring endpoint configuration' ' is up to date') ensure_initial_admin(config)
def synchronize_service_credentials(): ''' Broadcast service credentials to peers or consume those that have been broadcasted by peer, depending on hook context. ''' if (not cluster.eligible_leader(CLUSTER_RES) or not os.path.isfile(SERVICE_PASSWD_PATH)): return utils.juju_log('INFO', 'Synchronizing service passwords to all peers.') unison.sync_to_peers(peer_interface='cluster', paths=[SERVICE_PASSWD_PATH], user=SSH_USER, verbose=True)
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 db_changed(): relation_data = utils.relation_get_dict() if ('password' not in relation_data or 'db_host' not in relation_data): utils.juju_log('INFO', "db_host or password not set. Peer not ready, exit 0") return update_config_block('sql', connection="mysql://%s:%s@%s/%s" % (config["database-user"], relation_data["password"], relation_data["db_host"], config["database"])) if cluster.eligible_leader(CLUSTER_RES): utils.juju_log('INFO', 'Cluster leader, performing db-sync') execute("keystone-manage db_sync", echo=True) if config_dirty(): utils.restart('keystone') time.sleep(5) if cluster.eligible_leader(CLUSTER_RES): ensure_initial_admin(config) # If the backend database has been switched to something new and there # are existing identity-service relations,, service entries need to be # recreated in the new database. Re-executing identity-service-changed # will do this. for rid in utils.relation_ids('identity-service'): for unit in utils.relation_list(rid=rid): utils.juju_log('INFO', "Re-exec'ing identity-service-changed" " for: %s - %s" % (rid, unit)) identity_changed(relation_id=rid, remote_unit=unit)
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 ceph_changed(): utils.juju_log('INFO', 'Start Ceph Relation Changed') auth = utils.relation_get('auth') key = utils.relation_get('key') use_syslog = utils.relation_get('use_syslog') if None in [auth, key]: utils.juju_log('INFO', 'Missing key or auth in relation') return ceph.configure(service=SERVICE_NAME, key=key, auth=auth, use_syslog=use_syslog) if cluster.eligible_leader(LEADER_RES): sizemb = int(utils.config_get('block-size')) * 1024 rbd_img = utils.config_get('rbd-name') blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img) rbd_pool_rep_count = utils.config_get('ceph-osd-replication-count') ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME, rbd_img=rbd_img, sizemb=sizemb, fstype='ext4', mount_point=DATA_SRC_DST, blk_device=blk_device, system_services=['mysql'], rbd_pool_replicas=rbd_pool_rep_count) else: utils.juju_log('INFO', 'This is not the peer leader. Not configuring RBD.') # Stopping MySQL if utils.running('mysql'): utils.juju_log('INFO', 'Stopping MySQL...') utils.stop('mysql') # If 'ha' relation has been made before the 'ceph' relation # it is important to make sure the ha-relation data is being # sent. if utils.is_relation_made('ha'): utils.juju_log( 'INFO', '*ha* relation exists. Making sure the ha' ' relation data is sent.') ha_relation_joined() return utils.juju_log('INFO', 'Finish Ceph Relation Changed')
def ceph_changed(): utils.juju_log("INFO", "Start Ceph Relation Changed") auth = utils.relation_get("auth") key = utils.relation_get("key") use_syslog = utils.relation_get("use_syslog") if None in [auth, key]: utils.juju_log("INFO", "Missing key or auth in relation") return ceph.configure(service=SERVICE_NAME, key=key, auth=auth, use_syslog=use_syslog) if cluster.eligible_leader(LEADER_RES): sizemb = int(utils.config_get("block-size")) * 1024 rbd_img = utils.config_get("rbd-name") blk_device = "/dev/rbd/%s/%s" % (POOL_NAME, rbd_img) rbd_pool_rep_count = utils.config_get("ceph-osd-replication-count") ceph.ensure_ceph_storage( service=SERVICE_NAME, pool=POOL_NAME, rbd_img=rbd_img, sizemb=sizemb, fstype="ext4", mount_point=DATA_SRC_DST, blk_device=blk_device, system_services=["mysql"], rbd_pool_replicas=rbd_pool_rep_count, ) else: utils.juju_log("INFO", "This is not the peer leader. Not configuring RBD.") # Stopping MySQL if utils.running("mysql"): utils.juju_log("INFO", "Stopping MySQL...") utils.stop("mysql") # If 'ha' relation has been made before the 'ceph' relation # it is important to make sure the ha-relation data is being # sent. if utils.is_relation_made("ha"): utils.juju_log("INFO", "*ha* relation exists. Making sure the ha" " relation data is sent.") ha_relation_joined() return utils.juju_log("INFO", "Finish Ceph Relation Changed")
def ceph_changed(): utils.juju_log('INFO', 'Start Ceph Relation Changed') auth = utils.relation_get('auth') key = utils.relation_get('key') use_syslog = utils.relation_get('use_syslog') if None in [auth, key]: utils.juju_log('INFO', 'Missing key or auth in relation') return ceph.configure(service=SERVICE_NAME, key=key, auth=auth, use_syslog=use_syslog) if cluster.eligible_leader(LEADER_RES): sizemb = int(utils.config_get('block-size')) * 1024 rbd_img = utils.config_get('rbd-name') blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img) rbd_pool_rep_count = utils.config_get('ceph-osd-replication-count') ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME, rbd_img=rbd_img, sizemb=sizemb, fstype='ext4', mount_point=DATA_SRC_DST, blk_device=blk_device, system_services=['mysql'], rbd_pool_replicas=rbd_pool_rep_count) else: utils.juju_log('INFO', 'This is not the peer leader. Not configuring RBD.') # Stopping MySQL if utils.running('mysql'): utils.juju_log('INFO', 'Stopping MySQL...') utils.stop('mysql') # If 'ha' relation has been made before the 'ceph' relation # it is important to make sure the ha-relation data is being # sent. if utils.is_relation_made('ha'): utils.juju_log('INFO', '*ha* relation exists. Making sure the ha' ' relation data is sent.') ha_relation_joined() return utils.juju_log('INFO', 'Finish Ceph Relation Changed')
def ceph_changed(): utils.juju_log('INFO', 'Start Ceph Relation Changed') auth = utils.relation_get('auth') key = utils.relation_get('key') if None in [auth, key]: utils.juju_log('INFO', 'Missing key or auth in relation') sys.exit(0) ceph.configure(service=SERVICE_NAME, key=key, auth=auth) if cluster.eligible_leader('res_rabbitmq_vip'): rbd_img = utils.config_get('rbd-name') rbd_size = utils.config_get('rbd-size') sizemb = int(rbd_size.split('G')[0]) * 1024 blk_device = '/dev/rbd/%s/%s' % (POOL_NAME, rbd_img) rbd_pool_rep_count = utils.config_get('ceph-osd-replication-count') ceph.ensure_ceph_storage(service=SERVICE_NAME, pool=POOL_NAME, rbd_img=rbd_img, sizemb=sizemb, fstype='ext4', mount_point=RABBIT_DIR, blk_device=blk_device, system_services=['rabbitmq-server'], rbd_pool_replicas=rbd_pool_rep_count) else: utils.juju_log('INFO', 'This is not the peer leader. Not configuring RBD.') utils.juju_log('INFO', 'Stopping rabbitmq-server.') utils.stop('rabbitmq-server') # If 'ha' relation has been made before the 'ceph' relation # it is important to make sure the ha-relation data is being # sent. if utils.is_relation_made('ha'): utils.juju_log('INFO', '*ha* relation exists. Triggering ha_joined()') ha_joined() else: utils.juju_log('INFO', '*ha* relation does not exist.') utils.juju_log('INFO', 'Finish Ceph Relation Changed')
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 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(): 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 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 do_openstack_upgrade(install_src, packages): '''Upgrade packages from a given install src.''' config = config_get() old_vers = get_os_codename_package('keystone') new_vers = get_os_codename_install_source(install_src) utils.juju_log('INFO', "Beginning Keystone upgrade: %s -> %s" % \ (old_vers, new_vers)) # Backup previous config. utils.juju_log('INFO', "Backing up contents of /etc/keystone.") stamp = time.strftime('%Y%m%d%H%M') cmd = 'tar -pcf /var/lib/juju/keystone-backup-%s.tar /etc/keystone' % stamp execute(cmd, die=True, echo=True) configure_installation_source(install_src) execute('apt-get update', die=True, echo=True) os.environ['DEBIAN_FRONTEND'] = 'noninteractive' cmd = 'apt-get --option Dpkg::Options::=--force-confnew -y '\ 'install %s' % packages execute(cmd, echo=True, die=True) # we have new, fresh config files that need updating. # set the admin token, which is still stored in config. set_admin_token(config['admin-token']) # set the sql connection string if a shared-db relation is found. ids = utils.relation_ids('shared-db') if ids: for rid in ids: for unit in utils.relation_list(rid): utils.juju_log('INFO', 'Configuring new keystone.conf for ' 'database access on existing database' ' relation to %s' % unit) relation_data = utils.relation_get_dict(relation_id=rid, remote_unit=unit) update_config_block('sql', connection="mysql://%s:%s@%s/%s" % (config["database-user"], relation_data["password"], relation_data["private-address"], config["database"])) utils.stop('keystone') if (cluster.eligible_leader(CLUSTER_RES)): utils.juju_log('INFO', 'Running database migrations for %s' % new_vers) execute('keystone-manage db_sync', echo=True, die=True) else: utils.juju_log('INFO', 'Not cluster leader; snoozing whilst' ' leader upgrades DB') time.sleep(10) utils.start('keystone') time.sleep(5) utils.juju_log('INFO', 'Completed Keystone upgrade: ' '%s -> %s' % (old_vers, new_vers))