예제 #1
0
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"))
예제 #2
0
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)
예제 #4
0
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)
예제 #5
0
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'))
예제 #6
0
def db_joined():
    relation_data = {
        "database": config["database"],
        "username": config["database-user"],
        "hostname": config["hostname"]
        }
    utils.relation_set(**relation_data)
예제 #7
0
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)
예제 #8
0
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)
예제 #9
0
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)
예제 #10
0
파일: ha_relations.py 프로젝트: mjs/juju
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'))
예제 #11
0
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()
예제 #13
0
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'])
예제 #14
0
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)
예제 #17
0
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()
예제 #18
0
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
예제 #19
0
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)
예제 #20
0
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"))
예제 #22
0
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)
예제 #26
0
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)