213 lines
5.8 KiB
Python
Raw Normal View History

2013-08-01 20:42:16 -07:00
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