charm-neutron-api/hooks/neutron_api_utils.py

228 lines
6.9 KiB
Python

from collections import OrderedDict
from copy import deepcopy
import os
from base64 import b64encode
from charmhelpers.contrib.openstack import context, templating
from charmhelpers.contrib.openstack.neutron import (
neutron_plugin_attribute,
)
from charmhelpers.contrib.openstack.utils import (
os_release,
get_os_codename_install_source,
configure_installation_source,
)
from charmhelpers.core.hookenv import (
config,
log,
)
from charmhelpers.fetch import (
apt_update,
apt_install,
apt_upgrade,
add_source
)
from charmhelpers.core.host import (
lsb_release
)
import neutron_api_context
TEMPLATES = 'templates/'
CLUSTER_RES = 'grp_neutron_vips'
# removed from original: charm-helper-sh
BASE_PACKAGES = [
'apache2',
'haproxy',
'python-keystoneclient',
'python-mysqldb',
'python-psycopg2',
'uuid',
]
BASE_SERVICES = [
'neutron-server'
]
API_PORTS = {
'neutron-server': 9696,
}
NEUTRON_CONF_DIR = "/etc/neutron"
NEUTRON_CONF = '%s/neutron.conf' % NEUTRON_CONF_DIR
HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf'
NEUTRON_DEFAULT = '/etc/default/neutron-server'
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
BASE_RESOURCE_MAP = OrderedDict([
(NEUTRON_CONF, {
'services': ['neutron-server'],
'contexts': [context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR),
context.SharedDBContext(
user=config('database-user'),
database=config('database'),
ssl_dir=NEUTRON_CONF_DIR),
context.PostgresqlDBContext(database=config('database')),
neutron_api_context.IdentityServiceContext(),
neutron_api_context.NeutronCCContext(),
context.SyslogContext(),
context.BindHostContext(),
context.WorkerConfigContext()],
}),
(NEUTRON_DEFAULT, {
'services': ['neutron-server'],
'contexts': [neutron_api_context.NeutronCCContext()],
}),
(APACHE_CONF, {
'contexts': [neutron_api_context.ApacheSSLContext()],
'services': ['apache2'],
}),
(APACHE_24_CONF, {
'contexts': [neutron_api_context.ApacheSSLContext()],
'services': ['apache2'],
}),
(HAPROXY_CONF, {
'contexts': [context.HAProxyContext(),
neutron_api_context.HAProxyContext()],
'services': ['haproxy'],
}),
])
def api_port(service):
return API_PORTS[service]
def determine_packages():
# currently all packages match service names
packages = [] + BASE_PACKAGES
for v in resource_map().values():
packages.extend(v['services'])
pkgs = neutron_plugin_attribute(config('neutron-plugin'),
'server_packages',
'neutron')
packages.extend(pkgs)
return list(set(packages))
def determine_ports():
'''Assemble a list of API ports for services we are managing'''
ports = []
for services in restart_map().values():
for service in services:
try:
ports.append(API_PORTS[service])
except KeyError:
pass
return list(set(ports))
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 os.path.exists('/etc/apache2/conf-available'):
resource_map.pop(APACHE_CONF)
else:
resource_map.pop(APACHE_24_CONF)
# add neutron plugin requirements. nova-c-c only needs the neutron-server
# associated with configs, not the plugin agent.
plugin = config('neutron-plugin')
conf = neutron_plugin_attribute(plugin, 'config', 'neutron')
ctxts = (neutron_plugin_attribute(plugin, 'contexts', 'neutron')
or [])
services = neutron_plugin_attribute(plugin, 'server_services',
'neutron')
resource_map[conf] = {}
resource_map[conf]['services'] = services
resource_map[conf]['contexts'] = ctxts
resource_map[conf]['contexts'].append(
neutron_api_context.NeutronCCContext())
# update for postgres
resource_map[conf]['contexts'].append(
context.PostgresqlDBContext(database=config('database')))
return resource_map
def register_configs(release=None):
release = release or os_release('neutron-server')
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 OrderedDict([(cfg, v['services'])
for cfg, v in resource_map().iteritems()
if v['services']])
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 do_openstack_upgrade(configs):
"""
Perform an upgrade. Takes care of upgrading packages, rewriting
configs, database migrations and potentially any other post-upgrade
actions.
:param configs: The charms main OSConfigRenderer object.
"""
new_src = config('openstack-origin')
new_os_rel = get_os_codename_install_source(new_src)
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
configure_installation_source(new_src)
dpkg_opts = [
'--option', 'Dpkg::Options::=--force-confnew',
'--option', 'Dpkg::Options::=--force-confdef',
]
apt_update(fatal=True)
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
pkgs = determine_packages()
# Sort packages just to make unit tests easier
pkgs.sort()
apt_install(packages=pkgs,
options=dpkg_opts,
fatal=True)
# set CONFIGS to load templates from new release
configs.set_release(openstack_release=new_os_rel)
def setup_ipv6():
ubuntu_rel = lsb_release()['DISTRIB_CODENAME'].lower()
if ubuntu_rel < "trusty":
raise Exception("IPv6 is not supported in the charms for Ubuntu "
"versions less than Trusty 14.04")
# NOTE(xianghui): Need to install haproxy(1.5.3) from trusty-backports
# to support ipv6 address, so check is required to make sure not
# breaking other versions, IPv6 only support for >= Trusty
if ubuntu_rel == 'trusty':
add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports'
' main')
apt_update()
apt_install('haproxy/trusty-backports', fatal=True)