[hazmat,yolanda.robla,james-page,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
This commit is contained in:
commit
57cf231ee0
7
Makefile
7
Makefile
@ -1,11 +1,10 @@
|
||||
#!/usr/bin/make
|
||||
|
||||
lint:
|
||||
@echo -n "Running flake8 tests: "
|
||||
@flake8 --exclude hooks/charmhelpers hooks
|
||||
@flake8 unit_tests
|
||||
@echo "Running flake8 tests: "
|
||||
@flake8 --exclude hooks/charmhelpers hooks unit_tests
|
||||
@echo "OK"
|
||||
@echo -n "Running charm proof: "
|
||||
@echo "Running charm proof: "
|
||||
@charm proof
|
||||
@echo "OK"
|
||||
|
||||
|
13
config.yaml
13
config.yaml
@ -41,6 +41,14 @@ options:
|
||||
default: False
|
||||
description: |
|
||||
If set to True, supporting services will log to syslog.
|
||||
debug:
|
||||
default: False
|
||||
type: boolean
|
||||
description: Enable debug logging
|
||||
verbose:
|
||||
default: False
|
||||
type: boolean
|
||||
description: Enable verbose logging
|
||||
# HA configuration settings
|
||||
vip:
|
||||
type: string
|
||||
@ -75,6 +83,11 @@ options:
|
||||
ssl_key:
|
||||
type: string
|
||||
description: SSL key to use with certificate specified as ssl_cert.
|
||||
ssl_ca:
|
||||
type: string
|
||||
description: |
|
||||
SSL CA to use with the certificate and key provided - this is only
|
||||
required if you are providing a privately signed ssl_cert and ssl_key.
|
||||
rabbit-user:
|
||||
default: glance
|
||||
type: string
|
||||
|
@ -39,14 +39,15 @@ def get_cert():
|
||||
|
||||
|
||||
def get_ca_cert():
|
||||
ca_cert = None
|
||||
log("Inspecting identity-service relations for CA SSL certificate.",
|
||||
level=INFO)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
for unit in relation_list(r_id):
|
||||
if not ca_cert:
|
||||
ca_cert = relation_get('ca_cert',
|
||||
rid=r_id, unit=unit)
|
||||
ca_cert = config_get('ssl_ca')
|
||||
if ca_cert is None:
|
||||
log("Inspecting identity-service relations for CA SSL certificate.",
|
||||
level=INFO)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
for unit in relation_list(r_id):
|
||||
if ca_cert is None:
|
||||
ca_cert = relation_get('ca_cert',
|
||||
rid=r_id, unit=unit)
|
||||
return ca_cert
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
||||
from base64 import b64decode
|
||||
|
||||
@ -113,7 +114,8 @@ class OSContextGenerator(object):
|
||||
class SharedDBContext(OSContextGenerator):
|
||||
interfaces = ['shared-db']
|
||||
|
||||
def __init__(self, database=None, user=None, relation_prefix=None):
|
||||
def __init__(self,
|
||||
database=None, user=None, relation_prefix=None, ssl_dir=None):
|
||||
'''
|
||||
Allows inspecting relation for settings prefixed with relation_prefix.
|
||||
This is useful for parsing access for multiple databases returned via
|
||||
@ -122,6 +124,7 @@ class SharedDBContext(OSContextGenerator):
|
||||
self.relation_prefix = relation_prefix
|
||||
self.database = database
|
||||
self.user = user
|
||||
self.ssl_dir = ssl_dir
|
||||
|
||||
def __call__(self):
|
||||
self.database = self.database or config('database')
|
||||
@ -139,19 +142,74 @@ class SharedDBContext(OSContextGenerator):
|
||||
|
||||
for rid in relation_ids('shared-db'):
|
||||
for unit in related_units(rid):
|
||||
passwd = relation_get(password_setting, rid=rid, unit=unit)
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
ctxt = {
|
||||
'database_host': relation_get('db_host', rid=rid,
|
||||
unit=unit),
|
||||
'database_host': rdata.get('db_host'),
|
||||
'database': self.database,
|
||||
'database_user': self.user,
|
||||
'database_password': passwd,
|
||||
'database_password': rdata.get(password_setting),
|
||||
'database_type': 'mysql'
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
db_ssl(rdata, ctxt, self.ssl_dir)
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
|
||||
class PostgresqlDBContext(OSContextGenerator):
|
||||
interfaces = ['pgsql-db']
|
||||
|
||||
def __init__(self, database=None):
|
||||
self.database = database
|
||||
|
||||
def __call__(self):
|
||||
self.database = self.database or config('database')
|
||||
if self.database is None:
|
||||
log('Could not generate postgresql_db context. '
|
||||
'Missing required charm config options. '
|
||||
'(database name)')
|
||||
raise OSContextError
|
||||
ctxt = {}
|
||||
|
||||
for rid in relation_ids(self.interfaces[0]):
|
||||
for unit in related_units(rid):
|
||||
ctxt = {
|
||||
'database_host': relation_get('host', rid=rid, unit=unit),
|
||||
'database': self.database,
|
||||
'database_user': relation_get('user', rid=rid, unit=unit),
|
||||
'database_password': relation_get('password', rid=rid, unit=unit),
|
||||
'database_type': 'postgresql',
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
|
||||
def db_ssl(rdata, ctxt, ssl_dir):
|
||||
if 'ssl_ca' in rdata and ssl_dir:
|
||||
ca_path = os.path.join(ssl_dir, 'db-client.ca')
|
||||
with open(ca_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_ca']))
|
||||
ctxt['database_ssl_ca'] = ca_path
|
||||
elif 'ssl_ca' in rdata:
|
||||
log("Charm not setup for ssl support but ssl ca found")
|
||||
return ctxt
|
||||
if 'ssl_cert' in rdata:
|
||||
cert_path = os.path.join(
|
||||
ssl_dir, 'db-client.cert')
|
||||
if not os.path.exists(cert_path):
|
||||
log("Waiting 1m for ssl client cert validity")
|
||||
time.sleep(60)
|
||||
with open(cert_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_cert']))
|
||||
ctxt['database_ssl_cert'] = cert_path
|
||||
key_path = os.path.join(ssl_dir, 'db-client.key')
|
||||
with open(key_path, 'w') as fh:
|
||||
fh.write(b64decode(rdata['ssl_key']))
|
||||
ctxt['database_ssl_key'] = key_path
|
||||
return ctxt
|
||||
|
||||
|
||||
class IdentityServiceContext(OSContextGenerator):
|
||||
interfaces = ['identity-service']
|
||||
|
||||
@ -161,24 +219,25 @@ class IdentityServiceContext(OSContextGenerator):
|
||||
|
||||
for rid in relation_ids('identity-service'):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
ctxt = {
|
||||
'service_port': relation_get('service_port', rid=rid,
|
||||
unit=unit),
|
||||
'service_host': relation_get('service_host', rid=rid,
|
||||
unit=unit),
|
||||
'auth_host': relation_get('auth_host', rid=rid, unit=unit),
|
||||
'auth_port': relation_get('auth_port', rid=rid, unit=unit),
|
||||
'admin_tenant_name': relation_get('service_tenant',
|
||||
rid=rid, unit=unit),
|
||||
'admin_user': relation_get('service_username', rid=rid,
|
||||
unit=unit),
|
||||
'admin_password': relation_get('service_password', rid=rid,
|
||||
unit=unit),
|
||||
# XXX: Hard-coded http.
|
||||
'service_protocol': 'http',
|
||||
'auth_protocol': 'http',
|
||||
'service_port': rdata.get('service_port'),
|
||||
'service_host': rdata.get('service_host'),
|
||||
'auth_host': rdata.get('auth_host'),
|
||||
'auth_port': rdata.get('auth_port'),
|
||||
'admin_tenant_name': rdata.get('service_tenant'),
|
||||
'admin_user': rdata.get('service_username'),
|
||||
'admin_password': rdata.get('service_password'),
|
||||
'service_protocol':
|
||||
rdata.get('service_protocol') or 'http',
|
||||
'auth_protocol':
|
||||
rdata.get('auth_protocol') or 'http',
|
||||
}
|
||||
if context_complete(ctxt):
|
||||
# NOTE(jamespage) this is required for >= icehouse
|
||||
# so a missing value just indicates keystone needs
|
||||
# upgrading
|
||||
ctxt['admin_tenant_id'] = rdata.get('service_tenant_id')
|
||||
return ctxt
|
||||
return {}
|
||||
|
||||
@ -186,6 +245,9 @@ class IdentityServiceContext(OSContextGenerator):
|
||||
class AMQPContext(OSContextGenerator):
|
||||
interfaces = ['amqp']
|
||||
|
||||
def __init__(self, ssl_dir=None):
|
||||
self.ssl_dir = ssl_dir
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for amqp')
|
||||
conf = config()
|
||||
@ -196,7 +258,6 @@ class AMQPContext(OSContextGenerator):
|
||||
log('Could not generate shared_db context. '
|
||||
'Missing required charm config options: %s.' % e)
|
||||
raise OSContextError
|
||||
|
||||
ctxt = {}
|
||||
for rid in relation_ids('amqp'):
|
||||
ha_vip_only = False
|
||||
@ -214,6 +275,14 @@ class AMQPContext(OSContextGenerator):
|
||||
unit=unit),
|
||||
'rabbitmq_virtual_host': vhost,
|
||||
})
|
||||
|
||||
ssl_port = relation_get('ssl_port', rid=rid, unit=unit)
|
||||
if ssl_port:
|
||||
ctxt['rabbit_ssl_port'] = ssl_port
|
||||
ssl_ca = relation_get('ssl_ca', rid=rid, unit=unit)
|
||||
if ssl_ca:
|
||||
ctxt['rabbit_ssl_ca'] = ssl_ca
|
||||
|
||||
if relation_get('ha_queues', rid=rid, unit=unit) is not None:
|
||||
ctxt['rabbitmq_ha_queues'] = True
|
||||
|
||||
@ -221,6 +290,16 @@ class AMQPContext(OSContextGenerator):
|
||||
rid=rid, unit=unit) is not None
|
||||
|
||||
if context_complete(ctxt):
|
||||
if 'rabbit_ssl_ca' in ctxt:
|
||||
if not self.ssl_dir:
|
||||
log(("Charm not setup for ssl support "
|
||||
"but ssl ca found"))
|
||||
break
|
||||
ca_path = os.path.join(
|
||||
self.ssl_dir, 'rabbit-client-ca.pem')
|
||||
with open(ca_path, 'w') as fh:
|
||||
fh.write(b64decode(ctxt['rabbit_ssl_ca']))
|
||||
ctxt['rabbit_ssl_ca'] = ca_path
|
||||
# Sufficient information found = break out!
|
||||
break
|
||||
# Used for active/active rabbitmq >= grizzly
|
||||
@ -391,6 +470,8 @@ class ApacheSSLContext(OSContextGenerator):
|
||||
'private_address': unit_get('private-address'),
|
||||
'endpoints': []
|
||||
}
|
||||
if is_clustered():
|
||||
ctxt['private_address'] = config('vip')
|
||||
for api_port in self.external_ports:
|
||||
ext_port = determine_apache_port(api_port)
|
||||
int_port = determine_api_port(api_port)
|
||||
|
@ -17,6 +17,8 @@ def headers_package():
|
||||
kver = check_output(['uname', '-r']).strip()
|
||||
return 'linux-headers-%s' % kver
|
||||
|
||||
QUANTUM_CONF_DIR = '/etc/quantum'
|
||||
|
||||
|
||||
def kernel_version():
|
||||
""" Retrieve the current major kernel version as a tuple e.g. (3, 13) """
|
||||
@ -35,6 +37,8 @@ def determine_dkms_package():
|
||||
|
||||
|
||||
# legacy
|
||||
|
||||
|
||||
def quantum_plugins():
|
||||
from charmhelpers.contrib.openstack import context
|
||||
return {
|
||||
@ -46,7 +50,8 @@ def quantum_plugins():
|
||||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=QUANTUM_CONF_DIR)],
|
||||
'services': ['quantum-plugin-openvswitch-agent'],
|
||||
'packages': [[headers_package()] + determine_dkms_package(),
|
||||
['quantum-plugin-openvswitch-agent']],
|
||||
@ -61,7 +66,8 @@ def quantum_plugins():
|
||||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=QUANTUM_CONF_DIR)],
|
||||
'services': [],
|
||||
'packages': [],
|
||||
'server_packages': ['quantum-server',
|
||||
@ -70,6 +76,8 @@ def quantum_plugins():
|
||||
}
|
||||
}
|
||||
|
||||
NEUTRON_CONF_DIR = '/etc/neutron'
|
||||
|
||||
|
||||
def neutron_plugins():
|
||||
from charmhelpers.contrib.openstack import context
|
||||
@ -83,7 +91,8 @@ def neutron_plugins():
|
||||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=NEUTRON_CONF_DIR)],
|
||||
'services': ['neutron-plugin-openvswitch-agent'],
|
||||
'packages': [[headers_package()] + determine_dkms_package(),
|
||||
['neutron-plugin-openvswitch-agent']],
|
||||
@ -98,7 +107,8 @@ def neutron_plugins():
|
||||
'contexts': [
|
||||
context.SharedDBContext(user=config('neutron-database-user'),
|
||||
database=config('neutron-database'),
|
||||
relation_prefix='neutron')],
|
||||
relation_prefix='neutron',
|
||||
ssl_dir=NEUTRON_CONF_DIR)],
|
||||
'services': [],
|
||||
'packages': [],
|
||||
'server_packages': ['neutron-server',
|
||||
|
@ -65,6 +65,7 @@ SWIFT_CODENAMES = OrderedDict([
|
||||
('1.10.0', 'havana'),
|
||||
('1.9.1', 'havana'),
|
||||
('1.9.0', 'havana'),
|
||||
('1.13.1', 'icehouse'),
|
||||
('1.13.0', 'icehouse'),
|
||||
('1.12.0', 'icehouse'),
|
||||
('1.11.0', 'icehouse'),
|
||||
|
@ -75,3 +75,8 @@ class ApacheSSLContext(SSLContext):
|
||||
|
||||
def __call__(self):
|
||||
return super(ApacheSSLContext, self).__call__()
|
||||
|
||||
|
||||
class LoggingConfigContext(OSContextGenerator):
|
||||
def __call__(self):
|
||||
return {'debug': config('debug'), 'verbose': config('verbose')}
|
||||
|
@ -22,7 +22,9 @@ from charmhelpers.core.hookenv import (
|
||||
config,
|
||||
Hooks,
|
||||
log as juju_log,
|
||||
ERROR,
|
||||
open_port,
|
||||
is_relation_made,
|
||||
relation_get,
|
||||
relation_set,
|
||||
relation_ids,
|
||||
@ -32,11 +34,14 @@ from charmhelpers.core.hookenv import (
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
restart_on_change,
|
||||
service_stop,
|
||||
mkdir
|
||||
service_stop
|
||||
)
|
||||
|
||||
from charmhelpers.fetch import apt_install, apt_update
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
apt_update,
|
||||
filter_installed_packages
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
canonical_url, eligible_leader)
|
||||
@ -70,8 +75,8 @@ def install_hook():
|
||||
|
||||
configure_installation_source(src)
|
||||
|
||||
apt_update()
|
||||
apt_install(PACKAGES)
|
||||
apt_update(fatal=True)
|
||||
apt_install(PACKAGES, fatal=True)
|
||||
|
||||
for service in SERVICES:
|
||||
service_stop(service)
|
||||
@ -79,10 +84,29 @@ def install_hook():
|
||||
|
||||
@hooks.hook('shared-db-relation-joined')
|
||||
def db_joined():
|
||||
if is_relation_made('pgsql-db'):
|
||||
# error, postgresql is used
|
||||
e = ('Attempting to associate a mysql database when there is already '
|
||||
'associated a postgresql one')
|
||||
juju_log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
|
||||
relation_set(database=config('database'), username=config('database-user'),
|
||||
hostname=unit_get('private-address'))
|
||||
|
||||
|
||||
@hooks.hook('pgsql-db-relation-joined')
|
||||
def pgsql_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')
|
||||
juju_log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
|
||||
relation_set(database=config('database'))
|
||||
|
||||
|
||||
@hooks.hook('shared-db-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def db_changed():
|
||||
@ -108,6 +132,31 @@ def db_changed():
|
||||
migrate_database()
|
||||
|
||||
|
||||
@hooks.hook('pgsql-db-relation-changed')
|
||||
@restart_on_change(restart_map())
|
||||
def pgsql_db_changed():
|
||||
rel = get_os_codename_package("glance-common")
|
||||
|
||||
if 'pgsql-db' not in CONFIGS.complete_contexts():
|
||||
juju_log('pgsql-db relation incomplete. Peer not ready?')
|
||||
return
|
||||
|
||||
CONFIGS.write(GLANCE_REGISTRY_CONF)
|
||||
# since folsom, a db connection setting in glance-api.conf is required.
|
||||
if rel != "essex":
|
||||
CONFIGS.write(GLANCE_API_CONF)
|
||||
|
||||
if eligible_leader(CLUSTER_RES):
|
||||
if rel == "essex":
|
||||
status = call(['glance-manage', 'db_version'])
|
||||
if status != 0:
|
||||
juju_log('Setting version_control to 0')
|
||||
check_call(["glance-manage", "version_control", "0"])
|
||||
|
||||
juju_log('Cluster leader, performing db sync')
|
||||
migrate_database()
|
||||
|
||||
|
||||
@hooks.hook('image-service-relation-joined')
|
||||
def image_service_joined(relation_id=None):
|
||||
if not eligible_leader(CLUSTER_RES):
|
||||
@ -216,10 +265,10 @@ def config_changed():
|
||||
open_port(9292)
|
||||
configure_https()
|
||||
|
||||
#env_vars = {'OPENSTACK_PORT_MCASTPORT': config("ha-mcastport"),
|
||||
# env_vars = {'OPENSTACK_PORT_MCASTPORT': config("ha-mcastport"),
|
||||
# 'OPENSTACK_SERVICE_API': "glance-api",
|
||||
# 'OPENSTACK_SERVICE_REGISTRY': "glance-registry"}
|
||||
#save_script_rc(**env_vars)
|
||||
# save_script_rc(**env_vars)
|
||||
|
||||
|
||||
@hooks.hook('cluster-relation-changed')
|
||||
@ -231,8 +280,11 @@ def cluster_changed():
|
||||
|
||||
|
||||
@hooks.hook('upgrade-charm')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
def upgrade_charm():
|
||||
cluster_changed()
|
||||
apt_install(filter_installed_packages(PACKAGES), fatal=True)
|
||||
configure_https()
|
||||
CONFIGS.write_all()
|
||||
|
||||
|
||||
@hooks.hook('ha-relation-joined')
|
||||
@ -243,7 +295,7 @@ def ha_relation_joined():
|
||||
vip_iface = config("vip_iface")
|
||||
vip_cidr = config("vip_cidr")
|
||||
|
||||
#if vip and vip_iface and vip_cidr and \
|
||||
# if vip and vip_iface and vip_cidr and \
|
||||
# corosync_bindiface and corosync_mcastport:
|
||||
|
||||
resources = {
|
||||
@ -289,7 +341,8 @@ def ha_relation_changed():
|
||||
@hooks.hook('ceph-relation-broken',
|
||||
'identity-service-relation-broken',
|
||||
'object-store-relation-broken',
|
||||
'shared-db-relation-broken')
|
||||
'shared-db-relation-broken',
|
||||
'pgsql-db-relation-broken')
|
||||
def relation_broken():
|
||||
CONFIGS.write_all()
|
||||
|
||||
|
@ -8,8 +8,9 @@ import glance_contexts
|
||||
from collections import OrderedDict
|
||||
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
apt_update, )
|
||||
apt_upgrade,
|
||||
apt_update,
|
||||
apt_install, )
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
config,
|
||||
@ -17,7 +18,11 @@ from charmhelpers.core.hookenv import (
|
||||
relation_ids,
|
||||
service_name)
|
||||
|
||||
from charmhelpers.core.host import mkdir
|
||||
from charmhelpers.core.host import (
|
||||
mkdir,
|
||||
service_stop,
|
||||
service_start
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack import (
|
||||
templating,
|
||||
@ -41,17 +46,18 @@ CLUSTER_RES = "res_glance_vip"
|
||||
|
||||
PACKAGES = [
|
||||
"apache2", "glance", "python-mysqldb", "python-swift",
|
||||
"python-keystone", "uuid", "haproxy", ]
|
||||
"python-psycopg2", "python-keystone", "uuid", "haproxy", ]
|
||||
|
||||
SERVICES = [
|
||||
"glance-api", "glance-registry", ]
|
||||
|
||||
CHARM = "glance"
|
||||
|
||||
GLANCE_REGISTRY_CONF = "/etc/glance/glance-registry.conf"
|
||||
GLANCE_REGISTRY_PASTE_INI = "/etc/glance/glance-registry-paste.ini"
|
||||
GLANCE_API_CONF = "/etc/glance/glance-api.conf"
|
||||
GLANCE_API_PASTE_INI = "/etc/glance/glance-api-paste.ini"
|
||||
GLANCE_CONF_DIR = "/etc/glance"
|
||||
GLANCE_REGISTRY_CONF = "%s/glance-registry.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_REGISTRY_PASTE_INI = "%s/glance-registry-paste.ini" % GLANCE_CONF_DIR
|
||||
GLANCE_API_CONF = "%s/glance-api.conf" % GLANCE_CONF_DIR
|
||||
GLANCE_API_PASTE_INI = "%s/glance-api-paste.ini" % GLANCE_CONF_DIR
|
||||
CEPH_CONF = "/etc/ceph/ceph.conf"
|
||||
CHARM_CEPH_CONF = '/var/lib/charm/{}/ceph.conf'
|
||||
|
||||
@ -64,24 +70,29 @@ CONF_DIR = "/etc/glance"
|
||||
|
||||
TEMPLATES = 'templates/'
|
||||
|
||||
|
||||
def ceph_config_file():
|
||||
return CHARM_CEPH_CONF.format(service_name())
|
||||
|
||||
CONFIG_FILES = OrderedDict([
|
||||
(GLANCE_REGISTRY_CONF, {
|
||||
'hook_contexts': [context.SharedDBContext(),
|
||||
'hook_contexts': [context.SharedDBContext(ssl_dir=GLANCE_CONF_DIR),
|
||||
context.PostgresqlDBContext(),
|
||||
context.IdentityServiceContext(),
|
||||
context.SyslogContext()],
|
||||
context.SyslogContext(),
|
||||
glance_contexts.LoggingConfigContext()],
|
||||
'services': ['glance-registry']
|
||||
}),
|
||||
(GLANCE_API_CONF, {
|
||||
'hook_contexts': [context.SharedDBContext(),
|
||||
context.AMQPContext(),
|
||||
'hook_contexts': [context.SharedDBContext(ssl_dir=GLANCE_CONF_DIR),
|
||||
context.AMQPContext(ssl_dir=GLANCE_CONF_DIR),
|
||||
context.PostgresqlDBContext(),
|
||||
context.IdentityServiceContext(),
|
||||
glance_contexts.CephGlanceContext(),
|
||||
glance_contexts.ObjectStoreContext(),
|
||||
glance_contexts.HAProxyContext(),
|
||||
context.SyslogContext()],
|
||||
context.SyslogContext(),
|
||||
glance_contexts.LoggingConfigContext()],
|
||||
'services': ['glance-api']
|
||||
}),
|
||||
(GLANCE_API_PASTE_INI, {
|
||||
@ -111,6 +122,7 @@ CONFIG_FILES = OrderedDict([
|
||||
})
|
||||
])
|
||||
|
||||
|
||||
def register_configs():
|
||||
# Register config files with their respective contexts.
|
||||
# Regstration of some configs may not be required depending on
|
||||
@ -188,14 +200,17 @@ def do_openstack_upgrade(configs):
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
apt_update()
|
||||
apt_install(packages=PACKAGES, options=dpkg_opts, fatal=True)
|
||||
apt_upgrade(options=dpkg_opts, fatal=True, dist=True)
|
||||
apt_install(PACKAGES, fatal=True)
|
||||
|
||||
# set CONFIGS to load templates from new release and regenerate config
|
||||
configs.set_release(openstack_release=new_os_rel)
|
||||
configs.write_all()
|
||||
|
||||
[service_stop(s) for s in services()]
|
||||
if eligible_leader(CLUSTER_RES):
|
||||
migrate_database()
|
||||
[service_start(s) for s in services()]
|
||||
|
||||
|
||||
def restart_map():
|
||||
@ -213,3 +228,11 @@ def restart_map():
|
||||
if svcs:
|
||||
_map.append((f, svcs))
|
||||
return OrderedDict(_map)
|
||||
|
||||
|
||||
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))
|
||||
|
1
hooks/pgsql-db-relation-broken
Symbolic link
1
hooks/pgsql-db-relation-broken
Symbolic link
@ -0,0 +1 @@
|
||||
glance_relations.py
|
1
hooks/pgsql-db-relation-changed
Symbolic link
1
hooks/pgsql-db-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
glance_relations.py
|
1
hooks/pgsql-db-relation-joined
Symbolic link
1
hooks/pgsql-db-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
glance_relations.py
|
@ -14,6 +14,8 @@ provides:
|
||||
requires:
|
||||
shared-db:
|
||||
interface: mysql-shared
|
||||
pgsql-db:
|
||||
interface: pgsql
|
||||
amqp:
|
||||
interface: rabbitmq
|
||||
object-store:
|
||||
|
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
|
@ -44,7 +44,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -50,7 +50,7 @@ qpid_tcp_nodelay = True
|
||||
filesystem_store_datadir = /var/lib/glance/images/
|
||||
swift_store_auth_version = 2
|
||||
{% if swift_store %}
|
||||
swift_store_auth_address = http://{{ service_host }}:{{ service_port }}/v2.0/
|
||||
swift_store_auth_address = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v2.0/
|
||||
swift_store_user = {{ admin_tenant_name }}:{{ admin_user }}
|
||||
swift_store_key = {{ admin_password }}
|
||||
swift_store_create_container_on_put = True
|
||||
|
@ -21,7 +21,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -61,7 +61,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -19,30 +19,23 @@ bind_port = 9292
|
||||
{% endif %}
|
||||
log_file = /var/log/glance/api.log
|
||||
backlog = 4096
|
||||
{% if database_host %}
|
||||
sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% else %}
|
||||
sql_connection = sqlite:////var/lib/glance/glance.sqlite
|
||||
{% endif %}
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
sql_idle_timeout = 3600
|
||||
workers = 1
|
||||
registry_host = 0.0.0.0
|
||||
registry_port = 9191
|
||||
registry_client_protocol = http
|
||||
|
||||
{% if rabbitmq_host -%}
|
||||
notifier_strategy = rabbit
|
||||
rabbit_host = {{ rabbitmq_host }}
|
||||
rabbit_userid = {{ rabbitmq_user }}
|
||||
rabbit_password = {{ rabbitmq_password }}
|
||||
rabbit_virtual_host = {{ rabbitmq_virtual_host }}
|
||||
{% endif -%}
|
||||
{% include "parts/rabbitmq-single" %}
|
||||
|
||||
notifier_strategy = rabbit
|
||||
filesystem_store_datadir = /var/lib/glance/images/
|
||||
|
||||
{% if swift_store %}
|
||||
swift_store_auth_version = 2
|
||||
swift_store_auth_address = http://{{ service_host }}:{{ service_port }}/v2.0/
|
||||
swift_store_auth_address = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v2.0/
|
||||
swift_store_user = {{ admin_tenant_name }}:{{ admin_user }}
|
||||
swift_store_key = {{ admin_password }}
|
||||
swift_store_create_container_on_put = True
|
||||
|
@ -21,7 +21,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -6,9 +6,9 @@ bind_host = 0.0.0.0
|
||||
bind_port = 9191
|
||||
log_file = /var/log/glance/registry.log
|
||||
backlog = 4096
|
||||
{% if database_host %}
|
||||
sql_connection = mysql://{{ database_user }}:{{ database_password }}@{{ database_host }}/{{ database }}
|
||||
{% endif %}
|
||||
|
||||
{% include "parts/database" %}
|
||||
|
||||
sql_idle_timeout = 3600
|
||||
api_limit_max = 1000
|
||||
limit_param_default = 25
|
||||
|
@ -61,7 +61,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -23,7 +23,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
@ -61,7 +61,7 @@ service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
auth_uri = http://{{ service_host }}:{{ service_port }}/
|
||||
auth_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
|
72
templates/icehouse/glance-api-paste.ini
Normal file
72
templates/icehouse/glance-api-paste.ini
Normal file
@ -0,0 +1,72 @@
|
||||
# Use this pipeline for no auth or image caching - DEFAULT
|
||||
[pipeline:glance-api]
|
||||
pipeline = versionnegotiation unauthenticated-context rootapp
|
||||
|
||||
# Use this pipeline for image caching and no auth
|
||||
[pipeline:glance-api-caching]
|
||||
pipeline = versionnegotiation unauthenticated-context cache rootapp
|
||||
|
||||
# Use this pipeline for caching w/ management interface but no auth
|
||||
[pipeline:glance-api-cachemanagement]
|
||||
pipeline = versionnegotiation unauthenticated-context cache cachemanage rootapp
|
||||
|
||||
# Use this pipeline for keystone auth
|
||||
[pipeline:glance-api-keystone]
|
||||
pipeline = versionnegotiation authtoken context rootapp
|
||||
|
||||
# Use this pipeline for keystone auth with image caching
|
||||
[pipeline:glance-api-keystone+caching]
|
||||
pipeline = versionnegotiation authtoken context cache rootapp
|
||||
|
||||
# Use this pipeline for keystone auth with caching and cache management
|
||||
[pipeline:glance-api-keystone+cachemanagement]
|
||||
pipeline = versionnegotiation authtoken context cache cachemanage rootapp
|
||||
|
||||
# Use this pipeline for authZ only. This means that the registry will treat a
|
||||
# user as authenticated without making requests to keystone to reauthenticate
|
||||
# the user.
|
||||
[pipeline:glance-api-trusted-auth]
|
||||
pipeline = versionnegotiation context rootapp
|
||||
|
||||
# Use this pipeline for authZ only. This means that the registry will treat a
|
||||
# user as authenticated without making requests to keystone to reauthenticate
|
||||
# the user and uses cache management
|
||||
[pipeline:glance-api-trusted-auth+cachemanagement]
|
||||
pipeline = versionnegotiation context cache cachemanage rootapp
|
||||
|
||||
[composite:rootapp]
|
||||
paste.composite_factory = glance.api:root_app_factory
|
||||
/: apiversions
|
||||
/v1: apiv1app
|
||||
/v2: apiv2app
|
||||
|
||||
[app:apiversions]
|
||||
paste.app_factory = glance.api.versions:create_resource
|
||||
|
||||
[app:apiv1app]
|
||||
paste.app_factory = glance.api.v1.router:API.factory
|
||||
|
||||
[app:apiv2app]
|
||||
paste.app_factory = glance.api.v2.router:API.factory
|
||||
|
||||
[filter:versionnegotiation]
|
||||
paste.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory
|
||||
|
||||
[filter:cache]
|
||||
paste.filter_factory = glance.api.middleware.cache:CacheFilter.factory
|
||||
|
||||
[filter:cachemanage]
|
||||
paste.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter.factory
|
||||
|
||||
[filter:context]
|
||||
paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
|
||||
delay_auth_decision = true
|
||||
|
||||
[filter:gzip]
|
||||
paste.filter_factory = glance.api.middleware.gzip:GzipMiddleware.factory
|
64
templates/icehouse/glance-api.conf
Normal file
64
templates/icehouse/glance-api.conf
Normal file
@ -0,0 +1,64 @@
|
||||
[DEFAULT]
|
||||
verbose = {{ verbose }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
debug = {{ debug }}
|
||||
|
||||
{% if rbd_pool -%}
|
||||
default_store = rbd
|
||||
{% elif swift_store -%}
|
||||
default_store = swift
|
||||
{% else -%}
|
||||
default_store = file
|
||||
{% endif -%}
|
||||
|
||||
bind_host = 0.0.0.0
|
||||
|
||||
{% if ext -%}
|
||||
bind_port = {{ ext }}
|
||||
{% elif bind_port -%}
|
||||
bind_port = {{ bind_port }}
|
||||
{% else -%}
|
||||
bind_port = 9292
|
||||
{% endif -%}
|
||||
|
||||
log_file = /var/log/glance/api.log
|
||||
backlog = 4096
|
||||
|
||||
sql_idle_timeout = 3600
|
||||
workers = 1
|
||||
registry_host = 0.0.0.0
|
||||
registry_port = 9191
|
||||
registry_client_protocol = http
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
notifier_strategy = rabbit
|
||||
filesystem_store_datadir = /var/lib/glance/images/
|
||||
|
||||
{% if swift_store -%}
|
||||
swift_store_auth_version = 2
|
||||
swift_store_auth_address = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/v2.0/
|
||||
swift_store_user = {{ admin_tenant_name }}:{{ admin_user }}
|
||||
swift_store_key = {{ admin_password }}
|
||||
swift_store_create_container_on_put = True
|
||||
swift_store_container = glance
|
||||
swift_store_large_object_size = 5120
|
||||
swift_store_large_object_chunk_size = 200
|
||||
swift_enable_snet = False
|
||||
{% endif -%}
|
||||
|
||||
{% if rbd_pool -%}
|
||||
rbd_store_ceph_conf = /etc/ceph/ceph.conf
|
||||
rbd_store_user = {{ rbd_user }}
|
||||
rbd_store_pool = {{ rbd_pool }}
|
||||
rbd_store_chunk_size = 8
|
||||
{% endif -%}
|
||||
|
||||
delayed_delete = False
|
||||
scrub_time = 43200
|
||||
scrubber_datadir = /var/lib/glance/scrubber
|
||||
image_cache_dir = /var/lib/glance/image-cache/
|
||||
db_enforce_mysql_charset = False
|
||||
|
||||
{% include "parts/keystone" %}
|
||||
{% include "parts/section-database" %}
|
25
templates/icehouse/glance-registry-paste.ini
Normal file
25
templates/icehouse/glance-registry-paste.ini
Normal file
@ -0,0 +1,25 @@
|
||||
# Use this pipeline for no auth - DEFAULT
|
||||
[pipeline:glance-registry]
|
||||
pipeline = unauthenticated-context registryapp
|
||||
|
||||
# Use this pipeline for keystone auth
|
||||
[pipeline:glance-registry-keystone]
|
||||
pipeline = authtoken context registryapp
|
||||
|
||||
# Use this pipeline for authZ only. This means that the registry will treat a
|
||||
# user as authenticated without making requests to keystone to reauthenticate
|
||||
# the user.
|
||||
[pipeline:glance-registry-trusted-auth]
|
||||
pipeline = context registryapp
|
||||
|
||||
[app:registryapp]
|
||||
paste.app_factory = glance.registry.api:API.factory
|
||||
|
||||
[filter:context]
|
||||
paste.filter_factory = glance.api.middleware.context:ContextMiddleware.factory
|
||||
|
||||
[filter:unauthenticated-context]
|
||||
paste.filter_factory = glance.api.middleware.context:UnauthenticatedContextMiddleware.factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystoneclient.middleware.auth_token:filter_factory
|
15
templates/icehouse/glance-registry.conf
Normal file
15
templates/icehouse/glance-registry.conf
Normal file
@ -0,0 +1,15 @@
|
||||
[DEFAULT]
|
||||
verbose = {{ verbose }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
debug = {{ debug }}
|
||||
|
||||
bind_host = 0.0.0.0
|
||||
bind_port = 9191
|
||||
log_file = /var/log/glance/registry.log
|
||||
backlog = 4096
|
||||
sql_idle_timeout = 3600
|
||||
api_limit_max = 1000
|
||||
limit_param_default = 25
|
||||
|
||||
{% include "parts/keystone" %}
|
||||
{% include "parts/section-database" %}
|
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 -%}
|
13
templates/parts/keystone
Normal file
13
templates/parts/keystone
Normal file
@ -0,0 +1,13 @@
|
||||
{% 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 }}
|
||||
|
||||
[paste_deploy]
|
||||
flavor = keystone
|
||||
{% 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 -%}
|
13
templates/parts/rabbitmq-single
Normal file
13
templates/parts/rabbitmq-single
Normal file
@ -0,0 +1,13 @@
|
||||
{% if rabbitmq_host -%}
|
||||
rabbit_host = {{ rabbitmq_host }}
|
||||
rabbit_userid = {{ rabbitmq_user }}
|
||||
rabbit_password = {{ rabbitmq_password }}
|
||||
rabbit_virtual_host = {{ rabbitmq_virtual_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 -%}
|
||||
{% 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 -%}
|
@ -41,6 +41,7 @@ class TestGlanceContexts(CharmTestCase):
|
||||
{'rbd_pool': service,
|
||||
'rbd_user': service})
|
||||
|
||||
@patch('charmhelpers.contrib.openstack.context.is_clustered')
|
||||
@patch('charmhelpers.contrib.openstack.context.determine_apache_port')
|
||||
@patch('charmhelpers.contrib.openstack.context.determine_api_port')
|
||||
@patch('charmhelpers.contrib.openstack.context.unit_get')
|
||||
@ -48,11 +49,13 @@ class TestGlanceContexts(CharmTestCase):
|
||||
def test_apache_ssl_context_service_enabled(self, mock_https,
|
||||
mock_unit_get,
|
||||
mock_determine_api_port,
|
||||
mock_determine_apache_port):
|
||||
mock_determine_apache_port,
|
||||
mock_is_clustered):
|
||||
mock_https.return_value = True
|
||||
mock_unit_get.return_value = '1.2.3.4'
|
||||
mock_determine_api_port.return_value = '12'
|
||||
mock_determine_apache_port.return_value = '34'
|
||||
mock_is_clustered.return_value = False
|
||||
|
||||
ctxt = contexts.ApacheSSLContext()
|
||||
with patch.object(ctxt, 'enable_modules') as mock_enable_modules:
|
||||
@ -62,3 +65,5 @@ class TestGlanceContexts(CharmTestCase):
|
||||
'namespace': 'glance'})
|
||||
self.assertTrue(mock_https.called)
|
||||
mock_unit_get.assert_called_with('private-address')
|
||||
self.assertTrue(mock_enable_modules.called)
|
||||
self.assertTrue(mock_configure_cert.called)
|
||||
|
@ -23,6 +23,7 @@ TO_PATCH = [
|
||||
'canonical_url',
|
||||
'config',
|
||||
'juju_log',
|
||||
'is_relation_made',
|
||||
'open_port',
|
||||
'relation_ids',
|
||||
'relation_set',
|
||||
@ -53,7 +54,7 @@ TO_PATCH = [
|
||||
'check_call',
|
||||
'execd_preinstall',
|
||||
'lsb_release',
|
||||
'mkdir'
|
||||
'filter_installed_packages'
|
||||
]
|
||||
|
||||
|
||||
@ -69,12 +70,13 @@ class GlanceRelationTests(CharmTestCase):
|
||||
self.service_stop.return_value = True
|
||||
relations.install_hook()
|
||||
self.configure_installation_source.assert_called_with(repo)
|
||||
self.assertTrue(self.apt_update.called)
|
||||
self.apt_update.assert_called_with(fatal=True)
|
||||
self.apt_install.assert_called_with(['apache2', 'glance',
|
||||
'python-mysqldb',
|
||||
'python-swift',
|
||||
'python-psycopg2',
|
||||
'python-keystone',
|
||||
'uuid', 'haproxy'])
|
||||
'uuid', 'haproxy'], fatal=True)
|
||||
self.assertTrue(self.execd_preinstall.called)
|
||||
|
||||
def test_install_hook_precise_distro(self):
|
||||
@ -88,12 +90,37 @@ class GlanceRelationTests(CharmTestCase):
|
||||
|
||||
def test_db_joined(self):
|
||||
self.unit_get.return_value = 'glance.foohost.com'
|
||||
self.is_relation_made.return_value = False
|
||||
relations.db_joined()
|
||||
self.relation_set.assert_called_with(database='glance',
|
||||
username='glance',
|
||||
hostname='glance.foohost.com')
|
||||
self.unit_get.assert_called_with('private-address')
|
||||
|
||||
def test_postgresql_db_joined(self):
|
||||
self.unit_get.return_value = 'glance.foohost.com'
|
||||
self.is_relation_made.return_value = False
|
||||
relations.pgsql_db_joined()
|
||||
self.relation_set.assert_called_with(database='glance'),
|
||||
|
||||
def test_db_joined_with_postgresql(self):
|
||||
self.is_relation_made.return_value = True
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
relations.db_joined()
|
||||
self.assertEqual(context.exception.message,
|
||||
'Attempting to associate a mysql database when there '
|
||||
'is already associated a postgresql one')
|
||||
|
||||
def test_postgresql_joined_with_db(self):
|
||||
self.is_relation_made.return_value = True
|
||||
|
||||
with self.assertRaises(Exception) as context:
|
||||
relations.pgsql_db_joined()
|
||||
self.assertEqual(context.exception.message,
|
||||
'Attempting to associate a postgresql database when'
|
||||
' there is already associated a mysql one')
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_db_changed_missing_relation_data(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
@ -103,12 +130,27 @@ class GlanceRelationTests(CharmTestCase):
|
||||
'shared-db relation incomplete. Peer not ready?'
|
||||
)
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_postgresql_db_changed_missing_relation_data(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = []
|
||||
relations.pgsql_db_changed()
|
||||
self.juju_log.assert_called_with(
|
||||
'pgsql-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()
|
||||
relations.db_changed()
|
||||
|
||||
def _postgresql_db_test(self, configs):
|
||||
configs.complete_contexts = MagicMock()
|
||||
configs.complete_contexts.return_value = ['pgsql-db']
|
||||
configs.write = MagicMock()
|
||||
relations.pgsql_db_changed()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_db_changed_no_essex(self, configs):
|
||||
self._shared_db_test(configs)
|
||||
@ -120,6 +162,17 @@ class GlanceRelationTests(CharmTestCase):
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_postgresql_db_changed_no_essex(self, configs):
|
||||
self._postgresql_db_test(configs)
|
||||
self.assertEquals([call('/etc/glance/glance-registry.conf'),
|
||||
call('/etc/glance/glance-api.conf')],
|
||||
configs.write.call_args_list)
|
||||
self.juju_log.assert_called_with(
|
||||
'Cluster leader, performing db sync'
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_db_changed_with_essex_not_setting_version_control(self, configs):
|
||||
self.get_os_codename_package.return_value = "essex"
|
||||
@ -132,6 +185,19 @@ class GlanceRelationTests(CharmTestCase):
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_postgresql_db_changed_with_essex_not_setting_version_control(
|
||||
self, configs):
|
||||
self.get_os_codename_package.return_value = "essex"
|
||||
self.call.return_value = 0
|
||||
self._postgresql_db_test(configs)
|
||||
self.assertEquals([call('/etc/glance/glance-registry.conf')],
|
||||
configs.write.call_args_list)
|
||||
self.juju_log.assert_called_with(
|
||||
'Cluster leader, performing db sync'
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_db_changed_with_essex_setting_version_control(self, configs):
|
||||
self.get_os_codename_package.return_value = "essex"
|
||||
@ -147,6 +213,22 @@ class GlanceRelationTests(CharmTestCase):
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_postgresql_db_changed_with_essex_setting_version_control(
|
||||
self, configs):
|
||||
self.get_os_codename_package.return_value = "essex"
|
||||
self.call.return_value = 1
|
||||
self._postgresql_db_test(configs)
|
||||
self.assertEquals([call('/etc/glance/glance-registry.conf')],
|
||||
configs.write.call_args_list)
|
||||
self.check_call.assert_called_with(
|
||||
["glance-manage", "version_control", "0"]
|
||||
)
|
||||
self.juju_log.assert_called_with(
|
||||
'Cluster leader, performing db sync'
|
||||
)
|
||||
self.migrate_database.assert_called_with()
|
||||
|
||||
def test_image_service_joined_not_leader(self):
|
||||
self.eligible_leader.return_value = False
|
||||
relations.image_service_joined()
|
||||
@ -345,10 +427,12 @@ class GlanceRelationTests(CharmTestCase):
|
||||
call('/etc/haproxy/haproxy.cfg')],
|
||||
configs.write.call_args_list)
|
||||
|
||||
@patch.object(relations, 'cluster_changed')
|
||||
def test_upgrade_charm(self, cluster_changed):
|
||||
@patch.object(relations, 'CONFIGS')
|
||||
def test_upgrade_charm(self, configs):
|
||||
self.filter_installed_packages.return_value = ['test']
|
||||
relations.upgrade_charm()
|
||||
cluster_changed.assert_called_with()
|
||||
self.apt_install.assert_called_with(['test'], fatal=True)
|
||||
self.assertTrue(configs.write_all.called)
|
||||
|
||||
def test_ha_relation_joined(self):
|
||||
self.test_config.set('ha-bindiface', 'em0')
|
||||
|
@ -22,12 +22,20 @@ TO_PATCH = [
|
||||
'eligible_leader',
|
||||
'templating',
|
||||
'apt_update',
|
||||
'apt_upgrade',
|
||||
'apt_install',
|
||||
'mkdir',
|
||||
'service_start',
|
||||
'service_stop',
|
||||
'service_name',
|
||||
'install_alternative'
|
||||
]
|
||||
|
||||
DPKG_OPTS = [
|
||||
'--option', 'Dpkg::Options::=--force-confnew',
|
||||
'--option', 'Dpkg::Options::=--force-confdef',
|
||||
]
|
||||
|
||||
|
||||
class TestGlanceUtils(CharmTestCase):
|
||||
|
||||
@ -136,6 +144,9 @@ class TestGlanceUtils(CharmTestCase):
|
||||
configs = MagicMock()
|
||||
utils.do_openstack_upgrade(configs)
|
||||
self.assertTrue(configs.write_all.called)
|
||||
self.apt_install.assert_called_with(utils.PACKAGES, fatal=True)
|
||||
self.apt_upgrade.assert_called_with(options=DPKG_OPTS,
|
||||
fatal=True, dist=True)
|
||||
configs.set_release.assert_called_with(openstack_release='havana')
|
||||
self.assertTrue(migrate.called)
|
||||
|
||||
@ -148,5 +159,8 @@ class TestGlanceUtils(CharmTestCase):
|
||||
configs = MagicMock()
|
||||
utils.do_openstack_upgrade(configs)
|
||||
self.assertTrue(configs.write_all.called)
|
||||
self.apt_install.assert_called_with(utils.PACKAGES, fatal=True)
|
||||
self.apt_upgrade.assert_called_with(options=DPKG_OPTS,
|
||||
fatal=True, dist=True)
|
||||
configs.set_release.assert_called_with(openstack_release='havana')
|
||||
self.assertFalse(migrate.called)
|
||||
|
Loading…
x
Reference in New Issue
Block a user