Merged trunk in + LE charmhelper sync

This commit is contained in:
Liam Young
2015-05-11 09:04:17 +01:00
31 changed files with 294 additions and 89 deletions

View File

@@ -15,8 +15,7 @@ test:
# coreycb note: The -v should only be temporary until Amulet sends
# raise_status() messages to stderr:
# https://bugs.launchpad.net/amulet/+bug/1320357
@juju test -v -p AMULET_HTTP_PROXY --timeout 1200 \
00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse
@juju test -v -p AMULET_HTTP_PROXY,AMULET_OS_VIP --timeout 2700
bin/charm_helpers_sync.py:
@mkdir -p bin

View File

@@ -79,6 +79,12 @@ options:
default:
description: |
Base64 encoded SSL key to use with certificate specified as ssl_cert.
ssl_ca:
type: string
default:
description: |
Base64 encoded SSL CA to use with the certificate and key provided - only
required if you are providing a privately signed ssl_cert and ssl_key.
# General Swift Proxy configuration
bind-port:
default: 8080
@@ -116,6 +122,15 @@ options:
Timeouts from these requests can be recovered from so setting this to
something lower than node-timeout would provide quicker error recovery
while allowing for a longer timeout for non-recoverable requests (PUTs).
# Logging configuration
debug:
default: False
type: boolean
description: Enable debug level logging.
log-headers:
default: False
type: boolean
description: Enable logging of all request headers.
# Manual Keystone configuration.
keystone-auth-host:
type: string

View File

@@ -247,7 +247,9 @@ class NRPE(object):
service('restart', 'nagios-nrpe-server')
for rid in relation_ids("local-monitors"):
monitor_ids = relation_ids("local-monitors") + \
relation_ids("nrpe-external-master")
for rid in monitor_ids:
relation_set(relation_id=rid, monitors=yaml.dump(monitors))

View File

@@ -44,17 +44,24 @@ class OpenStackAmuletDeployment(AmuletDeployment):
Determine if the local branch being tested is derived from its
stable or next (dev) branch, and based on this, use the corresonding
stable or next branches for the other_services."""
base_charms = ['mysql', 'mongodb', 'rabbitmq-server']
base_charms = ['mysql', 'mongodb']
if self.series in ['precise', 'trusty']:
base_series = self.series
else:
base_series = self.current_next
if self.stable:
for svc in other_services:
temp = 'lp:charms/{}'
svc['location'] = temp.format(svc['name'])
temp = 'lp:charms/{}/{}'
svc['location'] = temp.format(base_series,
svc['name'])
else:
for svc in other_services:
if svc['name'] in base_charms:
temp = 'lp:charms/{}'
svc['location'] = temp.format(svc['name'])
temp = 'lp:charms/{}/{}'
svc['location'] = temp.format(base_series,
svc['name'])
else:
temp = 'lp:~openstack-charmers/charms/{}/{}/next'
svc['location'] = temp.format(self.current_next,
@@ -99,9 +106,12 @@ class OpenStackAmuletDeployment(AmuletDeployment):
Return an integer representing the enum value of the openstack
release.
"""
# Must be ordered by OpenStack release (not by Ubuntu release):
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
self.precise_havana, self.precise_icehouse,
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
self.trusty_icehouse, self.trusty_juno, self.utopic_juno,
self.trusty_kilo, self.vivid_kilo) = range(10)
releases = {
('precise', None): self.precise_essex,
('precise', 'cloud:precise-folsom'): self.precise_folsom,
@@ -110,7 +120,9 @@ class OpenStackAmuletDeployment(AmuletDeployment):
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
('trusty', None): self.trusty_icehouse,
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo,
('utopic', None): self.utopic_juno,
('vivid', None): self.vivid_kilo}
return releases[(self.series, self.openstack)]
def _get_openstack_release_string(self):

View File

@@ -459,6 +459,11 @@ class AMQPContext(OSContextGenerator):
ctxt['rabbitmq_hosts'] = ','.join(sorted(rabbitmq_hosts))
oslo_messaging_flags = conf.get('oslo-messaging-flags', None)
if oslo_messaging_flags:
ctxt['oslo_messaging_flags'] = config_flags_parser(
oslo_messaging_flags)
if not context_complete(ctxt):
return {}
@@ -808,6 +813,19 @@ class NeutronContext(OSContextGenerator):
return ovs_ctxt
def nuage_ctxt(self):
driver = neutron_plugin_attribute(self.plugin, 'driver',
self.network_manager)
config = neutron_plugin_attribute(self.plugin, 'config',
self.network_manager)
nuage_ctxt = {'core_plugin': driver,
'neutron_plugin': 'vsp',
'neutron_security_groups': self.neutron_security_groups,
'local_ip': unit_private_ip(),
'config': config}
return nuage_ctxt
def nvp_ctxt(self):
driver = neutron_plugin_attribute(self.plugin, 'driver',
self.network_manager)
@@ -891,6 +909,8 @@ class NeutronContext(OSContextGenerator):
ctxt.update(self.n1kv_ctxt())
elif self.plugin == 'Calico':
ctxt.update(self.calico_ctxt())
elif self.plugin == 'vsp':
ctxt.update(self.nuage_ctxt())
alchemy_flags = config('neutron-alchemy-flags')
if alchemy_flags:

View File

@@ -180,6 +180,19 @@ def neutron_plugins():
'nova-api-metadata']],
'server_packages': ['neutron-server', 'calico-control'],
'server_services': ['neutron-server']
},
'vsp': {
'config': '/etc/neutron/plugins/nuage/nuage_plugin.ini',
'driver': 'neutron.plugins.nuage.plugin.NuagePlugin',
'contexts': [
context.SharedDBContext(user=config('neutron-database-user'),
database=config('neutron-database'),
relation_prefix='neutron',
ssl_dir=NEUTRON_CONF_DIR)],
'services': [],
'packages': [],
'server_packages': ['neutron-server', 'neutron-plugin-nuage'],
'server_services': ['neutron-server']
}
}
if release >= 'icehouse':

View File

@@ -9,5 +9,9 @@ respawn
exec start-stop-daemon --start --chuid {{ user_name }} \
--chdir {{ start_dir }} --name {{ process_name }} \
--exec {{ executable_name }} -- \
{% for config_file in config_files -%}
--config-file={{ config_file }} \
{% endfor -%}
{% if log_file -%}
--log-file={{ log_file }}
{% endif -%}

View File

@@ -510,8 +510,10 @@ def git_clone_and_install(projects_yaml, core_project):
repository: 'git://git.openstack.org/openstack/requirements.git',
branch: 'stable/icehouse'}
directory: /mnt/openstack-git
http_proxy: http://squid.internal:3128
https_proxy: https://squid.internal:3128
The directory key is optional.
The directory, http_proxy, and https_proxy keys are optional.
"""
global requirements_dir
parent_dir = '/mnt/openstack-git'
@@ -522,6 +524,13 @@ def git_clone_and_install(projects_yaml, core_project):
projects = yaml.load(projects_yaml)
_git_validate_projects_yaml(projects, core_project)
old_environ = dict(os.environ)
if 'http_proxy' in projects.keys():
os.environ['http_proxy'] = projects['http_proxy']
if 'https_proxy' in projects.keys():
os.environ['https_proxy'] = projects['https_proxy']
if 'directory' in projects.keys():
parent_dir = projects['directory']
@@ -536,6 +545,8 @@ def git_clone_and_install(projects_yaml, core_project):
repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
update_requirements=True)
os.environ = old_environ
def _git_validate_projects_yaml(projects, core_project):
"""

View File

@@ -175,6 +175,8 @@ def peer_retrieve_by_prefix(prefix, relation_name='cluster', delimiter='_',
exc_list = exc_list if exc_list else []
peerdb_settings = peer_retrieve('-', relation_name=relation_name)
matched = {}
if peerdb_settings is None:
return matched
for k, v in peerdb_settings.items():
full_prefix = prefix + delimiter
if k.startswith(full_prefix):

View File

@@ -20,11 +20,14 @@
# Authors:
# Charm Helpers Developers <juju@lists.ubuntu.com>
from __future__ import print_function
from functools import wraps
import os
import json
import yaml
import subprocess
import sys
import errno
from subprocess import CalledProcessError
import six
@@ -56,15 +59,17 @@ def cached(func):
will cache the result of unit_get + 'test' for future calls.
"""
@wraps(func)
def wrapper(*args, **kwargs):
global cache
key = str((func, args, kwargs))
try:
return cache[key]
except KeyError:
res = func(*args, **kwargs)
cache[key] = res
return res
pass # Drop out of the exception handler scope.
res = func(*args, **kwargs)
cache[key] = res
return res
return wrapper
@@ -87,7 +92,18 @@ def log(message, level=None):
if not isinstance(message, six.string_types):
message = repr(message)
command += [message]
subprocess.call(command)
# Missing juju-log should not cause failures in unit tests
# Send log output to stderr
try:
subprocess.call(command)
except OSError as e:
if e.errno == errno.ENOENT:
if level:
message = "{}: {}".format(level, message)
message = "juju-log: {}".format(message)
print(message, file=sys.stderr)
else:
raise
class Serializable(UserDict):
@@ -165,7 +181,7 @@ def local_unit():
def remote_unit():
"""The remote unit for the current relation hook"""
return os.environ['JUJU_REMOTE_UNIT']
return os.environ.get('JUJU_REMOTE_UNIT', None)
def service_name():
@@ -237,6 +253,12 @@ class Config(dict):
except KeyError:
return (self._prev_dict or {})[key]
def get(self, key, default=None):
try:
return self[key]
except KeyError:
return default
def keys(self):
prev_keys = []
if self._prev_dict is not None:
@@ -507,6 +529,11 @@ def unit_get(attribute):
return None
def unit_public_ip():
"""Get this unit's public IP address"""
return unit_get('public-address')
def unit_private_ip():
"""Get this unit's private IP address"""
return unit_get('private-address')
@@ -664,3 +691,49 @@ def action_fail(message):
The results set by action_set are preserved."""
subprocess.check_call(['action-fail', message])
def status_set(workload_state, message):
"""Set the workload state with a message
Use status-set to set the workload state with a message which is visible
to the user via juju status. If the status-set command is not found then
assume this is juju < 1.23 and juju-log the message unstead.
workload_state -- valid juju workload state.
message -- status update message
"""
valid_states = ['maintenance', 'blocked', 'waiting', 'active']
if workload_state not in valid_states:
raise ValueError(
'{!r} is not a valid workload state'.format(workload_state)
)
cmd = ['status-set', workload_state, message]
try:
ret = subprocess.call(cmd)
if ret == 0:
return
except OSError as e:
if e.errno != errno.ENOENT:
raise
log_message = 'status-set failed: {} {}'.format(workload_state,
message)
log(log_message, level='INFO')
def status_get():
"""Retrieve the previously set juju workload state
If the status-set command is not found then assume this is juju < 1.23 and
return 'unknown'
"""
cmd = ['status-get']
try:
raw_status = subprocess.check_output(cmd, universal_newlines=True)
status = raw_status.rstrip()
return status
except OSError as e:
if e.errno == errno.ENOENT:
return 'unknown'
else:
raise

View File

@@ -90,7 +90,7 @@ def service_available(service_name):
['service', service_name, 'status'],
stderr=subprocess.STDOUT).decode('UTF-8')
except subprocess.CalledProcessError as e:
return 'unrecognized service' not in e.output
return b'unrecognized service' not in e.output
else:
return True

View File

@@ -17,7 +17,7 @@
import os
import re
import json
from collections import Iterable
from collections import Iterable, OrderedDict
from charmhelpers.core import host
from charmhelpers.core import hookenv
@@ -119,7 +119,7 @@ class ServiceManager(object):
"""
self._ready_file = os.path.join(hookenv.charm_dir(), 'READY-SERVICES.json')
self._ready = None
self.services = {}
self.services = OrderedDict()
for service in services or []:
service_name = service['service']
self.services[service_name] = service

View File

@@ -33,9 +33,9 @@ def bool_from_string(value):
value = value.strip().lower()
if value in ['y', 'yes', 'true', 't']:
if value in ['y', 'yes', 'true', 't', 'on']:
return True
elif value in ['n', 'no', 'false', 'f']:
elif value in ['n', 'no', 'false', 'f', 'off']:
return False
msg = "Unable to interpret string value '%s' as boolean" % (value)

View File

@@ -158,7 +158,7 @@ def filter_installed_packages(packages):
def apt_cache(in_memory=True):
"""Build and return an apt cache"""
import apt_pkg
from apt import apt_pkg
apt_pkg.init()
if in_memory:
apt_pkg.config.set("Dir::Cache::pkgcache", "")

View File

@@ -100,8 +100,14 @@ class SwiftIdentityContext(OSContextGenerator):
'delay_auth_decision': config('delay-auth-decision'),
'node_timeout': config('node-timeout'),
'recoverable_node_timeout': config('recoverable-node-timeout'),
'log_headers': config('log-headers')
}
if config('debug'):
ctxt['log_level'] = 'DEBUG'
else:
ctxt['log_level'] = 'INFO'
# Instead of duplicating code lets use charm-helpers to set signing_dir
# TODO(hopem): refactor this context handler to use charm-helpers
# code.

View File

@@ -82,7 +82,6 @@ from charmhelpers.contrib.network.ip import (
format_ipv6_addr,
)
from charmhelpers.contrib.openstack.context import ADDRESS_TYPES
from charmhelpers.contrib.charmsupport import nrpe
extra_pkgs = [
@@ -147,22 +146,18 @@ def config_changed():
@hooks.hook('identity-service-relation-joined')
def keystone_joined(relid=None):
if not is_elected_leader(SWIFT_HA_RES):
return
port = config('bind-port')
admin_url = '%s:%s' % (canonical_url(CONFIGS, ADMIN), port)
internal_url = '%s:%s/v1/AUTH_$(tenant_id)s' % \
(canonical_url(CONFIGS, INTERNAL), port)
public_url = '%s:%s/v1/AUTH_$(tenant_id)s' % \
(canonical_url(CONFIGS, PUBLIC), port)
relation_set(service='swift',
region=config('region'),
public_url=public_url,
internal_url=internal_url,
admin_url=admin_url,
requested_roles=config('operator-roles'),
relation_id=relid)
internal_url = ('%s:%s/v1/AUTH_$(tenant_id)s' %
(canonical_url(CONFIGS, INTERNAL), port))
public_url = ('%s:%s/v1/AUTH_$(tenant_id)s' %
(canonical_url(CONFIGS, PUBLIC), port))
region = config('region')
roles = config('operator-roles')
relation_set(service='swift', region=region, public_url=public_url,
internal_url=internal_url, admin_url=admin_url,
requested_roles=roles, relation_id=relid)
@hooks.hook('identity-service-relation-changed')

View File

@@ -3,6 +3,12 @@ bind_port = {{ bind_port }}
workers = {{ workers }}
user = swift
bind_ip = {{ bind_host }}
log_name = swift
log_facility = LOG_LOCAL0
log_level = {{ log_level }}
log_address = /dev/log
log_headers = {{ log_headers }}
{% if ssl %}
cert_file = {{ ssl_cert }}
key_file = {{ ssl_key }}
@@ -10,10 +16,10 @@ key_file = {{ ssl_key }}
{% if auth_type == 'keystone' %}
[pipeline:main]
pipeline = gatekeeper healthcheck cache swift3 s3token container_sync bulk tempurl slo dlo formpost authtoken keystoneauth staticweb container-quotas account-quotas proxy-server
pipeline = gatekeeper healthcheck proxy-logging cache swift3 s3token container_sync bulk tempurl slo dlo formpost authtoken keystoneauth staticweb container-quotas account-quotas proxy-logging proxy-server
{% else %}
[pipeline:main]
pipeline = gatekeeper healthcheck cache container_sync bulk tempurl slo dlo formpost tempauth staticweb container-quotas account-quotas proxy-server
pipeline = gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl slo dlo formpost tempauth staticweb container-quotas account-quotas proxy-logging proxy-server
{% endif %}
[app:proxy-server]
@@ -40,6 +46,9 @@ use = egg:swift#account_quotas
[filter:container-quotas]
use = egg:swift#container_quotas
[filter:proxy-logging]
use = egg:swift#proxy_logging
[filter:staticweb]
use = egg:swift#staticweb

View File

@@ -3,6 +3,12 @@ bind_port = {{ bind_port }}
workers = {{ workers }}
user = swift
bind_ip = {{ bind_host }}
log_name = swift
log_facility = LOG_LOCAL0
log_level = {{ log_level }}
log_address = /dev/log
log_headers = {{ log_headers }}
{% if ssl %}
cert_file = {{ ssl_cert }}
key_file = {{ ssl_key }}
@@ -10,10 +16,10 @@ key_file = {{ ssl_key }}
{% if auth_type == 'keystone' %}
[pipeline:main]
pipeline = gatekeeper healthcheck cache swift3 s3token container_sync bulk tempurl slo dlo formpost authtoken keystoneauth staticweb container-quotas account-quotas proxy-server
pipeline = gatekeeper healthcheck proxy-logging cache swift3 s3token container_sync bulk tempurl slo dlo formpost authtoken keystoneauth staticweb container-quotas account-quotas proxy-logging proxy-server
{% else %}
[pipeline:main]
pipeline = gatekeeper healthcheck cache container_sync bulk tempurl slo dlo formpost tempauth staticweb container-quotas account-quotas proxy-server
pipeline = gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl slo dlo formpost tempauth staticweb container-quotas account-quotas proxy-logging proxy-server
{% endif %}
[app:proxy-server]
@@ -40,6 +46,9 @@ use = egg:swift#account_quotas
[filter:container-quotas]
use = egg:swift#container_quotas
[filter:proxy-logging]
use = egg:swift#proxy_logging
[filter:staticweb]
use = egg:swift#staticweb

11
tests/016-basic-trusty-juno Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on trusty-juno."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='trusty',
openstack='cloud:trusty-juno',
source='cloud:trusty-updates/juno')
deployment.run_tests()

View File

@@ -0,0 +1,11 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on trusty-kilo."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='trusty',
openstack='cloud:trusty-kilo',
source='cloud:trusty-updates/kilo')
deployment.run_tests()

9
tests/018-basic-utopic-juno Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on utopic-juno."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='utopic')
deployment.run_tests()

View File

@@ -0,0 +1,9 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on vivid-kilo."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='vivid')
deployment.run_tests()

View File

@@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on precise-folsom."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='precise',
openstack='cloud:precise-folsom',
source='cloud:precise-updates/folsom')
deployment.run_tests()

View File

@@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on precise-grizzly."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='precise',
openstack='cloud:precise-grizzly',
source='cloud:precise-updates/grizzly')
deployment.run_tests()

View File

@@ -1,11 +0,0 @@
#!/usr/bin/python
"""Amulet tests on a basic swift-proxy deployment on precise-havana."""
from basic_deployment import SwiftProxyBasicDeployment
if __name__ == '__main__':
deployment = SwiftProxyBasicDeployment(series='precise',
openstack='cloud:precise-havana',
source='cloud:precise-updates/havana')
deployment.run_tests()

View File

@@ -14,7 +14,7 @@ from charmhelpers.contrib.openstack.amulet.utils import (
)
# Use DEBUG to turn on debug logging
u = OpenStackAmuletUtils(ERROR)
u = OpenStackAmuletUtils(DEBUG)
class SwiftProxyBasicDeployment(OpenStackAmuletDeployment):
@@ -368,13 +368,19 @@ class SwiftProxyBasicDeployment(OpenStackAmuletDeployment):
expected = {
'DEFAULT': {
'bind_port': '8070',
'user': 'swift'
'user': 'swift',
'log_name': 'swift',
'log_facility': 'LOG_LOCAL0',
'log_level': 'INFO',
'log_headers': 'False',
'log_address': '/dev/log'
},
'pipeline:main': {
'pipeline': 'gatekeeper healthcheck cache swift3 s3token '
'container_sync bulk tempurl slo dlo formpost '
'authtoken keystoneauth staticweb '
'container-quotas account-quotas proxy-server'
'pipeline': 'gatekeeper healthcheck proxy-logging cache swift3 '
's3token container_sync bulk tempurl slo dlo '
'formpost authtoken keystoneauth staticweb '
'container-quotas account-quotas proxy-logging '
'proxy-server'
},
'app:proxy-server': {
'use': 'egg:swift#proxy',
@@ -395,6 +401,7 @@ class SwiftProxyBasicDeployment(OpenStackAmuletDeployment):
},
'filter:account-quotas': {'use': 'egg:swift#account_quotas'},
'filter:container-quotas': {'use': 'egg:swift#container_quotas'},
'filter:proxy-logging': {'use': 'egg:swift#proxy_logging'},
'filter:staticweb': {'use': 'egg:swift#staticweb'},
'filter:bulk': {'use': 'egg:swift#bulk'},
'filter:slo': {'use': 'egg:swift#slo'},

View File

@@ -79,6 +79,9 @@ class AmuletUtils(object):
for k, v in six.iteritems(commands):
for cmd in v:
output, code = k.run(cmd)
self.log.debug('{} `{}` returned '
'{}'.format(k.info['unit_name'],
cmd, code))
if code != 0:
return "command `{}` returned {}".format(cmd, str(code))
return None
@@ -86,7 +89,11 @@ class AmuletUtils(object):
def _get_config(self, unit, filename):
"""Get a ConfigParser object for parsing a unit's config file."""
file_contents = unit.file_contents(filename)
config = ConfigParser.ConfigParser()
# NOTE(beisner): by default, ConfigParser does not handle options
# with no value, such as the flags used in the mysql my.cnf file.
# https://bugs.python.org/issue7005
config = ConfigParser.ConfigParser(allow_no_value=True)
config.readfp(io.StringIO(file_contents))
return config
@@ -118,6 +125,9 @@ class AmuletUtils(object):
longs, or can be a function that evaluate a variable and returns a
bool.
"""
self.log.debug('actual: {}'.format(repr(actual)))
self.log.debug('expected: {}'.format(repr(expected)))
for k, v in six.iteritems(expected):
if k in actual:
if (isinstance(v, six.string_types) or
@@ -134,7 +144,6 @@ class AmuletUtils(object):
def validate_relation_data(self, sentry_unit, relation, expected):
"""Validate actual relation data based on expected relation data."""
actual = sentry_unit.relation(relation[0], relation[1])
self.log.debug('actual: {}'.format(repr(actual)))
return self._validate_dict_data(expected, actual)
def _validate_list_data(self, expected, actual):

View File

@@ -44,17 +44,24 @@ class OpenStackAmuletDeployment(AmuletDeployment):
Determine if the local branch being tested is derived from its
stable or next (dev) branch, and based on this, use the corresonding
stable or next branches for the other_services."""
base_charms = ['mysql', 'mongodb', 'rabbitmq-server']
base_charms = ['mysql', 'mongodb']
if self.series in ['precise', 'trusty']:
base_series = self.series
else:
base_series = self.current_next
if self.stable:
for svc in other_services:
temp = 'lp:charms/{}'
svc['location'] = temp.format(svc['name'])
temp = 'lp:charms/{}/{}'
svc['location'] = temp.format(base_series,
svc['name'])
else:
for svc in other_services:
if svc['name'] in base_charms:
temp = 'lp:charms/{}'
svc['location'] = temp.format(svc['name'])
temp = 'lp:charms/{}/{}'
svc['location'] = temp.format(base_series,
svc['name'])
else:
temp = 'lp:~openstack-charmers/charms/{}/{}/next'
svc['location'] = temp.format(self.current_next,
@@ -99,9 +106,12 @@ class OpenStackAmuletDeployment(AmuletDeployment):
Return an integer representing the enum value of the openstack
release.
"""
# Must be ordered by OpenStack release (not by Ubuntu release):
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
self.precise_havana, self.precise_icehouse,
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
self.trusty_icehouse, self.trusty_juno, self.utopic_juno,
self.trusty_kilo, self.vivid_kilo) = range(10)
releases = {
('precise', None): self.precise_essex,
('precise', 'cloud:precise-folsom'): self.precise_folsom,
@@ -110,7 +120,9 @@ class OpenStackAmuletDeployment(AmuletDeployment):
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
('trusty', None): self.trusty_icehouse,
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo,
('utopic', None): self.utopic_juno,
('vivid', None): self.vivid_kilo}
return releases[(self.series, self.openstack)]
def _get_openstack_release_string(self):