diff --git a/charm-helpers-hooks.yaml b/charm-helpers-hooks.yaml index 1c2d6c0a..ee82b34b 100644 --- a/charm-helpers-hooks.yaml +++ b/charm-helpers-hooks.yaml @@ -11,7 +11,7 @@ include: - cluster - contrib.python - contrib.unison - - payload.execd + - payload - contrib.peerstorage - contrib.network.ip - contrib.python.packages diff --git a/charmhelpers/contrib/openstack/context.py b/charmhelpers/contrib/openstack/context.py index 25125ded..e930bf37 100644 --- a/charmhelpers/contrib/openstack/context.py +++ b/charmhelpers/contrib/openstack/context.py @@ -57,6 +57,7 @@ from charmhelpers.core.host import ( get_nic_hwaddr, mkdir, write_file, + pwgen, ) from charmhelpers.contrib.hahelpers.cluster import ( determine_apache_port, @@ -87,6 +88,8 @@ from charmhelpers.contrib.network.ip import ( is_bridge_member, ) from charmhelpers.contrib.openstack.utils import get_host_ip +from charmhelpers.core.unitdata import kv + CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt' ADDRESS_TYPES = ['admin', 'internal', 'public'] @@ -636,11 +639,18 @@ class HAProxyContext(OSContextGenerator): ctxt['ipv6'] = True ctxt['local_host'] = 'ip6-localhost' ctxt['haproxy_host'] = '::' - ctxt['stat_port'] = ':::8888' else: ctxt['local_host'] = '127.0.0.1' ctxt['haproxy_host'] = '0.0.0.0' - ctxt['stat_port'] = ':8888' + + ctxt['stat_port'] = '8888' + + db = kv() + ctxt['stat_password'] = db.get('stat-password') + if not ctxt['stat_password']: + ctxt['stat_password'] = db.set('stat-password', + pwgen(32)) + db.flush() for frontend in cluster_hosts: if (len(cluster_hosts[frontend]['backends']) > 1 or diff --git a/charmhelpers/contrib/openstack/templates/haproxy.cfg b/charmhelpers/contrib/openstack/templates/haproxy.cfg index 8721d8a1..32b62767 100644 --- a/charmhelpers/contrib/openstack/templates/haproxy.cfg +++ b/charmhelpers/contrib/openstack/templates/haproxy.cfg @@ -33,13 +33,14 @@ defaults timeout server 30000 {%- endif %} -listen stats {{ stat_port }} +listen stats + bind {{ local_host }}:{{ stat_port }} mode http stats enable stats hide-version stats realm Haproxy\ Statistics stats uri / - stats auth admin:password + stats auth admin:{{ stat_password }} {% if frontends -%} {% for service, ports in service_ports.items() -%} diff --git a/charmhelpers/contrib/openstack/utils.py b/charmhelpers/contrib/openstack/utils.py index 3cfc983e..2af4476d 100644 --- a/charmhelpers/contrib/openstack/utils.py +++ b/charmhelpers/contrib/openstack/utils.py @@ -593,7 +593,7 @@ def _git_yaml_load(projects_yaml): return yaml.load(projects_yaml) -def git_clone_and_install(projects_yaml, core_project, depth=1): +def git_clone_and_install(projects_yaml, core_project): """ Clone/install all specified OpenStack repositories. @@ -643,6 +643,9 @@ def git_clone_and_install(projects_yaml, core_project, depth=1): for p in projects['repositories']: repo = p['repository'] branch = p['branch'] + depth = '1' + if 'depth' in p.keys(): + depth = p['depth'] if p['name'] == 'requirements': repo_dir = _git_clone_and_install_single(repo, branch, depth, parent_dir, http_proxy, @@ -687,19 +690,13 @@ def _git_clone_and_install_single(repo, branch, depth, parent_dir, http_proxy, """ Clone and install a single git repository. """ - dest_dir = os.path.join(parent_dir, os.path.basename(repo)) - if not os.path.exists(parent_dir): juju_log('Directory already exists at {}. ' 'No need to create directory.'.format(parent_dir)) os.mkdir(parent_dir) - if not os.path.exists(dest_dir): - juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch)) - repo_dir = install_remote(repo, dest=parent_dir, branch=branch, - depth=depth) - else: - repo_dir = dest_dir + juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch)) + repo_dir = install_remote(repo, dest=parent_dir, branch=branch, depth=depth) venv = os.path.join(parent_dir, 'venv') diff --git a/charmhelpers/fetch/giturl.py b/charmhelpers/fetch/giturl.py index bbf89d5c..9ad8dc60 100644 --- a/charmhelpers/fetch/giturl.py +++ b/charmhelpers/fetch/giturl.py @@ -22,7 +22,6 @@ from charmhelpers.fetch import ( filter_installed_packages, apt_install, ) -from charmhelpers.core.host import mkdir if filter_installed_packages(['git']) != []: apt_install(['git']) @@ -50,8 +49,8 @@ class GitUrlFetchHandler(BaseFetchHandler): cmd = ['git', '-C', dest, 'pull', source, branch] else: cmd = ['git', 'clone', source, dest, '--branch', branch] - if depth: - cmd.extend(['--depth', depth]) + if depth: + cmd.extend(['--depth', depth]) check_call(cmd) def install(self, source, branch="master", dest=None, depth=None): @@ -62,8 +61,6 @@ class GitUrlFetchHandler(BaseFetchHandler): else: dest_dir = os.path.join(os.environ.get('CHARM_DIR'), "fetched", branch_name) - if not os.path.exists(dest_dir): - mkdir(dest_dir, perms=0o755) try: self.clone(source, dest_dir, branch, depth) except OSError as e: diff --git a/charmhelpers/payload/archive.py b/charmhelpers/payload/archive.py new file mode 100644 index 00000000..5aaf13e2 --- /dev/null +++ b/charmhelpers/payload/archive.py @@ -0,0 +1,73 @@ +# Copyright 2014-2015 Canonical Limited. +# +# This file is part of charm-helpers. +# +# charm-helpers is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 as +# published by the Free Software Foundation. +# +# charm-helpers is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with charm-helpers. If not, see . + +import os +import tarfile +import zipfile +from charmhelpers.core import ( + host, + hookenv, +) + + +class ArchiveError(Exception): + pass + + +def get_archive_handler(archive_name): + if os.path.isfile(archive_name): + if tarfile.is_tarfile(archive_name): + return extract_tarfile + elif zipfile.is_zipfile(archive_name): + return extract_zipfile + else: + # look at the file name + for ext in ('.tar', '.tar.gz', '.tgz', 'tar.bz2', '.tbz2', '.tbz'): + if archive_name.endswith(ext): + return extract_tarfile + for ext in ('.zip', '.jar'): + if archive_name.endswith(ext): + return extract_zipfile + + +def archive_dest_default(archive_name): + archive_file = os.path.basename(archive_name) + return os.path.join(hookenv.charm_dir(), "archives", archive_file) + + +def extract(archive_name, destpath=None): + handler = get_archive_handler(archive_name) + if handler: + if not destpath: + destpath = archive_dest_default(archive_name) + if not os.path.isdir(destpath): + host.mkdir(destpath) + handler(archive_name, destpath) + return destpath + else: + raise ArchiveError("No handler for archive") + + +def extract_tarfile(archive_name, destpath): + "Unpack a tar archive, optionally compressed" + archive = tarfile.open(archive_name) + archive.extractall(destpath) + + +def extract_zipfile(archive_name, destpath): + "Unpack a zip file" + archive = zipfile.ZipFile(archive_name) + archive.extractall(destpath) diff --git a/unit_tests/test_keystone_contexts.py b/unit_tests/test_keystone_contexts.py index ef732648..c8cd1329 100644 --- a/unit_tests/test_keystone_contexts.py +++ b/unit_tests/test_keystone_contexts.py @@ -97,10 +97,11 @@ class TestKeystoneContexts(CharmTestCase): @patch('charmhelpers.contrib.openstack.context.related_units') @patch('charmhelpers.contrib.openstack.context.relation_get') @patch('charmhelpers.contrib.openstack.context.log') + @patch('charmhelpers.contrib.openstack.context.kv') @patch('__builtin__.open') def test_haproxy_context_service_enabled( - self, mock_open, mock_log, mock_relation_get, mock_related_units, - mock_unit_get, mock_relation_ids, mock_config, + self, mock_open, mock_kv, mock_log, mock_relation_get, + mock_related_units, mock_unit_get, mock_relation_ids, mock_config, mock_get_address_in_network, mock_get_netmask_for_address, mock_api_port): os.environ['JUJU_UNIT_NAME'] = 'keystone' @@ -114,6 +115,7 @@ class TestKeystoneContexts(CharmTestCase): mock_get_netmask_for_address.return_value = '255.255.255.0' self.determine_apache_port.return_value = '34' mock_api_port.return_value = '12' + mock_kv().get.return_value = 'abcdefghijklmnopqrstuvwxyz123456' ctxt = context.HAProxyContext() @@ -124,7 +126,8 @@ class TestKeystoneContexts(CharmTestCase): 'public_port': '12'}, 'local_host': '127.0.0.1', 'haproxy_host': '0.0.0.0', - 'stat_port': ':8888', + 'stat_port': '8888', + 'stat_password': 'abcdefghijklmnopqrstuvwxyz123456', 'service_ports': {'admin-port': ['12', '34'], 'public-port': ['12', '34']}, 'default_backend': '1.2.3.4',