From aa8f65275626bd18685bfc2eaae235d9af7a283c Mon Sep 17 00:00:00 2001 From: James Page Date: Wed, 9 Nov 2016 11:39:45 +0000 Subject: [PATCH] Guard enablement of ext4 mounts in containers Its not possible to enable usernamespace ext4 mounting when LXD is being run from inside a container; leverage charm-helpers is_container function to guard writes to the /sys filesystem. Change-Id: Ie479dcf45cb4834308a055dde22d919830c60671 Closes-Bug: 1635659 --- .../contrib/openstack/amulet/utils.py | 11 +++++++++++ hooks/charmhelpers/contrib/openstack/context.py | 2 +- .../templates/openstack_https_frontend | 3 +++ .../templates/openstack_https_frontend.conf | 3 +++ hooks/charmhelpers/contrib/openstack/utils.py | 14 +++++++++++++- hooks/charmhelpers/core/hookenv.py | 2 ++ hooks/charmhelpers/core/host.py | 17 +++++++++++++++++ hooks/lxd_utils.py | 3 ++- tests/charmhelpers/contrib/amulet/utils.py | 2 +- .../contrib/openstack/amulet/utils.py | 11 +++++++++++ 10 files changed, 64 insertions(+), 4 deletions(-) diff --git a/hooks/charmhelpers/contrib/openstack/amulet/utils.py b/hooks/charmhelpers/contrib/openstack/amulet/utils.py index e4546c8..6a0ba83 100644 --- a/hooks/charmhelpers/contrib/openstack/amulet/utils.py +++ b/hooks/charmhelpers/contrib/openstack/amulet/utils.py @@ -28,6 +28,7 @@ import keystoneclient.v2_0 as keystone_client from keystoneclient.auth.identity import v3 as keystone_id_v3 from keystoneclient import session as keystone_session from keystoneclient.v3 import client as keystone_client_v3 +from novaclient import exceptions import novaclient.client as nova_client import pika @@ -377,6 +378,16 @@ class OpenStackAmuletUtils(AmuletUtils): tenant_name=tenant, auth_version='2.0') + def create_flavor(self, nova, name, ram, vcpus, disk, flavorid="auto", + ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True): + """Create the specified flavor.""" + try: + nova.flavors.find(name=name) + except (exceptions.NotFound, exceptions.NoUniqueMatch): + self.log.debug('Creating flavor ({})'.format(name)) + nova.flavors.create(name, ram, vcpus, disk, flavorid, + ephemeral, swap, rxtx_factor, is_public) + def create_cirros_image(self, glance, image_name): """Download the latest cirros image and upload it to glance, validate and return a resource pointer. diff --git a/hooks/charmhelpers/contrib/openstack/context.py b/hooks/charmhelpers/contrib/openstack/context.py index b601a22..cbbe466 100644 --- a/hooks/charmhelpers/contrib/openstack/context.py +++ b/hooks/charmhelpers/contrib/openstack/context.py @@ -644,7 +644,7 @@ class ApacheSSLContext(OSContextGenerator): service_namespace = None def enable_modules(self): - cmd = ['a2enmod', 'ssl', 'proxy', 'proxy_http'] + cmd = ['a2enmod', 'ssl', 'proxy', 'proxy_http', 'headers'] check_call(cmd) def configure_cert(self, cn=None): diff --git a/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend b/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend index 6a92380..f614b3f 100644 --- a/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend +++ b/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend @@ -9,10 +9,13 @@ Listen {{ ext_port }} SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} + # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 + SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} SSLCertificateKeyFile /etc/apache2/ssl/{{ namespace }}/key_{{ endpoint }} ProxyPass / http://localhost:{{ int }}/ ProxyPassReverse / http://localhost:{{ int }}/ ProxyPreserveHost on + RequestHeader set X-Forwarded-Proto "https" {% endfor -%} diff --git a/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf b/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf index 6a92380..f614b3f 100644 --- a/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf +++ b/hooks/charmhelpers/contrib/openstack/templates/openstack_https_frontend.conf @@ -9,10 +9,13 @@ Listen {{ ext_port }} SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2 SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM SSLCertificateFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} + # See LP 1484489 - this is to support <= 2.4.7 and >= 2.4.8 + SSLCertificateChainFile /etc/apache2/ssl/{{ namespace }}/cert_{{ endpoint }} SSLCertificateKeyFile /etc/apache2/ssl/{{ namespace }}/key_{{ endpoint }} ProxyPass / http://localhost:{{ int }}/ ProxyPassReverse / http://localhost:{{ int }}/ ProxyPreserveHost on + RequestHeader set X-Forwarded-Proto "https" {% endfor -%} diff --git a/hooks/charmhelpers/contrib/openstack/utils.py b/hooks/charmhelpers/contrib/openstack/utils.py index 8c89c3a..49767f4 100644 --- a/hooks/charmhelpers/contrib/openstack/utils.py +++ b/hooks/charmhelpers/contrib/openstack/utils.py @@ -410,14 +410,26 @@ def get_os_version_package(pkg, fatal=True): os_rel = None -def os_release(package, base='essex'): +def reset_os_release(): + '''Unset the cached os_release version''' + global os_rel + os_rel = None + + +def os_release(package, base='essex', reset_cache=False): ''' Returns OpenStack release codename from a cached global. + + If reset_cache then unset the cached os_release version and return the + freshly determined version. + If the codename can not be determined from either an installed package or the installation source, the earliest release supported by the charm should be returned. ''' global os_rel + if reset_cache: + reset_os_release() if os_rel: return os_rel os_rel = (git_os_codename_install_source(config('openstack-origin-git')) or diff --git a/hooks/charmhelpers/core/hookenv.py b/hooks/charmhelpers/core/hookenv.py index 996e81c..94fc996 100644 --- a/hooks/charmhelpers/core/hookenv.py +++ b/hooks/charmhelpers/core/hookenv.py @@ -332,6 +332,8 @@ def config(scope=None): config_cmd_line = ['config-get'] if scope is not None: config_cmd_line.append(scope) + else: + config_cmd_line.append('--all') config_cmd_line.append('--format=json') try: config_data = json.loads( diff --git a/hooks/charmhelpers/core/host.py b/hooks/charmhelpers/core/host.py index 0f1b2f3..04cadb3 100644 --- a/hooks/charmhelpers/core/host.py +++ b/hooks/charmhelpers/core/host.py @@ -732,3 +732,20 @@ def get_total_ram(): assert unit == 'kB', 'Unknown unit' return int(value) * 1024 # Classic, not KiB. raise NotImplementedError() + + +UPSTART_CONTAINER_TYPE = '/run/container_type' + + +def is_container(): + """Determine whether unit is running in a container + + @return: boolean indicating if unit is in a container + """ + if init_is_systemd(): + # Detect using systemd-detect-virt + return subprocess.call(['systemd-detect-virt', + '--container']) == 0 + else: + # Detect using upstart container file marker + return os.path.exists(UPSTART_CONTAINER_TYPE) diff --git a/hooks/lxd_utils.py b/hooks/lxd_utils.py index a66d3db..0dbf5d5 100644 --- a/hooks/lxd_utils.py +++ b/hooks/lxd_utils.py @@ -45,6 +45,7 @@ from charmhelpers.core.host import ( service_start, pwgen, lsb_release, + is_container, ) from charmhelpers.contrib.storage.linux.utils import ( is_block_device, @@ -425,7 +426,7 @@ def configure_lxd_host(): if ubuntu_release >= 'xenial': modprobe('netlink_diag') - if os.path.exists(EXT4_USERNS_MOUNTS): + if not is_container() and os.path.exists(EXT4_USERNS_MOUNTS): with open(EXT4_USERNS_MOUNTS, 'w') as userns_mounts: userns_mounts.write( 'Y\n' if config('enable-ext4-userns') else 'N\n' diff --git a/tests/charmhelpers/contrib/amulet/utils.py b/tests/charmhelpers/contrib/amulet/utils.py index a39ed4c..8e13ab1 100644 --- a/tests/charmhelpers/contrib/amulet/utils.py +++ b/tests/charmhelpers/contrib/amulet/utils.py @@ -546,7 +546,7 @@ class AmuletUtils(object): raise if it is present. :returns: List of process IDs """ - cmd = 'pidof -x {}'.format(process_name) + cmd = 'pidof -x "{}"'.format(process_name) if not expect_success: cmd += " || exit 0 && exit 1" output, code = sentry_unit.run(cmd) diff --git a/tests/charmhelpers/contrib/openstack/amulet/utils.py b/tests/charmhelpers/contrib/openstack/amulet/utils.py index e4546c8..6a0ba83 100644 --- a/tests/charmhelpers/contrib/openstack/amulet/utils.py +++ b/tests/charmhelpers/contrib/openstack/amulet/utils.py @@ -28,6 +28,7 @@ import keystoneclient.v2_0 as keystone_client from keystoneclient.auth.identity import v3 as keystone_id_v3 from keystoneclient import session as keystone_session from keystoneclient.v3 import client as keystone_client_v3 +from novaclient import exceptions import novaclient.client as nova_client import pika @@ -377,6 +378,16 @@ class OpenStackAmuletUtils(AmuletUtils): tenant_name=tenant, auth_version='2.0') + def create_flavor(self, nova, name, ram, vcpus, disk, flavorid="auto", + ephemeral=0, swap=0, rxtx_factor=1.0, is_public=True): + """Create the specified flavor.""" + try: + nova.flavors.find(name=name) + except (exceptions.NotFound, exceptions.NoUniqueMatch): + self.log.debug('Creating flavor ({})'.format(name)) + nova.flavors.create(name, ram, vcpus, disk, flavorid, + ephemeral, swap, rxtx_factor, is_public) + def create_cirros_image(self, glance, image_name): """Download the latest cirros image and upload it to glance, validate and return a resource pointer.