From ddf4fbc2aeab6b239b4c7812f8fcf3389ad7d068 Mon Sep 17 00:00:00 2001 From: Hui Xiang Date: Thu, 21 Aug 2014 17:04:33 +0800 Subject: [PATCH] Sync charm-helpers, support haproxy for IPv6. --- charm-helpers-hooks.yaml | 1 + .../contrib/peerstorage/__init__.py | 83 +++++++++++++++++++ hooks/charmhelpers/fetch/__init__.py | 1 + hooks/nova_cc_context.py | 20 +++-- hooks/nova_cc_hooks.py | 22 ++++- 5 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 hooks/charmhelpers/contrib/peerstorage/__init__.py diff --git a/charm-helpers-hooks.yaml b/charm-helpers-hooks.yaml index e8d393c9..e99898f8 100644 --- a/charm-helpers-hooks.yaml +++ b/charm-helpers-hooks.yaml @@ -9,3 +9,4 @@ include: - apache - payload.execd - contrib.network.ip + - contrib.peerstorage diff --git a/hooks/charmhelpers/contrib/peerstorage/__init__.py b/hooks/charmhelpers/contrib/peerstorage/__init__.py new file mode 100644 index 00000000..e0eeab5b --- /dev/null +++ b/hooks/charmhelpers/contrib/peerstorage/__init__.py @@ -0,0 +1,83 @@ +from charmhelpers.core.hookenv import ( + relation_ids, + relation_get, + local_unit, + relation_set, +) + +""" +This helper provides functions to support use of a peer relation +for basic key/value storage, with the added benefit that all storage +can be replicated across peer units, so this is really useful for +services that issue usernames/passwords to remote services. + +def shared_db_changed() + # Only the lead unit should create passwords + if not is_leader(): + return + username = relation_get('username') + key = '{}.password'.format(username) + # Attempt to retrieve any existing password for this user + password = peer_retrieve(key) + if password is None: + # New user, create password and store + password = pwgen(length=64) + peer_store(key, password) + create_access(username, password) + relation_set(password=password) + + +def cluster_changed() + # Echo any relation data other that *-address + # back onto the peer relation so all units have + # all *.password keys stored on their local relation + # for later retrieval. + peer_echo() + +""" + + +def peer_retrieve(key, relation_name='cluster'): + """ Retrieve a named key from peer relation relation_name """ + cluster_rels = relation_ids(relation_name) + if len(cluster_rels) > 0: + cluster_rid = cluster_rels[0] + return relation_get(attribute=key, rid=cluster_rid, + unit=local_unit()) + else: + raise ValueError('Unable to detect' + 'peer relation {}'.format(relation_name)) + + +def peer_store(key, value, relation_name='cluster'): + """ Store the key/value pair on the named peer relation relation_name """ + cluster_rels = relation_ids(relation_name) + if len(cluster_rels) > 0: + cluster_rid = cluster_rels[0] + relation_set(relation_id=cluster_rid, + relation_settings={key: value}) + else: + raise ValueError('Unable to detect ' + 'peer relation {}'.format(relation_name)) + + +def peer_echo(includes=None): + """Echo filtered attributes back onto the same relation for storage + + Note that this helper must only be called within a peer relation + changed hook + """ + rdata = relation_get() + echo_data = {} + if includes is None: + echo_data = rdata.copy() + for ex in ['private-address', 'public-address']: + if ex in echo_data: + echo_data.pop(ex) + else: + for attribute, value in rdata.iteritems(): + for include in includes: + if include in attribute: + echo_data[attribute] = value + if len(echo_data) > 0: + relation_set(relation_settings=echo_data) diff --git a/hooks/charmhelpers/fetch/__init__.py b/hooks/charmhelpers/fetch/__init__.py index 5be512ce..d73cc34e 100644 --- a/hooks/charmhelpers/fetch/__init__.py +++ b/hooks/charmhelpers/fetch/__init__.py @@ -122,6 +122,7 @@ def filter_installed_packages(packages): # Tell apt to build an in-memory cache to prevent race conditions (if # another process is already building the cache). apt_pkg.config.set("Dir::Cache::pkgcache", "") + apt_pkg.config.set("Dir::Cache::srcpkgcache", "") cache = apt_pkg.Cache() _pkgs = [] diff --git a/hooks/nova_cc_context.py b/hooks/nova_cc_context.py index 47c2cc36..bdb0c967 100644 --- a/hooks/nova_cc_context.py +++ b/hooks/nova_cc_context.py @@ -163,10 +163,16 @@ def canonical_url(vip_setting='vip'): scheme = 'http' if https(): scheme = 'https' - if is_clustered(): - addr = config(vip_setting) + if config('prefer-ipv6'): + if is_clustered(): + addr = '[%s]' % config(vip_setting) + else: + addr = '[%s]' % get_ipv6_addr() else: - addr = unit_get('private-address') + if is_clustered(): + addr = config(vip_setting) + else: + addr = unit_get('private-address') return '%s://%s' % (scheme, addr) @@ -208,7 +214,8 @@ class NeutronCCContext(context.NeutronContext): _config['nvp-controllers'].split() ctxt['nova_url'] = "{}:8774/v2".format(canonical_url()) if config('prefer-ipv6'): - ctxt['bind_host'] = '%s' % get_ipv6_addr() + ctxt['bind_host'] = '::' + ctxt['neutron_url'] = "{}:9696".format(canonical_url()) return ctxt @@ -248,8 +255,9 @@ class NovaIPv6Context(context.OSContextGenerator): ctxt = {} if config('prefer-ipv6'): ctxt['use_ipv6'] = True - ctxt['host_ip'] = '%s' % get_ipv6_addr() + ctxt['host_ip'] = '::' + ctxt['neutron_url'] = "{}:9696".format(canonical_url()) else: ctxt['use_ipv6'] = False - ctxt['host_ip'] = '%s' % unit_get('private-address') + ctxt['host_ip'] = ctxt['neutron_url'] = unit_get('private-address') return ctxt diff --git a/hooks/nova_cc_hooks.py b/hooks/nova_cc_hooks.py index 3a2569f8..e92d0d98 100755 --- a/hooks/nova_cc_hooks.py +++ b/hooks/nova_cc_hooks.py @@ -28,10 +28,13 @@ from charmhelpers.core.host import ( restart_on_change, service_running, service_stop, + lsb_release, ) from charmhelpers.fetch import ( - apt_install, apt_update + apt_install, + apt_update, + add_source ) from charmhelpers.contrib.openstack.utils import ( @@ -95,6 +98,8 @@ from charmhelpers.contrib.network.ip import ( get_ipv6_addr, ) +from charmhelpers.contrib.peerstorage import peer_store + hooks = Hooks() CONFIGS = register_configs() @@ -103,8 +108,18 @@ CONFIGS = register_configs() def install(): execd_preinstall() configure_installation_source(config('openstack-origin')) + + trusty = lsb_release()['DISTRIB_CODENAME'] == 'trusty' + if config('prefer-ipv6') and trusty: + add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports' + ' main') + add_source('deb-src http://archive.ubuntu.com/ubuntu trusty-backports' + ' main') + apt_update() apt_install(determine_packages(), fatal=True) + if config('prefer-ipv6') and trusty: + apt_install('haproxy/trusty-backports', fatal=True) _files = os.path.join(charm_dir(), 'files') if os.path.isdir(_files): @@ -524,11 +539,14 @@ def quantum_joined(rid=None): @hooks.hook('cluster-relation-changed', - 'cluster-relation-departed') + 'cluster-relation-departed', + 'cluster-relation-joined') @service_guard(guard_map(), CONFIGS, active=config('service-guard')) @restart_on_change(restart_map(), stopstart=True) def cluster_changed(): + if config('prefer-ipv6'): + peer_store('private-address', get_ipv6_addr()) CONFIGS.write_all()