charm-nova-compute-proxy/hooks/nova_compute_context.py

227 lines
7.3 KiB
Python

from charmhelpers.contrib.openstack import context
from charmhelpers.core.hookenv import (
config,
log,
relation_get,
relation_ids,
related_units,
ERROR,
)
# compatability functions to help with quantum -> neutron transition
def _network_manager():
from nova_compute_utils import network_manager as manager
return manager()
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))
class NovaComputeVirtContext(context.OSContextGenerator):
interfaces = []
def __call__(self):
ctxt = {}
if config('instances-path') is not None:
ctxt['instances_path'] = config('instances-path')
return {}
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 determining
correct network and volume service configuration on the compute node,
as advertised by the cloud-controller.
Note: individual neutroj plugin contexts are handled elsewhere.
'''
interfaces = ['cloud-compute']
@property
def network_manager(self):
return _network_manager()
@property
def volume_service(self):
for rid in relation_ids('cloud-compute'):
for unit in related_units(rid):
volume_service = relation_get('volume_service',
rid=rid, unit=unit)
if volume_service:
return volume_service
return None
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
def _legacy_quantum(ctxt):
# rename neutron flags to support legacy quantum.
renamed = {}
for k, v in ctxt.iteritems():
k = k.replace('neutron', 'quantum')
renamed[k] = v
return renamed
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',
'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),
'neutron_plugin': _neutron_plugin(),
'neutron_url': url,
}
missing = [k for k, v in neutron_ctxt.iteritems() 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/v2.0' % (neutron_ctxt['auth_protocol'],
neutron_ctxt['keystone_host'],
neutron_ctxt['auth_port'])
neutron_ctxt['neutron_admin_auth_url'] = ks_url
if self.network_manager == 'quantum':
return _legacy_quantum(neutron_ctxt)
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 in ['neutron', 'quantum']:
ctxt = self.neutron_context()
log('Generated config context for %s network manager.' %
self.network_manager)
return ctxt
def restart_trigger(self):
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
return None
def __call__(self):
rids = relation_ids('cloud-compute')
if not rids:
return {}
ctxt = {}
net_manager = self.network_manager_context()
if net_manager:
ctxt['network_manager'] = self.network_manager
ctxt['network_manager_config'] = net_manager
vol_service = self.volume_context()
if vol_service:
ctxt['volume_service'] = vol_service
if self.restart_trigger():
ctxt['restart_trigger'] = self.restart_trigger()
return ctxt
class NeutronPowerComputeContext(context.NeutronContext):
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 _ensure_packages(self):
# NOTE(jamespage) no-op for nova-compute-power
pass
def ovs_ctxt(self):
ovs_ctxt = {
'core_plugin': 'neutron.plugins.ml2.plugin.Ml2Plugin',
'neutron_plugin': 'ovs',
'neutron_security_groups': self.neutron_security_groups,
'config': '/etc/neutron/plugins/ml2/ml2_conf.ini'
}
return ovs_ctxt