charm-nova-compute/hooks/nova_compute_context.py
James Page 5f4f95ef13 Add support for Erasure Coded pools
Enable support for use of Erasure Coded (EC) pools for
nova disks when RBD is used to back ephemeral storage volumes.

Add the standard set of EC based configuration options to the
charm.

Update Ceph broker request to create a replicated pool, an erasure
coding profile and an erasure coded pool (using the profile) when
pool-type == erasure-coded is specified.

Resync charm-helpers to pick changes to the standard ceph.conf
template and associated contexts for rbd default data pool mangle
due to lack for explicit support in OpenStack Services.

Update context to use metadata pool name in nova configuration
when erasure-coding is enabled.

Change-Id: Ida0b9c889ddf9fcc0847a9cee01b3206239d9318
Depends-On: Iec4de19f7b39f0b08158d96c5cc1561b40aefa10
2020-08-07 10:44:38 +01:00

876 lines
30 KiB
Python

# Copyright 2016 Canonical Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
import os
import platform
import shutil
import uuid
from charmhelpers.core.unitdata import kv
from charmhelpers.contrib.openstack import context
from charmhelpers.core.host import (
lsb_release,
CompareHostReleases,
)
from charmhelpers.core.strutils import (
bool_from_string,
)
from charmhelpers.fetch import apt_install, filter_installed_packages
from charmhelpers.core.hookenv import (
config,
log,
relation_get,
relation_ids,
related_units,
service_name,
ERROR,
INFO,
WARNING,
)
from charmhelpers.contrib.openstack.utils import (
get_os_version_package,
get_os_version_codename,
os_release,
CompareOpenStackReleases,
)
from charmhelpers.contrib.openstack.ip import (
INTERNAL,
resolve_address,
)
from charmhelpers.contrib.network.ip import (
get_relation_ip,
)
# This is just a label and it must be consistent across
# nova-compute nodes to support live migration.
CEPH_SECRET_UUID = '514c9fca-8cbe-11e2-9c52-3bc8c7819472'
OVS_BRIDGE = 'br-int'
CEPH_CONF = '/etc/ceph/ceph.conf'
CHARM_CEPH_CONF = '/var/lib/charm/{}/ceph.conf'
NOVA_API_AA_PROFILE = 'usr.bin.nova-api'
NOVA_COMPUTE_AA_PROFILE = 'usr.bin.nova-compute'
NOVA_NETWORK_AA_PROFILE = 'usr.bin.nova-network'
def ceph_config_file():
return CHARM_CEPH_CONF.format(service_name())
def _save_flag_file(path, data):
'''
Saves local state about plugin or manager to specified file.
'''
# Wonder if we can move away from this now?
if data is None:
return
with open(path, 'wt') as out:
out.write(data)
os.chmod(path, 0o640)
shutil.chown(path, 'root', 'nova')
# compatability functions to help with quantum -> neutron transition
def _network_manager():
from nova_compute_utils import network_manager as manager
return manager()
def _get_availability_zone():
from nova_compute_utils import get_availability_zone as get_az
return get_az()
def _neutron_security_groups():
'''
Inspects current cloud-compute relation and determine if nova-c-c has
instructed us to use neutron security groups.
'''
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
groups = [
relation_get('neutron_security_groups',
rid=rid, unit=unit),
relation_get('quantum_security_groups',
rid=rid, unit=unit)
]
if ('yes' in groups or 'Yes' in groups):
return True
return False
def _neutron_plugin():
from nova_compute_utils import neutron_plugin
return neutron_plugin()
def _neutron_url(rid, unit):
# supports legacy relation settings.
return (relation_get('neutron_url', rid=rid, unit=unit) or
relation_get('quantum_url', rid=rid, unit=unit))
def nova_metadata_requirement():
enable = False
secret = None
for rid in relation_ids('neutron-plugin'):
for unit in related_units(rid):
rdata = relation_get(rid=rid, unit=unit)
if 'metadata-shared-secret' in rdata:
secret = rdata['metadata-shared-secret']
enable = True
if bool_from_string(rdata.get('enable-metadata', 'False')):
enable = True
return enable, secret
class LxdContext(context.OSContextGenerator):
def __call__(self):
lxd_context = {
'storage_pool': None
}
for rid in relation_ids('lxd'):
for unit in related_units(rid):
rel = {'rid': rid, 'unit': unit}
lxd_context = {
'storage_pool': relation_get(
'pool', **rel)
}
return lxd_context
class NovaComputeLibvirtContext(context.OSContextGenerator):
'''
Determines various libvirt and nova options depending on live migration
configuration.
'''
interfaces = []
def __call__(self):
# distro defaults
ctxt = {
# /etc/libvirt/libvirtd.conf (
'listen_tls': 0
}
cmp_distro_codename = CompareHostReleases(
lsb_release()['DISTRIB_CODENAME'].lower())
cmp_os_release = CompareOpenStackReleases(os_release('nova-common'))
# NOTE(jamespage): deal with switch to systemd
if cmp_distro_codename < "wily":
ctxt['libvirtd_opts'] = '-d'
else:
ctxt['libvirtd_opts'] = ''
# NOTE(jamespage): deal with alignment with Debian in
# Ubuntu yakkety and beyond.
if cmp_distro_codename >= 'yakkety' or cmp_os_release >= 'ocata':
ctxt['libvirt_user'] = 'libvirt'
else:
ctxt['libvirt_user'] = 'libvirtd'
# get the processor architecture to use in the nova.conf template
ctxt['arch'] = platform.machine()
# enable tcp listening if configured for live migration.
if config('enable-live-migration'):
ctxt['libvirtd_opts'] += ' -l'
if config('enable-live-migration') and \
config('migration-auth-type') in ['none', 'None', 'ssh']:
ctxt['listen_tls'] = 0
if config('enable-live-migration') and \
config('migration-auth-type') == 'ssh':
migration_address = get_relation_ip(
'migration', cidr_network=config('libvirt-migration-network'))
if cmp_os_release >= 'ocata':
ctxt['live_migration_scheme'] = config('migration-auth-type')
ctxt['live_migration_inbound_addr'] = migration_address
else:
ctxt['live_migration_uri'] = 'qemu+ssh://%s/system'
if config('enable-live-migration'):
ctxt['live_migration_completion_timeout'] = \
config('live-migration-completion-timeout')
ctxt['live_migration_downtime'] = \
config('live-migration-downtime')
ctxt['live_migration_downtime_steps'] = \
config('live-migration-downtime-steps')
ctxt['live_migration_downtime_delay'] = \
config('live-migration-downtime-delay')
ctxt['live_migration_permit_post_copy'] = \
config('live-migration-permit-post-copy')
ctxt['live_migration_permit_auto_converge'] = \
config('live-migration-permit-auto-converge')
if config('instances-path') is not None:
ctxt['instances_path'] = config('instances-path')
if config('disk-cachemodes'):
ctxt['disk_cachemodes'] = config('disk-cachemodes')
if config('use-multipath'):
ctxt['use_multipath'] = config('use-multipath')
if config('default-ephemeral-format'):
ctxt['default_ephemeral_format'] = \
config('default-ephemeral-format')
if config('cpu-mode'):
ctxt['cpu_mode'] = config('cpu-mode')
elif ctxt['arch'] in ('ppc64el', 'ppc64le', 'aarch64'):
ctxt['cpu_mode'] = 'host-passthrough'
elif ctxt['arch'] == 's390x':
ctxt['cpu_mode'] = 'none'
if config('cpu-model'):
ctxt['cpu_model'] = config('cpu-model')
if config('cpu-model-extra-flags'):
ctxt['cpu_model_extra_flags'] = ', '.join(
config('cpu-model-extra-flags').split(' '))
if config('hugepages'):
ctxt['hugepages'] = True
ctxt['kvm_hugepages'] = 1
else:
ctxt['kvm_hugepages'] = 0
if config('ksm') in ("1", "0",):
ctxt['ksm'] = config('ksm')
else:
if cmp_os_release < 'kilo':
log("KSM set to 1 by default on openstack releases < kilo",
level=INFO)
ctxt['ksm'] = "1"
else:
ctxt['ksm'] = "AUTO"
if config('reserved-huge-pages'):
# To bypass juju limitation with list of strings, we
# consider separate the option's values per semicolons.
ctxt['reserved_huge_pages'] = (
[o.strip() for o in config('reserved-huge-pages').split(";")])
if config('pci-passthrough-whitelist'):
ctxt['pci_passthrough_whitelist'] = \
config('pci-passthrough-whitelist')
if config('pci-alias'):
ctxt['pci_alias'] = config('pci-alias')
if config('vcpu-pin-set'):
ctxt['vcpu_pin_set'] = config('vcpu-pin-set')
if config('cpu-shared-set'):
ctxt['cpu_shared_set'] = config('cpu-shared-set')
if config('cpu-dedicated-set'):
ctxt['cpu_dedicated_set'] = config('cpu-dedicated-set')
if ctxt['vcpu_pin_set']:
w = ("Ignoring vcpu-pin-set config since that option can't be "
"used with cpu-dedicated-set.")
log(w, level=WARNING)
ctxt['vcpu_pin_set'] = None
if config('virtio-net-tx-queue-size'):
ctxt['virtio_net_tx_queue_size'] = (
config('virtio-net-tx-queue-size'))
if config('virtio-net-rx-queue-size'):
ctxt['virtio_net_rx_queue_size'] = (
config('virtio-net-rx-queue-size'))
ctxt['reserved_host_memory'] = config('reserved-host-memory')
db = kv()
if db.get('host_uuid'):
ctxt['host_uuid'] = db.get('host_uuid')
else:
host_uuid = str(uuid.uuid4())
db.set('host_uuid', host_uuid)
db.flush()
ctxt['host_uuid'] = host_uuid
if config('libvirt-image-backend'):
ctxt['libvirt_images_type'] = config('libvirt-image-backend')
ctxt['force_raw_images'] = config('force-raw-images')
return ctxt
class NovaComputeLibvirtOverrideContext(context.OSContextGenerator):
"""Provides overrides to the libvirt-bin service"""
interfaces = []
def __call__(self):
ctxt = {}
ctxt['overrides'] = "limit nofile 65535 65535"
return ctxt
class NovaComputeVirtContext(context.OSContextGenerator):
interfaces = []
def __call__(self):
ctxt = {}
_release = lsb_release()['DISTRIB_CODENAME'].lower()
if CompareHostReleases(_release) >= "yakkety":
ctxt['virt_type'] = config('virt-type')
ctxt['enable_live_migration'] = config('enable-live-migration')
ctxt['resume_guests_state_on_host_boot'] =\
config('resume-guests-state-on-host-boot')
return ctxt
def assert_libvirt_rbd_imagebackend_allowed():
os_rel = "Juno"
os_ver = get_os_version_package('nova-common')
if float(os_ver) < float(get_os_version_codename(os_rel.lower())):
msg = ("Libvirt RBD imagebackend only supported for openstack >= %s" %
os_rel)
raise Exception(msg)
return True
class NovaComputeCephContext(context.CephContext):
def __call__(self):
ctxt = super(NovaComputeCephContext, self).__call__()
if not ctxt:
return {}
svc = service_name()
# secret.xml
ctxt['ceph_secret_uuid'] = CEPH_SECRET_UUID
# nova.conf
ctxt['service_name'] = svc
ctxt['rbd_user'] = svc
ctxt['rbd_secret_uuid'] = CEPH_SECRET_UUID
if config('pool-type') == 'erasure-coded':
ctxt['rbd_pool'] = (
config('ec-rbd-metadata-pool') or
"{}-metadata".format(config('rbd-pool'))
)
else:
ctxt['rbd_pool'] = config('rbd-pool')
if (config('libvirt-image-backend') == 'rbd' and
assert_libvirt_rbd_imagebackend_allowed()):
ctxt['libvirt_rbd_images_ceph_conf'] = ceph_config_file()
rbd_cache = config('rbd-client-cache') or ""
if rbd_cache.lower() == "enabled":
# We use write-though only to be safe for migration
ctxt['rbd_client_cache_settings'] = \
{'rbd cache': 'true',
'rbd cache size': '64 MiB',
'rbd cache max dirty': '0 MiB',
'rbd cache writethrough until flush': 'true',
'admin socket': '/var/run/ceph/rbd-client-$pid.asok'}
asok_path = '/var/run/ceph/'
if not os.path.isdir(asok_path):
os.mkdir(asok_path)
shutil.chown(asok_path, group='kvm')
elif rbd_cache.lower() == "disabled":
ctxt['rbd_client_cache_settings'] = {'rbd cache': 'false'}
return ctxt
class SerialConsoleContext(context.OSContextGenerator):
@property
def enable_serial_console(self):
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
_enable_sc = relation_get('enable_serial_console', rid=rid,
unit=unit)
if _enable_sc and bool_from_string(_enable_sc):
return 'true'
return 'false'
@property
def serial_console_base_url(self):
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
base_url = relation_get('serial_console_base_url',
rid=rid, unit=unit)
if base_url is not None:
return base_url
return 'ws://127.0.0.1:6083/'
def __call__(self):
return {
'enable_serial_console': self.enable_serial_console,
'serial_console_base_url': self.serial_console_base_url,
}
class CloudComputeVendorJSONContext(context.OSContextGenerator):
"""Receives vendor_data.json from nova cloud controller node."""
interfaces = ['cloud-compute']
@property
def vendor_json(self):
"""
Returns the json string to be written in vendor_data.json file,
received from nova-cloud-controller charm through relation attribute
vendor_json.
"""
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
vendor_data_string = relation_get(
'vendor_json', rid=rid, unit=unit)
if vendor_data_string:
return vendor_data_string
def __call__(self):
"""
Returns a dict in which the value of vendor_data_json is the json
string to be written in vendor_data.json file.
"""
ctxt = {'vendor_data_json': '{}'}
vendor_data = self.vendor_json
if vendor_data:
ctxt['vendor_data_json'] = vendor_data
return ctxt
class CloudComputeContext(context.OSContextGenerator):
'''
Generates main context for writing nova.conf and quantum.conf templates
from a cloud-compute relation changed hook. Mainly used for determinig
correct network and volume service configuration on the compute node,
as advertised by the cloud-controller.
Note: individual quantum plugin contexts are handled elsewhere.
'''
interfaces = ['cloud-compute']
def _ensure_packages(self, packages):
'''Install but do not upgrade required packages'''
required = filter_installed_packages(packages)
if required:
apt_install(required, fatal=True)
@property
def network_manager(self):
return _network_manager()
@property
def volume_service(self):
volume_service = None
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
volume_service = relation_get('volume_service',
rid=rid, unit=unit)
return volume_service
@property
def region(self):
region = None
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
region = relation_get('region', rid=rid, unit=unit)
return region
@property
def vendor_data(self):
"""
Returns vendor metadata related parameters to be written in
nova.conf, received from nova-cloud-controller charm through relation
attribute vendor_data.
"""
vendor_data_json = {}
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
vendor_data_string = relation_get(
'vendor_data', rid=rid, unit=unit)
if vendor_data_string:
vendor_data_json = json.loads(vendor_data_string)
return vendor_data_json
def vendor_data_context(self):
vdata_ctxt = {}
vendor_data_json = self.vendor_data
if vendor_data_json:
# NOTE(ganso): avoid returning any extra keys to context
if vendor_data_json.get('vendor_data'):
vdata_ctxt['vendor_data'] = vendor_data_json['vendor_data']
if vendor_data_json.get('vendor_data_url'):
vdata_ctxt['vendor_data_url'] = vendor_data_json[
'vendor_data_url']
if vendor_data_json.get('vendordata_providers'):
vdata_ctxt['vendordata_providers'] = vendor_data_json[
'vendordata_providers']
return vdata_ctxt
def flat_dhcp_context(self):
ec2_host = None
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
ec2_host = relation_get('ec2_host', rid=rid, unit=unit)
if not ec2_host:
return {}
if config('multi-host').lower() == 'yes':
cmp_os_release = CompareOpenStackReleases(
os_release('nova-common'))
if cmp_os_release <= 'train':
# nova-network only available until ussuri
self._ensure_packages(['nova-api', 'nova-network'])
else:
self._ensure_packages(['nova-api'])
return {
'flat_interface': config('flat-interface'),
'ec2_dmz_host': ec2_host,
}
def neutron_context(self):
# generate config context for neutron or quantum. these get converted
# directly into flags in nova.conf
# NOTE: Its up to release templates to set correct driver
neutron_ctxt = {'neutron_url': None}
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
rel = {'rid': rid, 'unit': unit}
url = _neutron_url(**rel)
if not url:
# only bother with units that have a neutron url set.
continue
neutron_ctxt = {
'auth_protocol': relation_get(
'auth_protocol', **rel) or 'http',
'service_protocol': relation_get(
'service_protocol', **rel) or 'http',
'service_port': relation_get(
'service_port', **rel) or '5000',
'neutron_auth_strategy': 'keystone',
'keystone_host': relation_get(
'auth_host', **rel),
'auth_port': relation_get(
'auth_port', **rel),
'neutron_admin_tenant_name': relation_get(
'service_tenant_name', **rel),
'neutron_admin_username': relation_get(
'service_username', **rel),
'neutron_admin_password': relation_get(
'service_password', **rel),
'api_version': relation_get(
'api_version', **rel) or '2.0',
'neutron_plugin': _neutron_plugin(),
'neutron_url': url,
}
# DNS domain is optional
dns_domain = relation_get('dns_domain', **rel)
if dns_domain:
neutron_ctxt['dns_domain'] = dns_domain
admin_domain = relation_get('admin_domain_name', **rel)
if admin_domain:
neutron_ctxt['neutron_admin_domain_name'] = admin_domain
missing = [k for k, v in neutron_ctxt.items() if v in ['', None]]
if missing:
log('Missing required relation settings for Quantum: ' +
' '.join(missing))
return {}
neutron_ctxt['neutron_security_groups'] = _neutron_security_groups()
ks_url = '%s://%s:%s/v%s' % (neutron_ctxt['auth_protocol'],
neutron_ctxt['keystone_host'],
neutron_ctxt['auth_port'],
neutron_ctxt['api_version'])
neutron_ctxt['neutron_admin_auth_url'] = ks_url
return neutron_ctxt
def neutron_context_no_auth_data(self):
"""If the charm has a cloud-credentials relation then a subset
of data is needed to complete this context."""
neutron_ctxt = {'neutron_url': None}
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
rel = {'rid': rid, 'unit': unit}
url = _neutron_url(**rel)
if not url:
# only bother with units that have a neutron url set.
continue
neutron_ctxt = {
'neutron_auth_strategy': 'keystone',
'neutron_plugin': _neutron_plugin(),
'neutron_url': url,
}
return neutron_ctxt
def volume_context(self):
# provide basic validation that the volume manager is supported on the
# given openstack release (nova-volume is only supported for E and F)
# it is up to release templates to set the correct volume driver.
if not self.volume_service:
return {}
# ensure volume service is supported on specific openstack release.
if self.volume_service == 'cinder':
return 'cinder'
else:
e = ('Invalid volume service received via cloud-compute: %s' %
self.volume_service)
log(e, level=ERROR)
raise context.OSContextError(e)
def network_manager_context(self):
ctxt = {}
if self.network_manager == 'flatdhcpmanager':
ctxt = self.flat_dhcp_context()
elif self.network_manager == 'neutron':
ctxt = self.neutron_context()
# If charm has a cloud-credentials relation then auth data is not
# needed.
if relation_ids('cloud-credentials') and not ctxt:
ctxt = self.neutron_context_no_auth_data()
_save_flag_file(path='/etc/nova/nm.conf', data=self.network_manager)
log('Generated config context for %s network manager.' %
self.network_manager)
return ctxt
def restart_trigger(self):
rt = None
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
rt = relation_get('restart_trigger', rid=rid, unit=unit)
if rt:
return rt
def __call__(self):
rids = relation_ids('cloud-compute')
if not rids:
return {}
ctxt = {}
net_manager = self.network_manager_context()
if net_manager:
if net_manager.get('neutron_admin_password'):
ctxt['network_manager'] = self.network_manager
ctxt['network_manager_config'] = net_manager
# This is duplicating information in the context to enable
# common keystone fragment to be used in template
ctxt['service_protocol'] = net_manager.get('service_protocol')
ctxt['service_host'] = net_manager.get('keystone_host')
ctxt['service_port'] = net_manager.get('service_port')
ctxt['admin_tenant_name'] = net_manager.get(
'neutron_admin_tenant_name')
ctxt['admin_user'] = net_manager.get('neutron_admin_username')
ctxt['admin_password'] = net_manager.get(
'neutron_admin_password')
ctxt['auth_protocol'] = net_manager.get('auth_protocol')
ctxt['auth_host'] = net_manager.get('keystone_host')
ctxt['auth_port'] = net_manager.get('auth_port')
ctxt['api_version'] = net_manager.get('api_version')
if net_manager.get('dns_domain'):
ctxt['dns_domain'] = net_manager.get('dns_domain')
if net_manager.get('neutron_admin_domain_name'):
ctxt['admin_domain_name'] = net_manager.get(
'neutron_admin_domain_name')
else:
ctxt['network_manager'] = self.network_manager
ctxt['network_manager_config'] = net_manager
net_dev_mtu = config('network-device-mtu')
if net_dev_mtu:
ctxt['network_device_mtu'] = net_dev_mtu
vol_service = self.volume_context()
if vol_service:
ctxt['volume_service'] = vol_service
if self.restart_trigger():
ctxt['restart_trigger'] = self.restart_trigger()
region = self.region
if region:
ctxt['region'] = region
ctxt.update(self.vendor_data_context())
if self.context_complete(ctxt):
return ctxt
return {}
class InstanceConsoleContext(context.OSContextGenerator):
interfaces = []
def get_console_info(self, proto, **kwargs):
console_settings = {
proto + '_proxy_address':
relation_get('console_proxy_%s_address' % (proto), **kwargs),
proto + '_proxy_host':
relation_get('console_proxy_%s_host' % (proto), **kwargs),
proto + '_proxy_port':
relation_get('console_proxy_%s_port' % (proto), **kwargs),
}
return console_settings
def __call__(self):
ctxt = {}
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
rel = {'rid': rid, 'unit': unit}
proto = relation_get('console_access_protocol', **rel)
if not proto:
# only bother with units that have a proto set.
continue
ctxt['console_keymap'] = relation_get('console_keymap', **rel)
ctxt['console_access_protocol'] = proto
ctxt['spice_agent_enabled'] = relation_get(
'spice_agent_enabled', **rel)
ctxt['console_vnc_type'] = True if 'vnc' in proto else False
if proto == 'vnc':
ctxt = dict(ctxt, **self.get_console_info('xvpvnc', **rel))
ctxt = dict(ctxt, **self.get_console_info('novnc', **rel))
else:
ctxt = dict(ctxt, **self.get_console_info(proto, **rel))
break
ctxt['console_listen_addr'] = resolve_address(endpoint_type=INTERNAL)
return ctxt
class MetadataServiceContext(context.OSContextGenerator):
def __call__(self):
ctxt = {}
_, secret = nova_metadata_requirement()
if secret:
ctxt['metadata_shared_secret'] = secret
return ctxt
class NeutronComputeContext(context.OSContextGenerator):
interfaces = []
@property
def plugin(self):
return _neutron_plugin()
@property
def network_manager(self):
return _network_manager()
@property
def neutron_security_groups(self):
return _neutron_security_groups()
def __call__(self):
if self.plugin:
return {
'network_manager': self.network_manager,
'neutron_plugin': self.plugin,
'neutron_security_groups': self.neutron_security_groups
}
return {}
class HostIPContext(context.OSContextGenerator):
def __call__(self):
ctxt = {}
# Use the address used in the cloud-compute relation in templates for
# this host
host_ip = get_relation_ip('cloud-compute',
cidr_network=config('os-internal-network'))
if host_ip:
# NOTE: do not format this even for ipv6 (see bug 1499656)
ctxt['host_ip'] = host_ip
return ctxt
class NovaAPIAppArmorContext(context.AppArmorContext):
def __init__(self):
super(NovaAPIAppArmorContext, self).__init__()
self.aa_profile = NOVA_API_AA_PROFILE
def __call__(self):
super(NovaAPIAppArmorContext, self).__call__()
if not self.ctxt:
return self.ctxt
self._ctxt.update({'aa_profile': self.aa_profile})
return self.ctxt
class NovaComputeAppArmorContext(context.AppArmorContext):
def __init__(self):
super(NovaComputeAppArmorContext, self).__init__()
self.aa_profile = NOVA_COMPUTE_AA_PROFILE
def __call__(self):
super(NovaComputeAppArmorContext, self).__call__()
if not self.ctxt:
return self.ctxt
self._ctxt.update({'virt_type': config('virt-type')})
self._ctxt.update({'aa_profile': self.aa_profile})
return self.ctxt
class NovaNetworkAppArmorContext(context.AppArmorContext):
def __init__(self):
super(NovaNetworkAppArmorContext, self).__init__()
self.aa_profile = NOVA_NETWORK_AA_PROFILE
def __call__(self):
super(NovaNetworkAppArmorContext, self).__call__()
if not self.ctxt:
return self.ctxt
self._ctxt.update({'aa_profile': self.aa_profile})
return self.ctxt
class NovaComputeAvailabilityZoneContext(context.OSContextGenerator):
def __call__(self):
ctxt = {}
ctxt['default_availability_zone'] = _get_availability_zone()
return ctxt