213 lines
5.8 KiB
Python
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
|