charm-nova-cloud-controller/hooks/nova_cc_utils.py

213 lines
5.8 KiB
Python

import os
import subprocess
import ConfigParser
from base64 import b64encode
from collections import OrderedDict
from copy import deepcopy
from charmhelpers.contrib.openstack import templating, context
from charmhelpers.contrib.openstack.utils import (
get_os_codename_package,
save_script_rc as _save_script_rc,
)
from charmhelpers.core.hookenv import (
config,
relation_ids,
)
import nova_cc_context
TEMPLATES = 'templates/'
CLUSTER_RES = 'res_nova_vip'
# removed from original: python-mysqldb python-keystone charm-helper-sh
BASE_PACKAGES = [
'apache2',
'haproxy',
'uuid',
]
BASE_SERVICES = [
'nova-api-ec2',
'nova-api-os-compute',
'nova-objectstore',
'nova-cert',
'nova-scheduler',
]
API_PORTS = {
'nova-api-ec2': 8773,
'nova-api-os-compute': 8774,
'nova-api-os-volume': 8776,
'nova-objectstore': 3333,
'quantum-server': 9696,
}
BASE_RESOURCE_MAP = OrderedDict([
('/etc/nova/nova.conf', {
'services': BASE_SERVICES,
'contexts': [context.AMQPContext(),
context.SharedDBContext(),
context.ImageServiceContext(),
nova_cc_context.VolumeServiceContext()],
}),
('/etc/nova/api-paste.ini', {
'services': [s for s in BASE_SERVICES if 'api' in s],
'contexts': [context.IdentityServiceContext()],
}),
('/etc/quantum/quantum.conf', {
'services': ['quantum-server'],
'contexts': [],
}),
('/etc/quantum/api-paste.ini', {
'services': ['quantum-server'],
'contexts': [],
}),
('/etc/haproxy/haproxy.cfg', {
'contexts': [context.HAProxyContext(),
nova_cc_context.HAProxyContext()],
'services': ['haproxy'],
}),
('/etc/apache2/sites-available/openstack_https_frontend', {
'contexts': [],
'contexts': [nova_cc_context.ApacheSSLContext()],
'services': ['apache2'],
}),
])
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
def resource_map():
'''
Dynamically generate a map of resources that will be managed for a single
hook execution.
'''
resource_map = deepcopy(BASE_RESOURCE_MAP)
if relation_ids('nova-volume-service'):
# if we have a relation to a nova-volume service, we're
# also managing the nova-volume API endpoint (legacy)
resource_map['/etc/nova/nova.conf']['services'].append(
'nova-api-os-volume')
if config('network-manager').lower() != 'quantum':
# pop out quantum resources if not deploying it. easier to
# remove it from the base ordered dict than add it in later
# and still preserve ordering for restart_map().
[resource_map.pop(k) for k in list(resource_map.iterkeys())
if 'quantum' in k]
return resource_map
def register_configs():
release = get_os_codename_package('nova-common', fatal=False) or 'essex'
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
openstack_release=release)
for cfg, rscs in resource_map.iteritems():
configs.register(cfg, rscs['contexts'])
return configs
def restart_map():
return {k: v['services'] for k, v in resource_map().iteritems()}
def determine_ports():
'''Assemble a list of API ports for services we are managing'''
ports = []
for cfg, services in restart_map().iteritems():
for service in services:
try:
ports.append(API_PORTS[service])
except KeyError:
pass
return ports
def determine_packages():
# currently all packages match service names
packages = [] + BASE_PACKAGES
for k, v in resource_map().iteritems():
packages.extend(v['services'])
return list(set(packages))
def save_script_rc():
env_vars = {
'OPENSTACK_PORT_MCASTPORT': config('ha-mcastport'),
'OPENSTACK_SERVICE_API_EC2': 'nova-api-ec2',
'OPENSTACK_SERVICE_API_OS_COMPUTE': 'nova-api-os-compute',
'OPENSTACK_SERVICE_CERT': 'nova-cert',
'OPENSTACK_SERVICE_CONDUCTOR': 'nova-conductor',
'OPENSTACK_SERVICE_OBJECTSTORE': 'nova-objectstore',
'OPENSTACK_SERVICE_SCHEDULER': 'nova-scheduler',
}
if relation_ids('nova-volume-service'):
env_vars['OPENSTACK_SERVICE_API_OS_VOL'] = 'nova-api-os-volume'
if config('network-manager').lower() == 'quantum':
env_vars['OPENSTACK_SERVICE_API_QUANTUM'] = 'quantum-server'
_save_script_rc(**env_vars)
def do_openstack_upgrade():
# TODO
pass
def quantum_plugin():
return config('quantum-plugin').lower()
def volume_service():
'''Specifies correct volume API for specific OS release'''
os_vers = get_os_codename_package('nova-common')
if os_vers == 'essex':
return 'nova-volume'
elif os_vers == 'folsom': # support both drivers in folsom.
if not relation_ids('cinder-volume-service'):
return 'nova-volume'
return 'cinder'
def migrate_database():
'''Runs nova-manage to initialize a new database or migrate existing'''
cmd = ['nova-manage', 'db', 'sync']
subprocess.check_call(cmd)
def auth_token_config(setting):
'''
Returns currently configured value for setting in api-paste.ini's
authtoken section, or None.
'''
config = ConfigParser.RawConfigParser()
config.read('/etc/nova/api-paste.ini')
try:
value = config.get('filter:authtoken', setting)
except:
return None
if value.startswith('%'):
return None
return value
def keystone_ca_cert_b64():
'''Returns the local Keystone-provided CA cert if it exists, or None.'''
if not os.path.isfile(CA_CERT_PATH):
return None
with open(CA_CERT_PATH) as _in:
return b64encode(_in.read())
def ssh_compute_add():
pass
def determine_endpoints():
pass