[james-page, r=gnuoy] Add 0mq support
This commit is contained in:
commit
679b42a79e
|
@ -15,6 +15,7 @@
|
||||||
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
from collections import OrderedDict
|
||||||
from charmhelpers.contrib.amulet.deployment import (
|
from charmhelpers.contrib.amulet.deployment import (
|
||||||
AmuletDeployment
|
AmuletDeployment
|
||||||
)
|
)
|
||||||
|
@ -100,12 +101,34 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||||
"""
|
"""
|
||||||
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
||||||
self.precise_havana, self.precise_icehouse,
|
self.precise_havana, self.precise_icehouse,
|
||||||
self.trusty_icehouse) = range(6)
|
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
|
||||||
releases = {
|
releases = {
|
||||||
('precise', None): self.precise_essex,
|
('precise', None): self.precise_essex,
|
||||||
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
||||||
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
||||||
('precise', 'cloud:precise-havana'): self.precise_havana,
|
('precise', 'cloud:precise-havana'): self.precise_havana,
|
||||||
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
||||||
('trusty', None): self.trusty_icehouse}
|
('trusty', None): self.trusty_icehouse,
|
||||||
|
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
|
||||||
|
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
|
||||||
return releases[(self.series, self.openstack)]
|
return releases[(self.series, self.openstack)]
|
||||||
|
|
||||||
|
def _get_openstack_release_string(self):
|
||||||
|
"""Get openstack release string.
|
||||||
|
|
||||||
|
Return a string representing the openstack release.
|
||||||
|
"""
|
||||||
|
releases = OrderedDict([
|
||||||
|
('precise', 'essex'),
|
||||||
|
('quantal', 'folsom'),
|
||||||
|
('raring', 'grizzly'),
|
||||||
|
('saucy', 'havana'),
|
||||||
|
('trusty', 'icehouse'),
|
||||||
|
('utopic', 'juno'),
|
||||||
|
('vivid', 'kilo'),
|
||||||
|
])
|
||||||
|
if self.openstack:
|
||||||
|
os_origin = self.openstack.split(':')[1]
|
||||||
|
return os_origin.split('%s-' % self.series)[1].split('/')[0]
|
||||||
|
else:
|
||||||
|
return releases[self.series]
|
||||||
|
|
|
@ -47,6 +47,7 @@ from charmhelpers.core.hookenv import (
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.core.sysctl import create as sysctl_create
|
from charmhelpers.core.sysctl import create as sysctl_create
|
||||||
|
from charmhelpers.core.strutils import bool_from_string
|
||||||
|
|
||||||
from charmhelpers.core.host import (
|
from charmhelpers.core.host import (
|
||||||
list_nics,
|
list_nics,
|
||||||
|
@ -67,6 +68,7 @@ from charmhelpers.contrib.hahelpers.apache import (
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.openstack.neutron import (
|
from charmhelpers.contrib.openstack.neutron import (
|
||||||
neutron_plugin_attribute,
|
neutron_plugin_attribute,
|
||||||
|
parse_data_port_mappings,
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.openstack.ip import (
|
from charmhelpers.contrib.openstack.ip import (
|
||||||
resolve_address,
|
resolve_address,
|
||||||
|
@ -82,7 +84,6 @@ from charmhelpers.contrib.network.ip import (
|
||||||
is_bridge_member,
|
is_bridge_member,
|
||||||
)
|
)
|
||||||
from charmhelpers.contrib.openstack.utils import get_host_ip
|
from charmhelpers.contrib.openstack.utils import get_host_ip
|
||||||
|
|
||||||
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
|
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
|
||||||
ADDRESS_TYPES = ['admin', 'internal', 'public']
|
ADDRESS_TYPES = ['admin', 'internal', 'public']
|
||||||
|
|
||||||
|
@ -1162,3 +1163,145 @@ class SysctlContext(OSContextGenerator):
|
||||||
sysctl_create(sysctl_dict,
|
sysctl_create(sysctl_dict,
|
||||||
'/etc/sysctl.d/50-{0}.conf'.format(charm_name()))
|
'/etc/sysctl.d/50-{0}.conf'.format(charm_name()))
|
||||||
return {'sysctl': sysctl_dict}
|
return {'sysctl': sysctl_dict}
|
||||||
|
|
||||||
|
|
||||||
|
class NeutronAPIContext(OSContextGenerator):
|
||||||
|
'''
|
||||||
|
Inspects current neutron-plugin-api relation for neutron settings. Return
|
||||||
|
defaults if it is not present.
|
||||||
|
'''
|
||||||
|
interfaces = ['neutron-plugin-api']
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
self.neutron_defaults = {
|
||||||
|
'l2_population': {
|
||||||
|
'rel_key': 'l2-population',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
'overlay_network_type': {
|
||||||
|
'rel_key': 'overlay-network-type',
|
||||||
|
'default': 'gre',
|
||||||
|
},
|
||||||
|
'neutron_security_groups': {
|
||||||
|
'rel_key': 'neutron-security-groups',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
'network_device_mtu': {
|
||||||
|
'rel_key': 'network-device-mtu',
|
||||||
|
'default': None,
|
||||||
|
},
|
||||||
|
'enable_dvr': {
|
||||||
|
'rel_key': 'enable-dvr',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
'enable_l3ha': {
|
||||||
|
'rel_key': 'enable-l3ha',
|
||||||
|
'default': False,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ctxt = self.get_neutron_options({})
|
||||||
|
for rid in relation_ids('neutron-plugin-api'):
|
||||||
|
for unit in related_units(rid):
|
||||||
|
rdata = relation_get(rid=rid, unit=unit)
|
||||||
|
if 'l2-population' in rdata:
|
||||||
|
ctxt.update(self.get_neutron_options(rdata))
|
||||||
|
|
||||||
|
return ctxt
|
||||||
|
|
||||||
|
def get_neutron_options(self, rdata):
|
||||||
|
settings = {}
|
||||||
|
for nkey in self.neutron_defaults.keys():
|
||||||
|
defv = self.neutron_defaults[nkey]['default']
|
||||||
|
rkey = self.neutron_defaults[nkey]['rel_key']
|
||||||
|
if rkey in rdata.keys():
|
||||||
|
if type(defv) is bool:
|
||||||
|
settings[nkey] = bool_from_string(rdata[rkey])
|
||||||
|
else:
|
||||||
|
settings[nkey] = rdata[rkey]
|
||||||
|
else:
|
||||||
|
settings[nkey] = defv
|
||||||
|
return settings
|
||||||
|
|
||||||
|
|
||||||
|
class ExternalPortContext(NeutronPortContext):
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
ctxt = {}
|
||||||
|
ports = config('ext-port')
|
||||||
|
if ports:
|
||||||
|
ports = [p.strip() for p in ports.split()]
|
||||||
|
ports = self.resolve_ports(ports)
|
||||||
|
if ports:
|
||||||
|
ctxt = {"ext_port": ports[0]}
|
||||||
|
napi_settings = NeutronAPIContext()()
|
||||||
|
mtu = napi_settings.get('network_device_mtu')
|
||||||
|
if mtu:
|
||||||
|
ctxt['ext_port_mtu'] = mtu
|
||||||
|
|
||||||
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
|
class DataPortContext(NeutronPortContext):
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
ports = config('data-port')
|
||||||
|
if ports:
|
||||||
|
portmap = parse_data_port_mappings(ports)
|
||||||
|
ports = portmap.values()
|
||||||
|
resolved = self.resolve_ports(ports)
|
||||||
|
normalized = {get_nic_hwaddr(port): port for port in resolved
|
||||||
|
if port not in ports}
|
||||||
|
normalized.update({port: port for port in resolved
|
||||||
|
if port in ports})
|
||||||
|
if resolved:
|
||||||
|
return {bridge: normalized[port] for bridge, port in
|
||||||
|
six.iteritems(portmap) if port in normalized.keys()}
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class PhyNICMTUContext(DataPortContext):
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
ctxt = {}
|
||||||
|
mappings = super(PhyNICMTUContext, self).__call__()
|
||||||
|
if mappings and mappings.values():
|
||||||
|
ports = mappings.values()
|
||||||
|
napi_settings = NeutronAPIContext()()
|
||||||
|
mtu = napi_settings.get('network_device_mtu')
|
||||||
|
if mtu:
|
||||||
|
ctxt["devs"] = '\\n'.join(ports)
|
||||||
|
ctxt['mtu'] = mtu
|
||||||
|
|
||||||
|
return ctxt
|
||||||
|
|
||||||
|
|
||||||
|
class NetworkServiceContext(OSContextGenerator):
|
||||||
|
|
||||||
|
def __init__(self, rel_name='quantum-network-service'):
|
||||||
|
self.rel_name = rel_name
|
||||||
|
self.interfaces = [rel_name]
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
for rid in relation_ids(self.rel_name):
|
||||||
|
for unit in related_units(rid):
|
||||||
|
rdata = relation_get(rid=rid, unit=unit)
|
||||||
|
ctxt = {
|
||||||
|
'keystone_host': rdata.get('keystone_host'),
|
||||||
|
'service_port': rdata.get('service_port'),
|
||||||
|
'auth_port': rdata.get('auth_port'),
|
||||||
|
'service_tenant': rdata.get('service_tenant'),
|
||||||
|
'service_username': rdata.get('service_username'),
|
||||||
|
'service_password': rdata.get('service_password'),
|
||||||
|
'quantum_host': rdata.get('quantum_host'),
|
||||||
|
'quantum_port': rdata.get('quantum_port'),
|
||||||
|
'quantum_url': rdata.get('quantum_url'),
|
||||||
|
'region': rdata.get('region'),
|
||||||
|
'service_protocol':
|
||||||
|
rdata.get('service_protocol') or 'http',
|
||||||
|
'auth_protocol':
|
||||||
|
rdata.get('auth_protocol') or 'http',
|
||||||
|
}
|
||||||
|
if context_complete(ctxt):
|
||||||
|
return ctxt
|
||||||
|
return {}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
description "{{ service_description }}"
|
||||||
|
author "Juju {{ service_name }} Charm <juju@localhost>"
|
||||||
|
|
||||||
|
start on runlevel [2345]
|
||||||
|
stop on runlevel [!2345]
|
||||||
|
|
||||||
|
respawn
|
||||||
|
|
||||||
|
exec start-stop-daemon --start --chuid {{ user_name }} \
|
||||||
|
--chdir {{ start_dir }} --name {{ process_name }} \
|
||||||
|
--exec {{ executable_name }} -- \
|
||||||
|
--config-file={{ config_file }} \
|
||||||
|
--log-file={{ log_file }}
|
|
@ -3,12 +3,12 @@
|
||||||
rpc_backend = zmq
|
rpc_backend = zmq
|
||||||
rpc_zmq_host = {{ zmq_host }}
|
rpc_zmq_host = {{ zmq_host }}
|
||||||
{% if zmq_redis_address -%}
|
{% if zmq_redis_address -%}
|
||||||
rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
|
rpc_zmq_matchmaker = redis
|
||||||
matchmaker_heartbeat_freq = 15
|
matchmaker_heartbeat_freq = 15
|
||||||
matchmaker_heartbeat_ttl = 30
|
matchmaker_heartbeat_ttl = 30
|
||||||
[matchmaker_redis]
|
[matchmaker_redis]
|
||||||
host = {{ zmq_redis_address }}
|
host = {{ zmq_redis_address }}
|
||||||
{% else -%}
|
{% else -%}
|
||||||
rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_ring.MatchMakerRing
|
rpc_zmq_matchmaker = ring
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{% endif -%}
|
{% endif -%}
|
|
@ -30,6 +30,10 @@ import yaml
|
||||||
|
|
||||||
from charmhelpers.contrib.network import ip
|
from charmhelpers.contrib.network import ip
|
||||||
|
|
||||||
|
from charmhelpers.core import (
|
||||||
|
unitdata,
|
||||||
|
)
|
||||||
|
|
||||||
from charmhelpers.core.hookenv import (
|
from charmhelpers.core.hookenv import (
|
||||||
config,
|
config,
|
||||||
log as juju_log,
|
log as juju_log,
|
||||||
|
@ -330,6 +334,21 @@ def configure_installation_source(rel):
|
||||||
error_out("Invalid openstack-release specified: %s" % rel)
|
error_out("Invalid openstack-release specified: %s" % rel)
|
||||||
|
|
||||||
|
|
||||||
|
def config_value_changed(option):
|
||||||
|
"""
|
||||||
|
Determine if config value changed since last call to this function.
|
||||||
|
"""
|
||||||
|
hook_data = unitdata.HookData()
|
||||||
|
with hook_data():
|
||||||
|
db = unitdata.kv()
|
||||||
|
current = config(option)
|
||||||
|
saved = db.get(option)
|
||||||
|
db.set(option, current)
|
||||||
|
if saved is None:
|
||||||
|
return False
|
||||||
|
return current != saved
|
||||||
|
|
||||||
|
|
||||||
def save_script_rc(script_path="scripts/scriptrc", **env_vars):
|
def save_script_rc(script_path="scripts/scriptrc", **env_vars):
|
||||||
"""
|
"""
|
||||||
Write an rc file in the charm-delivered directory containing
|
Write an rc file in the charm-delivered directory containing
|
||||||
|
@ -469,82 +488,95 @@ def os_requires_version(ostack_release, pkg):
|
||||||
|
|
||||||
|
|
||||||
def git_install_requested():
|
def git_install_requested():
|
||||||
"""Returns true if openstack-origin-git is specified."""
|
"""
|
||||||
return config('openstack-origin-git') != "None"
|
Returns true if openstack-origin-git is specified.
|
||||||
|
"""
|
||||||
|
return config('openstack-origin-git') is not None
|
||||||
|
|
||||||
|
|
||||||
requirements_dir = None
|
requirements_dir = None
|
||||||
|
|
||||||
|
|
||||||
def git_clone_and_install(file_name, core_project):
|
def git_clone_and_install(projects_yaml, core_project):
|
||||||
"""Clone/install all OpenStack repos specified in yaml config file."""
|
"""
|
||||||
global requirements_dir
|
Clone/install all specified OpenStack repositories.
|
||||||
|
|
||||||
if file_name == "None":
|
The expected format of projects_yaml is:
|
||||||
|
repositories:
|
||||||
|
- {name: keystone,
|
||||||
|
repository: 'git://git.openstack.org/openstack/keystone.git',
|
||||||
|
branch: 'stable/icehouse'}
|
||||||
|
- {name: requirements,
|
||||||
|
repository: 'git://git.openstack.org/openstack/requirements.git',
|
||||||
|
branch: 'stable/icehouse'}
|
||||||
|
directory: /mnt/openstack-git
|
||||||
|
|
||||||
|
The directory key is optional.
|
||||||
|
"""
|
||||||
|
global requirements_dir
|
||||||
|
parent_dir = '/mnt/openstack-git'
|
||||||
|
|
||||||
|
if not projects_yaml:
|
||||||
return
|
return
|
||||||
|
|
||||||
yaml_file = os.path.join(charm_dir(), file_name)
|
projects = yaml.load(projects_yaml)
|
||||||
|
_git_validate_projects_yaml(projects, core_project)
|
||||||
|
|
||||||
# clone/install the requirements project first
|
if 'directory' in projects.keys():
|
||||||
installed = _git_clone_and_install_subset(yaml_file,
|
parent_dir = projects['directory']
|
||||||
whitelist=['requirements'])
|
|
||||||
if 'requirements' not in installed:
|
|
||||||
error_out('requirements git repository must be specified')
|
|
||||||
|
|
||||||
# clone/install all other projects except requirements and the core project
|
for p in projects['repositories']:
|
||||||
blacklist = ['requirements', core_project]
|
repo = p['repository']
|
||||||
_git_clone_and_install_subset(yaml_file, blacklist=blacklist,
|
branch = p['branch']
|
||||||
update_requirements=True)
|
if p['name'] == 'requirements':
|
||||||
|
repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
|
||||||
# clone/install the core project
|
update_requirements=False)
|
||||||
whitelist = [core_project]
|
requirements_dir = repo_dir
|
||||||
installed = _git_clone_and_install_subset(yaml_file, whitelist=whitelist,
|
else:
|
||||||
update_requirements=True)
|
repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
|
||||||
if core_project not in installed:
|
update_requirements=True)
|
||||||
error_out('{} git repository must be specified'.format(core_project))
|
|
||||||
|
|
||||||
|
|
||||||
def _git_clone_and_install_subset(yaml_file, whitelist=[], blacklist=[],
|
def _git_validate_projects_yaml(projects, core_project):
|
||||||
update_requirements=False):
|
"""
|
||||||
"""Clone/install subset of OpenStack repos specified in yaml config file."""
|
Validate the projects yaml.
|
||||||
global requirements_dir
|
"""
|
||||||
installed = []
|
_git_ensure_key_exists('repositories', projects)
|
||||||
|
|
||||||
with open(yaml_file, 'r') as fd:
|
for project in projects['repositories']:
|
||||||
projects = yaml.load(fd)
|
_git_ensure_key_exists('name', project.keys())
|
||||||
for proj, val in projects.items():
|
_git_ensure_key_exists('repository', project.keys())
|
||||||
# The project subset is chosen based on the following 3 rules:
|
_git_ensure_key_exists('branch', project.keys())
|
||||||
# 1) If project is in blacklist, we don't clone/install it, period.
|
|
||||||
# 2) If whitelist is empty, we clone/install everything else.
|
if projects['repositories'][0]['name'] != 'requirements':
|
||||||
# 3) If whitelist is not empty, we clone/install everything in the
|
error_out('{} git repo must be specified first'.format('requirements'))
|
||||||
# whitelist.
|
|
||||||
if proj in blacklist:
|
if projects['repositories'][-1]['name'] != core_project:
|
||||||
continue
|
error_out('{} git repo must be specified last'.format(core_project))
|
||||||
if whitelist and proj not in whitelist:
|
|
||||||
continue
|
|
||||||
repo = val['repository']
|
|
||||||
branch = val['branch']
|
|
||||||
repo_dir = _git_clone_and_install_single(repo, branch,
|
|
||||||
update_requirements)
|
|
||||||
if proj == 'requirements':
|
|
||||||
requirements_dir = repo_dir
|
|
||||||
installed.append(proj)
|
|
||||||
return installed
|
|
||||||
|
|
||||||
|
|
||||||
def _git_clone_and_install_single(repo, branch, update_requirements=False):
|
def _git_ensure_key_exists(key, keys):
|
||||||
"""Clone and install a single git repository."""
|
"""
|
||||||
dest_parent_dir = "/mnt/openstack-git/"
|
Ensure that key exists in keys.
|
||||||
dest_dir = os.path.join(dest_parent_dir, os.path.basename(repo))
|
"""
|
||||||
|
if key not in keys:
|
||||||
|
error_out('openstack-origin-git key \'{}\' is missing'.format(key))
|
||||||
|
|
||||||
if not os.path.exists(dest_parent_dir):
|
|
||||||
juju_log('Host dir not mounted at {}. '
|
def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
|
||||||
'Creating directory there instead.'.format(dest_parent_dir))
|
"""
|
||||||
os.mkdir(dest_parent_dir)
|
Clone and install a single git repository.
|
||||||
|
"""
|
||||||
|
dest_dir = os.path.join(parent_dir, os.path.basename(repo))
|
||||||
|
|
||||||
|
if not os.path.exists(parent_dir):
|
||||||
|
juju_log('Directory already exists at {}. '
|
||||||
|
'No need to create directory.'.format(parent_dir))
|
||||||
|
os.mkdir(parent_dir)
|
||||||
|
|
||||||
if not os.path.exists(dest_dir):
|
if not os.path.exists(dest_dir):
|
||||||
juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
|
juju_log('Cloning git repo: {}, branch: {}'.format(repo, branch))
|
||||||
repo_dir = install_remote(repo, dest=dest_parent_dir, branch=branch)
|
repo_dir = install_remote(repo, dest=parent_dir, branch=branch)
|
||||||
else:
|
else:
|
||||||
repo_dir = dest_dir
|
repo_dir = dest_dir
|
||||||
|
|
||||||
|
@ -561,16 +593,39 @@ def _git_clone_and_install_single(repo, branch, update_requirements=False):
|
||||||
|
|
||||||
|
|
||||||
def _git_update_requirements(package_dir, reqs_dir):
|
def _git_update_requirements(package_dir, reqs_dir):
|
||||||
"""Update from global requirements.
|
"""
|
||||||
|
Update from global requirements.
|
||||||
|
|
||||||
Update an OpenStack git directory's requirements.txt and
|
Update an OpenStack git directory's requirements.txt and
|
||||||
test-requirements.txt from global-requirements.txt."""
|
test-requirements.txt from global-requirements.txt.
|
||||||
|
"""
|
||||||
orig_dir = os.getcwd()
|
orig_dir = os.getcwd()
|
||||||
os.chdir(reqs_dir)
|
os.chdir(reqs_dir)
|
||||||
cmd = "python update.py {}".format(package_dir)
|
cmd = ['python', 'update.py', package_dir]
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(cmd.split(' '))
|
subprocess.check_call(cmd)
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
package = os.path.basename(package_dir)
|
package = os.path.basename(package_dir)
|
||||||
error_out("Error updating {} from global-requirements.txt".format(package))
|
error_out("Error updating {} from global-requirements.txt".format(package))
|
||||||
os.chdir(orig_dir)
|
os.chdir(orig_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def git_src_dir(projects_yaml, project):
|
||||||
|
"""
|
||||||
|
Return the directory where the specified project's source is located.
|
||||||
|
"""
|
||||||
|
parent_dir = '/mnt/openstack-git'
|
||||||
|
|
||||||
|
if not projects_yaml:
|
||||||
|
return
|
||||||
|
|
||||||
|
projects = yaml.load(projects_yaml)
|
||||||
|
|
||||||
|
if 'directory' in projects.keys():
|
||||||
|
parent_dir = projects['directory']
|
||||||
|
|
||||||
|
for p in projects['repositories']:
|
||||||
|
if p['name'] == project:
|
||||||
|
return os.path.join(parent_dir, os.path.basename(p['repository']))
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
|
@ -443,7 +443,7 @@ class HookData(object):
|
||||||
data = hookenv.execution_environment()
|
data = hookenv.execution_environment()
|
||||||
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
|
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
|
||||||
self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
|
self.rels = rels_delta = self.kv.delta(data['rels'], 'rels')
|
||||||
self.kv.set('env', data['env'])
|
self.kv.set('env', dict(data['env']))
|
||||||
self.kv.set('unit', data['unit'])
|
self.kv.set('unit', data['unit'])
|
||||||
self.kv.set('relid', data.get('relid'))
|
self.kv.set('relid', data.get('relid'))
|
||||||
return conf_delta, rels_delta
|
return conf_delta, rels_delta
|
||||||
|
|
|
@ -30,6 +30,7 @@ from charmhelpers.fetch import (
|
||||||
from charmhelpers.contrib.openstack.utils import (
|
from charmhelpers.contrib.openstack.utils import (
|
||||||
configure_installation_source,
|
configure_installation_source,
|
||||||
openstack_upgrade_available,
|
openstack_upgrade_available,
|
||||||
|
os_requires_version,
|
||||||
)
|
)
|
||||||
|
|
||||||
from charmhelpers.contrib.storage.linux.ceph import (
|
from charmhelpers.contrib.storage.linux.ceph import (
|
||||||
|
@ -57,6 +58,7 @@ from nova_compute_utils import (
|
||||||
ceph_config_file, CEPH_SECRET,
|
ceph_config_file, CEPH_SECRET,
|
||||||
enable_shell, disable_shell,
|
enable_shell, disable_shell,
|
||||||
fix_path_ownership,
|
fix_path_ownership,
|
||||||
|
get_topics,
|
||||||
assert_charm_supports_ipv6,
|
assert_charm_supports_ipv6,
|
||||||
manage_ovs,
|
manage_ovs,
|
||||||
)
|
)
|
||||||
|
@ -118,6 +120,8 @@ def config_changed():
|
||||||
fix_path_ownership(fp, user='nova')
|
fix_path_ownership(fp, user='nova')
|
||||||
|
|
||||||
[compute_joined(rid) for rid in relation_ids('cloud-compute')]
|
[compute_joined(rid) for rid in relation_ids('cloud-compute')]
|
||||||
|
for rid in relation_ids('zeromq-configuration'):
|
||||||
|
zeromq_configuration_relation_joined(rid)
|
||||||
|
|
||||||
update_nrpe_config()
|
update_nrpe_config()
|
||||||
|
|
||||||
|
@ -316,6 +320,20 @@ def nova_ceilometer_relation_changed():
|
||||||
CONFIGS.write_all()
|
CONFIGS.write_all()
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.hook('zeromq-configuration-relation-joined')
|
||||||
|
@os_requires_version('kilo', 'nova-common')
|
||||||
|
def zeromq_configuration_relation_joined(relid=None):
|
||||||
|
relation_set(relation_id=relid,
|
||||||
|
topics=" ".join(get_topics()),
|
||||||
|
users="nova")
|
||||||
|
|
||||||
|
|
||||||
|
@hooks.hook('zeromq-configuration-relation-changed')
|
||||||
|
@restart_on_change(restart_map())
|
||||||
|
def zeromq_configuration_relation_changed():
|
||||||
|
CONFIGS.write(NOVA_CONF)
|
||||||
|
|
||||||
|
|
||||||
@hooks.hook('nrpe-external-master-relation-joined',
|
@hooks.hook('nrpe-external-master-relation-joined',
|
||||||
'nrpe-external-master-relation-changed')
|
'nrpe-external-master-relation-changed')
|
||||||
def update_nrpe_config():
|
def update_nrpe_config():
|
||||||
|
|
|
@ -101,6 +101,8 @@ BASE_RESOURCE_MAP = {
|
||||||
service='nova',
|
service='nova',
|
||||||
config_file=NOVA_CONF),
|
config_file=NOVA_CONF),
|
||||||
InstanceConsoleContext(),
|
InstanceConsoleContext(),
|
||||||
|
context.ZeroMQContext(),
|
||||||
|
context.NotificationDriverContext(),
|
||||||
MetadataServiceContext(),
|
MetadataServiceContext(),
|
||||||
HostIPContext()],
|
HostIPContext()],
|
||||||
},
|
},
|
||||||
|
@ -496,6 +498,10 @@ def fix_path_ownership(path, user='nova'):
|
||||||
check_call(cmd)
|
check_call(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
def get_topics():
|
||||||
|
return ['compute']
|
||||||
|
|
||||||
|
|
||||||
def assert_charm_supports_ipv6():
|
def assert_charm_supports_ipv6():
|
||||||
"""Check whether we are able to support charms ipv6."""
|
"""Check whether we are able to support charms ipv6."""
|
||||||
if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty":
|
if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty":
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
nova_compute_hooks.py
|
|
@ -0,0 +1 @@
|
||||||
|
nova_compute_hooks.py
|
|
@ -30,6 +30,6 @@ requires:
|
||||||
neutron-plugin:
|
neutron-plugin:
|
||||||
interface: neutron-plugin
|
interface: neutron-plugin
|
||||||
scope: container
|
scope: container
|
||||||
peers:
|
zeromq-configuration:
|
||||||
compute-peer:
|
interface: zeromq-configuration
|
||||||
interface: nova
|
scope: container
|
||||||
|
|
|
@ -101,6 +101,8 @@ instances_path = {{ instances_path }}
|
||||||
{% endfor -%}
|
{% endfor -%}
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
||||||
|
{% include "section-zeromq" %}
|
||||||
|
|
||||||
{% if network_manager == 'neutron' and network_manager_config -%}
|
{% if network_manager == 'neutron' and network_manager_config -%}
|
||||||
[neutron]
|
[neutron]
|
||||||
url = {{ network_manager_config.neutron_url }}
|
url = {{ network_manager_config.neutron_url }}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
from collections import OrderedDict
|
||||||
from charmhelpers.contrib.amulet.deployment import (
|
from charmhelpers.contrib.amulet.deployment import (
|
||||||
AmuletDeployment
|
AmuletDeployment
|
||||||
)
|
)
|
||||||
|
@ -100,12 +101,34 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||||
"""
|
"""
|
||||||
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
||||||
self.precise_havana, self.precise_icehouse,
|
self.precise_havana, self.precise_icehouse,
|
||||||
self.trusty_icehouse) = range(6)
|
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
|
||||||
releases = {
|
releases = {
|
||||||
('precise', None): self.precise_essex,
|
('precise', None): self.precise_essex,
|
||||||
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
||||||
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
||||||
('precise', 'cloud:precise-havana'): self.precise_havana,
|
('precise', 'cloud:precise-havana'): self.precise_havana,
|
||||||
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
('precise', 'cloud:precise-icehouse'): self.precise_icehouse,
|
||||||
('trusty', None): self.trusty_icehouse}
|
('trusty', None): self.trusty_icehouse,
|
||||||
|
('trusty', 'cloud:trusty-juno'): self.trusty_juno,
|
||||||
|
('trusty', 'cloud:trusty-kilo'): self.trusty_kilo}
|
||||||
return releases[(self.series, self.openstack)]
|
return releases[(self.series, self.openstack)]
|
||||||
|
|
||||||
|
def _get_openstack_release_string(self):
|
||||||
|
"""Get openstack release string.
|
||||||
|
|
||||||
|
Return a string representing the openstack release.
|
||||||
|
"""
|
||||||
|
releases = OrderedDict([
|
||||||
|
('precise', 'essex'),
|
||||||
|
('quantal', 'folsom'),
|
||||||
|
('raring', 'grizzly'),
|
||||||
|
('saucy', 'havana'),
|
||||||
|
('trusty', 'icehouse'),
|
||||||
|
('utopic', 'juno'),
|
||||||
|
('vivid', 'kilo'),
|
||||||
|
])
|
||||||
|
if self.openstack:
|
||||||
|
os_origin = self.openstack.split(':')[1]
|
||||||
|
return os_origin.split('%s-' % self.series)[1].split('/')[0]
|
||||||
|
else:
|
||||||
|
return releases[self.series]
|
||||||
|
|
|
@ -85,6 +85,7 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||||
@patch.object(hooks, 'compute_joined')
|
@patch.object(hooks, 'compute_joined')
|
||||||
def test_config_changed_with_migration(self, compute_joined):
|
def test_config_changed_with_migration(self, compute_joined):
|
||||||
self.migration_enabled.return_value = True
|
self.migration_enabled.return_value = True
|
||||||
|
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
|
||||||
self.test_config.set('migration-auth-type', 'ssh')
|
self.test_config.set('migration-auth-type', 'ssh')
|
||||||
self.relation_ids.return_value = [
|
self.relation_ids.return_value = [
|
||||||
'cloud-compute:0',
|
'cloud-compute:0',
|
||||||
|
@ -97,10 +98,12 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||||
]
|
]
|
||||||
self.assertEquals(ex, compute_joined.call_args_list)
|
self.assertEquals(ex, compute_joined.call_args_list)
|
||||||
self.assertTrue(self.initialize_ssh_keys.called)
|
self.assertTrue(self.initialize_ssh_keys.called)
|
||||||
|
self.assertTrue(_zmq_joined.called)
|
||||||
|
|
||||||
@patch.object(hooks, 'compute_joined')
|
@patch.object(hooks, 'compute_joined')
|
||||||
def test_config_changed_with_resize(self, compute_joined):
|
def test_config_changed_with_resize(self, compute_joined):
|
||||||
self.test_config.set('enable-resize', True)
|
self.test_config.set('enable-resize', True)
|
||||||
|
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
|
||||||
self.relation_ids.return_value = [
|
self.relation_ids.return_value = [
|
||||||
'cloud-compute:0',
|
'cloud-compute:0',
|
||||||
'cloud-compute:1'
|
'cloud-compute:1'
|
||||||
|
@ -113,10 +116,12 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||||
self.assertEquals(ex, compute_joined.call_args_list)
|
self.assertEquals(ex, compute_joined.call_args_list)
|
||||||
self.initialize_ssh_keys.assert_called_with(user='nova')
|
self.initialize_ssh_keys.assert_called_with(user='nova')
|
||||||
self.enable_shell.assert_called_with(user='nova')
|
self.enable_shell.assert_called_with(user='nova')
|
||||||
|
self.assertTrue(_zmq_joined.called)
|
||||||
|
|
||||||
@patch.object(hooks, 'compute_joined')
|
@patch.object(hooks, 'compute_joined')
|
||||||
def test_config_changed_without_resize(self, compute_joined):
|
def test_config_changed_without_resize(self, compute_joined):
|
||||||
self.test_config.set('enable-resize', False)
|
self.test_config.set('enable-resize', False)
|
||||||
|
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
|
||||||
self.relation_ids.return_value = [
|
self.relation_ids.return_value = [
|
||||||
'cloud-compute:0',
|
'cloud-compute:0',
|
||||||
'cloud-compute:1'
|
'cloud-compute:1'
|
||||||
|
@ -128,6 +133,7 @@ class NovaComputeRelationsTests(CharmTestCase):
|
||||||
]
|
]
|
||||||
self.assertEquals(ex, compute_joined.call_args_list)
|
self.assertEquals(ex, compute_joined.call_args_list)
|
||||||
self.disable_shell.assert_called_with(user='nova')
|
self.disable_shell.assert_called_with(user='nova')
|
||||||
|
self.assertTrue(_zmq_joined.called)
|
||||||
|
|
||||||
@patch.object(hooks, 'compute_joined')
|
@patch.object(hooks, 'compute_joined')
|
||||||
def test_config_changed_no_upgrade_no_migration(self, compute_joined):
|
def test_config_changed_no_upgrade_no_migration(self, compute_joined):
|
||||||
|
|
Loading…
Reference in New Issue