def configure_ssl(self, keystone_interface=None): """Configure SSL certificates and keys NOTE(AJK): This function tries to minimise the work it does, particularly with writing files and restarting apache. @param keystone_interface KeystoneRequires class """ keystone_interface = ( relations.endpoint_from_flag('identity-service.available.ssl') or relations.endpoint_from_flag( 'identity-service.available.ssl_legacy')) ssl_objects = self.get_certs_and_keys( keystone_interface=keystone_interface) with is_data_changed('configure_ssl.ssl_objects', ssl_objects) as changed: if ssl_objects: if changed: for ssl in ssl_objects: self.set_state('ssl.requested', True) self.configure_cert(ssl['cert'], ssl['key'], cn=ssl['cn']) self.configure_ca(ssl['ca']) if not os_utils.snap_install_requested(): self.configure_apache() self.remove_state('ssl.requested') self.set_state('ssl.enabled', True) else: self.set_state('ssl.enabled', False) amqp_ssl = relations.endpoint_from_flag('amqp.available.ssl') if amqp_ssl: self.configure_rabbit_cert(amqp_ssl)
def render_stuff(*args): """Render the configuration for Manila when all the interfaces are available. Note that the charm class actually calls on the manila-plugin directly to get the config, so we unconditionally clear the changed status here, if it was set. """ with charms_openstack.charm.provide_charm_instance() as manila_charm: pre_ssl_enabled = manila_charm.get_state('ssl.enabled') tls = relations.endpoint_from_flag('certificates.available') manila_charm.configure_tls(certificates_interface=tls) if pre_ssl_enabled != manila_charm.get_state('ssl.enabled'): keystone = relations.endpoint_from_flag( 'identity-service.available') manila_charm.register_endpoints(keystone) manila_charm.render_with_interfaces(args) manila_charm.assess_status() charms.reactive.set_state('manila.config.rendered') manila_plugin = \ relations.endpoint_from_flag('manila-plugin.changed') or \ relations.endpoint_from_flag('remote-manila-plugin.changed') if manila_plugin: manila_plugin.clear_changed() manila_charm.enable_webserver_site()
def configure(): zookeeper = relations.endpoint_from_flag('endpoint.zookeeper.available') connections = [] try: connections_yaml = hookenv.config().get('connections') if connections_yaml: connections = yaml.safe_load(connections_yaml) except yaml.YAMLError: pass mysql = relations.endpoint_from_flag('shared-db.available') conf = { 'zk_servers': [], 'connections': connections, 'database': mysql, 'git_username': hookenv.config().get('git_username'), 'git_email': hookenv.config().get('git_email'), 'executor_disk_limit': hookenv.config().get('executor_disk_limit', '-1'), 'public_ip': hookenv.unit_public_ip(), } if hookenv.config()['tenant-config']: conf['tenant_config_script'] = True for zk_unit in zookeeper.list_unit_data(): conf['zk_servers'].append("{}:{}".format( zk_unit['host'].replace('"', ''), zk_unit['port'])) templating.render('zuul.conf', '/etc/zuul/zuul.conf', context=conf, perms=0o650, group='zuul', owner='zuul') if reactive.helpers.any_file_changed(['/etc/zuul/zuul.conf']): reactive.set_flag('service.zuul.restart') reactive.set_flag('zuul.reload_config') reactive.set_flag('zuul.configured')
def send_cell_data(): ncc_ep = endpoint_from_flag('endpoint.nova-cell-compute.joined') amqp_conv = endpoint_from_flag('amqp.available').conversation() # Push this calculation of service names down into the interfaces amqp_service_names = [u.split('/')[0] for u in amqp_conv.units if u] db_conv = endpoint_from_flag('shared-db.available').conversation() db_service_names = [u.split('/')[0] for u in db_conv.units if u] ncc_ep.send_cell_data(hookenv.config('cell-name'), amqp_service_names[0], db_service_names[0])
def configure_designate_basic(*args): """Configure the minimum to boostrap designate""" # If cluster relation is available it needs to passed in cluster = relations.endpoint_from_flag('cluster.available') if cluster is not None: args = args + (cluster, ) dns_backend = relations.endpoint_from_flag('dns-backend.available') if dns_backend is not None: args = args + (dns_backend, ) with provide_charm_instance() as instance: instance.render_base_config(args) reactive.set_state('base-config.rendered')
def kubernetes_status_update(): kubernetes = endpoint_from_flag('endpoint.kubernetes.new-status') k8s_status = kubernetes.get_status() if not k8s_status or not k8s_status['status']: return nodeport = None deployment_running = False # Check if service and deployment has been created on k8s # If the service is created, set the connection string # else clear it. for resource in k8s_status['status']: if resource['kind'] == "Service": nodeport = resource['spec']['ports'][0]['nodePort'] elif resource['kind'] == "Deployment": if 'availableReplicas' in resource['status'] and \ resource['status']['availableReplicas'] == \ resource['status']['readyReplicas']: deployment_running = True kubernetes_workers = kubernetes.get_worker_ips() if nodeport and kubernetes_workers and deployment_running: unitdata.kv().set('kafka-connect-service', kubernetes_workers[0] + ':' + str(nodeport)) status.active('K8s deployment running') clear_flag('endpoint.kubernetes.new-status') set_flag('kafka-connect.running') else: unitdata.kv().set('kafka-connect-service', '') clear_flag('kafka-connect.running')
def publish_global_client_cert(): """ This is for backwards compatibility with older tls-certificate clients only. Obviously, it's not good security / design to have clients sharing a certificate, but it seems that there are clients that depend on this (though some, like etcd, only block on the flag that it triggers but don't actually use the cert), so we have to set it for now. """ if not client_approle_authorized(): log("Vault not authorized: Skipping publish_global_client_cert", "WARNING") return cert_created = is_flag_set('charm.vault.global-client-cert.created') reissue_requested = is_flag_set('certificates.reissue.global.requested') tls = endpoint_from_flag('certificates.available') if not cert_created or reissue_requested: ttl = config()['default-ttl'] max_ttl = config()['max-ttl'] bundle = vault_pki.generate_certificate('client', 'global-client', [], ttl, max_ttl) unitdata.kv().set('charm.vault.global-client-cert', bundle) set_flag('charm.vault.global-client-cert.created') clear_flag('certificates.reissue.global.requested') else: bundle = unitdata.kv().get('charm.vault.global-client-cert') tls.set_client_cert(bundle['certificate'], bundle['private_key'])
def configure_vault(context): log("Running configure_vault", level=DEBUG) context['disable_mlock'] = is_container() or config('disable-mlock') context['ssl_available'] = is_state('vault.ssl.available') if is_flag_set('etcd.tls.available'): etcd = endpoint_from_flag('etcd.available') log("Etcd detected, adding to context", level=DEBUG) context['etcd_conn'] = etcd.connection_string() context['etcd_tls_ca_file'] = '/var/snap/vault/common/etcd-ca.pem' context['etcd_tls_cert_file'] = '/var/snap/vault/common/etcd-cert.pem' context['etcd_tls_key_file'] = '/var/snap/vault/common/etcd.key' save_etcd_client_credentials(etcd, key=context['etcd_tls_key_file'], cert=context['etcd_tls_cert_file'], ca=context['etcd_tls_ca_file']) context['api_addr'] = vault.get_api_url() context['cluster_addr'] = vault.get_cluster_url() log("Etcd detected, setting api_addr to {}".format( context['api_addr'])) else: log("Etcd not detected", level=DEBUG) log("Rendering vault.hcl.j2", level=DEBUG) render('vault.hcl.j2', VAULT_CONFIG, context, perms=0o600) log("Rendering vault systemd configuation", level=DEBUG) render('vault.service.j2', VAULT_SYSTEMD_CONFIG, {}, perms=0o644) service('enable', 'vault') log("Opening vault port", level=DEBUG) open_port(8200) set_flag('configured') if any_file_changed([VAULT_CONFIG, VAULT_SYSTEMD_CONFIG]): # force a restart if config has changed clear_flag('started')
def create_cert_request(): if not config.get('fqdns'): status_set('blocked', 'Waiting for fqdns config') return ssl_termination = endpoint_from_flag('endpoint.ssl-termination.available') upstream_config = config.get('upstreams').split(' ') upstreams = [] for u in upstream_config: host, port = u.split(':') upstreams.append({ 'hostname': host, 'port': port, }) cert_request = { 'fqdn': config.get('fqdns').rstrip().split(), 'contact-email': config.get('contact-email', ''), 'credentials': config.get('credentials', ''), 'upstreams': upstreams, 'nginx-config': parse_nginx_config(), } ssl_termination.send_cert_info(cert_request) status_set('waiting', 'Waiting for proxy to register certificate') set_flag('client.cert-requested')
def create_cert_request(): if not config.get('fqdns'): status_set('blocked', 'Waiting for fqdns config') return ssl_termination = endpoint_from_flag('endpoint.ssl-termination.available') workers = get_worker_node_ips() if not workers: return upstreams = [] ingress_nodeport = get_ingress_nodeport() for worker in workers: host = [{ 'hostname': worker, 'private-address': worker, 'port': ingress_nodeport }] upstreams.extend(host) print(upstreams) ssl_termination.send_cert_info({ 'fqdn': config.get('fqdns').rstrip().split(), 'contact-email': config.get('contact-email', ''), 'credentials': config.get('credentials', ''), 'upstreams': upstreams, }) status_set('waiting', 'Waiting for proxy to register certificate') set_flag('client.cert-requested')
def send_vault_url_and_ca(): secrets = endpoint_from_flag('secrets.connected') vault_url_external = None if is_flag_set('ha.available'): hostname = config('hostname') if hostname: vault_url = vault.get_api_url(address=hostname) else: vip = vault.get_vip() vault_url = vault.get_api_url(address=vip) ext_vip = vault.get_vip(binding='external') if ext_vip and ext_vip != vip: vault_url_external = vault.get_api_url(address=ext_vip, binding='external') else: vault_url = vault.get_api_url() vault_url_external = vault.get_api_url(binding='external') if vault_url_external == vault_url: vault_url_external = None secrets.publish_url(vault_url=vault_url, remote_binding='access') if vault_url_external: secrets.publish_url(vault_url=vault_url_external, remote_binding='external') if config('ssl-ca'): secrets.publish_ca(vault_ca=config('ssl-ca'))
def send_vault_url_and_ca(): secrets = endpoint_from_flag('secrets.connected') vault_url_external = None hostname = config('hostname') vip = vault.get_vip() if is_flag_set('ha.available'): if hostname: vault_url = vault.get_api_url(address=hostname) else: vault_url = vault.get_api_url(address=vip) ext_vip = vault.get_vip(binding='external') if ext_vip and ext_vip != vip: vault_url_external = vault.get_api_url(address=ext_vip, binding='external') elif vip: log( "VIP is set but ha.available is not yet set, skipping " "send_vault_url_and_ca.", level=DEBUG) return else: vault_url = vault.get_api_url() vault_url_external = vault.get_api_url(binding='external') if vault_url_external == vault_url: vault_url_external = None secrets.publish_url(vault_url=vault_url, remote_binding='access') if vault_url_external: secrets.publish_url(vault_url=vault_url_external, remote_binding='external') if config('ssl-ca'): secrets.publish_ca(vault_ca=config('ssl-ca'))
def create_certs(): reissue_requested = is_flag_set('certificates.reissue.requested') tls = endpoint_from_flag('certificates.available') requests = tls.all_requests if reissue_requested else tls.new_requests if reissue_requested: log('Reissuing all certs') processed_applications = [] for request in requests: log('Processing certificate request from {} for {}'.format( request.unit_name, request.common_name)) if request.cert_type == 'application': cert_type = 'server' # When an application cert is published all units recieve the same # data so one need to process one request per application. if request.application_name in processed_applications: log('Already done {}'.format(request.application_name)) continue else: processed_applications.append(request.application_name) else: cert_type = request.cert_type try: ttl = config()['default-ttl'] max_ttl = config()['max-ttl'] bundle = vault_pki.generate_certificate(cert_type, request.common_name, request.sans, ttl, max_ttl) request.set_cert(bundle['certificate'], bundle['private_key']) except vault.VaultInvalidRequest as e: log(str(e), level=ERROR) continue # TODO: report failure back to client clear_flag('certificates.reissue.requested')
def configure_ssl(self, keystone_interface=None): """Configure SSL certificates and keys NOTE(AJK): This function tries to minimise the work it does, particularly with writing files and restarting apache. @param keystone_interface KeystoneRequires class """ keystone_interface = ( relations.endpoint_from_flag('identity-service.available.ssl') or relations .endpoint_from_flag('identity-service.available.ssl_legacy')) certificates_interface = relations.endpoint_from_flag( 'certificates.batch.cert.available') ssl_objects = self.get_certs_and_keys( keystone_interface=keystone_interface, certificates_interface=certificates_interface) with is_data_changed('configure_ssl.ssl_objects', ssl_objects) as changed: if ssl_objects: # NOTE(fnordahl): regardless of changes to data we may # have other changes we want to apply to the files. # (e.g. ownership, permissions) # # Also note that c-h.host.write_file used in configure_cert() # has it's own logic to detect data changes. # # LP: #1821314 for ssl in ssl_objects: self.set_state('ssl.requested', True) self.configure_cert( ssl['cert'], ssl['key'], cn=ssl['cn']) self.configure_ca(ssl['ca']) cert_utils.create_ip_cert_links( os.path.join('/etc/apache2/ssl/', self.name)) if not os_utils.snap_install_requested() and changed: self.configure_apache() ch_host.service_reload('apache2') self.remove_state('ssl.requested') self.set_state('ssl.enabled', True) else: self.set_state('ssl.enabled', False) amqp_ssl = relations.endpoint_from_flag('amqp.available.ssl') if amqp_ssl: self.configure_rabbit_cert(amqp_ssl)
def configure_kafka_connect_base(): kafka = endpoint_from_flag('kafka.ready') kubernetes = endpoint_from_flag('endpoint.kubernetes.available') kafka_brokers = [] for kafka_unit in kafka.kafkas(): kafka_brokers.append(kafka_unit['host'] + ':' + kafka_unit['port']) worker_config = generate_worker_config() worker_config['bootstrap.servers'] = ','.join(kafka_brokers) port = worker_config['rest.port'] if 'rest.port' in worker_config else 8083 uuid = kubernetes.get_uuid() resource_context = { 'configmap_name': 'cfgmap-{}'.format(uuid), 'label': uuid, 'properties': worker_config, 'service_name': 'svc-{}'.format(uuid), 'port': port, 'deployment_name': 'depl-{}'.format(uuid), 'replicas': conf.get('workers', 1), 'container_name': uuid, 'image': unitdata.kv().get('docker-image'), 'containerport': port, } if data_changed('resource-context', resource_context): # Trigger a rolling update by setting a new annotation in the deployment resource_context['configmap_annotation'] = hashlib.sha1(datetime.datetime.now() .isoformat() .encode('utf-8')).hexdigest() templating.render(source="resources.j2", target="/etc/kafka-connect/resources.yaml", context=resource_context) resources = [] with open('/etc/kafka-connect/resources.yaml', 'r') as f: docs = yaml.load_all(f) for doc in docs: resources.append(doc) kubernetes.send_create_request(resources) status.waiting('Waiting for k8s deployment (will happen in next hook)') set_flag('kafka-connect-base.configured')
def send_storage_backend_data(self): cbend = relations.endpoint_from_flag('storage-backend.connected') cbend.configure_principal(backend_name=self.service_name, configuration=self.cinder_configuration(), stateless=self.stateless) # Add an assess status which will be picked up later by the atexit() # handler. self.assess_status()
def configure_ssl(self, keystone_interface=None): """Configure SSL certificates and keys NOTE(AJK): This function tries to minimise the work it does, particularly with writing files and restarting apache. @param keystone_interface KeystoneRequires class """ keystone_interface = ( relations.endpoint_from_flag('identity-service.available.ssl') or relations.endpoint_from_flag( 'identity-service.available.ssl_legacy')) certificates_interface = relations.endpoint_from_flag( 'certificates.batch.cert.available') ssl_objects = self.get_certs_and_keys( keystone_interface=keystone_interface, certificates_interface=certificates_interface) with is_data_changed('configure_ssl.ssl_objects', ssl_objects) as changed: if ssl_objects: # NOTE(fnordahl): regardless of changes to data we may # have other changes we want to apply to the files. # (e.g. ownership, permissions) # # Also note that c-h.host.write_file used in configure_cert() # has it's own logic to detect data changes. # # LP: #1821314 for ssl in ssl_objects: self.set_state('ssl.requested', True) self.configure_cert(ssl['cert'], ssl['key'], cn=ssl['cn']) self.configure_ca(ssl['ca']) cert_utils.create_ip_cert_links( os.path.join('/etc/apache2/ssl/', self.name)) if not os_utils.snap_install_requested() and changed: self.configure_apache() ch_host.service_reload('apache2') self.remove_state('ssl.requested') self.set_state('ssl.enabled', True) else: self.set_state('ssl.enabled', False) amqp_ssl = relations.endpoint_from_flag('amqp.available.ssl') if amqp_ssl: self.configure_rabbit_cert(amqp_ssl)
def setup_rabbitmq(): rabbitmq = endpoint_from_flag('rabbitmq.connected') juju_app_name = (MODEL_NAME.replace("/", '-') + '.' + JUJU_UNIT_NAME.split('/')[0]) username = JUJU_UNIT_NAME.split('/')[0] vhost = '/' + juju_app_name rabbitmq.request_access(username, vhost) status.waiting('Waiting on RabbitMQ to configure vhost')
def send_compute_data(): nc = endpoint_from_flag('endpoint.cloud-compute.joined') ncc_ep = endpoint_from_flag('endpoint.nova-cell-compute.changed') ncc_console_data = ncc_ep.get_console_data() ncc_network_data = ncc_ep.get_network_data() nc.set_network_data( ncc_network_data['quantum_url'], neutron_plugin=ncc_network_data['quantum_plugin'], network_manager=ncc_network_data['network_manager'], enable_security_groups=ncc_network_data['quantum_security_groups']) nc.set_console_data( serial_console_base_url=ncc_console_data['serial_console_base_url'], enable_serial_console=ncc_console_data['enable_serial_console']) nc.set_region(ncc_ep.get_region()['region']) nc.set_volume_data(ncc_ep.get_volume_data()['volume_service']) nc.set_ec2_data(ncc_ep.get_ec2_data()['ec2_host']) nc.trigger_remote_restart( restart_key=ncc_ep.get_restart_trigger()['restart_trigger'])
def configure_cinder_backup(): # don't always have a relation context - obtain from the flag endp = endpoint_from_flag('endpoint.backup-backend.joined') with charms_openstack.charm.provide_charm_instance() as charm_instance: # publish config options for all remote units of a given rel name, config = charm_instance.get_swift_backup_config() endp.publish(name, config) charm_instance.configure_ca() flags.set_flag('config.complete')
def send_storage_backend_data(self): cbend = relations.endpoint_from_flag('storage-backend.connected') cbend.configure_principal( backend_name=self.service_name, configuration=self.cinder_configuration(), stateless=self.stateless) # Add an assess status which will be picked up later by the atexit() # handler. self.assess_status()
def optional_interfaces(args, *interfaces): """Return a tuple with possible optional interfaces :param args: a list of reactive interfaces :param *interfaces: list of strings representing possible reactive interfaces. :returns: [list of reactive interfaces] """ return args + tuple(ri for ri in (relations.endpoint_from_flag(i) for i in interfaces) if ri is not None)
def send_vault_url_and_ca(): secrets = endpoint_from_flag('secrets.connected') if is_flag_set('ha.available'): vault_url = vault.get_api_url(address=config('vip')) else: vault_url = vault.get_api_url() secrets.publish_url(vault_url=vault_url) if config('ssl-ca'): secrets.publish_ca(vault_ca=config('ssl-ca'))
def configure_websso(): # don't always have a relation context - obtain from the flag websso_fid_sp = endpoint_from_flag( 'endpoint.websso-fid-service-provider.joined') with charm.provide_charm_instance() as charm_instance: # publish config options for all remote units of a given rel options = charm_instance.options websso_fid_sp.publish(options.protocol_name, options.idp_name, options.user_facing_name)
def update_status_info(): endpoint = endpoint_from_flag('endpoint.kubernetes-deployer.available') status = check_predefined_resources() error_states = unitdata.kv().get('error-states', {}) status.update(error_states) worker_ips = get_worker_node_ips() # Only report if the status has changed if (data_changed('status-info', status) or data_changed('worker-ips', worker_ips)): endpoint.send_status(status) endpoint.send_worker_ips(worker_ips)
def get_certificate_requests(): endpoint = endpoint_from_flag('endpoint.ssl-termination.update') clear_flag('endpoint.ssl-termination.update') cert_requests = endpoint.get_cert_requests() if data_changed('sslterm.requests', cert_requests) and cert_requests: old_requests = unitdata.kv().get('sslterm.cert-requests', []) delete_old_certs(old_requests, cert_requests) unitdata.kv().set('sslterm.cert-requests', cert_requests) lets_encrypt.set_requested_certificates(cert_requests) set_flag('ssl-termination.waiting') clean_nginx('/etc/nginx/sites-available/ssl-termination')
def configure_dbd(mysql_endpoint): '''A dbd is only configured after leader election is performed and a database is believed to be configured''' hookenv.status_set('maintenance', 'Configuring slurm-dbd') is_active = dbd.is_active_dbd() role = dbd.ROLES[is_active] peer_role = dbd.ROLES[not is_active] dbd_conf = copy.deepcopy(hookenv.config()) dbd_conf.update({ 'db_hostname': mysql_endpoint.db_host(), 'db_port': dbd.MYSQL_DB_PORT, 'db_password': mysql_endpoint.password(), 'db_name': mysql_endpoint.database(), 'db_username': mysql_endpoint.username(), }) ha_endpoint = relations.endpoint_from_flag('endpoint.slurm-dbd-ha.joined') if ha_endpoint: net_details = dbd.add_key_prefix(ha_endpoint.network_details(), role) dbd_conf.update(net_details) # add prefixed peer data peer_data = dbd.add_key_prefix(ha_endpoint.peer_data, peer_role) dbd_conf.update(peer_data) else: # if running in standalone mode, just use network-get with HA endpoint # name to get an ingress address and a hostname net_details = dbd.add_key_prefix(dbd.network_details(), role) dbd_conf.update(net_details) peer_data = None # a dbd service is configurable if it is an active dbd # or a backup dbd that knows about an active dbd is_configurable = is_active or (not is_active and peer_data) if is_configurable: hookenv.log('dbd is configurable ({})'.format(role)) # Setup slurm dirs and config dbd.render_slurmdbd_config(context=dbd_conf) # Render a minimal dummy slurm.conf dbd.render_slurm_config(context=dbd_conf) # Make sure slurmctld is running if not host.service_running(dbd.SLURMDBD_SERVICE): host.service_start(dbd.SLURMDBD_SERVICE) flags.set_flag('slurm-dbd.configured') flags.clear_flag('slurm-dbd.standalone_startup') host.service_restart(dbd.SLURMDBD_SERVICE) else: hookenv.log('dbd is NOT configurable ({})'.format(role)) if not is_active: hookenv.status_set('maintenance', 'Backup dbd is waiting for peer data')
def custom_assess_status_check(self): if not hookenv.config('nameservers'): return 'blocked', ('nameservers must be set') invalid_dns = self.options.invalid_pool_config() if invalid_dns: return 'blocked', invalid_dns dns_backend_available = ( relations.endpoint_from_flag('dns-backend.available')) if not (dns_backend_available or hookenv.config('dns-slaves')): return 'blocked', ('Need either a dns-backend relation or ' 'config(dns-slaves) or both.') return None, None
def send_k8s_request(): if not config.get('fqdns'): status_set('blocked', 'Waiting for fqdns config') return if not config.get('nodeport'): status_set('blocked', 'Waiting for nodeport config') return endpoint = endpoint_from_flag('endpoint.kubernetes-deployer.available') context = {'name': application_name(), 'fqdns': config.get('fqdns'), 'nodeport': config.get('nodeport')} resource = render('resource.yaml', None, context) endpoint.send_create_request([yaml.load(resource)]) set_flag('client.k8s-requested')
def create_topics(): if not os.path.exists('/usr/lib/kafka/bin'): status.blocked('Could not find Kafka library, make sure the Kafka Connect charm is colocated with a Kafka unit.') return kafka = endpoint_from_flag('kafka.ready') zookeepers = [] for zookeeper in kafka.zookeepers(): zookeepers.append(zookeeper['host'] + ":" + zookeeper['port']) if not zookeepers: return # Set replication factor as number of Kafka brokers # Use the zookeeper-shell because Juju sets the Kafka # broker info one hook at a time and therefore we do not # know beforehand howmany brokers there are p = Popen(['/usr/lib/kafka/bin/zookeeper-shell.sh', zookeepers[0]], stdin=PIPE, stdout=PIPE) output = p.communicate(b'ls /brokers/ids')[0] # The broker info is in the last line between [id1,id2,id3] replication_factor = output.decode('utf-8') \ .strip() \ .split('\n')[-1] \ .count(',') \ + 1 topics_suffixes = ['connectconfigs', 'connectoffsets', 'connectstatus'] partitions = [1, 50, 10] # Best effort partition numbers model = os.environ['JUJU_MODEL_NAME'] app = os.environ['JUJU_UNIT_NAME'].split('/')[0] prefix = "{}.{}.".format(model, app) for (suffix, partitions) in zip(topics_suffixes, partitions): topic = prefix + suffix unitdata.kv().set(suffix, topic) if topic_exists(topic, zookeepers): continue try: output = run(['/usr/lib/kafka/bin/kafka-topics.sh', '--zookeeper', ",".join(zookeepers), "--create", "--topic", topic, "--partitions", str(partitions), "--replication-factor", str(replication_factor, "--config", "cleanup.policy=compact")], stdout=PIPE) output.check_returncode() except CalledProcessError as e: log(e) set_flag('kafka-connect-base.topic-created')
def configure_ssl(self, keystone_interface=None): """Configure SSL certificates and keys NOTE(AJK): This function tries to minimise the work it does, particularly with writing files and restarting apache. @param keystone_interface KeystoneRequires class """ keystone_interface = ( relations.endpoint_from_flag('identity-service.available.ssl') or relations .endpoint_from_flag('identity-service.available.ssl_legacy')) certificates_interface = relations.endpoint_from_flag( 'certificates.batch.cert.available') ssl_objects = self.get_certs_and_keys( keystone_interface=keystone_interface, certificates_interface=certificates_interface) with is_data_changed('configure_ssl.ssl_objects', ssl_objects) as changed: if ssl_objects: if changed: for ssl in ssl_objects: self.set_state('ssl.requested', True) self.configure_cert( ssl['cert'], ssl['key'], cn=ssl['cn']) self.configure_ca(ssl['ca']) cert_utils.create_ip_cert_links( os.path.join('/etc/apache2/ssl/', self.name)) if not os_utils.snap_install_requested(): self.configure_apache() ch_host.service_reload('apache2') self.remove_state('ssl.requested') self.set_state('ssl.enabled', True) else: self.set_state('ssl.enabled', False) amqp_ssl = relations.endpoint_from_flag('amqp.available.ssl') if amqp_ssl: self.configure_rabbit_cert(amqp_ssl)
def create_client_cert(): """Create client certificates with the request information from the relation object.""" tls = endpoint_from_flag("client.client.certs.requested") # Iterate over all new requests for request in tls.new_client_requests: # Create a client certificate for this request. name = request.common_name client_cert, client_key = create_client_certificate(name) # Set the client certificate and key on the relationship object. request.set_cert(client_cert, client_key)
def check_cert_created(): ssl_termination = endpoint_from_flag('endpoint.ssl-termination.update') status = ssl_termination.get_status() # Only one fqdn will be returned for shared certs. # If any fqdn match, the cert has been created. match_fqdn = config.get('fqdns').rstrip().split() for unit_status in status: for fqdn in unit_status['status']: if fqdn in match_fqdn: status_set('active', 'Ready') set_flag('client.cert-created') clear_flag('endpoint.ssl-termination.update')
def __resolve_cluster(self): """ Resolve what the cluster adapter is. LY: The cluster interface only gets initialised if there are more than one unit in a cluster, however, a cluster of one unit is valid for the Openstack API charms. So, create and populate the 'cluster' namespace with data for a single unit if there are no peers. :returns: cluster adapter or None """ smm = PeerHARelationAdapter(relation_name='cluster').single_mode_map if smm: return smm else: # LY: Automatically add the cluster relation if it exists and # has not been passed through. cluster_rel = relations.endpoint_from_flag('cluster.connected') if cluster_rel: return PeerHARelationAdapter(relation=cluster_rel) return None
#!/usr/bin/env python3 import sys sys.path.append('lib') # Make sure that reactive is bootstrapped and all the states are setup # properly from charms.layer import basic basic.bootstrap_charm_deps() basic.init_config_states() import charm.openstack.tempest as tempest import charms.reactive.relations as relations import charmhelpers.core.hookenv as hookenv if __name__ == '__main__': identity_int = relations.endpoint_from_flag('identity-admin.available') if identity_int is None: # The interface isn't connected, so we can't do this yet hookenv.action_fail( "The identity-admin interface is not available - bailing") else: tempest.render_configs([identity_int]) tempest.run_test('smoke')