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
This commit is contained in:
James Page 2016-11-09 11:39:45 +00:00
parent b9be248dc4
commit aa8f652756
10 changed files with 64 additions and 4 deletions

View File

@ -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.

View File

@ -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):

View File

@ -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"
</VirtualHost>
{% endfor -%}
<Proxy *>

View File

@ -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"
</VirtualHost>
{% endfor -%}
<Proxy *>

View File

@ -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

View File

@ -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(

View File

@ -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)

View File

@ -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'

View File

@ -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)

View File

@ -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.