[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
|
PYTHON := /usr/bin/env python
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
@flake8 --exclude hooks/charmhelpers hooks
|
@flake8 --exclude hooks/charmhelpers hooks unit_tests
|
||||||
@flake8 --exclude hooks/charmhelpers unit_tests
|
|
||||||
@charm proof
|
@charm proof
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
15
README.txt
Normal file
15
README.txt
Normal file
@ -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
|
type: string
|
||||||
description: |
|
description: |
|
||||||
SSL certificate to install and use for API ports. Setting this value
|
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
|
Keystone catalog to use https, and override any certficiate and key
|
||||||
issued by Keystone (if it is configured to do so).
|
issued by Keystone (if it is configured to do so).
|
||||||
ssl_key:
|
ssl_key:
|
||||||
type: string
|
type: string
|
||||||
description: SSL key to use with certificate specified as ssl_cert.
|
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:
|
use-syslog:
|
||||||
type: boolean
|
type: boolean
|
||||||
default: False
|
default: False
|
||||||
description: |
|
|
||||||
If set to True, supporting services will log to syslog.
|
If set to True, supporting services will log to syslog.
|
||||||
# Neutron NVP Plugin configuration
|
# Neutron NVP Plugin configuration
|
||||||
nvp-controllers:
|
nvp-controllers:
|
||||||
|
1
hooks/amqp-relation-departed
Symbolic link
1
hooks/amqp-relation-departed
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
@ -39,14 +39,15 @@ def get_cert():
|
|||||||
|
|
||||||
|
|
||||||
def get_ca_cert():
|
def get_ca_cert():
|
||||||
ca_cert = None
|
ca_cert = config_get('ssl_ca')
|
||||||
log("Inspecting identity-service relations for CA SSL certificate.",
|
if ca_cert is None:
|
||||||
level=INFO)
|
log("Inspecting identity-service relations for CA SSL certificate.",
|
||||||
for r_id in relation_ids('identity-service'):
|
level=INFO)
|
||||||
for unit in relation_list(r_id):
|
for r_id in relation_ids('identity-service'):
|
||||||
if not ca_cert:
|
for unit in relation_list(r_id):
|
||||||
ca_cert = relation_get('ca_cert',
|
if ca_cert is None:
|
||||||
rid=r_id, unit=unit)
|
ca_cert = relation_get('ca_cert',
|
||||||
|
rid=r_id, unit=unit)
|
||||||
return ca_cert
|
return ca_cert
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
|
||||||
@ -113,7 +114,8 @@ class OSContextGenerator(object):
|
|||||||
class SharedDBContext(OSContextGenerator):
|
class SharedDBContext(OSContextGenerator):
|
||||||
interfaces = ['shared-db']
|
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.
|
Allows inspecting relation for settings prefixed with relation_prefix.
|
||||||
This is useful for parsing access for multiple databases returned via
|
This is useful for parsing access for multiple databases returned via
|
||||||
@ -122,6 +124,7 @@ class SharedDBContext(OSContextGenerator):
|
|||||||
self.relation_prefix = relation_prefix
|
self.relation_prefix = relation_prefix
|
||||||
self.database = database
|
self.database = database
|
||||||
self.user = user
|
self.user = user
|
||||||
|
self.ssl_dir = ssl_dir
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
self.database = self.database or config('database')
|
self.database = self.database or config('database')
|
||||||
@ -139,19 +142,74 @@ class SharedDBContext(OSContextGenerator):
|
|||||||
|
|
||||||
for rid in relation_ids('shared-db'):
|
for rid in relation_ids('shared-db'):
|
||||||
for unit in related_units(rid):
|
for unit in related_units(rid):
|
||||||
passwd = relation_get(password_setting, rid=rid, unit=unit)
|
rdata = relation_get(rid=rid, unit=unit)
|
||||||
ctxt = {
|
ctxt = {
|
||||||
'database_host': relation_get('db_host', rid=rid,
|
'database_host': rdata.get('db_host'),
|
||||||
unit=unit),
|
|
||||||
'database': self.database,
|
'database': self.database,
|
||||||
'database_user': self.user,
|
'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):
|
if context_complete(ctxt):
|
||||||
return ctxt
|
return ctxt
|
||||||
return {}
|
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):
|
class IdentityServiceContext(OSContextGenerator):
|
||||||
interfaces = ['identity-service']
|
interfaces = ['identity-service']
|
||||||
|
|
||||||
@ -161,24 +219,25 @@ class IdentityServiceContext(OSContextGenerator):
|
|||||||
|
|
||||||
for rid in relation_ids('identity-service'):
|
for rid in relation_ids('identity-service'):
|
||||||
for unit in related_units(rid):
|
for unit in related_units(rid):
|
||||||
|
rdata = relation_get(rid=rid, unit=unit)
|
||||||
ctxt = {
|
ctxt = {
|
||||||
'service_port': relation_get('service_port', rid=rid,
|
'service_port': rdata.get('service_port'),
|
||||||
unit=unit),
|
'service_host': rdata.get('service_host'),
|
||||||
'service_host': relation_get('service_host', rid=rid,
|
'auth_host': rdata.get('auth_host'),
|
||||||
unit=unit),
|
'auth_port': rdata.get('auth_port'),
|
||||||
'auth_host': relation_get('auth_host', rid=rid, unit=unit),
|
'admin_tenant_name': rdata.get('service_tenant'),
|
||||||
'auth_port': relation_get('auth_port', rid=rid, unit=unit),
|
'admin_user': rdata.get('service_username'),
|
||||||
'admin_tenant_name': relation_get('service_tenant',
|
'admin_password': rdata.get('service_password'),
|
||||||
rid=rid, unit=unit),
|
'service_protocol':
|
||||||
'admin_user': relation_get('service_username', rid=rid,
|
rdata.get('service_protocol') or 'http',
|
||||||
unit=unit),
|
'auth_protocol':
|
||||||
'admin_password': relation_get('service_password', rid=rid,
|
rdata.get('auth_protocol') or 'http',
|
||||||
unit=unit),
|
|
||||||
# XXX: Hard-coded http.
|
|
||||||
'service_protocol': 'http',
|
|
||||||
'auth_protocol': 'http',
|
|
||||||
}
|
}
|
||||||
if context_complete(ctxt):
|
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 ctxt
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@ -186,6 +245,9 @@ class IdentityServiceContext(OSContextGenerator):
|
|||||||
class AMQPContext(OSContextGenerator):
|
class AMQPContext(OSContextGenerator):
|
||||||
interfaces = ['amqp']
|
interfaces = ['amqp']
|
||||||
|
|
||||||
|
def __init__(self, ssl_dir=None):
|
||||||
|
self.ssl_dir = ssl_dir
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
log('Generating template context for amqp')
|
log('Generating template context for amqp')
|
||||||
conf = config()
|
conf = config()
|
||||||
@ -196,7 +258,6 @@ class AMQPContext(OSContextGenerator):
|
|||||||
log('Could not generate shared_db context. '
|
log('Could not generate shared_db context. '
|
||||||
'Missing required charm config options: %s.' % e)
|
'Missing required charm config options: %s.' % e)
|
||||||
raise OSContextError
|
raise OSContextError
|
||||||
|
|
||||||
ctxt = {}
|
ctxt = {}
|
||||||
for rid in relation_ids('amqp'):
|
for rid in relation_ids('amqp'):
|
||||||
ha_vip_only = False
|
ha_vip_only = False
|
||||||
@ -214,6 +275,14 @@ class AMQPContext(OSContextGenerator):
|
|||||||
unit=unit),
|
unit=unit),
|
||||||
'rabbitmq_virtual_host': vhost,
|
'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:
|
if relation_get('ha_queues', rid=rid, unit=unit) is not None:
|
||||||
ctxt['rabbitmq_ha_queues'] = True
|
ctxt['rabbitmq_ha_queues'] = True
|
||||||
|
|
||||||
@ -221,6 +290,16 @@ class AMQPContext(OSContextGenerator):
|
|||||||
rid=rid, unit=unit) is not None
|
rid=rid, unit=unit) is not None
|
||||||
|
|
||||||
if context_complete(ctxt):
|
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!
|
# Sufficient information found = break out!
|
||||||
break
|
break
|
||||||
# Used for active/active rabbitmq >= grizzly
|
# Used for active/active rabbitmq >= grizzly
|
||||||
@ -391,6 +470,8 @@ class ApacheSSLContext(OSContextGenerator):
|
|||||||
'private_address': unit_get('private-address'),
|
'private_address': unit_get('private-address'),
|
||||||
'endpoints': []
|
'endpoints': []
|
||||||
}
|
}
|
||||||
|
if is_clustered():
|
||||||
|
ctxt['private_address'] = config('vip')
|
||||||
for api_port in self.external_ports:
|
for api_port in self.external_ports:
|
||||||
ext_port = determine_apache_port(api_port)
|
ext_port = determine_apache_port(api_port)
|
||||||
int_port = determine_api_port(api_port)
|
int_port = determine_api_port(api_port)
|
||||||
|
@ -17,6 +17,8 @@ def headers_package():
|
|||||||
kver = check_output(['uname', '-r']).strip()
|
kver = check_output(['uname', '-r']).strip()
|
||||||
return 'linux-headers-%s' % kver
|
return 'linux-headers-%s' % kver
|
||||||
|
|
||||||
|
QUANTUM_CONF_DIR = '/etc/quantum'
|
||||||
|
|
||||||
|
|
||||||
def kernel_version():
|
def kernel_version():
|
||||||
""" Retrieve the current major kernel version as a tuple e.g. (3, 13) """
|
""" Retrieve the current major kernel version as a tuple e.g. (3, 13) """
|
||||||
@ -35,6 +37,8 @@ def determine_dkms_package():
|
|||||||
|
|
||||||
|
|
||||||
# legacy
|
# legacy
|
||||||
|
|
||||||
|
|
||||||
def quantum_plugins():
|
def quantum_plugins():
|
||||||
from charmhelpers.contrib.openstack import context
|
from charmhelpers.contrib.openstack import context
|
||||||
return {
|
return {
|
||||||
@ -46,7 +50,8 @@ def quantum_plugins():
|
|||||||
'contexts': [
|
'contexts': [
|
||||||
context.SharedDBContext(user=config('neutron-database-user'),
|
context.SharedDBContext(user=config('neutron-database-user'),
|
||||||
database=config('neutron-database'),
|
database=config('neutron-database'),
|
||||||
relation_prefix='neutron')],
|
relation_prefix='neutron',
|
||||||
|
ssl_dir=QUANTUM_CONF_DIR)],
|
||||||
'services': ['quantum-plugin-openvswitch-agent'],
|
'services': ['quantum-plugin-openvswitch-agent'],
|
||||||
'packages': [[headers_package()] + determine_dkms_package(),
|
'packages': [[headers_package()] + determine_dkms_package(),
|
||||||
['quantum-plugin-openvswitch-agent']],
|
['quantum-plugin-openvswitch-agent']],
|
||||||
@ -61,7 +66,8 @@ def quantum_plugins():
|
|||||||
'contexts': [
|
'contexts': [
|
||||||
context.SharedDBContext(user=config('neutron-database-user'),
|
context.SharedDBContext(user=config('neutron-database-user'),
|
||||||
database=config('neutron-database'),
|
database=config('neutron-database'),
|
||||||
relation_prefix='neutron')],
|
relation_prefix='neutron',
|
||||||
|
ssl_dir=QUANTUM_CONF_DIR)],
|
||||||
'services': [],
|
'services': [],
|
||||||
'packages': [],
|
'packages': [],
|
||||||
'server_packages': ['quantum-server',
|
'server_packages': ['quantum-server',
|
||||||
@ -70,6 +76,8 @@ def quantum_plugins():
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NEUTRON_CONF_DIR = '/etc/neutron'
|
||||||
|
|
||||||
|
|
||||||
def neutron_plugins():
|
def neutron_plugins():
|
||||||
from charmhelpers.contrib.openstack import context
|
from charmhelpers.contrib.openstack import context
|
||||||
@ -83,7 +91,8 @@ def neutron_plugins():
|
|||||||
'contexts': [
|
'contexts': [
|
||||||
context.SharedDBContext(user=config('neutron-database-user'),
|
context.SharedDBContext(user=config('neutron-database-user'),
|
||||||
database=config('neutron-database'),
|
database=config('neutron-database'),
|
||||||
relation_prefix='neutron')],
|
relation_prefix='neutron',
|
||||||
|
ssl_dir=NEUTRON_CONF_DIR)],
|
||||||
'services': ['neutron-plugin-openvswitch-agent'],
|
'services': ['neutron-plugin-openvswitch-agent'],
|
||||||
'packages': [[headers_package()] + determine_dkms_package(),
|
'packages': [[headers_package()] + determine_dkms_package(),
|
||||||
['neutron-plugin-openvswitch-agent']],
|
['neutron-plugin-openvswitch-agent']],
|
||||||
@ -98,7 +107,8 @@ def neutron_plugins():
|
|||||||
'contexts': [
|
'contexts': [
|
||||||
context.SharedDBContext(user=config('neutron-database-user'),
|
context.SharedDBContext(user=config('neutron-database-user'),
|
||||||
database=config('neutron-database'),
|
database=config('neutron-database'),
|
||||||
relation_prefix='neutron')],
|
relation_prefix='neutron',
|
||||||
|
ssl_dir=NEUTRON_CONF_DIR)],
|
||||||
'services': [],
|
'services': [],
|
||||||
'packages': [],
|
'packages': [],
|
||||||
'server_packages': ['neutron-server',
|
'server_packages': ['neutron-server',
|
||||||
|
@ -65,6 +65,7 @@ SWIFT_CODENAMES = OrderedDict([
|
|||||||
('1.10.0', 'havana'),
|
('1.10.0', 'havana'),
|
||||||
('1.9.1', 'havana'),
|
('1.9.1', 'havana'),
|
||||||
('1.9.0', 'havana'),
|
('1.9.0', 'havana'),
|
||||||
|
('1.13.1', 'icehouse'),
|
||||||
('1.13.0', 'icehouse'),
|
('1.13.0', 'icehouse'),
|
||||||
('1.12.0', 'icehouse'),
|
('1.12.0', 'icehouse'),
|
||||||
('1.11.0', 'icehouse'),
|
('1.11.0', 'icehouse'),
|
||||||
|
@ -2,7 +2,9 @@ from os import stat
|
|||||||
from stat import S_ISBLK
|
from stat import S_ISBLK
|
||||||
|
|
||||||
from subprocess import (
|
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.
|
:param block_device: str: Full path of block device to clean.
|
||||||
'''
|
'''
|
||||||
check_call(['sgdisk', '--zap-all', '--clear',
|
# sometimes sgdisk exits non-zero; this is OK, dd will clean up
|
||||||
'--mbrtogpt', block_device])
|
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 (
|
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.fetch import apt_install, filter_installed_packages
|
||||||
from charmhelpers.contrib.openstack import context, neutron, utils
|
from charmhelpers.contrib.openstack import context, neutron, utils
|
||||||
|
|
||||||
from charmhelpers.contrib.hahelpers.cluster import (
|
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):
|
class ApacheSSLContext(context.ApacheSSLContext):
|
||||||
@ -112,6 +117,24 @@ class HAProxyContext(context.HAProxyContext):
|
|||||||
return ctxt
|
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):
|
class NeutronCCContext(context.NeutronContext):
|
||||||
interfaces = []
|
interfaces = []
|
||||||
|
|
||||||
@ -148,10 +171,12 @@ class NeutronCCContext(context.NeutronContext):
|
|||||||
','.join(_config['nvp-controllers'].split())
|
','.join(_config['nvp-controllers'].split())
|
||||||
ctxt['nvp_controllers_list'] = \
|
ctxt['nvp_controllers_list'] = \
|
||||||
_config['nvp-controllers'].split()
|
_config['nvp-controllers'].split()
|
||||||
|
ctxt['nova_url'] = "{}:8774/v2".format(canonical_url())
|
||||||
return ctxt
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
class IdentityServiceContext(context.IdentityServiceContext):
|
class IdentityServiceContext(context.IdentityServiceContext):
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
ctxt = super(IdentityServiceContext, self).__call__()
|
ctxt = super(IdentityServiceContext, self).__call__()
|
||||||
if not ctxt:
|
if not ctxt:
|
||||||
@ -159,7 +184,23 @@ class IdentityServiceContext(context.IdentityServiceContext):
|
|||||||
|
|
||||||
# the ec2 api needs to know the location of the keystone ec2
|
# the ec2 api needs to know the location of the keystone ec2
|
||||||
# tokens endpoint, set in nova.conf
|
# tokens endpoint, set in nova.conf
|
||||||
ec2_tokens = 'http://%s:%s/v2.0/ec2tokens' % (ctxt['service_host'],
|
ec2_tokens = '%s://%s:%s/v2.0/ec2tokens' % (
|
||||||
ctxt['service_port'])
|
ctxt['service_protocol'] or 'http',
|
||||||
|
ctxt['service_host'],
|
||||||
|
ctxt['service_port']
|
||||||
|
)
|
||||||
ctxt['keystone_ec2_url'] = ec2_tokens
|
ctxt['keystone_ec2_url'] = ec2_tokens
|
||||||
|
ctxt['region'] = config('region')
|
||||||
return ctxt
|
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,
|
UnregisteredHookError,
|
||||||
config,
|
config,
|
||||||
charm_dir,
|
charm_dir,
|
||||||
|
is_relation_made,
|
||||||
log,
|
log,
|
||||||
|
ERROR,
|
||||||
relation_get,
|
relation_get,
|
||||||
relation_ids,
|
relation_ids,
|
||||||
relation_set,
|
relation_set,
|
||||||
@ -96,8 +98,9 @@ def install():
|
|||||||
@hooks.hook('config-changed')
|
@hooks.hook('config-changed')
|
||||||
@restart_on_change(restart_map(), stopstart=True)
|
@restart_on_change(restart_map(), stopstart=True)
|
||||||
def config_changed():
|
def config_changed():
|
||||||
|
global CONFIGS
|
||||||
if openstack_upgrade_available('nova-common'):
|
if openstack_upgrade_available('nova-common'):
|
||||||
do_openstack_upgrade(configs=CONFIGS)
|
CONFIGS = do_openstack_upgrade()
|
||||||
save_script_rc()
|
save_script_rc()
|
||||||
configure_https()
|
configure_https()
|
||||||
CONFIGS.write_all()
|
CONFIGS.write_all()
|
||||||
@ -110,6 +113,7 @@ def amqp_joined(relation_id=None):
|
|||||||
|
|
||||||
|
|
||||||
@hooks.hook('amqp-relation-changed')
|
@hooks.hook('amqp-relation-changed')
|
||||||
|
@hooks.hook('amqp-relation-departed')
|
||||||
@restart_on_change(restart_map())
|
@restart_on_change(restart_map())
|
||||||
def amqp_changed():
|
def amqp_changed():
|
||||||
if 'amqp' not in CONFIGS.complete_contexts():
|
if 'amqp' not in CONFIGS.complete_contexts():
|
||||||
@ -124,6 +128,14 @@ def amqp_changed():
|
|||||||
|
|
||||||
@hooks.hook('shared-db-relation-joined')
|
@hooks.hook('shared-db-relation-joined')
|
||||||
def db_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'),
|
relation_set(nova_database=config('database'),
|
||||||
nova_username=config('database-user'),
|
nova_username=config('database-user'),
|
||||||
nova_hostname=unit_get('private-address'))
|
nova_hostname=unit_get('private-address'))
|
||||||
@ -134,18 +146,37 @@ def db_joined():
|
|||||||
neutron_hostname=unit_get('private-address'))
|
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')
|
@hooks.hook('shared-db-relation-changed')
|
||||||
@restart_on_change(restart_map())
|
@restart_on_change(restart_map())
|
||||||
def db_changed():
|
def db_changed():
|
||||||
if 'shared-db' not in CONFIGS.complete_contexts():
|
if 'shared-db' not in CONFIGS.complete_contexts():
|
||||||
log('shared-db relation incomplete. Peer not ready?')
|
log('shared-db relation incomplete. Peer not ready?')
|
||||||
return
|
return
|
||||||
CONFIGS.write(NOVA_CONF)
|
CONFIGS.write_all()
|
||||||
|
|
||||||
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'))
|
|
||||||
|
|
||||||
if eligible_leader(CLUSTER_RES):
|
if eligible_leader(CLUSTER_RES):
|
||||||
migrate_database()
|
migrate_database()
|
||||||
@ -154,6 +185,30 @@ def db_changed():
|
|||||||
for rid in relation_ids('cloud-compute')]
|
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')
|
@hooks.hook('image-service-relation-changed')
|
||||||
@restart_on_change(restart_map())
|
@restart_on_change(restart_map())
|
||||||
def image_service_changed():
|
def image_service_changed():
|
||||||
@ -211,6 +266,8 @@ def _auth_config():
|
|||||||
cfg = {
|
cfg = {
|
||||||
'auth_host': ks_auth_host,
|
'auth_host': ks_auth_host,
|
||||||
'auth_port': auth_token_config('auth_port'),
|
'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_port': auth_token_config('service_port'),
|
||||||
'service_username': auth_token_config('admin_user'),
|
'service_username': auth_token_config('admin_user'),
|
||||||
'service_password': auth_token_config('admin_password'),
|
'service_password': auth_token_config('admin_password'),
|
||||||
@ -226,7 +283,8 @@ def _auth_config():
|
|||||||
def save_novarc():
|
def save_novarc():
|
||||||
auth = _auth_config()
|
auth = _auth_config()
|
||||||
# XXX hard-coded http
|
# 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:
|
with open('/etc/quantum/novarc', 'wb') as out:
|
||||||
out.write('export OS_USERNAME=%s\n' % auth['service_username'])
|
out.write('export OS_USERNAME=%s\n' % auth['service_username'])
|
||||||
out.write('export OS_PASSWORD=%s\n' % auth['service_password'])
|
out.write('export OS_PASSWORD=%s\n' % auth['service_password'])
|
||||||
@ -385,7 +443,9 @@ def ha_changed():
|
|||||||
'identity-service-relation-broken',
|
'identity-service-relation-broken',
|
||||||
'image-service-relation-broken',
|
'image-service-relation-broken',
|
||||||
'nova-volume-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')
|
'quantum-network-service-relation-broken')
|
||||||
def relation_broken():
|
def relation_broken():
|
||||||
CONFIGS.write_all()
|
CONFIGS.write_all()
|
||||||
@ -436,6 +496,8 @@ def nova_vmware_relation_changed():
|
|||||||
def upgrade_charm():
|
def upgrade_charm():
|
||||||
for r_id in relation_ids('amqp'):
|
for r_id in relation_ids('amqp'):
|
||||||
amqp_joined(relation_id=r_id)
|
amqp_joined(relation_id=r_id)
|
||||||
|
for r_id in relation_ids('identity-service'):
|
||||||
|
identity_joined(rid=r_id)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -22,8 +22,9 @@ from charmhelpers.contrib.openstack.utils import (
|
|||||||
save_script_rc as _save_script_rc)
|
save_script_rc as _save_script_rc)
|
||||||
|
|
||||||
from charmhelpers.fetch import (
|
from charmhelpers.fetch import (
|
||||||
apt_install,
|
apt_upgrade,
|
||||||
apt_update,
|
apt_update,
|
||||||
|
apt_install,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.core.hookenv import (
|
from charmhelpers.core.hookenv import (
|
||||||
@ -36,6 +37,10 @@ from charmhelpers.core.hookenv import (
|
|||||||
ERROR,
|
ERROR,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from charmhelpers.core.host import (
|
||||||
|
service_start
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
import nova_cc_context
|
import nova_cc_context
|
||||||
|
|
||||||
@ -49,6 +54,7 @@ BASE_PACKAGES = [
|
|||||||
'haproxy',
|
'haproxy',
|
||||||
'python-keystoneclient',
|
'python-keystoneclient',
|
||||||
'python-mysqldb',
|
'python-mysqldb',
|
||||||
|
'python-psycopg2',
|
||||||
'uuid',
|
'uuid',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -69,11 +75,15 @@ API_PORTS = {
|
|||||||
'quantum-server': 9696,
|
'quantum-server': 9696,
|
||||||
}
|
}
|
||||||
|
|
||||||
NOVA_CONF = '/etc/nova/nova.conf'
|
NOVA_CONF_DIR = "/etc/nova"
|
||||||
NOVA_API_PASTE = '/etc/nova/api-paste.ini'
|
QUANTUM_CONF_DIR = "/etc/quantum"
|
||||||
QUANTUM_CONF = '/etc/quantum/quantum.conf'
|
NEUTRON_CONF_DIR = "/etc/neutron"
|
||||||
QUANTUM_API_PASTE = '/etc/quantum/api-paste.ini'
|
|
||||||
NEUTRON_CONF = '/etc/neutron/neutron.conf'
|
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'
|
HAPROXY_CONF = '/etc/haproxy/haproxy.cfg'
|
||||||
APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
|
APACHE_CONF = '/etc/apache2/sites-available/openstack_https_frontend'
|
||||||
APACHE_24_CONF = '/etc/apache2/sites-available/openstack_https_frontend.conf'
|
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([
|
BASE_RESOURCE_MAP = OrderedDict([
|
||||||
(NOVA_CONF, {
|
(NOVA_CONF, {
|
||||||
'services': BASE_SERVICES,
|
'services': BASE_SERVICES,
|
||||||
'contexts': [context.AMQPContext(),
|
'contexts': [context.AMQPContext(ssl_dir=NOVA_CONF_DIR),
|
||||||
context.SharedDBContext(relation_prefix='nova'),
|
context.SharedDBContext(
|
||||||
|
relation_prefix='nova', ssl_dir=NOVA_CONF_DIR),
|
||||||
|
nova_cc_context.NovaPostgresqlDBContext(),
|
||||||
context.ImageServiceContext(),
|
context.ImageServiceContext(),
|
||||||
context.OSConfigFlagContext(),
|
context.OSConfigFlagContext(),
|
||||||
context.SubordinateConfigContext(
|
context.SubordinateConfigContext(
|
||||||
@ -104,11 +116,17 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||||||
}),
|
}),
|
||||||
(QUANTUM_CONF, {
|
(QUANTUM_CONF, {
|
||||||
'services': ['quantum-server'],
|
'services': ['quantum-server'],
|
||||||
'contexts': [context.AMQPContext(),
|
'contexts': [context.AMQPContext(ssl_dir=QUANTUM_CONF_DIR),
|
||||||
context.SyslogContext(),
|
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.HAProxyContext(),
|
||||||
nova_cc_context.IdentityServiceContext(),
|
nova_cc_context.IdentityServiceContext(),
|
||||||
nova_cc_context.NeutronCCContext()],
|
nova_cc_context.NeutronCCContext()
|
||||||
|
context.SyslogContext()],
|
||||||
}),
|
}),
|
||||||
(QUANTUM_DEFAULT, {
|
(QUANTUM_DEFAULT, {
|
||||||
'services': ['quantum-server'],
|
'services': ['quantum-server'],
|
||||||
@ -120,11 +138,17 @@ BASE_RESOURCE_MAP = OrderedDict([
|
|||||||
}),
|
}),
|
||||||
(NEUTRON_CONF, {
|
(NEUTRON_CONF, {
|
||||||
'services': ['neutron-server'],
|
'services': ['neutron-server'],
|
||||||
'contexts': [context.AMQPContext(),
|
'contexts': [context.AMQPContext(ssl_dir=NEUTRON_CONF_DIR),
|
||||||
context.SyslogContext(),
|
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.IdentityServiceContext(),
|
||||||
nova_cc_context.NeutronCCContext(),
|
nova_cc_context.NeutronCCContext(),
|
||||||
nova_cc_context.HAProxyContext()],
|
nova_cc_context.HAProxyContext()
|
||||||
|
context.SyslogContext()],
|
||||||
}),
|
}),
|
||||||
(NEUTRON_DEFAULT, {
|
(NEUTRON_DEFAULT, {
|
||||||
'services': ['neutron-server'],
|
'services': ['neutron-server'],
|
||||||
@ -195,6 +219,10 @@ def resource_map():
|
|||||||
resource_map[conf]['contexts'].append(
|
resource_map[conf]['contexts'].append(
|
||||||
nova_cc_context.NeutronCCContext())
|
nova_cc_context.NeutronCCContext())
|
||||||
|
|
||||||
|
# update for postgres
|
||||||
|
resource_map[conf]['contexts'].append(
|
||||||
|
nova_cc_context.NeutronPostgresqlDBContext())
|
||||||
|
|
||||||
# nova-conductor for releases >= G.
|
# nova-conductor for releases >= G.
|
||||||
if os_release('nova-common') not in ['essex', 'folsom']:
|
if os_release('nova-common') not in ['essex', 'folsom']:
|
||||||
resource_map['/etc/nova/nova.conf']['services'] += ['nova-conductor']
|
resource_map['/etc/nova/nova.conf']['services'] += ['nova-conductor']
|
||||||
@ -211,8 +239,8 @@ def resource_map():
|
|||||||
return resource_map
|
return resource_map
|
||||||
|
|
||||||
|
|
||||||
def register_configs():
|
def register_configs(release=None):
|
||||||
release = os_release('nova-common')
|
release = release or os_release('nova-common')
|
||||||
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
configs = templating.OSConfigRenderer(templates_dir=TEMPLATES,
|
||||||
openstack_release=release)
|
openstack_release=release)
|
||||||
for cfg, rscs in resource_map().iteritems():
|
for cfg, rscs in resource_map().iteritems():
|
||||||
@ -226,10 +254,18 @@ def restart_map():
|
|||||||
if v['services']])
|
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():
|
def determine_ports():
|
||||||
'''Assemble a list of API ports for services we are managing'''
|
'''Assemble a list of API ports for services we are managing'''
|
||||||
ports = []
|
ports = []
|
||||||
for cfg, services in restart_map().iteritems():
|
for services in restart_map().values():
|
||||||
for service in services:
|
for service in services:
|
||||||
try:
|
try:
|
||||||
ports.append(API_PORTS[service])
|
ports.append(API_PORTS[service])
|
||||||
@ -245,7 +281,7 @@ def api_port(service):
|
|||||||
def determine_packages():
|
def determine_packages():
|
||||||
# currently all packages match service names
|
# currently all packages match service names
|
||||||
packages = [] + BASE_PACKAGES
|
packages = [] + BASE_PACKAGES
|
||||||
for k, v in resource_map().iteritems():
|
for v in resource_map().values():
|
||||||
packages.extend(v['services'])
|
packages.extend(v['services'])
|
||||||
if network_manager() in ['neutron', 'quantum']:
|
if network_manager() in ['neutron', 'quantum']:
|
||||||
pkgs = neutron_plugin_attribute(neutron_plugin(), 'server_packages',
|
pkgs = neutron_plugin_attribute(neutron_plugin(), 'server_packages',
|
||||||
@ -273,27 +309,162 @@ def save_script_rc():
|
|||||||
_save_script_rc(**env_vars)
|
_save_script_rc(**env_vars)
|
||||||
|
|
||||||
|
|
||||||
def do_openstack_upgrade(configs):
|
def get_step_upgrade_source(new_src):
|
||||||
new_src = config('openstack-origin')
|
'''
|
||||||
|
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)
|
new_os_rel = get_os_codename_install_source(new_src)
|
||||||
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
|
log('Performing OpenStack upgrade to %s.' % (new_os_rel))
|
||||||
|
|
||||||
configure_installation_source(new_src)
|
configure_installation_source(new_src)
|
||||||
apt_update()
|
|
||||||
|
|
||||||
dpkg_opts = [
|
dpkg_opts = [
|
||||||
'--option', 'Dpkg::Options::=--force-confnew',
|
'--option', 'Dpkg::Options::=--force-confnew',
|
||||||
'--option', 'Dpkg::Options::=--force-confdef',
|
'--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
|
apt_update(fatal=True)
|
||||||
configs.set_release(openstack_release=new_os_rel)
|
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
|
||||||
configs.write_all()
|
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):
|
if eligible_leader(CLUSTER_RES):
|
||||||
migrate_database()
|
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():
|
def volume_service():
|
||||||
@ -315,10 +486,10 @@ def migrate_database():
|
|||||||
|
|
||||||
|
|
||||||
def auth_token_config(setting):
|
def auth_token_config(setting):
|
||||||
'''
|
"""
|
||||||
Returns currently configured value for setting in api-paste.ini's
|
Returns currently configured value for setting in api-paste.ini's
|
||||||
authtoken section, or None.
|
authtoken section, or None.
|
||||||
'''
|
"""
|
||||||
config = ConfigParser.RawConfigParser()
|
config = ConfigParser.RawConfigParser()
|
||||||
config.read('/etc/nova/api-paste.ini')
|
config.read('/etc/nova/api-paste.ini')
|
||||||
try:
|
try:
|
||||||
@ -363,7 +534,10 @@ def authorized_keys(user=None):
|
|||||||
|
|
||||||
def ssh_known_host_key(host, user=None):
|
def ssh_known_host_key(host, user=None):
|
||||||
cmd = ['ssh-keygen', '-f', known_hosts(user), '-H', '-F', host]
|
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):
|
def remove_known_host(host, user=None):
|
||||||
@ -459,10 +633,14 @@ def determine_endpoints(url):
|
|||||||
'''Generates a dictionary containing all relevant endpoints to be
|
'''Generates a dictionary containing all relevant endpoints to be
|
||||||
passed to keystone as relation settings.'''
|
passed to keystone as relation settings.'''
|
||||||
region = config('region')
|
region = config('region')
|
||||||
|
os_rel = os_release('nova-common')
|
||||||
|
|
||||||
# TODO: Configurable nova API version.
|
if os_rel >= 'grizzly':
|
||||||
nova_url = ('%s:%s/v1.1/$(tenant_id)s' %
|
nova_url = ('%s:%s/v2/$(tenant_id)s' %
|
||||||
(url, api_port('nova-api-os-compute')))
|
(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'))
|
ec2_url = '%s:%s/services/Cloud' % (url, api_port('nova-api-ec2'))
|
||||||
nova_volume_url = ('%s:%s/v1/$(tenant_id)s' %
|
nova_volume_url = ('%s:%s/v1/$(tenant_id)s' %
|
||||||
(url, api_port('nova-api-os-compute')))
|
(url, api_port('nova-api-os-compute')))
|
||||||
|
1
hooks/pgsql-neutron-db-relation-broken
Symbolic link
1
hooks/pgsql-neutron-db-relation-broken
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/pgsql-neutron-db-relation-changed
Symbolic link
1
hooks/pgsql-neutron-db-relation-changed
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/pgsql-neutron-db-relation-joined
Symbolic link
1
hooks/pgsql-neutron-db-relation-joined
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/pgsql-nova-db-relation-broken
Symbolic link
1
hooks/pgsql-nova-db-relation-broken
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/pgsql-nova-db-relation-changed
Symbolic link
1
hooks/pgsql-nova-db-relation-changed
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
1
hooks/pgsql-nova-db-relation-joined
Symbolic link
1
hooks/pgsql-nova-db-relation-joined
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
nova_cc_hooks.py
|
@ -12,6 +12,10 @@ provides:
|
|||||||
requires:
|
requires:
|
||||||
shared-db:
|
shared-db:
|
||||||
interface: mysql-shared
|
interface: mysql-shared
|
||||||
|
pgsql-nova-db:
|
||||||
|
interface: pgsql
|
||||||
|
pgsql-neutron-db:
|
||||||
|
interface: pgsql
|
||||||
amqp:
|
amqp:
|
||||||
interface: rabbitmq
|
interface: rabbitmq
|
||||||
image-service:
|
image-service:
|
||||||
|
5
setup.cfg
Normal file
5
setup.cfg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
[nosetests]
|
||||||
|
verbosity=2
|
||||||
|
with-coverage=1
|
||||||
|
cover-erase=1
|
||||||
|
cover-package=hooks
|
@ -17,7 +17,7 @@
|
|||||||
--use_syslog={{ use_syslog }}
|
--use_syslog={{ use_syslog }}
|
||||||
--ec2_private_dns_show_ip
|
--ec2_private_dns_show_ip
|
||||||
{% if database_host -%}
|
{% 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 -%}
|
{% endif -%}
|
||||||
{% if rabbitmq_host -%}
|
{% if rabbitmq_host -%}
|
||||||
--rabbit_host={{ rabbitmq_host }}
|
--rabbit_host={{ rabbitmq_host }}
|
||||||
|
@ -25,11 +25,16 @@ compute_driver=libvirt.LibvirtDriver
|
|||||||
keystone_ec2_url = {{ keystone_ec2_url }}
|
keystone_ec2_url = {{ keystone_ec2_url }}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
{% if database_host -%}
|
{% include "parts/database" %}
|
||||||
sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
|
||||||
{% endif -%}
|
|
||||||
|
|
||||||
{% if rabbitmq_host -%}
|
{% 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_host = {{ rabbitmq_host }}
|
||||||
rabbit_userid = {{ rabbitmq_user }}
|
rabbit_userid = {{ rabbitmq_user }}
|
||||||
rabbit_password = {{ rabbitmq_password }}
|
rabbit_password = {{ rabbitmq_password }}
|
||||||
|
@ -11,7 +11,7 @@ local_ip = {{ local_ip }}
|
|||||||
|
|
||||||
[DATABASE]
|
[DATABASE]
|
||||||
{% if database_host -%}
|
{% 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
|
reconnect_interval = 2
|
||||||
{% else -%}
|
{% else -%}
|
||||||
connection = sqlite:////var/lib/quantum/quantum.sqlite
|
connection = sqlite:////var/lib/quantum/quantum.sqlite
|
||||||
|
115
templates/grizzly/nova.conf
Normal file
115
templates/grizzly/nova.conf
Normal file
@ -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 -%}
|
45
templates/grizzly/quantum.conf
Normal file
45
templates/grizzly/quantum.conf
Normal file
@ -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 -%}
|
{% endif -%}
|
||||||
{% if core_plugin -%}
|
{% if core_plugin -%}
|
||||||
core_plugin = {{ core_plugin }}
|
core_plugin = {{ core_plugin }}
|
||||||
|
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||||
|
service_plugins = neutron.services.metering.metering_plugin.MeteringPlugin
|
||||||
|
{% endif -%}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{% if neutron_security_groups -%}
|
{% if neutron_security_groups -%}
|
||||||
allow_overlapping_ips = True
|
allow_overlapping_ips = True
|
||||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{% if rabbitmq_host -%}
|
|
||||||
rabbit_host = {{ rabbitmq_host }}
|
{% include "parts/rabbitmq" %}
|
||||||
rabbit_userid = {{ rabbitmq_user }}
|
|
||||||
rabbit_password = {{ rabbitmq_password }}
|
|
||||||
rabbit_virtual_host = {{ rabbitmq_virtual_host }}
|
|
||||||
{% endif -%}
|
|
||||||
|
|
||||||
[quotas]
|
[quotas]
|
||||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||||
@ -51,5 +50,7 @@ admin_user = {{ admin_user }}
|
|||||||
admin_password = {{ admin_password }}
|
admin_password = {{ admin_password }}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
|
{% include "parts/section-database" %}
|
||||||
|
|
||||||
[lbaas]
|
[lbaas]
|
||||||
[service_providers]
|
[service_providers]
|
||||||
|
119
templates/havana/nova.conf
Normal file
119
templates/havana/nova.conf
Normal file
@ -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 }}
|
nvp_controllers = {{ nvp_controllers }}
|
||||||
default_tz_uuid = {{ nvp_tz_uuid }}
|
default_tz_uuid = {{ nvp_tz_uuid }}
|
||||||
default_l3_gw_service_uuid = {{ nvp_l3_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
|
enable_tunneling = True
|
||||||
local_ip = {{ local_ip }}
|
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]
|
[securitygroup]
|
||||||
{% if neutron_security_groups -%}
|
{% if neutron_security_groups -%}
|
||||||
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||||
|
124
templates/icehouse/etc_nova_api-paste.ini
Normal file
124
templates/icehouse/etc_nova_api-paste.ini
Normal file
@ -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 -%}
|
30
templates/icehouse/ml2_conf.ini
Normal file
30
templates/icehouse/ml2_conf.ini
Normal file
@ -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 -%}
|
71
templates/icehouse/neutron.conf
Normal file
71
templates/icehouse/neutron.conf
Normal file
@ -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
|
130
templates/icehouse/nova.conf
Normal file
130
templates/icehouse/nova.conf
Normal file
@ -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
|
||||||
|
|
3
templates/parts/database
Normal file
3
templates/parts/database
Normal file
@ -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 -%}
|
21
templates/parts/rabbitmq
Normal file
21
templates/parts/rabbitmq
Normal file
@ -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 -%}
|
4
templates/parts/section-database
Normal file
4
templates/parts/section-database
Normal file
@ -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
|
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
|
_reg = utils.register_configs
|
||||||
_map = utils.restart_map
|
_map = utils.restart_map
|
||||||
@ -15,7 +16,6 @@ import nova_cc_hooks as hooks
|
|||||||
utils.register_configs = _reg
|
utils.register_configs = _reg
|
||||||
utils.restart_map = _map
|
utils.restart_map = _map
|
||||||
|
|
||||||
|
|
||||||
TO_PATCH = [
|
TO_PATCH = [
|
||||||
'api_port',
|
'api_port',
|
||||||
'apt_update',
|
'apt_update',
|
||||||
@ -29,8 +29,11 @@ TO_PATCH = [
|
|||||||
'determine_packages',
|
'determine_packages',
|
||||||
'determine_ports',
|
'determine_ports',
|
||||||
'open_port',
|
'open_port',
|
||||||
|
'is_relation_made',
|
||||||
|
'log',
|
||||||
'relation_get',
|
'relation_get',
|
||||||
'relation_set',
|
'relation_set',
|
||||||
|
'relation_ids',
|
||||||
'ssh_compute_add',
|
'ssh_compute_add',
|
||||||
'ssh_known_hosts_b64',
|
'ssh_known_hosts_b64',
|
||||||
'ssh_authorized_keys_b64',
|
'ssh_authorized_keys_b64',
|
||||||
@ -42,6 +45,7 @@ TO_PATCH = [
|
|||||||
'eligible_leader',
|
'eligible_leader',
|
||||||
'keystone_ca_cert_b64',
|
'keystone_ca_cert_b64',
|
||||||
'neutron_plugin',
|
'neutron_plugin',
|
||||||
|
'migrate_database',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -63,6 +67,7 @@ class NovaCCHooksTests(CharmTestCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(NovaCCHooksTests, self).setUp(hooks, TO_PATCH)
|
super(NovaCCHooksTests, self).setUp(hooks, TO_PATCH)
|
||||||
|
|
||||||
self.config.side_effect = self.test_config.get
|
self.config.side_effect = self.test_config.get
|
||||||
self.relation_get.side_effect = self.test_relation.get
|
self.relation_get.side_effect = self.test_relation.get
|
||||||
self.charm_dir.return_value = '/var/lib/juju/charms/nova/charm'
|
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',
|
quantum_url='http://nova-cc-host1:9696', quantum_plugin='nvp',
|
||||||
relation_id=None,
|
relation_id=None,
|
||||||
**FAKE_KS_AUTH_CFG)
|
**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
|
hookenv.config = _conf
|
||||||
|
|
||||||
TO_PATCH = [
|
TO_PATCH = [
|
||||||
|
'apt_update',
|
||||||
|
'apt_upgrade',
|
||||||
|
'apt_install',
|
||||||
'config',
|
'config',
|
||||||
|
'configure_installation_source',
|
||||||
|
'disable_policy_rcd',
|
||||||
|
'eligible_leader',
|
||||||
|
'enable_policy_rcd',
|
||||||
|
'get_os_codename_install_source',
|
||||||
'log',
|
'log',
|
||||||
|
'ml2_migration',
|
||||||
'network_manager',
|
'network_manager',
|
||||||
|
'neutron_db_manage',
|
||||||
'neutron_plugin',
|
'neutron_plugin',
|
||||||
'neutron_plugin_attribute',
|
'neutron_plugin_attribute',
|
||||||
'os_release',
|
'os_release',
|
||||||
|
'register_configs',
|
||||||
'relation_ids',
|
'relation_ids',
|
||||||
'remote_unit',
|
'remote_unit',
|
||||||
'_save_script_rc',
|
'_save_script_rc',
|
||||||
|
'service_start',
|
||||||
|
'services'
|
||||||
]
|
]
|
||||||
|
|
||||||
SCRIPTRC_ENV_VARS = {
|
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):
|
def fake_plugin_attribute(plugin, attr, net_manager):
|
||||||
if plugin in PLUGIN_ATTRIBUTES:
|
if plugin in PLUGIN_ATTRIBUTES:
|
||||||
try:
|
try:
|
||||||
@ -345,7 +364,9 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||||||
ssh_dir.return_value = '/tmp/foo'
|
ssh_dir.return_value = '/tmp/foo'
|
||||||
self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')
|
self.assertEquals(utils.authorized_keys(), '/tmp/foo/authorized_keys')
|
||||||
ssh_dir.assert_called_with(None)
|
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')
|
ssh_dir.assert_called_with('bar')
|
||||||
|
|
||||||
@patch.object(utils, 'known_hosts')
|
@patch.object(utils, 'known_hosts')
|
||||||
@ -374,7 +395,8 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||||||
@patch.object(utils, 'known_hosts')
|
@patch.object(utils, 'known_hosts')
|
||||||
@patch.object(utils, 'authorized_keys')
|
@patch.object(utils, 'authorized_keys')
|
||||||
@patch('os.path.isfile')
|
@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
|
isfile.return_value = False
|
||||||
|
|
||||||
removed_key = AUTHORIZED_KEYS.split('\n')[2]
|
removed_key = AUTHORIZED_KEYS.split('\n')[2]
|
||||||
@ -454,3 +476,82 @@ class NovaCCUtilsTests(CharmTestCase):
|
|||||||
_known_hosts.assert_called_with(None)
|
_known_hosts.assert_called_with(None)
|
||||||
utils.remove_known_host('test', 'bar')
|
utils.remove_known_host('test', 'bar')
|
||||||
_known_hosts.assert_called_with('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
Block a user