[james-page,hazmat,ivoks,coreycb,yolanda.robla,r=james-page,t=*]
Support for Icehouse on 12.04 and 14.04 Support for Active/Active and SSL RabbitMQ Support for SSL MySQL Support for SSL endpoints Support for PostgreSQL Fixes for upgrades on 12.04 grizzly->havana->icehouse
This commit is contained in:
commit
f1ecf4d81d
3
Makefile
3
Makefile
|
@ -2,8 +2,7 @@
|
|||
PYTHON := /usr/bin/env python
|
||||
|
||||
lint:
|
||||
@flake8 --exclude hooks/charmhelpers hooks
|
||||
@flake8 --exclude hooks/charmhelpers unit_tests
|
||||
@flake8 --exclude hooks/charmhelpers hooks unit_tests
|
||||
@charm proof
|
||||
|
||||
test:
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
=====================
|
||||
nova-cloud-controller
|
||||
=====================
|
||||
|
||||
Cloud controller node for Openstack nova. Contains nova-schedule, nova-api, nova-network and nova-objectstore.
|
||||
|
||||
******************************************************
|
||||
Special considerations to be deployed using Postgresql
|
||||
******************************************************
|
||||
|
||||
juju deploy nova-cloud-controller
|
||||
juju deploy postgresql
|
||||
|
||||
juju add-relation "nova-cloud-controller:pgsql-nova-db" "postgresql:db"
|
||||
juju add-relation "nova-cloud-controller:pgsql-neutron-db" "postgresql:db"
|
|
@ -120,16 +120,20 @@ options:
|
|||
type: string
|
||||
description: |
|
||||
SSL certificate to install and use for API ports. Setting this value
|
||||
and ssl_key will enable reverse proxying, point Glance's entry in the
|
||||
and ssl_key will enable reverse proxying, point Nova's entry in the
|
||||
Keystone catalog to use https, and override any certficiate and key
|
||||
issued by Keystone (if it is configured to do so).
|
||||
ssl_key:
|
||||
type: string
|
||||
description: SSL key to use with certificate specified as ssl_cert.
|
||||
ssl_ca:
|
||||
type: string
|
||||
description: |
|
||||
SSL CA to use with the certificate and key provided - this is only
|
||||
required if you are providing a privately signed ssl_cert and ssl_key.
|
||||
use-syslog:
|
||||
type: boolean
|
||||
default: False
|
||||
description: |
|
||||
If set to True, supporting services will log to syslog.
|
||||
# Neutron NVP Plugin configuration
|
||||
nvp-controllers:
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -39,14 +39,15 @@ def get_cert():
|
|||
|
||||
|
||||
def get_ca_cert():
|
||||
ca_cert = None
|
||||
log("Inspecting identity-service relations for CA SSL certificate.",
|
||||
level=INFO)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
for unit in relation_list(r_id):
|
||||
if not ca_cert:
|
||||
ca_cert = relation_get('ca_cert',
|
||||
rid=r_id, unit=unit)
|
||||
ca_cert = config_get('ssl_ca')
|
||||
if ca_cert is None:
|
||||
log("Inspecting identity-service relations for CA SSL certificate.",
|
||||
level=INFO)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
for unit in relation_list(r_id):
|
||||
if ca_cert is None:
|
||||
ca_cert = relation_get('ca_cert',
|
||||
rid=r_id, unit=unit)
|
||||
return ca_cert
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
from base64 import b64decode
|
||||
|
||||
|
@ -113,7 +114,8 @@ class OSContextGenerator(object):
|
|||
class SharedDBContext(OSContextGenerator):
|
||||
interfaces = ['shared-db']
|
||||
|
||||
def __init__(self, database=None, user=None, relation_prefix=None):
|
||||
def __init__(self,
|
||||
database=None, user=None, relation_prefix=None, ssl_dir=None):
|
||||
'''
|
||||
Allows inspecting relation for settings prefixed with relation_prefix.
|
||||
This is useful for parsing access for multiple databases returned via
|
||||
|
@ -122,6 +124,7 @@ class SharedDBContext(OSContextGenerator):
|
|||
self.relation_prefix = relation_prefix
|
||||
self.database = database
|
||||
self.user = user
|
||||
self.ssl_dir = ssl_dir
|
||||
|
||||
def __call__(self):
|
||||
self.database = self.database or config('database')
|
||||
|
@ -139,19 +142,74 @@ class SharedDBContext(OSContextGenerator):
|
|||
|
||||
for rid in relation_ids('shared-db'):
|
||||
for unit in related_units(rid):
|
||||
passwd = relation_get(password_setting, rid=rid, unit=unit)
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
ctxt = {
|
||||
'database_host': relation_get('db_host', rid=rid,
|
||||
unit=unit),
|
||||
'database_host': rdata.get('db_host'),
|
||||
'database': self.database,
|
||||
'database_user': self.user,
|
||||
'database_password': passwd,
|
||||
'database_password': rdata.get(password_setting),
|
||||
'database_type': 'mysql'
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
db_ssl(rdata, ctxt, self.ssl_dir)
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
|
||||
class PostgresqlDBContext(OSContextGenerator):
|
||||
interfaces = ['pgsql-db']
|
||||
|
||||
def __init__(self, database=None):
|
||||
self.database = database
|
||||
|
||||
def __call__(self):
|
||||
self.database = self.database or config('database')
|
||||
if self.database is None:
|
||||
log('Could not generate postgresql_db context. '
|
||||
'Missing required charm config options. '
|
||||
'(database name)')
|
||||
raise OSContextError
|
||||
ctxt = {}
|
||||
|
||||
for rid in relation_ids(self.interfaces[0]):
|
||||
for unit in related_units(rid):
|
||||
ctxt = {
|
||||
'database_host': relation_get('host', rid=rid, unit=unit),
|
||||
'database': self.database,
|
||||
'database_user': relation_get('user', rid=rid, unit=unit),
|
||||
'database_password': relation_get('password', rid=rid, unit=unit),
|
||||
'database_type': 'postgresql',
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
|
||||
def db_ssl(rdata, ctxt, ssl_dir):
|
||||
if 'ssl_ca' in rdata and ssl_dir:
|
||||
ca_path = os.path.join(ssl_dir, 'db-client.ca')
|
||||
with open(ca_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_ca']))
|
||||
ctxt['database_ssl_ca'] = ca_path
|
||||
elif 'ssl_ca' in rdata:
|
||||
log("Charm not setup for ssl support but ssl ca found")
|
||||
return ctxt
|
||||
if 'ssl_cert' in rdata:
|
||||
cert_path = os.path.join(
|
||||
ssl_dir, 'db-client.cert')
|
||||
if not os.path.exists(cert_path):
|
||||
log("Waiting 1m for ssl client cert validity")
|
||||
time.sleep(60)
|
||||
with open(cert_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_cert']))
|
||||
ctxt['database_ssl_cert'] = cert_path
|
||||
key_path = os.path.join(ssl_dir, 'db-client.key')
|
||||
with open(key_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_key']))
|
||||
ctxt['database_ssl_key'] = key_path
|
||||
return ctxt
|
||||
|
||||
|
||||
class IdentityServiceContext(OSContextGenerator):
|
||||
interfaces = ['identity-service']
|
||||
|
||||
|
@ -161,24 +219,25 @@ class IdentityServiceContext(OSContextGenerator):
|
|||
|
||||
for rid in relation_ids('identity-service'):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
ctxt = {
|
||||
'service_port': relation_get('service_port', rid=rid,
|
||||
unit=unit),
|
||||
'service_host': relation_get('service_host', rid=rid,
|
||||
unit=unit),
|
||||
'auth_host': relation_get('auth_host', rid=rid, unit=unit),
|
||||
'auth_port': relation_get('auth_port', rid=rid, unit=unit),
|
||||
'admin_tenant_name': relation_get('service_tenant',
|
||||
rid=rid, unit=unit),
|
||||
'admin_user': relation_get('service_username', rid=rid,
|
||||
unit=unit),
|
||||
'admin_password': relation_get('service_password', rid=rid,
|
||||
unit=unit),
|
||||
# XXX: Hard-coded http.
|
||||
'service_protocol': 'http',
|
||||
'auth_protocol': 'http',
|
||||
'service_port': rdata.get('service_port'),
|
||||
'service_host': rdata.get('service_host'),
|
||||
'auth_host': rdata.get('auth_host'),
|
||||
'auth_port': rdata.get('auth_port'),
|
||||
'admin_tenant_name': rdata.get('service_tenant'),
|
||||
'admin_user': rdata.get('service_username'),
|
||||
'admin_password': rdata.get('service_password'),
|
||||
'service_protocol':
|
||||
rdata.get('service_protocol') or 'http',
|
||||
'auth_protocol':
|
||||
rdata.get('auth_protocol') or 'http',
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
# NOTE(jamespage) this is required for >= icehouse
|
||||
# so a missing value just indicates keystone needs
|
||||
# upgrading
|
||||
ctxt['admin_tenant_id'] = rdata.get('service_tenant_id')
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
|
@ -186,6 +245,9 @@ class IdentityServiceContext(OSContextGenerator):
|
|||
class AMQPContext(OSContextGenerator):
|
||||
interfaces = ['amqp']
|
||||
|
||||
def __init__(self, ssl_dir=None):
|
||||
self.ssl_dir = ssl_dir
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for amqp')
|
||||
conf = config()
|
||||
|
@ -196,7 +258,6 @@ class AMQPContext(OSContextGenerator):
|
|||
log('Could not generate shared_db context. '
|
||||
'Missing required charm config options: %s.' % e)
|
||||
raise OSContextError
|
||||
|
||||
ctxt = {}
|
||||
for rid in relation_ids('amqp'):
|
||||
ha_vip_only = False
|
||||
|
@ -214,6 +275,14 @@ class AMQPContext(OSContextGenerator):
|
|||
unit=unit),
|
||||
'rabbitmq_virtual_host': vhost,
|
||||
})
|
||||
|
||||
ssl_port = relation_get('ssl_port', rid=rid, unit=unit)
|
||||
if ssl_port:
|
||||
ctxt['rabbit_ssl_port'] = ssl_port
|
||||
ssl_ca = relation_get('ssl_ca', rid=rid, unit=unit)
|
||||
if ssl_ca:
|
||||
ctxt['rabbit_ssl_ca'] = ssl_ca
|
||||
|
||||
if relation_get('ha_queues', rid=rid, unit=unit) is not None:
|
||||
ctxt['rabbitmq_ha_queues'] = True
|
||||
|
||||
|
@ -221,6 +290,16 @@ class AMQPContext(OSContextGenerator):
|
|||
rid=rid, unit=unit) is not None
|
||||
|
||||
if context_complete(ctxt):
|
||||
if 'rabbit_ssl_ca' in ctxt:
|
||||
if not self.ssl_dir:
|
||||
log(("Charm not setup for ssl support "
|
||||
"but ssl ca found"))
|
||||
break
|
||||
ca_path = os.path.join(
|
||||
self.ssl_dir, 'rabbit-client-ca.pem')
|
||||
with open(ca_path, 'w') as fh:
|
||||
fh.write(b64decode(ctxt['rabbit_ssl_ca']))
|
||||
ctxt['rabbit_ssl_ca'] = ca_path
|
||||
# Sufficient information found = break out!
|
||||
break
|
||||
# Used for active/active rabbitmq >= grizzly
|
||||
|
@ -391,6 +470,8 @@ class ApacheSSLContext(OSContextGenerator):
|
|||
'private_address': unit_get('private-address'),
|
||||
'endpoints': []
|
||||
}
|
||||
if is_clustered():
|
||||
ctxt['private_address'] = config('vip')
|
||||
for api_port in self.external_ports:
|
||||
ext_port = determine_apache_port(api_port)
|
||||
int_port = determine_api_port(api_port)
|
||||
|
|
|
@ -17,6 +17,8 @@ def headers_package():
|
|||
kver = check_output(['uname', '-r']).strip()
|
||||
return 'linux-headers-%s' % kver
|
||||
|
||||
QUANTUM_CONF_DIR = '/etc/quantum'
|
||||
|
||||
|
||||
def kernel_version():
|
||||
""" Retrieve the current major kernel version as a tuple e.g. (3, 13) """
|
||||
|
@ -35,6 +37,8 @@ def determine_dkms_package():
|
|||
|
||||
|
||||
# legacy
|
||||
|
||||
|
||||
def quantum_plugins():
|
||||
from charmhelpers.contrib.openstack import context
|
||||
return {
|
||||
|
@ -46,7 +50,8 @@ def quantum_plugins():
|
|||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=QUANTUM_CONF_DIR)],
|
||||
'services': ['quantum-plugin-openvswitch-agent'],
|
||||
'packages': [[headers_package()] + determine_dkms_package(),
|
||||
['quantum-plugin-openvswitch-agent']],
|
||||
|
@ -61,7 +66,8 @@ def quantum_plugins():
|
|||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=QUANTUM_CONF_DIR)],
|
||||
'services': [],
|
||||
'packages': [],
|
||||
'server_packages': ['quantum-server',
|
||||
|
@ -70,6 +76,8 @@ def quantum_plugins():
|
|||
}
|
||||
}
|
||||
|
||||
NEUTRON_CONF_DIR = '/etc/neutron'
|
||||
|
||||
|
||||
def neutron_plugins():
|
||||
from charmhelpers.contrib.openstack import context
|
||||
|
@ -83,7 +91,8 @@ def neutron_plugins():
|
|||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=NEUTRON_CONF_DIR)],
|
||||
'services': ['neutron-plugin-openvswitch-agent'],
|
||||
'packages': [[headers_package()] + determine_dkms_package(),
|
||||
['neutron-plugin-openvswitch-agent']],
|
||||
|
@ -98,7 +107,8 @@ def neutron_plugins():
|
|||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=NEUTRON_CONF_DIR)],
|
||||
'services': [],
|
||||
'packages': [],
|
||||
'server_packages': ['neutron-server',
|
||||
|
|
|
@ -65,6 +65,7 @@ SWIFT_CODENAMES = OrderedDict([
|
|||
('1.10.0', 'havana'),
|
||||
('1.9.1', 'havana'),
|
||||
('1.9.0', 'havana'),
|
||||
('1.13.1', 'icehouse'),
|
||||
('1.13.0', 'icehouse'),
|
||||
('1.12.0', 'icehouse'),
|
||||
('1.11.0', 'icehouse'),
|
||||
|
|
|
@ -2,7 +2,9 @@ from os import stat
|
|||
from stat import S_ISBLK
|
||||
|
||||
from subprocess import (
|
||||
check_call
|
||||
check_call,
|
||||
check_output,
|
||||
call
|
||||
)
|
||||
|
||||
|
||||
|
@ -22,5 +24,12 @@ def zap_disk(block_device):
|
|||
|
||||
:param block_device: str: Full path of block device to clean.
|
||||
'''
|
||||
check_call(['sgdisk', '--zap-all', '--clear',
|
||||
'--mbrtogpt', block_device])
|
||||
# sometimes sgdisk exits non-zero; this is OK, dd will clean up
|
||||
call(['sgdisk', '--zap-all', '--mbrtogpt',
|
||||
'--clear', block_device])
|
||||
dev_end = check_output(['blockdev', '--getsz', block_device])
|
||||
gpt_end = int(dev_end.split()[0]) - 100
|
||||
check_call(['dd', 'if=/dev/zero', 'of=%s'%(block_device),
|
||||
'bs=1M', 'count=1'])
|
||||
check_call(['dd', 'if=/dev/zero', 'of=%s'%(block_device),
|
||||
'bs=512', 'count=100', 'seek=%s'%(gpt_end)])
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
|
||||
from charmhelpers.core.hookenv import (
|
||||
config, relation_ids, relation_set, log, ERROR)
|
||||
config, relation_ids, relation_set, log, ERROR,
|
||||
unit_get)
|
||||
|
||||
from charmhelpers.fetch import apt_install, filter_installed_packages
|
||||
from charmhelpers.contrib.openstack import context, neutron, utils
|
||||
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
determine_apache_port, determine_api_port)
|
||||
determine_apache_port,
|
||||
determine_api_port,
|
||||
https,
|
||||
is_clustered
|
||||
)
|
||||
|
||||
|
||||
class ApacheSSLContext(context.ApacheSSLContext):
|
||||
|
@ -112,6 +117,24 @@ class HAProxyContext(context.HAProxyContext):
|
|||
return ctxt
|
||||
|
||||
|
||||
def canonical_url(vip_setting='vip'):
|
||||
'''
|
||||
Returns the correct HTTP URL to this host given the state of HTTPS
|
||||
configuration and hacluster.
|
||||
|
||||
:vip_setting: str: Setting in charm config that specifies
|
||||
VIP address.
|
||||
'''
|
||||
scheme = 'http'
|
||||
if https():
|
||||
scheme = 'https'
|
||||
if is_clustered():
|
||||
addr = config(vip_setting)
|
||||
else:
|
||||
addr = unit_get('private-address')
|
||||
return '%s://%s' % (scheme, addr)
|
||||
|
||||
|
||||
class NeutronCCContext(context.NeutronContext):
|
||||
interfaces = []
|
||||
|
||||
|
@ -148,10 +171,12 @@ class NeutronCCContext(context.NeutronContext):
|
|||
','.join(_config['nvp-controllers'].split())
|
||||
ctxt['nvp_controllers_list'] = \
|
||||
_config['nvp-controllers'].split()
|
||||
ctxt['nova_url'] = "{}:8774/v2".format(canonical_url())
|
||||
return ctxt
|
||||
|
||||
|
||||
class IdentityServiceContext(context.IdentityServiceContext):
|
||||
|
||||
def __call__(self):
|
||||
ctxt = super(IdentityServiceContext, self).__call__()
|
||||
if not ctxt:
|
||||
|
@ -159,7 +184,23 @@ class IdentityServiceContext(context.IdentityServiceContext):
|
|||
|
||||
# the ec2 api needs to know the location of the keystone ec2
|
||||
# tokens endpoint, set in nova.conf
|
||||
ec2_tokens = 'http://%s:%s/v2.0/ec2tokens' % (ctxt['service_host'],
|
||||
ctxt['service_port'])
|
||||
ec2_tokens = '%s://%s:%s/v2.0/ec2tokens' % (
|
||||
ctxt['service_protocol'] or 'http',
|
||||
ctxt['service_host'],
|
||||
ctxt['service_port']
|
||||
)
|
||||
ctxt['keystone_ec2_url'] = ec2_tokens
|
||||
ctxt['region'] = config('region')
|
||||
return ctxt
|
||||
|
||||
|
||||
class NovaPostgresqlDBContext(context.PostgresqlDBContext):
|
||||
interfaces = ['pgsql-nova-db']
|
||||
|
||||
|
||||
class NeutronPostgresqlDBContext(context.PostgresqlDBContext):
|
||||
interfaces = ['pgsql-neutron-db']
|
||||
|
||||
def __init__(self):
|
||||
super(NeutronPostgresqlDBContext,
|
||||
self).__init__(config('neutron-database'))
|
||||
|
|
|
@ -13,7 +13,9 @@ from charmhelpers.core.hookenv import (
|
|||
UnregisteredHookError,
|
||||
config,
|
||||
charm_dir,
|
||||
is_relation_made,
|
||||
log,
|
||||
ERROR,
|
||||
relation_get,
|
||||
relation_ids,
|
||||
relation_set,
|
||||
|
@ -96,8 +98,9 @@ def install():
|
|||
@hooks.hook('config-changed')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
def config_changed():
|
||||
global CONFIGS
|
||||
if openstack_upgrade_available('nova-common'):
|
||||
do_openstack_upgrade(configs=CONFIGS)
|
||||
CONFIGS = do_openstack_upgrade()
|
||||
save_script_rc()
|
||||
configure_https()
|
||||
CONFIGS.write_all()
|
||||
|
@ -110,6 +113,7 @@ def amqp_joined(relation_id=None):
|
|||
|
||||
|
||||
@hooks.hook('amqp-relation-changed')
|
||||
@hooks.hook('amqp-relation-departed')
|
||||
@restart_on_change(restart_map())
|
||||
def amqp_changed():
|
||||
if 'amqp' not in CONFIGS.complete_contexts():
|
||||
|
@ -124,6 +128,14 @@ def amqp_changed():
|
|||
|
||||
@hooks.hook('shared-db-relation-joined')
|
||||
def db_joined():
|
||||
if is_relation_made('pgsql-nova-db') or \
|
||||
is_relation_made('pgsql-neutron-db'):
|
||||
# error, postgresql is used
|
||||
e = ('Attempting to associate a mysql database when there is already '
|
||||
'associated a postgresql one')
|
||||
log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
|
||||
relation_set(nova_database=config('database'),
|
||||
nova_username=config('database-user'),
|
||||
nova_hostname=unit_get('private-address'))
|
||||
|
@ -134,18 +146,37 @@ def db_joined():
|
|||
neutron_hostname=unit_get('private-address'))
|
||||
|
||||
|
||||
@hooks.hook('pgsql-nova-db-relation-joined')
|
||||
def pgsql_nova_db_joined():
|
||||
if is_relation_made('shared-db'):
|
||||
# raise error
|
||||
e = ('Attempting to associate a postgresql database'
|
||||
' when there is already associated a mysql one')
|
||||
log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
|
||||
relation_set(database=config('database'))
|
||||
|
||||
|
||||
@hooks.hook('pgsql-neutron-db-relation-joined')
|
||||
def pgsql_neutron_db_joined():
|
||||
if is_relation_made('shared-db'):
|
||||
# raise error
|
||||
e = ('Attempting to associate a postgresql database'
|
||||
' when there is already associated a mysql one')
|
||||
log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
|
||||
relation_set(database=config('neutron-database'))
|
||||
|
||||
|
||||
@hooks.hook('shared-db-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def db_changed():
|
||||
if 'shared-db' not in CONFIGS.complete_contexts():
|
||||
log('shared-db relation incomplete. Peer not ready?')
|
||||
return
|
||||
CONFIGS.write(NOVA_CONF)
|
||||
|
||||
if network_manager() in ['neutron', 'quantum']:
|
||||
plugin = neutron_plugin()
|
||||
# DB config might have been moved to main neutron.conf in H?
|
||||
CONFIGS.write(neutron_plugin_attribute(plugin, 'config'))
|
||||
CONFIGS.write_all()
|
||||
|
||||
if eligible_leader(CLUSTER_RES):
|
||||
migrate_database()
|
||||
|
@ -154,6 +185,30 @@ def db_changed():
|
|||
for rid in relation_ids('cloud-compute')]
|
||||
|
||||
|
||||
@hooks.hook('pgsql-nova-db-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def postgresql_nova_db_changed():
|
||||
if 'pgsql-nova-db' not in CONFIGS.complete_contexts():
|
||||
log('pgsql-nova-db relation incomplete. Peer not ready?')
|
||||
return
|
||||
CONFIGS.write_all()
|
||||
|
||||
if eligible_leader(CLUSTER_RES):
|
||||
migrate_database()
|
||||
log('Triggering remote cloud-compute restarts.')
|
||||
[compute_joined(rid=rid, remote_restart=True)
|
||||
for rid in relation_ids('cloud-compute')]
|
||||
|
||||
|
||||
@hooks.hook('pgsql-neutron-db-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def postgresql_neutron_db_changed():
|
||||
if network_manager() in ['neutron', 'quantum']:
|
||||
plugin = neutron_plugin()
|
||||
# DB config might have been moved to main neutron.conf in H?
|
||||
CONFIGS.write(neutron_plugin_attribute(plugin, 'config'))
|
||||
|
||||
|
||||
@hooks.hook('image-service-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def image_service_changed():
|
||||
|
@ -211,6 +266,8 @@ def _auth_config():
|
|||
cfg = {
|
||||
'auth_host': ks_auth_host,
|
||||
'auth_port': auth_token_config('auth_port'),
|
||||
'auth_protocol': auth_token_config('auth_protocol'),
|
||||
'service_protocol': auth_token_config('service_protocol'),
|
||||
'service_port': auth_token_config('service_port'),
|
||||
'service_username': auth_token_config('admin_user'),
|
||||
'service_password': auth_token_config('admin_password'),
|
||||
|
@ -226,7 +283,8 @@ def _auth_config():
|
|||
def save_novarc():
|
||||
auth = _auth_config()
|
||||
# XXX hard-coded http
|
||||
ks_url = 'http://%s:%s/v2.0' % (auth['auth_host'], auth['auth_port'])
|
||||
ks_url = '%s://%s:%s/v2.0' % (auth['auth_protocol'],
|
||||
auth['auth_host'], auth['auth_port'])
|
||||
with open('/etc/quantum/novarc', 'wb') as out:
|
||||
out.write('export OS_USERNAME=%s\n' % auth['service_username'])
|
||||
out.write('export OS_PASSWORD=%s\n' % auth['service_password'])
|
||||
|
@ -385,7 +443,9 @@ def ha_changed():
|
|||
'identity-service-relation-broken',
|
||||
'image-service-relation-broken',
|
||||
'nova-volume-service-relation-broken',
|
||||
'shared-db-relation-broken'
|
||||
'shared-db-relation-broken',
|
||||
'pgsql-nova-db-relation-broken',
|
||||
'pgsql-neutron-db-relation-broken',
|
||||
'quantum-network-service-relation-broken')
|
||||
def relation_broken():
|
||||
CONFIGS.write_all()
|
||||
|
@ -436,6 +496,8 @@ def nova_vmware_relation_changed():
|
|||
def upgrade_charm():
|
||||
for r_id in relation_ids('amqp'):
|
||||
amqp_joined(relation_id=r_id)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
identity_joined(rid=r_id)
|
||||
|
||||
|
||||
def main():
|
||||
|
|
|
@ -22,8 +22,9 @@ from charmhelpers.contrib.openstack.utils import (
|
|||
save_script_rc as _save_script_rc)
|
||||
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
apt_upgrade,
|
||||
apt_update,
|
||||
apt_install,
|
||||
)
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
|
@ -36,6 +37,10 @@ from charmhelpers.core.hookenv import (
|
|||
ERROR,
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
service_start
|
||||
)
|
||||
|
||||
|
||||
import nova_cc_context
|
||||
|
||||
|
@ -49,6 +54,7 @@ BASE_PACKAGES = [
|
|||
'haproxy',
|
||||
'python-keystoneclient',
|
||||
'python-mysqldb',
|
||||
'python-psycopg2',
|
||||
'uuid',
|
||||
]
|
||||
|
||||
|
@ -69,11 +75,15 @@ API_PORTS = {
|
|||
'quantum-server': 9696,
|
||||
}
|
||||
|
||||
NOVA_CONF = '/etc/nova/nova.conf'
|
||||
NOVA_API_PASTE = '/etc/nova/api-paste.ini'
|
||||
QUANTUM_CONF = '/etc/quantum/quantum.conf'
|
||||
QUANTUM_API_PASTE = '/etc/quantum/api-paste.ini'
|
||||
NEUTRON_CONF = '/etc/neutron/neutron.conf'
|
||||
NOVA_CONF_DIR = "/etc/nova"
|
||||
QUANTUM_CONF_DIR = "/etc/quantum"
|
||||
NEUTRON_CONF_DIR = "/etc/neutron"
|
||||
|
||||
NOVA_CONF = '%s/nova.conf' % NOVA_CONF_DIR
|
||||
NOVA_API_PASTE = '%s/api-paste.ini' % NOVA_CONF_DIR
|
||||
QUANTUM_CONF = '%s/quantum.conf' % QUANTUM_CONF_DIR
|
||||
QUANTUM_API_PASTE = '%s/api-paste.ini' % QUANTUM_CONF_DIR
|
||||
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'
|
||||
|
@ -83,8 +93,10 @@ QUANTUM_DEFAULT = '/etc/default/quantum-server'
|
|||
BASE_RESOURCE_MAP = OrderedDict([
|
||||
(NOVA_CONF, {
|
||||
'services': BASE_SERVICES,
|
||||
'contexts': [context.AMQPContext(),
|
||||
context.SharedDBContext(relation_prefix='nova'),
|
||||
'contexts': [context.AMQPContext(ssl_dir=NOVA_CONF_DIR),
|
||||
context.SharedDBContext(
|
||||
relation_prefix='nova', ssl_dir=NOVA_CONF_DIR),
|
||||
nova_cc_context.NovaPostgresqlDBContext(),
|
||||
context.ImageServiceContext(),
|
||||
context.OSConfigFlagContext(),
|
||||
context.SubordinateConfigContext(
|
||||
|
@ -104,11 +116,17 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||
}),
|
||||
(QUANTUM_CONF, {
|
||||
'services': ['quantum-server'],
|
||||
'contexts': [context.AMQPContext(),
|
||||
context.SyslogContext(),
|
||||
'contexts': [context.AMQPContext(ssl_dir=QUANTUM_CONF_DIR),
|
||||
context.SharedDBContext(
|
||||
user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=QUANTUM_CONF_DIR),
|
||||
nova_cc_context.NeutronPostgresqlDBContext(),
|
||||
nova_cc_context.HAProxyContext(),
|
||||
nova_cc_context.IdentityServiceContext(),
|
||||
nova_cc_context.NeutronCCContext()],
|
||||
nova_cc_context.NeutronCCContext()
|
||||
context.SyslogContext()],
|
||||
}),
|
||||
(QUANTUM_DEFAULT, {
|
||||
'services': ['quantum-server'],
|
||||
|
@ -120,11 +138,17 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||
}),
|
||||
(NEUTRON_CONF, {
|
||||
'services': ['neutron-server'],
|
||||
'contexts': [context.AMQPContext(),
|
||||
context.SyslogContext(),
|
||||
'contexts': [context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR),
|
||||
context.SharedDBContext(
|
||||
user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=NEUTRON_CONF_DIR),
|
||||
nova_cc_context.NeutronPostgresqlDBContext(),
|
||||
nova_cc_context.IdentityServiceContext(),
|
||||
nova_cc_context.NeutronCCContext(),
|
||||
nova_cc_context.HAProxyContext()],
|
||||
nova_cc_context.HAProxyContext()
|
||||
context.SyslogContext()],
|
||||
}),
|
||||
(NEUTRON_DEFAULT, {
|
||||
'services': ['neutron-server'],
|
||||
|
@ -195,6 +219,10 @@ def resource_map():
|
|||
resource_map[conf]['contexts'].append(
|
||||
nova_cc_context.NeutronCCContext())
|
||||
|
||||
# update for postgres
|
||||
resource_map[conf]['contexts'].append(
|
||||
nova_cc_context.NeutronPostgresqlDBContext())
|
||||
|
||||
# nova-conductor for releases >= G.
|
||||
if os_release('nova-common') not in ['essex', 'folsom']:
|
||||
resource_map['/etc/nova/nova.conf']['services'] += ['nova-conductor']
|
||||
|
@ -211,8 +239,8 @@ def resource_map():
|
|||
return resource_map
|
||||
|
||||
|
||||
def register_configs():
|
||||
release = os_release('nova-common')
|
||||
def register_configs(release=None):
|
||||
release = release or os_release('nova-common')
|
||||
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
||||
openstack_release=release)
|
||||
for cfg, rscs in resource_map().iteritems():
|
||||
|
@ -226,10 +254,18 @@ def restart_map():
|
|||
if v['services']])
|
||||
|
||||
|
||||
def services():
|
||||
''' Returns a list of services associate with this charm '''
|
||||
_services = []
|
||||
for v in restart_map().values():
|
||||
_services = _services + v
|
||||
return list(set(_services))
|
||||
|
||||
|
||||
def determine_ports():
|
||||
'''Assemble a list of API ports for services we are managing'''
|
||||
ports = []
|
||||
for cfg, services in restart_map().iteritems():
|
||||
for services in restart_map().values():
|
||||
for service in services:
|
||||
try:
|
||||
ports.append(API_PORTS[service])
|
||||
|
@ -245,7 +281,7 @@ def api_port(service):
|
|||
def determine_packages():
|
||||
# currently all packages match service names
|
||||
packages = [] + BASE_PACKAGES
|
||||
for k, v in resource_map().iteritems():
|
||||
for v in resource_map().values():
|
||||
packages.extend(v['services'])
|
||||
if network_manager() in ['neutron', 'quantum']:
|
||||
pkgs = neutron_plugin_attribute(neutron_plugin(), 'server_packages',
|
||||
|
@ -273,27 +309,162 @@ def save_script_rc():
|
|||
_save_script_rc(**env_vars)
|
||||
|
||||
|
||||
def do_openstack_upgrade(configs):
|
||||
new_src = config('openstack-origin')
|
||||
def get_step_upgrade_source(new_src):
|
||||
'''
|
||||
Determine if upgrade skips a release and, if so, return source
|
||||
of skipped release.
|
||||
'''
|
||||
sources = {
|
||||
# target_src: (cur_pocket, step_src)
|
||||
'cloud:precise-icehouse':
|
||||
('precise-updates/grizzly', 'cloud:precise-havana'),
|
||||
'cloud:precise-icehouse/proposed':
|
||||
('precise-proposed/grizzly', 'cloud:precise-havana/proposed')
|
||||
}
|
||||
|
||||
with open('/etc/apt/sources.list.d/cloud-archive.list', 'r') as f:
|
||||
line = f.readline()
|
||||
for target_src, (cur_pocket, step_src) in sources.items():
|
||||
if target_src != new_src:
|
||||
continue
|
||||
if cur_pocket in line:
|
||||
return step_src
|
||||
|
||||
return None
|
||||
|
||||
POLICY_RC_D = """#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
case $1 in
|
||||
neutron-server|quantum-server|nova-*)
|
||||
[ $2 = "start" ] && exit 101
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
"""
|
||||
|
||||
|
||||
def enable_policy_rcd():
|
||||
with open('/usr/sbin/policy-rc.d', 'w') as policy:
|
||||
policy.write(POLICY_RC_D)
|
||||
os.chmod('/usr/sbin/policy-rc.d', 0o755)
|
||||
|
||||
|
||||
def disable_policy_rcd():
|
||||
os.unlink('/usr/sbin/policy-rc.d')
|
||||
|
||||
|
||||
QUANTUM_DB_MANAGE = "/usr/bin/quantum-db-manage"
|
||||
NEUTRON_DB_MANAGE = "/usr/bin/neutron-db-manage"
|
||||
|
||||
|
||||
def reset_os_release():
|
||||
# Ugly hack to make os_release re-read versions
|
||||
import charmhelpers.contrib.openstack.utils as utils
|
||||
utils.os_rel = None
|
||||
|
||||
|
||||
def neutron_db_manage(actions):
|
||||
net_manager = network_manager()
|
||||
if net_manager in ['neutron', 'quantum']:
|
||||
plugin = neutron_plugin()
|
||||
conf = neutron_plugin_attribute(plugin, 'config', net_manager)
|
||||
if net_manager == 'quantum':
|
||||
cmd = QUANTUM_DB_MANAGE
|
||||
else:
|
||||
cmd = NEUTRON_DB_MANAGE
|
||||
subprocess.check_call([
|
||||
cmd, '--config-file=/etc/{mgr}/{mgr}.conf'.format(mgr=net_manager),
|
||||
'--config-file={}'.format(conf)] + actions
|
||||
)
|
||||
|
||||
|
||||
def get_db_connection():
|
||||
config = ConfigParser.RawConfigParser()
|
||||
config.read('/etc/neutron/neutron.conf')
|
||||
try:
|
||||
return config.get('database', 'connection')
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def ml2_migration():
|
||||
reset_os_release()
|
||||
net_manager = network_manager()
|
||||
if net_manager == 'neutron':
|
||||
plugin = neutron_plugin()
|
||||
if plugin == 'ovs':
|
||||
log('Migrating from openvswitch to ml2 plugin')
|
||||
cmd = [
|
||||
'python',
|
||||
'/usr/lib/python2.7/dist-packages/neutron'
|
||||
'/db/migration/migrate_to_ml2.py',
|
||||
'--tunnel-type', 'gre',
|
||||
'--release', 'icehouse',
|
||||
'openvswitch', get_db_connection()
|
||||
]
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def _do_openstack_upgrade(new_src):
|
||||
enable_policy_rcd()
|
||||
cur_os_rel = os_release('nova-common')
|
||||
new_os_rel = get_os_codename_install_source(new_src)
|
||||
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
|
||||
|
||||
configure_installation_source(new_src)
|
||||
apt_update()
|
||||
|
||||
dpkg_opts = [
|
||||
'--option', 'Dpkg::Options::=--force-confnew',
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
|
||||
apt_install(packages=determine_packages(), options=dpkg_opts, fatal=True)
|
||||
# NOTE(jamespage) pre-stamp neutron database before upgrade from grizzly
|
||||
if cur_os_rel == 'grizzly':
|
||||
neutron_db_manage(['stamp', 'grizzly'])
|
||||
|
||||
# set CONFIGS to load templates from new release and regenerate config
|
||||
configs.set_release(openstack_release=new_os_rel)
|
||||
configs.write_all()
|
||||
apt_update(fatal=True)
|
||||
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
|
||||
apt_install(determine_packages(), fatal=True)
|
||||
|
||||
if cur_os_rel == 'grizzly':
|
||||
# NOTE(jamespage) when upgrading from grizzly->havana, config
|
||||
# files need to be generated prior to performing the db upgrade
|
||||
reset_os_release()
|
||||
configs = register_configs(release=new_os_rel)
|
||||
configs.write_all()
|
||||
neutron_db_manage(['upgrade', 'head'])
|
||||
else:
|
||||
# NOTE(jamespage) upgrade with existing config files as the
|
||||
# havana->icehouse migration enables new service_plugins which
|
||||
# create issues with db upgrades
|
||||
neutron_db_manage(['upgrade', 'head'])
|
||||
reset_os_release()
|
||||
configs = register_configs(release=new_os_rel)
|
||||
configs.write_all()
|
||||
|
||||
if new_os_rel == 'icehouse':
|
||||
# NOTE(jamespage) default plugin switch to ml2@icehouse
|
||||
ml2_migration()
|
||||
|
||||
if eligible_leader(CLUSTER_RES):
|
||||
migrate_database()
|
||||
[service_start(s) for s in services()]
|
||||
|
||||
disable_policy_rcd()
|
||||
|
||||
return configs
|
||||
|
||||
|
||||
def do_openstack_upgrade():
|
||||
new_src = config('openstack-origin')
|
||||
step_src = get_step_upgrade_source(new_src)
|
||||
if step_src is not None:
|
||||
_do_openstack_upgrade(step_src)
|
||||
return _do_openstack_upgrade(new_src)
|
||||
|
||||
|
||||
def volume_service():
|
||||
|
@ -315,10 +486,10 @@ def migrate_database():
|
|||
|
||||
|
||||
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:
|
||||
|
@ -363,7 +534,10 @@ def authorized_keys(user=None):
|
|||
|
||||
def ssh_known_host_key(host, user=None):
|
||||
cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host]
|
||||
return subprocess.check_output(cmd).strip()
|
||||
try:
|
||||
return subprocess.check_output(cmd).strip()
|
||||
except subprocess.CalledProcessError:
|
||||
return None
|
||||
|
||||
|
||||
def remove_known_host(host, user=None):
|
||||
|
@ -459,10 +633,14 @@ def determine_endpoints(url):
|
|||
'''Generates a dictionary containing all relevant endpoints to be
|
||||
passed to keystone as relation settings.'''
|
||||
region = config('region')
|
||||
os_rel = os_release('nova-common')
|
||||
|
||||
# TODO: Configurable nova API version.
|
||||
nova_url = ('%s:%s/v1.1/$(tenant_id)s' %
|
||||
(url, api_port('nova-api-os-compute')))
|
||||
if os_rel >= 'grizzly':
|
||||
nova_url = ('%s:%s/v2/$(tenant_id)s' %
|
||||
(url, api_port('nova-api-os-compute')))
|
||||
else:
|
||||
nova_url = ('%s:%s/v1.1/$(tenant_id)s' %
|
||||
(url, api_port('nova-api-os-compute')))
|
||||
ec2_url = '%s:%s/services/Cloud' % (url, api_port('nova-api-ec2'))
|
||||
nova_volume_url = ('%s:%s/v1/$(tenant_id)s' %
|
||||
(url, api_port('nova-api-os-compute')))
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -0,0 +1 @@
|
|||
nova_cc_hooks.py
|
|
@ -12,6 +12,10 @@ provides:
|
|||
requires:
|
||||
shared-db:
|
||||
interface: mysql-shared
|
||||
pgsql-nova-db:
|
||||
interface: pgsql
|
||||
pgsql-neutron-db:
|
||||
interface: pgsql
|
||||
amqp:
|
||||
interface: rabbitmq
|
||||
image-service:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
[nosetests]
|
||||
verbosity=2
|
||||
with-coverage=1
|
||||
cover-erase=1
|
||||
cover-package=hooks
|
|
@ -17,7 +17,7 @@
|
|||
--use_syslog={{ use_syslog }}
|
||||
--ec2_private_dns_show_ip
|
||||
{% if database_host -%}
|
||||
--sql_connection=mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
--sql_connection={{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% endif -%}
|
||||
{% if rabbitmq_host -%}
|
||||
--rabbit_host={{ rabbitmq_host }}
|
||||
|
|
|
@ -25,11 +25,16 @@ compute_driver=libvirt.LibvirtDriver
|
|||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
||||
{% if database_host -%}
|
||||
sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% endif -%}
|
||||
{% include "parts/database" %}
|
||||
|
||||
{% if rabbitmq_host -%}
|
||||
{% if rabbit_ssl_port %}
|
||||
rabbit_use_ssl=True
|
||||
rabbit_port={{ rabbit_ssl_port }}
|
||||
{% if rabbit_ssl_ca %}
|
||||
kombu_ssl_ca_certs={{rabbit_ssl_ca}}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
rabbit_host = {{ rabbitmq_host }}
|
||||
rabbit_userid = {{ rabbitmq_user }}
|
||||
rabbit_password = {{ rabbitmq_password }}
|
||||
|
|
|
@ -11,7 +11,7 @@ local_ip = {{ local_ip }}
|
|||
|
||||
[DATABASE]
|
||||
{% if database_host -%}
|
||||
sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}?quantum?charset=utf8
|
||||
sql_connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %}
|
||||
reconnect_interval = 2
|
||||
{% else -%}
|
||||
connection = sqlite:////var/lib/quantum/quantum.sqlite
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
dhcpbridge_flagfile=/etc/nova/nova.conf
|
||||
dhcpbridge=/usr/bin/nova-dhcpbridge
|
||||
logdir=/var/log/nova
|
||||
state_path=/var/lib/nova
|
||||
lock_path=/var/lock/nova
|
||||
force_dhcp_release=True
|
||||
iscsi_helper=tgtadm
|
||||
libvirt_use_virtio_for_bridges=True
|
||||
connection_type=libvirt
|
||||
root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf
|
||||
verbose=True
|
||||
ec2_private_dns_show_ip=True
|
||||
api_paste_config=/etc/nova/api-paste.ini
|
||||
volumes_path=/var/lib/nova/volumes
|
||||
enabled_apis=ec2,osapi_compute,metadata
|
||||
auth_strategy=keystone
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
{% if glance_api_servers -%}
|
||||
glance_api_servers = {{ glance_api_servers }}
|
||||
{% endif -%}
|
||||
|
||||
{% if rbd_pool -%}
|
||||
rbd_pool = {{ rbd_pool }}
|
||||
rbd_user = {{ rbd_user }}
|
||||
rbd_secret_uuid = {{ rbd_secret_uuid }}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'ovs' -%}
|
||||
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
|
||||
libvirt_user_virtio_for_bridges = True
|
||||
{% if neutron_security_groups -%}
|
||||
security_group_api = {{ network_manager }}
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% endif -%}
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'nvp' -%}
|
||||
security_group_api = neutron
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager_config -%}
|
||||
{% for key, value in network_manager_config.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager and network_manager == 'quantum' -%}
|
||||
network_api_class = nova.network.quantumv2.api.API
|
||||
quantum_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
quantum_auth_strategy = keystone
|
||||
quantum_admin_tenant_name = {{ admin_tenant_name }}
|
||||
quantum_admin_username = {{ admin_user }}
|
||||
quantum_admin_password = {{ admin_password }}
|
||||
quantum_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% elif network_manager and network_manager == 'neutron' -%}
|
||||
network_api_class = nova.network.neutronv2.api.API
|
||||
neutron_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
neutron_auth_strategy = keystone
|
||||
neutron_admin_tenant_name = {{ admin_tenant_name }}
|
||||
neutron_admin_username = {{ admin_user }}
|
||||
neutron_admin_password = {{ admin_password }}
|
||||
neutron_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
network_manager = nova.network.manager.FlatDHCPManager
|
||||
{% endif -%}
|
||||
|
||||
{% if default_floating_pool -%}
|
||||
default_floating_pool = {{ default_floating_pool }}
|
||||
{% endif -%}
|
||||
|
||||
{% if volume_service -%}
|
||||
volume_api_class=nova.volume.cinder.API
|
||||
{% endif -%}
|
||||
|
||||
{% if user_config_flags -%}
|
||||
{% for key, value in user_config_flags.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if listen_ports -%}
|
||||
{% for key, value in listen_ports.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
|
@ -0,0 +1,45 @@
|
|||
# grizzly
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
state_path = /var/lib/quantum
|
||||
lock_path = $state_path/lock
|
||||
bind_host = 0.0.0.0
|
||||
{% if neutron_bind_port -%}
|
||||
bind_port = {{ neutron_bind_port }}
|
||||
{% else -%}
|
||||
bind_port = 9696
|
||||
{% endif -%}
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% endif -%}
|
||||
api_paste_config = /etc/quantum/api-paste.ini
|
||||
auth_strategy = keystone
|
||||
control_exchange = quantum
|
||||
notification_driver = quantum.openstack.common.notifier.rpc_notifier
|
||||
default_notification_level = INFO
|
||||
notification_topics = notifications
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
{% endif -%}
|
||||
|
||||
[QUOTAS]
|
||||
quota_driver = quantum.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
quota_items = network,subnet,port,security_group,security_group_rule
|
||||
{% endif -%}
|
||||
|
||||
[DEFAULT_SERVICETYPE]
|
||||
|
||||
[AGENT]
|
||||
root_helper = sudo quantum-rootwrap /etc/quantum/rootwrap.conf
|
||||
|
||||
[keystone_authtoken]
|
||||
# auth_token middleware currently set in /etc/quantum/api-paste.ini
|
|
@ -16,17 +16,16 @@ bind_port = 9696
|
|||
{% endif -%}
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
service_plugins = neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
{% if rabbitmq_host -%}
|
||||
rabbit_host = {{ rabbitmq_host }}
|
||||
rabbit_userid = {{ rabbitmq_user }}
|
||||
rabbit_password = {{ rabbitmq_password }}
|
||||
rabbit_virtual_host = {{ rabbitmq_virtual_host }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
|
@ -51,5 +50,7 @@ admin_user = {{ admin_user }}
|
|||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/section-database" %}
|
||||
|
||||
[lbaas]
|
||||
[service_providers]
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
dhcpbridge_flagfile=/etc/nova/nova.conf
|
||||
dhcpbridge=/usr/bin/nova-dhcpbridge
|
||||
logdir=/var/log/nova
|
||||
state_path=/var/lib/nova
|
||||
lock_path=/var/lock/nova
|
||||
force_dhcp_release=True
|
||||
iscsi_helper=tgtadm
|
||||
libvirt_use_virtio_for_bridges=True
|
||||
connection_type=libvirt
|
||||
root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf
|
||||
verbose=True
|
||||
ec2_private_dns_show_ip=True
|
||||
api_paste_config=/etc/nova/api-paste.ini
|
||||
volumes_path=/var/lib/nova/volumes
|
||||
enabled_apis=ec2,osapi_compute,metadata
|
||||
auth_strategy=keystone
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
{% if glance_api_servers -%}
|
||||
glance_api_servers = {{ glance_api_servers }}
|
||||
{% endif -%}
|
||||
|
||||
{% if rbd_pool -%}
|
||||
rbd_pool = {{ rbd_pool }}
|
||||
rbd_user = {{ rbd_user }}
|
||||
rbd_secret_uuid = {{ rbd_secret_uuid }}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'ovs' -%}
|
||||
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
|
||||
libvirt_user_virtio_for_bridges = True
|
||||
{% if neutron_security_groups -%}
|
||||
security_group_api = {{ network_manager }}
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% endif -%}
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'nvp' -%}
|
||||
security_group_api = neutron
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager_config -%}
|
||||
{% for key, value in network_manager_config.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager and network_manager == 'quantum' -%}
|
||||
network_api_class = nova.network.quantumv2.api.API
|
||||
quantum_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
quantum_auth_strategy = keystone
|
||||
quantum_admin_tenant_name = {{ admin_tenant_name }}
|
||||
quantum_admin_username = {{ admin_user }}
|
||||
quantum_admin_password = {{ admin_password }}
|
||||
quantum_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% elif network_manager and network_manager == 'neutron' -%}
|
||||
network_api_class = nova.network.neutronv2.api.API
|
||||
neutron_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
neutron_auth_strategy = keystone
|
||||
neutron_admin_tenant_name = {{ admin_tenant_name }}
|
||||
neutron_admin_username = {{ admin_user }}
|
||||
neutron_admin_password = {{ admin_password }}
|
||||
neutron_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
network_manager = nova.network.manager.FlatDHCPManager
|
||||
{% endif -%}
|
||||
|
||||
{% if default_floating_pool -%}
|
||||
default_floating_pool = {{ default_floating_pool }}
|
||||
{% endif -%}
|
||||
|
||||
{% if volume_service -%}
|
||||
volume_api_class=nova.volume.cinder.API
|
||||
{% endif -%}
|
||||
|
||||
{% if user_config_flags -%}
|
||||
{% for key, value in user_config_flags.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if listen_ports -%}
|
||||
{% for key, value in listen_ports.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
[osapi_v3]
|
||||
enabled=True
|
||||
|
|
@ -9,10 +9,3 @@ nvp_password = {{ nvp_password }}
|
|||
nvp_controllers = {{ nvp_controllers }}
|
||||
default_tz_uuid = {{ nvp_tz_uuid }}
|
||||
default_l3_gw_service_uuid = {{ nvp_l3_uuid }}
|
||||
|
||||
[database]
|
||||
{% if database_host -%}
|
||||
connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% else -%}
|
||||
connection = sqlite:////var/lib/neutron/neutron.sqlite
|
||||
{% endif -%}
|
||||
|
|
|
@ -4,13 +4,6 @@ tenant_network_type = gre
|
|||
enable_tunneling = True
|
||||
local_ip = {{ local_ip }}
|
||||
|
||||
[database]
|
||||
{% if database_host -%}
|
||||
connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% else -%}
|
||||
connection = sqlite:////var/lib/neutron/neutron.sqlite
|
||||
{% endif -%}
|
||||
|
||||
[securitygroup]
|
||||
{% if neutron_security_groups -%}
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
############
|
||||
# Metadata #
|
||||
############
|
||||
[composite:metadata]
|
||||
use = egg:Paste#urlmap
|
||||
/: meta
|
||||
|
||||
[pipeline:meta]
|
||||
pipeline = ec2faultwrap logrequest metaapp
|
||||
|
||||
[app:metaapp]
|
||||
paste.app_factory = nova.api.metadata.handler:MetadataRequestHandler.factory
|
||||
|
||||
#######
|
||||
# EC2 #
|
||||
#######
|
||||
|
||||
[composite:ec2]
|
||||
use = egg:Paste#urlmap
|
||||
/services/Cloud: ec2cloud
|
||||
|
||||
[composite:ec2cloud]
|
||||
use = call:nova.api.auth:pipeline_factory
|
||||
noauth = ec2faultwrap logrequest ec2noauth cloudrequest validator ec2executor
|
||||
keystone = ec2faultwrap logrequest ec2keystoneauth cloudrequest validator ec2executor
|
||||
|
||||
[filter:ec2faultwrap]
|
||||
paste.filter_factory = nova.api.ec2:FaultWrapper.factory
|
||||
|
||||
[filter:logrequest]
|
||||
paste.filter_factory = nova.api.ec2:RequestLogging.factory
|
||||
|
||||
[filter:ec2lockout]
|
||||
paste.filter_factory = nova.api.ec2:Lockout.factory
|
||||
|
||||
[filter:ec2keystoneauth]
|
||||
paste.filter_factory = nova.api.ec2:EC2KeystoneAuth.factory
|
||||
|
||||
[filter:ec2noauth]
|
||||
paste.filter_factory = nova.api.ec2:NoAuth.factory
|
||||
|
||||
[filter:cloudrequest]
|
||||
controller = nova.api.ec2.cloud.CloudController
|
||||
paste.filter_factory = nova.api.ec2:Requestify.factory
|
||||
|
||||
[filter:authorizer]
|
||||
paste.filter_factory = nova.api.ec2:Authorizer.factory
|
||||
|
||||
[filter:validator]
|
||||
paste.filter_factory = nova.api.ec2:Validator.factory
|
||||
|
||||
[app:ec2executor]
|
||||
paste.app_factory = nova.api.ec2:Executor.factory
|
||||
|
||||
#############
|
||||
# OpenStack #
|
||||
#############
|
||||
|
||||
[composite:osapi_compute]
|
||||
use = call:nova.api.openstack.urlmap:urlmap_factory
|
||||
/: oscomputeversions
|
||||
/v1.1: openstack_compute_api_v2
|
||||
/v2: openstack_compute_api_v2
|
||||
/v3: openstack_compute_api_v3
|
||||
|
||||
[composite:openstack_compute_api_v2]
|
||||
use = call:nova.api.auth:pipeline_factory
|
||||
noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2
|
||||
keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2
|
||||
keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v2
|
||||
|
||||
[composite:openstack_compute_api_v3]
|
||||
use = call:nova.api.auth:pipeline_factory_v3
|
||||
noauth = faultwrap sizelimit noauth_v3 osapi_compute_app_v3
|
||||
keystone = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v3
|
||||
|
||||
[filter:faultwrap]
|
||||
paste.filter_factory = nova.api.openstack:FaultWrapper.factory
|
||||
|
||||
[filter:noauth]
|
||||
paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory
|
||||
|
||||
[filter:noauth_v3]
|
||||
paste.filter_factory = nova.api.openstack.auth:NoAuthMiddlewareV3.factory
|
||||
|
||||
[filter:ratelimit]
|
||||
paste.filter_factory = nova.api.openstack.compute.limits:RateLimitingMiddleware.factory
|
||||
|
||||
[filter:sizelimit]
|
||||
paste.filter_factory = nova.api.sizelimit:RequestBodySizeLimiter.factory
|
||||
|
||||
[app:osapi_compute_app_v2]
|
||||
paste.app_factory = nova.api.openstack.compute:APIRouter.factory
|
||||
|
||||
[app:osapi_compute_app_v3]
|
||||
paste.app_factory = nova.api.openstack.compute:APIRouterV3.factory
|
||||
|
||||
[pipeline:oscomputeversions]
|
||||
pipeline = faultwrap oscomputeversionapp
|
||||
|
||||
[app:oscomputeversionapp]
|
||||
paste.app_factory = nova.api.openstack.compute.versions:Versions.factory
|
||||
|
||||
##########
|
||||
# Shared #
|
||||
##########
|
||||
|
||||
[filter:keystonecontext]
|
||||
paste.filter_factory = nova.api.auth:NovaKeystoneContext.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
|
||||
{% if service_host -%}
|
||||
# NOTE(jamespage) - not used - but required for relation to nova-compute
|
||||
service_protocol = {{ service_protocol }}
|
||||
service_host = {{ service_host }}
|
||||
service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
|
@ -0,0 +1,30 @@
|
|||
# icehouse
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[ml2]
|
||||
type_drivers = gre,vxlan
|
||||
tenant_network_types = gre,vxlan
|
||||
mechanism_drivers = openvswitch
|
||||
|
||||
[ml2_type_gre]
|
||||
tunnel_id_ranges = 1:1000
|
||||
|
||||
[ml2_type_vxlan]
|
||||
vni_ranges = 1001:2000
|
||||
|
||||
[ovs]
|
||||
enable_tunneling = True
|
||||
local_ip = {{ local_ip }}
|
||||
|
||||
[agent]
|
||||
tunnel_types = gre
|
||||
|
||||
[securitygroup]
|
||||
{% if neutron_security_groups -%}
|
||||
enable_security_group = True
|
||||
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% else -%}
|
||||
enable_security_group = False
|
||||
{% endif -%}
|
|
@ -0,0 +1,71 @@
|
|||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
state_path = /var/lib/neutron
|
||||
lock_path = $state_path/lock
|
||||
bind_host = 0.0.0.0
|
||||
auth_strategy = keystone
|
||||
notification_driver = neutron.openstack.common.notifier.rpc_notifier
|
||||
|
||||
{% if neutron_bind_port -%}
|
||||
bind_port = {{ neutron_bind_port }}
|
||||
{% else -%}
|
||||
bind_port = 9696
|
||||
{% endif -%}
|
||||
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
notify_nova_on_port_status_changes = True
|
||||
notify_nova_on_port_data_changes = True
|
||||
nova_url = {{ nova_url }}
|
||||
nova_region_name = {{ region }}
|
||||
{% if auth_host -%}
|
||||
nova_admin_username = {{ admin_user }}
|
||||
nova_admin_tenant_id = {{ admin_tenant_id }}
|
||||
nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
quota_items = network,subnet,port,security_group,security_group_rule
|
||||
{% endif -%}
|
||||
|
||||
[agent]
|
||||
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
|
||||
|
||||
[keystone_authtoken]
|
||||
signing_dir = $state_path/keystone-signing
|
||||
{% if service_host -%}
|
||||
service_protocol = {{ service_protocol }}
|
||||
service_host = {{ service_host }}
|
||||
service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/section-database" %}
|
||||
|
||||
[service_providers]
|
||||
service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
|
||||
service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
|
||||
service_provider=FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
|
|
@ -0,0 +1,130 @@
|
|||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
dhcpbridge_flagfile=/etc/nova/nova.conf
|
||||
dhcpbridge=/usr/bin/nova-dhcpbridge
|
||||
logdir=/var/log/nova
|
||||
state_path=/var/lib/nova
|
||||
lock_path=/var/lock/nova
|
||||
force_dhcp_release=True
|
||||
iscsi_helper=tgtadm
|
||||
libvirt_use_virtio_for_bridges=True
|
||||
connection_type=libvirt
|
||||
root_helper=sudo nova-rootwrap /etc/nova/rootwrap.conf
|
||||
verbose=True
|
||||
ec2_private_dns_show_ip=True
|
||||
api_paste_config=/etc/nova/api-paste.ini
|
||||
volumes_path=/var/lib/nova/volumes
|
||||
enabled_apis=ec2,osapi_compute,metadata
|
||||
auth_strategy=keystone
|
||||
compute_driver=libvirt.LibvirtDriver
|
||||
{% if keystone_ec2_url -%}
|
||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
{% if glance_api_servers -%}
|
||||
glance_api_servers = {{ glance_api_servers }}
|
||||
{% endif -%}
|
||||
|
||||
{% if rbd_pool -%}
|
||||
rbd_pool = {{ rbd_pool }}
|
||||
rbd_user = {{ rbd_user }}
|
||||
rbd_secret_uuid = {{ rbd_secret_uuid }}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'ovs' -%}
|
||||
libvirt_vif_driver = nova.virt.libvirt.vif.LibvirtGenericVIFDriver
|
||||
libvirt_user_virtio_for_bridges = True
|
||||
{% if neutron_security_groups -%}
|
||||
security_group_api = {{ network_manager }}
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% endif -%}
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_plugin and neutron_plugin == 'nvp' -%}
|
||||
security_group_api = neutron
|
||||
nova_firewall_driver = nova.virt.firewall.NoopFirewallDriver
|
||||
{% if external_network -%}
|
||||
default_floating_pool = {{ external_network }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager_config -%}
|
||||
{% for key, value in network_manager_config.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if network_manager and network_manager == 'quantum' -%}
|
||||
network_api_class = nova.network.quantumv2.api.API
|
||||
quantum_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
quantum_auth_strategy = keystone
|
||||
quantum_admin_tenant_name = {{ admin_tenant_name }}
|
||||
quantum_admin_username = {{ admin_user }}
|
||||
quantum_admin_password = {{ admin_password }}
|
||||
quantum_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% elif network_manager and network_manager == 'neutron' -%}
|
||||
network_api_class = nova.network.neutronv2.api.API
|
||||
neutron_url = {{ neutron_url }}
|
||||
{% if auth_host -%}
|
||||
neutron_auth_strategy = keystone
|
||||
neutron_admin_tenant_name = {{ admin_tenant_name }}
|
||||
neutron_admin_username = {{ admin_user }}
|
||||
neutron_admin_password = {{ admin_password }}
|
||||
neutron_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
network_manager = nova.network.manager.FlatDHCPManager
|
||||
{% endif -%}
|
||||
|
||||
{% if default_floating_pool -%}
|
||||
default_floating_pool = {{ default_floating_pool }}
|
||||
{% endif -%}
|
||||
|
||||
{% if volume_service -%}
|
||||
volume_api_class=nova.volume.cinder.API
|
||||
{% endif -%}
|
||||
|
||||
{% if user_config_flags -%}
|
||||
{% for key, value in user_config_flags.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if listen_ports -%}
|
||||
{% for key, value in listen_ports.iteritems() -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if sections and 'DEFAULT' in sections -%}
|
||||
{% for key, value in sections['DEFAULT'] -%}
|
||||
{{ key }} = {{ value }}
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if auth_host -%}
|
||||
[keystone_authtoken]
|
||||
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
||||
|
||||
[osapi_v3]
|
||||
enabled=True
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
{% if database_host -%}
|
||||
sql_connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %}
|
||||
{% endif -%}
|
|
@ -0,0 +1,21 @@
|
|||
{% if rabbitmq_host or rabbitmq_hosts -%}
|
||||
rabbit_userid = {{ rabbitmq_user }}
|
||||
rabbit_virtual_host = {{ rabbitmq_virtual_host }}
|
||||
rabbit_password = {{ rabbitmq_password }}
|
||||
{% if rabbitmq_hosts -%}
|
||||
rabbit_hosts = {{ rabbitmq_hosts }}
|
||||
{% if rabbitmq_ha_queues -%}
|
||||
rabbit_ha_queues = True
|
||||
rabbit_durable_queues = False
|
||||
{% endif -%}
|
||||
{% else -%}
|
||||
rabbit_host = {{ rabbitmq_host }}
|
||||
{% endif -%}
|
||||
{% if rabbit_ssl_port -%}
|
||||
rabbit_use_ssl = True
|
||||
rabbit_port = {{ rabbit_ssl_port }}
|
||||
{% if rabbit_ssl_ca -%}
|
||||
kombu_ssl_ca_certs = {{ rabbit_ssl_ca }}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
{% endif -%}
|
|
@ -0,0 +1,4 @@
|
|||
{% if database_host -%}
|
||||
[database]
|
||||
connection = {{ database_type }}://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}{% if database_ssl_ca %}?ssl_ca={{ database_ssl_ca }}{% if database_ssl_cert %}&ssl_cert={{ database_ssl_cert }}&ssl_key={{ database_ssl_key }}{% endif %}{% endif %}
|
||||
{% endif -%}
|
|
@ -1,8 +1,9 @@
|
|||
from mock import MagicMock, patch
|
||||
|
||||
from mock import call, MagicMock, patch
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
import nova_cc_utils as utils
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
config.return_value = 'neutron'
|
||||
import nova_cc_utils as utils
|
||||
|
||||
_reg = utils.register_configs
|
||||
_map = utils.restart_map
|
||||
|
@ -15,7 +16,6 @@ import nova_cc_hooks as hooks
|
|||
utils.register_configs = _reg
|
||||
utils.restart_map = _map
|
||||
|
||||
|
||||
TO_PATCH = [
|
||||
'api_port',
|
||||
'apt_update',
|
||||
|
@ -29,8 +29,11 @@ TO_PATCH = [
|
|||
'determine_packages',
|
||||
'determine_ports',
|
||||
'open_port',
|
||||
'is_relation_made',
|
||||
'log',
|
||||
'relation_get',
|
||||
'relation_set',
|
||||
'relation_ids',
|
||||
'ssh_compute_add',
|
||||
'ssh_known_hosts_b64',
|
||||
'ssh_authorized_keys_b64',
|
||||
|
@ -42,6 +45,7 @@ TO_PATCH = [
|
|||
'eligible_leader',
|
||||
'keystone_ca_cert_b64',
|
||||
'neutron_plugin',
|
||||
'migrate_database',
|
||||
]
|
||||
|
||||
|
||||
|
@ -63,6 +67,7 @@ class NovaCCHooksTests(CharmTestCase):
|
|||
|
||||
def setUp(self):
|
||||
super(NovaCCHooksTests, self).setUp(hooks, TO_PATCH)
|
||||
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
self.charm_dir.return_value = '/var/lib/juju/charms/nova/charm'
|
||||
|
@ -138,3 +143,91 @@ class NovaCCHooksTests(CharmTestCase):
|
|||
quantum_url='http://nova-cc-host1:9696', quantum_plugin='nvp',
|
||||
relation_id=None,
|
||||
**FAKE_KS_AUTH_CFG)
|
||||
|
||||
def test_db_joined(self):
|
||||
self.unit_get.return_value = 'nova.foohost.com'
|
||||
self.is_relation_made.return_value = False
|
||||
hooks.db_joined()
|
||||
self.relation_set.assert_called_with(nova_database='nova',
|
||||
nova_username='nova',
|
||||
nova_hostname='nova.foohost.com')
|
||||
self.unit_get.assert_called_with('private-address')
|
||||
|
||||
def test_postgresql_nova_db_joined(self):
|
||||
self.is_relation_made.return_value = False
|
||||
hooks.pgsql_nova_db_joined()
|
||||
self.relation_set.assert_called_with(database='nova')
|
||||
|
||||
def test_postgresql_neutron_db_joined(self):
|
||||
self.is_relation_made.return_value = False
|
||||
hooks.pgsql_neutron_db_joined()
|
||||
self.relation_set.assert_called_with(database='neutron')
|
||||
|
||||
def test_db_joined_with_postgresql(self):
|
||||
self.is_relation_made.return_value = True
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
hooks.db_joined()
|
||||
self.assertEqual(context.exception.message,
|
||||
'Attempting to associate a mysql database when'
|
||||
' there is already associated a postgresql one')
|
||||
|
||||
def test_postgresql_nova_joined_with_db(self):
|
||||
self.is_relation_made.return_value = True
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
hooks.pgsql_nova_db_joined()
|
||||
self.assertEqual(context.exception.message,
|
||||
'Attempting to associate a postgresql database when'
|
||||
' there is already associated a mysql one')
|
||||
|
||||
def test_postgresql_neutron_joined_with_db(self):
|
||||
self.is_relation_made.return_value = True
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
hooks.pgsql_neutron_db_joined()
|
||||
self.assertEqual(context.exception.message,
|
||||
'Attempting to associate a postgresql database when'
|
||||
' there is already associated a mysql one')
|
||||
|
||||
@patch.object(hooks, 'CONFIGS')
|
||||
def test_db_changed_missing_relation_data(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = []
|
||||
hooks.db_changed()
|
||||
self.log.assert_called_with(
|
||||
'shared-db relation incomplete. Peer not ready?'
|
||||
)
|
||||
|
||||
@patch.object(hooks, 'CONFIGS')
|
||||
def test_postgresql_nova_db_changed_missing_relation_data(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = []
|
||||
hooks.postgresql_nova_db_changed()
|
||||
self.log.assert_called_with(
|
||||
'pgsql-nova-db relation incomplete. Peer not ready?'
|
||||
)
|
||||
|
||||
def _shared_db_test(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = ['shared-db']
|
||||
configs.write = MagicMock()
|
||||
hooks.db_changed()
|
||||
|
||||
def _postgresql_db_test(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = ['pgsql-nova-db']
|
||||
configs.write = MagicMock()
|
||||
hooks.postgresql_nova_db_changed()
|
||||
|
||||
@patch.object(hooks, 'CONFIGS')
|
||||
def test_db_changed(self, configs):
|
||||
self._shared_db_test(configs)
|
||||
self.assertTrue(configs.write_all.called)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(hooks, 'CONFIGS')
|
||||
def test_postgresql_db_changed(self, configs):
|
||||
self._postgresql_db_test(configs)
|
||||
self.assertTrue(configs.write_all.called)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
|
|
@ -13,15 +13,28 @@ import nova_cc_utils as utils
|
|||
hookenv.config = _conf
|
||||
|
||||
TO_PATCH = [
|
||||
'apt_update',
|
||||
'apt_upgrade',
|
||||
'apt_install',
|
||||
'config',
|
||||
'configure_installation_source',
|
||||
'disable_policy_rcd',
|
||||
'eligible_leader',
|
||||
'enable_policy_rcd',
|
||||
'get_os_codename_install_source',
|
||||
'log',
|
||||
'ml2_migration',
|
||||
'network_manager',
|
||||
'neutron_db_manage',
|
||||
'neutron_plugin',
|
||||
'neutron_plugin_attribute',
|
||||
'os_release',
|
||||
'register_configs',
|
||||
'relation_ids',
|
||||
'remote_unit',
|
||||
'_save_script_rc',
|
||||
'service_start',
|
||||
'services'
|
||||
]
|
||||
|
||||
SCRIPTRC_ENV_VARS = {
|
||||
|
@ -103,6 +116,12 @@ PLUGIN_ATTRIBUTES = {
|
|||
}
|
||||
|
||||
|
||||
DPKG_OPTS = [
|
||||
'--option', 'Dpkg::Options::=--force-confnew',
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
|
||||
|
||||
def fake_plugin_attribute(plugin, attr, net_manager):
|
||||
if plugin in PLUGIN_ATTRIBUTES:
|
||||
try:
|
||||
|
@ -345,7 +364,9 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||
ssh_dir.return_value = '/tmp/foo'
|
||||
self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')
|
||||
ssh_dir.assert_called_with(None)
|
||||
self.assertEquals(utils.authorized_keys('bar'), '/tmp/foo/authorized_keys')
|
||||
self.assertEquals(
|
||||
utils.authorized_keys('bar'),
|
||||
'/tmp/foo/authorized_keys')
|
||||
ssh_dir.assert_called_with('bar')
|
||||
|
||||
@patch.object(utils, 'known_hosts')
|
||||
|
@ -374,7 +395,8 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||
@patch.object(utils, 'known_hosts')
|
||||
@patch.object(utils, 'authorized_keys')
|
||||
@patch('os.path.isfile')
|
||||
def test_ssh_compute_remove(self, isfile, auth_key, known_host):
|
||||
def test_ssh_compute_remove(self, isfile,
|
||||
auth_key, known_host):
|
||||
isfile.return_value = False
|
||||
|
||||
removed_key = AUTHORIZED_KEYS.split('\n')[2]
|
||||
|
@ -454,3 +476,82 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||
_known_hosts.assert_called_with(None)
|
||||
utils.remove_known_host('test', 'bar')
|
||||
_known_hosts.assert_called_with('bar')
|
||||
|
||||
@patch('subprocess.check_output')
|
||||
def test_migrate_database(self, check_output):
|
||||
"Migrate database with nova-manage"
|
||||
utils.migrate_database()
|
||||
check_output.assert_called_with(['nova-manage', 'db', 'sync'])
|
||||
|
||||
@patch.object(utils, 'get_step_upgrade_source')
|
||||
@patch.object(utils, 'migrate_database')
|
||||
@patch.object(utils, 'determine_packages')
|
||||
def test_upgrade_grizzly_icehouse(self, determine_packages,
|
||||
migrate_database,
|
||||
get_step_upgrade_source):
|
||||
"Simulate a call to do_openstack_upgrade() for grizzly->icehouse"
|
||||
get_step_upgrade_source.return_value = 'cloud:precise-havana'
|
||||
self.os_release.side_effect = ['grizzly', 'havana']
|
||||
self.get_os_codename_install_source.side_effect = [
|
||||
'havana',
|
||||
'icehouse']
|
||||
self.eligible_leader.return_value = True
|
||||
utils.do_openstack_upgrade()
|
||||
expected = [call(['stamp', 'grizzly']), call(['upgrade', 'head']),
|
||||
call(['upgrade', 'head'])]
|
||||
self.assertEquals(self.neutron_db_manage.call_args_list, expected)
|
||||
self.apt_update.assert_called_with(fatal=True)
|
||||
self.apt_upgrade.assert_called_with(options=DPKG_OPTS, fatal=True,
|
||||
dist=True)
|
||||
self.apt_install.assert_called_with(determine_packages(), fatal=True)
|
||||
expected = [call(release='havana'), call(release='icehouse')]
|
||||
self.assertEquals(self.register_configs.call_args_list, expected)
|
||||
self.assertEquals(self.ml2_migration.call_count, 1)
|
||||
self.assertTrue(migrate_database.call_count, 2)
|
||||
|
||||
@patch.object(utils, 'get_step_upgrade_source')
|
||||
@patch.object(utils, 'migrate_database')
|
||||
@patch.object(utils, 'determine_packages')
|
||||
def test_upgrade_havana_icehouse(self, determine_packages,
|
||||
migrate_database,
|
||||
get_step_upgrade_source):
|
||||
"Simulate a call to do_openstack_upgrade() for havana->icehouse"
|
||||
get_step_upgrade_source.return_value = None
|
||||
self.os_release.return_value = 'havana'
|
||||
self.get_os_codename_install_source.return_value = 'icehouse'
|
||||
self.eligible_leader.return_value = True
|
||||
utils.do_openstack_upgrade()
|
||||
self.neutron_db_manage.assert_called_with(['upgrade', 'head'])
|
||||
self.apt_update.assert_called_with(fatal=True)
|
||||
self.apt_upgrade.assert_called_with(options=DPKG_OPTS, fatal=True,
|
||||
dist=True)
|
||||
self.apt_install.assert_called_with(determine_packages(), fatal=True)
|
||||
self.register_configs.assert_called_with(release='icehouse')
|
||||
self.assertEquals(self.ml2_migration.call_count, 1)
|
||||
self.assertTrue(migrate_database.call_count, 1)
|
||||
|
||||
@patch.object(utils, '_do_openstack_upgrade')
|
||||
def test_upgrade_grizzly_icehouse_source(self, _do_openstack_upgrade):
|
||||
"Verify get_step_upgrade_source() for grizzly->icehouse"
|
||||
self.config.side_effect = None
|
||||
self.config.return_value = 'cloud:precise-icehouse'
|
||||
with patch_open() as (_open, _file):
|
||||
_file.read = MagicMock()
|
||||
_file.readline.return_value = ("deb url"
|
||||
" precise-updates/grizzly main")
|
||||
utils.do_openstack_upgrade()
|
||||
expected = [call('cloud:precise-havana'),
|
||||
call('cloud:precise-icehouse')]
|
||||
self.assertEquals(_do_openstack_upgrade.call_args_list, expected)
|
||||
|
||||
@patch.object(utils, '_do_openstack_upgrade')
|
||||
def test_upgrade_havana_icehouse_source(self, _do_openstack_upgrade):
|
||||
"Verify get_step_upgrade_source() for havana->icehouse"
|
||||
self.config.side_effect = None
|
||||
self.config.return_value = 'cloud:precise-icehouse'
|
||||
with patch_open() as (_open, _file):
|
||||
_file.read = MagicMock()
|
||||
_file.readline.return_value = "deb url precise-updates/havana main"
|
||||
utils.do_openstack_upgrade()
|
||||
expected = [call('cloud:precise-icehouse')]
|
||||
self.assertEquals(_do_openstack_upgrade.call_args_list, expected)
|
||||
|
|
Loading…
Reference in New Issue