Deploy from source
This commit is contained in:
commit
18be463b62
@ -1,2 +1,3 @@
|
||||
bin
|
||||
.coverage
|
||||
tags
|
||||
|
7
Makefile
7
Makefile
@ -2,7 +2,7 @@
|
||||
PYTHON := /usr/bin/env python
|
||||
|
||||
lint:
|
||||
@flake8 --exclude hooks/charmhelpers hooks unit_tests tests
|
||||
@flake8 --exclude hooks/charmhelpers actions hooks unit_tests tests
|
||||
@charm proof
|
||||
|
||||
unit_test:
|
||||
@ -23,9 +23,10 @@ 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 900 \
|
||||
@juju test -e trusty -v -p AMULET_HTTP_PROXY --timeout 900 \
|
||||
00-setup 14-basic-precise-icehouse 15-basic-trusty-icehouse \
|
||||
16-basic-trusty-juno
|
||||
16-basic-trusty-icehouse-git 17-basic-trusty-juno \
|
||||
18-basic-trusty-juno-git
|
||||
|
||||
publish: lint unit_test
|
||||
bzr push lp:charms/neutron-api
|
||||
|
87
README.md
87
README.md
@ -23,6 +23,93 @@ This charm also supports scale out and high availability using the hacluster cha
|
||||
juju set neutron-api vip=<VIP FOR ACCESS>
|
||||
juju add-relation neutron-hacluster neutron-api
|
||||
|
||||
# Deploying from source
|
||||
|
||||
The minimum openstack-origin-git config required to deploy from source is:
|
||||
|
||||
openstack-origin-git:
|
||||
"repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: stable/juno}
|
||||
- {name: neutron,
|
||||
repository: 'git://git.openstack.org/openstack/neutron',
|
||||
branch: stable/juno}"
|
||||
|
||||
Note that there are only two 'name' values the charm knows about: 'requirements'
|
||||
and 'neutron'. These repositories must correspond to these 'name' values.
|
||||
Additionally, the requirements repository must be specified first and the
|
||||
neutron repository must be specified last. All other repostories are installed
|
||||
in the order in which they are specified.
|
||||
|
||||
The following is a full list of current tip repos (may not be up-to-date):
|
||||
|
||||
openstack-origin-git:
|
||||
"repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: master}
|
||||
- {name: oslo-concurrency,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.concurrency',
|
||||
branch: master}
|
||||
- {name: oslo-config,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.config',
|
||||
branch: master}
|
||||
- {name: oslo-context,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.context.git',
|
||||
branch: master}
|
||||
- {name: oslo-db,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.db',
|
||||
branch: master}
|
||||
- {name: oslo-i18n,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.i18n',
|
||||
branch: master}
|
||||
- {name: oslo-messaging,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.messaging.git',
|
||||
branch: master}
|
||||
- {name: oslo-middleware,
|
||||
repository': 'git://git.openstack.org/openstack/oslo.middleware.git',
|
||||
branch: master}
|
||||
- {name: oslo-rootwrap',
|
||||
repository: 'git://git.openstack.org/openstack/oslo.rootwrap.git',
|
||||
branch: master}
|
||||
- {name: oslo-serialization,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.serialization',
|
||||
branch: master}
|
||||
- {name: oslo-utils,
|
||||
repository: 'git://git.openstack.org/openstack/oslo.utils',
|
||||
branch: master}
|
||||
- {name: pbr,
|
||||
repository: 'git://git.openstack.org/openstack-dev/pbr',
|
||||
branch: master}
|
||||
- {name: stevedore,
|
||||
repository: 'git://git.openstack.org/openstack/stevedore.git',
|
||||
branch: 'master'}
|
||||
- {name: python-keystoneclient,
|
||||
repository: 'git://git.openstack.org/openstack/python-keystoneclient',
|
||||
branch: master}
|
||||
- {name: python-neutronclient,
|
||||
repository: 'git://git.openstack.org/openstack/python-neutronclient.git',
|
||||
branch: master}
|
||||
- {name: python-novaclient,
|
||||
repository': 'git://git.openstack.org/openstack/python-novaclient.git',
|
||||
branch: master}
|
||||
- {name: keystonemiddleware,
|
||||
repository: 'git://git.openstack.org/openstack/keystonemiddleware',
|
||||
branch: master}
|
||||
- {name: neutron-fwaas,
|
||||
repository': 'git://git.openstack.org/openstack/neutron-fwaas.git',
|
||||
branch: master}
|
||||
- {name: neutron-lbaas,
|
||||
repository: 'git://git.openstack.org/openstack/neutron-lbaas.git',
|
||||
branch: master}
|
||||
- {name: neutron-vpnaas,
|
||||
repository: 'git://git.openstack.org/openstack/neutron-vpnaas.git',
|
||||
branch: master}
|
||||
- {name: neutron,
|
||||
repository: 'git://git.openstack.org/openstack/neutron',
|
||||
branch: master}"
|
||||
|
||||
# Restrictions
|
||||
|
||||
This charm only support deployment with OpenStack Icehouse or better.
|
||||
|
2
actions.yaml
Normal file
2
actions.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
git-reinstall:
|
||||
description: Reinstall neutron-api from the openstack-origin-git repositories.
|
1
actions/git-reinstall
Symbolic link
1
actions/git-reinstall
Symbolic link
@ -0,0 +1 @@
|
||||
git_reinstall.py
|
40
actions/git_reinstall.py
Executable file
40
actions/git_reinstall.py
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
sys.path.append('hooks/')
|
||||
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
git_install_requested,
|
||||
)
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
action_set,
|
||||
action_fail,
|
||||
config,
|
||||
)
|
||||
|
||||
from neutron_api_utils import (
|
||||
git_install,
|
||||
)
|
||||
|
||||
|
||||
def git_reinstall():
|
||||
"""Reinstall from source and restart services.
|
||||
|
||||
If the openstack-origin-git config option was used to install openstack
|
||||
from source git repositories, then this action can be used to reinstall
|
||||
from updated git repositories, followed by a restart of services."""
|
||||
if not git_install_requested():
|
||||
action_fail('openstack-origin-git is not configured')
|
||||
return
|
||||
|
||||
try:
|
||||
git_install(config('openstack-origin-git'))
|
||||
except:
|
||||
action_set({'traceback': traceback.format_exc()})
|
||||
action_fail('git-reinstall resulted in an unexpected error')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
git_reinstall()
|
38
config.yaml
38
config.yaml
@ -14,6 +14,22 @@ options:
|
||||
Note that updating this setting to a source that is known to
|
||||
provide a later version of OpenStack will trigger a software
|
||||
upgrade.
|
||||
|
||||
Note that when openstack-origin-git is specified, openstack
|
||||
specific packages will be installed from source rather than
|
||||
from the openstack-origin repository.
|
||||
openstack-origin-git:
|
||||
default:
|
||||
type: string
|
||||
description: |
|
||||
Specifies a YAML-formatted dictionary listing the git
|
||||
repositories and branches from which to install OpenStack and
|
||||
its dependencies.
|
||||
|
||||
Note that the installed config files will be determined based on
|
||||
the OpenStack release of the openstack-origin option.
|
||||
|
||||
For more details see README.md.
|
||||
rabbit-user:
|
||||
default: neutron
|
||||
type: string
|
||||
@ -285,6 +301,28 @@ options:
|
||||
juju-myservice-0
|
||||
If you're running multiple environments with the same services in them
|
||||
this allows you to differentiate between them.
|
||||
enable-dvr:
|
||||
default: False
|
||||
type: boolean
|
||||
description: |
|
||||
Enable Distributed Virtual Routing (juno and above).
|
||||
enable-l3ha:
|
||||
default: False
|
||||
type: boolean
|
||||
description: |
|
||||
Enable L3 HA (juno and above).
|
||||
max-l3-agents-per-router:
|
||||
default: 2
|
||||
type: int
|
||||
description: |
|
||||
Maximum number of l3 agents to host a router. Only used when enable-l3ha
|
||||
is True
|
||||
min-l3-agents-per-router:
|
||||
default: 2
|
||||
type: int
|
||||
description: |
|
||||
Minimum number of l3 agents to host a router. Only used when enable-l3ha
|
||||
is True
|
||||
nagios_servicegroups:
|
||||
default: ""
|
||||
type: string
|
||||
|
@ -15,6 +15,7 @@
|
||||
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import six
|
||||
from collections import OrderedDict
|
||||
from charmhelpers.contrib.amulet.deployment import (
|
||||
AmuletDeployment
|
||||
)
|
||||
@ -100,12 +101,34 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||
"""
|
||||
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
||||
self.precise_havana, self.precise_icehouse,
|
||||
self.trusty_icehouse) = range(6)
|
||||
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
|
||||
releases = {
|
||||
('precise', None): self.precise_essex,
|
||||
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
||||
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
||||
('precise', 'cloud:precise-havana'): self.precise_havana,
|
||||
('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)]
|
||||
|
||||
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.strutils import bool_from_string
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
list_nics,
|
||||
@ -67,6 +68,7 @@ from charmhelpers.contrib.hahelpers.apache import (
|
||||
)
|
||||
from charmhelpers.contrib.openstack.neutron import (
|
||||
neutron_plugin_attribute,
|
||||
parse_data_port_mappings,
|
||||
)
|
||||
from charmhelpers.contrib.openstack.ip import (
|
||||
resolve_address,
|
||||
@ -82,7 +84,6 @@ from charmhelpers.contrib.network.ip import (
|
||||
is_bridge_member,
|
||||
)
|
||||
from charmhelpers.contrib.openstack.utils import get_host_ip
|
||||
|
||||
CA_CERT_PATH = '/usr/local/share/ca-certificates/keystone_juju_ca_cert.crt'
|
||||
ADDRESS_TYPES = ['admin', 'internal', 'public']
|
||||
|
||||
@ -319,14 +320,15 @@ def db_ssl(rdata, ctxt, ssl_dir):
|
||||
|
||||
|
||||
class IdentityServiceContext(OSContextGenerator):
|
||||
interfaces = ['identity-service']
|
||||
|
||||
def __init__(self, service=None, service_user=None):
|
||||
def __init__(self, service=None, service_user=None, rel_name='identity-service'):
|
||||
self.service = service
|
||||
self.service_user = service_user
|
||||
self.rel_name = rel_name
|
||||
self.interfaces = [self.rel_name]
|
||||
|
||||
def __call__(self):
|
||||
log('Generating template context for identity-service', level=DEBUG)
|
||||
log('Generating template context for ' + self.rel_name, level=DEBUG)
|
||||
ctxt = {}
|
||||
|
||||
if self.service and self.service_user:
|
||||
@ -340,7 +342,7 @@ class IdentityServiceContext(OSContextGenerator):
|
||||
|
||||
ctxt['signing_dir'] = cachedir
|
||||
|
||||
for rid in relation_ids('identity-service'):
|
||||
for rid in relation_ids(self.rel_name):
|
||||
for unit in related_units(rid):
|
||||
rdata = relation_get(rid=rid, unit=unit)
|
||||
serv_host = rdata.get('service_host')
|
||||
@ -1162,3 +1164,145 @@ class SysctlContext(OSContextGenerator):
|
||||
sysctl_create(sysctl_dict,
|
||||
'/etc/sysctl.d/50-{0}.conf'.format(charm_name()))
|
||||
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 {}
|
||||
|
13
hooks/charmhelpers/contrib/openstack/templates/git.upstart
Normal file
13
hooks/charmhelpers/contrib/openstack/templates/git.upstart
Normal file
@ -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 }}
|
@ -0,0 +1,9 @@
|
||||
{% if auth_host -%}
|
||||
[keystone_authtoken]
|
||||
identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/{{ auth_admin_prefix }}
|
||||
auth_uri = {{ service_protocol }}://{{ service_host }}:{{ service_port }}/{{ service_admin_prefix }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
signing_dir = {{ signing_dir }}
|
||||
{% endif -%}
|
@ -0,0 +1,22 @@
|
||||
{% if rabbitmq_host or rabbitmq_hosts -%}
|
||||
[oslo_messaging_rabbit]
|
||||
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 -%}
|
@ -3,12 +3,12 @@
|
||||
rpc_backend = zmq
|
||||
rpc_zmq_host = {{ zmq_host }}
|
||||
{% if zmq_redis_address -%}
|
||||
rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_redis.MatchMakerRedis
|
||||
rpc_zmq_matchmaker = redis
|
||||
matchmaker_heartbeat_freq = 15
|
||||
matchmaker_heartbeat_ttl = 30
|
||||
[matchmaker_redis]
|
||||
host = {{ zmq_redis_address }}
|
||||
{% else -%}
|
||||
rpc_zmq_matchmaker = oslo.messaging._drivers.matchmaker_ring.MatchMakerRing
|
||||
rpc_zmq_matchmaker = ring
|
||||
{% endif -%}
|
||||
{% endif -%}
|
@ -30,6 +30,10 @@ import yaml
|
||||
|
||||
from charmhelpers.contrib.network import ip
|
||||
|
||||
from charmhelpers.core import (
|
||||
unitdata,
|
||||
)
|
||||
|
||||
from charmhelpers.core.hookenv import (
|
||||
config,
|
||||
log as juju_log,
|
||||
@ -330,6 +334,21 @@ def configure_installation_source(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):
|
||||
"""
|
||||
Write an rc file in the charm-delivered directory containing
|
||||
@ -469,82 +488,103 @@ def os_requires_version(ostack_release, pkg):
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
def git_clone_and_install(file_name, core_project):
|
||||
"""Clone/install all OpenStack repos specified in yaml config file."""
|
||||
global requirements_dir
|
||||
def git_clone_and_install(projects_yaml, core_project):
|
||||
"""
|
||||
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
|
||||
http_proxy: http://squid.internal:3128
|
||||
https_proxy: https://squid.internal:3128
|
||||
|
||||
The directory, http_proxy, and https_proxy keys are optional.
|
||||
"""
|
||||
global requirements_dir
|
||||
parent_dir = '/mnt/openstack-git'
|
||||
|
||||
if not projects_yaml:
|
||||
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
|
||||
installed = _git_clone_and_install_subset(yaml_file,
|
||||
whitelist=['requirements'])
|
||||
if 'requirements' not in installed:
|
||||
error_out('requirements git repository must be specified')
|
||||
if 'http_proxy' in projects.keys():
|
||||
os.environ['http_proxy'] = projects['http_proxy']
|
||||
|
||||
# clone/install all other projects except requirements and the core project
|
||||
blacklist = ['requirements', core_project]
|
||||
_git_clone_and_install_subset(yaml_file, blacklist=blacklist,
|
||||
update_requirements=True)
|
||||
if 'https_proxy' in projects.keys():
|
||||
os.environ['https_proxy'] = projects['https_proxy']
|
||||
|
||||
# clone/install the core project
|
||||
whitelist = [core_project]
|
||||
installed = _git_clone_and_install_subset(yaml_file, whitelist=whitelist,
|
||||
update_requirements=True)
|
||||
if core_project not in installed:
|
||||
error_out('{} git repository must be specified'.format(core_project))
|
||||
if 'directory' in projects.keys():
|
||||
parent_dir = projects['directory']
|
||||
|
||||
for p in projects['repositories']:
|
||||
repo = p['repository']
|
||||
branch = p['branch']
|
||||
if p['name'] == 'requirements':
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
|
||||
update_requirements=False)
|
||||
requirements_dir = repo_dir
|
||||
else:
|
||||
repo_dir = _git_clone_and_install_single(repo, branch, parent_dir,
|
||||
update_requirements=True)
|
||||
|
||||
|
||||
def _git_clone_and_install_subset(yaml_file, whitelist=[], blacklist=[],
|
||||
update_requirements=False):
|
||||
"""Clone/install subset of OpenStack repos specified in yaml config file."""
|
||||
global requirements_dir
|
||||
installed = []
|
||||
def _git_validate_projects_yaml(projects, core_project):
|
||||
"""
|
||||
Validate the projects yaml.
|
||||
"""
|
||||
_git_ensure_key_exists('repositories', projects)
|
||||
|
||||
with open(yaml_file, 'r') as fd:
|
||||
projects = yaml.load(fd)
|
||||
for proj, val in projects.items():
|
||||
# The project subset is chosen based on the following 3 rules:
|
||||
# 1) If project is in blacklist, we don't clone/install it, period.
|
||||
# 2) If whitelist is empty, we clone/install everything else.
|
||||
# 3) If whitelist is not empty, we clone/install everything in the
|
||||
# whitelist.
|
||||
if proj in blacklist:
|
||||
continue
|
||||
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
|
||||
for project in projects['repositories']:
|
||||
_git_ensure_key_exists('name', project.keys())
|
||||
_git_ensure_key_exists('repository', project.keys())
|
||||
_git_ensure_key_exists('branch', project.keys())
|
||||
|
||||
if projects['repositories'][0]['name'] != 'requirements':
|
||||
error_out('{} git repo must be specified first'.format('requirements'))
|
||||
|
||||
if projects['repositories'][-1]['name'] != core_project:
|
||||
error_out('{} git repo must be specified last'.format(core_project))
|
||||
|
||||
|
||||
def _git_clone_and_install_single(repo, branch, update_requirements=False):
|
||||
"""Clone and install a single git repository."""
|
||||
dest_parent_dir = "/mnt/openstack-git/"
|
||||
dest_dir = os.path.join(dest_parent_dir, os.path.basename(repo))
|
||||
def _git_ensure_key_exists(key, keys):
|
||||
"""
|
||||
Ensure that key exists in keys.
|
||||
"""
|
||||
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 {}. '
|
||||
'Creating directory there instead.'.format(dest_parent_dir))
|
||||
os.mkdir(dest_parent_dir)
|
||||
|
||||
def _git_clone_and_install_single(repo, branch, parent_dir, update_requirements):
|
||||
"""
|
||||
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):
|
||||
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:
|
||||
repo_dir = dest_dir
|
||||
|
||||
@ -561,16 +601,39 @@ def _git_clone_and_install_single(repo, branch, update_requirements=False):
|
||||
|
||||
|
||||
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
|
||||
test-requirements.txt from global-requirements.txt."""
|
||||
Update an OpenStack git directory's requirements.txt and
|
||||
test-requirements.txt from global-requirements.txt.
|
||||
"""
|
||||
orig_dir = os.getcwd()
|
||||
os.chdir(reqs_dir)
|
||||
cmd = "python update.py {}".format(package_dir)
|
||||
cmd = ['python', 'update.py', package_dir]
|
||||
try:
|
||||
subprocess.check_call(cmd.split(' '))
|
||||
subprocess.check_call(cmd)
|
||||
except subprocess.CalledProcessError:
|
||||
package = os.path.basename(package_dir)
|
||||
error_out("Error updating {} from global-requirements.txt".format(package))
|
||||
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()
|
||||
self.conf = conf_delta = self.kv.delta(data['conf'], 'config')
|
||||
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('relid', data.get('relid'))
|
||||
return conf_delta, rels_delta
|
||||
|
@ -3,12 +3,16 @@ from charmhelpers.core.hookenv import (
|
||||
relation_ids,
|
||||
related_units,
|
||||
relation_get,
|
||||
log,
|
||||
)
|
||||
from charmhelpers.contrib.openstack import context
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
determine_api_port,
|
||||
determine_apache_port,
|
||||
)
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
os_release,
|
||||
)
|
||||
|
||||
|
||||
def get_l2population():
|
||||
@ -23,6 +27,43 @@ def get_overlay_network_type():
|
||||
return overlay_net
|
||||
|
||||
|
||||
def get_l3ha():
|
||||
if config('enable-l3ha'):
|
||||
if os_release('neutron-server') < 'juno':
|
||||
log('Disabling L3 HA, enable-l3ha is not valid before Juno')
|
||||
return False
|
||||
if config('overlay-network-type') not in ['vlan', 'gre', 'vxlan']:
|
||||
log('Disabling L3 HA, enable-l3ha requires the use of the vxlan, '
|
||||
'vlan or gre overlay network')
|
||||
return False
|
||||
if get_l2population():
|
||||
log('Disabling L3 HA, l2-population must be disabled with L3 HA')
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_dvr():
|
||||
if config('enable-dvr'):
|
||||
if os_release('neutron-server') < 'juno':
|
||||
log('Disabling DVR, enable-dvr is not valid before Juno')
|
||||
return False
|
||||
if config('overlay-network-type') != 'vxlan':
|
||||
log('Disabling DVR, enable-dvr requires the use of the vxlan '
|
||||
'overlay network')
|
||||
return False
|
||||
if get_l3ha():
|
||||
log('Disabling DVR, enable-l3ha must be disabled with dvr')
|
||||
return False
|
||||
if not get_l2population():
|
||||
log('Disabling DVR, l2-population must be enabled to use dvr')
|
||||
return False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class ApacheSSLContext(context.ApacheSSLContext):
|
||||
|
||||
interfaces = ['https']
|
||||
@ -69,6 +110,14 @@ class NeutronCCContext(context.NeutronContext):
|
||||
def neutron_overlay_network_type(self):
|
||||
return get_overlay_network_type()
|
||||
|
||||
@property
|
||||
def neutron_dvr(self):
|
||||
return get_dvr()
|
||||
|
||||
@property
|
||||
def neutron_l3ha(self):
|
||||
return get_l3ha()
|
||||
|
||||
# Do not need the plugin agent installed on the api server
|
||||
def _ensure_packages(self):
|
||||
pass
|
||||
@ -91,6 +140,13 @@ class NeutronCCContext(context.NeutronContext):
|
||||
ctxt['nsx_controllers_list'] = \
|
||||
config('nsx-controllers').split()
|
||||
ctxt['l2_population'] = self.neutron_l2_population
|
||||
ctxt['enable_dvr'] = self.neutron_dvr
|
||||
ctxt['l3_ha'] = self.neutron_l3ha
|
||||
if self.neutron_l3ha:
|
||||
ctxt['max_l3_agents_per_router'] = \
|
||||
config('max-l3-agents-per-router')
|
||||
ctxt['min_l3_agents_per_router'] = \
|
||||
config('min-l3-agents-per-router')
|
||||
ctxt['overlay_network_type'] = self.neutron_overlay_network_type
|
||||
ctxt['external_network'] = config('neutron-external-network')
|
||||
ctxt['verbose'] = config('verbose')
|
||||
|
@ -2,8 +2,10 @@
|
||||
|
||||
import sys
|
||||
import uuid
|
||||
from subprocess import (
|
||||
check_call,
|
||||
)
|
||||
|
||||
from subprocess import check_call
|
||||
from charmhelpers.core.hookenv import (
|
||||
Hooks,
|
||||
UnregisteredHookError,
|
||||
@ -20,6 +22,7 @@ from charmhelpers.core.hookenv import (
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
restart_on_change,
|
||||
service_reload,
|
||||
)
|
||||
|
||||
from charmhelpers.fetch import (
|
||||
@ -29,8 +32,11 @@ from charmhelpers.fetch import (
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
config_value_changed,
|
||||
configure_installation_source,
|
||||
git_install_requested,
|
||||
openstack_upgrade_available,
|
||||
os_requires_version,
|
||||
sync_db_with_multi_ipv6_addresses
|
||||
)
|
||||
|
||||
@ -40,14 +46,21 @@ from neutron_api_utils import (
|
||||
determine_packages,
|
||||
determine_ports,
|
||||
do_openstack_upgrade,
|
||||
git_install,
|
||||
dvr_router_present,
|
||||
l3ha_router_present,
|
||||
register_configs,
|
||||
restart_map,
|
||||
services,
|
||||
setup_ipv6
|
||||
setup_ipv6,
|
||||
get_topics,
|
||||
)
|
||||
from neutron_api_context import (
|
||||
get_dvr,
|
||||
get_l3ha,
|
||||
get_l2population,
|
||||
get_overlay_network_type,
|
||||
IdentityServiceContext,
|
||||
)
|
||||
|
||||
from charmhelpers.contrib.hahelpers.cluster import (
|
||||
@ -92,6 +105,10 @@ def configure_https():
|
||||
cmd = ['a2dissite', 'openstack_https_frontend']
|
||||
check_call(cmd)
|
||||
|
||||
# TODO: improve this by checking if local CN certs are available
|
||||
# first then checking reload status (see LP #1433114).
|
||||
service_reload('apache2', restart_on_failure=True)
|
||||
|
||||
for rid in relation_ids('identity-service'):
|
||||
identity_joined(rid=rid)
|
||||
|
||||
@ -100,9 +117,13 @@ def configure_https():
|
||||
def install():
|
||||
execd_preinstall()
|
||||
configure_installation_source(config('openstack-origin'))
|
||||
|
||||
apt_update()
|
||||
apt_install(determine_packages(config('openstack-origin')),
|
||||
fatal=True)
|
||||
|
||||
git_install(config('openstack-origin-git'))
|
||||
|
||||
[open_port(port) for port in determine_ports()]
|
||||
|
||||
|
||||
@ -110,6 +131,16 @@ def install():
|
||||
@hooks.hook('config-changed')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
def config_changed():
|
||||
if l3ha_router_present() and not get_l3ha():
|
||||
e = ('Cannot disable Router HA while ha enabled routers exist. Please'
|
||||
' remove any ha routers')
|
||||
log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
if dvr_router_present() and not get_dvr():
|
||||
e = ('Cannot disable dvr while dvr enabled routers exist. Please'
|
||||
' remove any distributed routers')
|
||||
log(e, level=ERROR)
|
||||
raise Exception(e)
|
||||
apt_install(filter_installed_packages(
|
||||
determine_packages(config('openstack-origin'))),
|
||||
fatal=True)
|
||||
@ -119,8 +150,12 @@ def config_changed():
|
||||
config('database-user'))
|
||||
|
||||
global CONFIGS
|
||||
if openstack_upgrade_available('neutron-server'):
|
||||
do_openstack_upgrade(CONFIGS)
|
||||
if git_install_requested():
|
||||
if config_value_changed('openstack-origin-git'):
|
||||
git_install(config('openstack-origin-git'))
|
||||
else:
|
||||
if openstack_upgrade_available('neutron-server'):
|
||||
do_openstack_upgrade(CONFIGS)
|
||||
configure_https()
|
||||
update_nrpe_config()
|
||||
CONFIGS.write_all()
|
||||
@ -132,6 +167,8 @@ def config_changed():
|
||||
amqp_joined(relation_id=r_id)
|
||||
for r_id in relation_ids('identity-service'):
|
||||
identity_joined(rid=r_id)
|
||||
for rid in relation_ids('zeromq-configuration'):
|
||||
zeromq_configuration_relation_joined(rid)
|
||||
[cluster_joined(rid) for rid in relation_ids('cluster')]
|
||||
|
||||
|
||||
@ -235,6 +272,8 @@ def identity_changed():
|
||||
CONFIGS.write(NEUTRON_CONF)
|
||||
for r_id in relation_ids('neutron-api'):
|
||||
neutron_api_relation_joined(rid=r_id)
|
||||
for r_id in relation_ids('neutron-plugin-api'):
|
||||
neutron_plugin_api_relation_joined(rid=r_id)
|
||||
configure_https()
|
||||
|
||||
|
||||
@ -278,6 +317,8 @@ def neutron_plugin_api_relation_joined(rid=None):
|
||||
relation_data = {
|
||||
'neutron-security-groups': config('neutron-security-groups'),
|
||||
'l2-population': get_l2population(),
|
||||
'enable-dvr': get_dvr(),
|
||||
'enable-l3ha': get_l3ha(),
|
||||
'overlay-network-type': get_overlay_network_type(),
|
||||
}
|
||||
|
||||
@ -287,6 +328,23 @@ def neutron_plugin_api_relation_joined(rid=None):
|
||||
if net_dev_mtu:
|
||||
relation_data['network-device-mtu'] = net_dev_mtu
|
||||
|
||||
identity_ctxt = IdentityServiceContext()()
|
||||
if not identity_ctxt:
|
||||
identity_ctxt = {}
|
||||
|
||||
relation_data.update({
|
||||
'auth_host': identity_ctxt.get('auth_host'),
|
||||
'auth_port': identity_ctxt.get('auth_port'),
|
||||
'auth_protocol': identity_ctxt.get('auth_protocol'),
|
||||
'service_protocol': identity_ctxt.get('service_protocol'),
|
||||
'service_host': identity_ctxt.get('service_host'),
|
||||
'service_port': identity_ctxt.get('service_port'),
|
||||
'service_tenant': identity_ctxt.get('admin_tenant_name'),
|
||||
'service_username': identity_ctxt.get('admin_user'),
|
||||
'service_password': identity_ctxt.get('admin_password'),
|
||||
'region': config('region'),
|
||||
})
|
||||
|
||||
relation_set(relation_id=rid, **relation_data)
|
||||
|
||||
|
||||
@ -381,6 +439,20 @@ def ha_changed():
|
||||
neutron_api_relation_joined(rid=rid)
|
||||
|
||||
|
||||
@hooks.hook('zeromq-configuration-relation-joined')
|
||||
@os_requires_version('kilo', 'neutron-server')
|
||||
def zeromq_configuration_relation_joined(relid=None):
|
||||
relation_set(relation_id=relid,
|
||||
topics=" ".join(get_topics()),
|
||||
users="neutron")
|
||||
|
||||
|
||||
@hooks.hook('zeromq-configuration-relation-changed')
|
||||
@restart_on_change(restart_map(), stopstart=True)
|
||||
def zeromq_configuration_relation_changed():
|
||||
CONFIGS.write_all()
|
||||
|
||||
|
||||
@hooks.hook('nrpe-external-master-relation-joined',
|
||||
'nrpe-external-master-relation-changed')
|
||||
def update_nrpe_config():
|
||||
|
@ -1,6 +1,8 @@
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
from functools import partial
|
||||
import os
|
||||
import shutil
|
||||
from base64 import b64encode
|
||||
from charmhelpers.contrib.openstack import context, templating
|
||||
from charmhelpers.contrib.openstack.neutron import (
|
||||
@ -10,6 +12,9 @@ from charmhelpers.contrib.openstack.neutron import (
|
||||
from charmhelpers.contrib.openstack.utils import (
|
||||
os_release,
|
||||
get_os_codename_install_source,
|
||||
git_install_requested,
|
||||
git_clone_and_install,
|
||||
git_src_dir,
|
||||
configure_installation_source,
|
||||
)
|
||||
|
||||
@ -26,9 +31,17 @@ from charmhelpers.fetch import (
|
||||
)
|
||||
|
||||
from charmhelpers.core.host import (
|
||||
lsb_release
|
||||
adduser,
|
||||
add_group,
|
||||
add_user_to_group,
|
||||
mkdir,
|
||||
lsb_release,
|
||||
service_restart,
|
||||
write_file,
|
||||
)
|
||||
|
||||
from charmhelpers.core.templating import render
|
||||
|
||||
import neutron_api_context
|
||||
|
||||
TEMPLATES = 'templates/'
|
||||
@ -52,6 +65,29 @@ KILO_PACKAGES = [
|
||||
'python-neutron-vpnaas',
|
||||
]
|
||||
|
||||
BASE_GIT_PACKAGES = [
|
||||
'libxml2-dev',
|
||||
'libxslt1-dev',
|
||||
'python-dev',
|
||||
'python-pip',
|
||||
'python-setuptools',
|
||||
'zlib1g-dev',
|
||||
]
|
||||
|
||||
# ubuntu packages that should not be installed when deploying from git
|
||||
GIT_PACKAGE_BLACKLIST = [
|
||||
'neutron-server',
|
||||
'neutron-plugin-ml2',
|
||||
'python-keystoneclient',
|
||||
'python-six',
|
||||
]
|
||||
|
||||
GIT_PACKAGE_BLACKLIST_KILO = [
|
||||
'python-neutron-lbaas',
|
||||
'python-neutron-fwaas',
|
||||
'python-neutron-vpnaas',
|
||||
]
|
||||
|
||||
BASE_SERVICES = [
|
||||
'neutron-server'
|
||||
]
|
||||
@ -82,6 +118,8 @@ BASE_RESOURCE_MAP = OrderedDict([
|
||||
service_user='neutron'),
|
||||
neutron_api_context.NeutronCCContext(),
|
||||
context.SyslogContext(),
|
||||
context.ZeroMQContext(),
|
||||
context.NotificationDriverContext(),
|
||||
context.BindHostContext(),
|
||||
context.WorkerConfigContext()],
|
||||
}),
|
||||
@ -112,14 +150,27 @@ def api_port(service):
|
||||
def determine_packages(source=None):
|
||||
# currently all packages match service names
|
||||
packages = [] + BASE_PACKAGES
|
||||
|
||||
for v in resource_map().values():
|
||||
packages.extend(v['services'])
|
||||
pkgs = neutron_plugin_attribute(config('neutron-plugin'),
|
||||
'server_packages',
|
||||
'neutron')
|
||||
packages.extend(pkgs)
|
||||
|
||||
if get_os_codename_install_source(source) >= 'kilo':
|
||||
packages.extend(KILO_PACKAGES)
|
||||
|
||||
if git_install_requested():
|
||||
packages.extend(BASE_GIT_PACKAGES)
|
||||
# don't include packages that will be installed from git
|
||||
packages = list(set(packages))
|
||||
for p in GIT_PACKAGE_BLACKLIST:
|
||||
packages.remove(p)
|
||||
if get_os_codename_install_source(source) >= 'kilo':
|
||||
for p in GIT_PACKAGE_BLACKLIST_KILO:
|
||||
packages.remove(p)
|
||||
|
||||
return list(set(packages))
|
||||
|
||||
|
||||
@ -230,6 +281,16 @@ def do_openstack_upgrade(configs):
|
||||
configs.set_release(openstack_release=new_os_rel)
|
||||
|
||||
|
||||
def get_topics():
|
||||
return ['q-l3-plugin',
|
||||
'q-firewall-plugin',
|
||||
'n-lbaas-plugin',
|
||||
'ipsec_driver',
|
||||
'q-metering-plugin',
|
||||
'q-plugin',
|
||||
'neutron']
|
||||
|
||||
|
||||
def setup_ipv6():
|
||||
ubuntu_rel = lsb_release()['DISTRIB_CODENAME'].lower()
|
||||
if ubuntu_rel < "trusty":
|
||||
@ -244,3 +305,104 @@ def setup_ipv6():
|
||||
' main')
|
||||
apt_update()
|
||||
apt_install('haproxy/trusty-backports', fatal=True)
|
||||
|
||||
|
||||
def router_feature_present(feature):
|
||||
''' Check For dvr enabled routers '''
|
||||
env = neutron_api_context.IdentityServiceContext()()
|
||||
if not env:
|
||||
log('Unable to check resources at this time')
|
||||
return
|
||||
|
||||
auth_url = '%(auth_protocol)s://%(auth_host)s:%(auth_port)s/v2.0' % env
|
||||
# Late import to avoid install hook failures when pkg hasnt been installed
|
||||
from neutronclient.v2_0 import client
|
||||
neutron_client = client.Client(username=env['admin_user'],
|
||||
password=env['admin_password'],
|
||||
tenant_name=env['admin_tenant_name'],
|
||||
auth_url=auth_url,
|
||||
region_name=env['region'])
|
||||
for router in neutron_client.list_routers()['routers']:
|
||||
if router.get(feature, False):
|
||||
return True
|
||||
return False
|
||||
|
||||
l3ha_router_present = partial(router_feature_present, feature='ha')
|
||||
|
||||
dvr_router_present = partial(router_feature_present, feature='distributed')
|
||||
|
||||
|
||||
def git_install(projects_yaml):
|
||||
"""Perform setup, and install git repos specified in yaml parameter."""
|
||||
if git_install_requested():
|
||||
git_pre_install()
|
||||
git_clone_and_install(projects_yaml, core_project='neutron')
|
||||
git_post_install(projects_yaml)
|
||||
|
||||
|
||||
def git_pre_install():
|
||||
"""Perform pre-install setup."""
|
||||
dirs = [
|
||||
'/etc/neutron',
|
||||
'/etc/neutron/rootwrap.d',
|
||||
'/etc/neutron/plugins',
|
||||
'/etc/neutron/plugins/ml2',
|
||||
'/var/lib/neutron',
|
||||
'/var/lib/neutron/lock',
|
||||
'/var/log/neutron',
|
||||
]
|
||||
|
||||
logs = [
|
||||
'/var/log/neutron/server.log',
|
||||
]
|
||||
|
||||
adduser('neutron', shell='/bin/bash', system_user=True)
|
||||
add_group('neutron', system_group=True)
|
||||
add_user_to_group('neutron', 'neutron')
|
||||
|
||||
for d in dirs:
|
||||
mkdir(d, owner='neutron', group='neutron', perms=0700, force=False)
|
||||
|
||||
for l in logs:
|
||||
write_file(l, '', owner='neutron', group='neutron', perms=0600)
|
||||
|
||||
|
||||
def git_post_install(projects_yaml):
|
||||
"""Perform post-install setup."""
|
||||
src_etc = os.path.join(git_src_dir(projects_yaml, 'neutron'), 'etc')
|
||||
configs = {
|
||||
'api-paste': {
|
||||
'src': os.path.join(src_etc, 'api-paste.ini'),
|
||||
'dest': '/etc/neutron/api-paste.ini',
|
||||
},
|
||||
'debug-filters': {
|
||||
'src': os.path.join(src_etc, 'neutron/rootwrap.d/debug.filters'),
|
||||
'dest': '/etc/neutron/rootwrap.d/debug.filters',
|
||||
},
|
||||
'policy': {
|
||||
'src': os.path.join(src_etc, 'policy.json'),
|
||||
'dest': '/etc/neutron/policy.json',
|
||||
},
|
||||
'rootwrap': {
|
||||
'src': os.path.join(src_etc, 'rootwrap.conf'),
|
||||
'dest': '/etc/neutron/rootwrap.conf',
|
||||
},
|
||||
}
|
||||
|
||||
for conf, files in configs.iteritems():
|
||||
shutil.copyfile(files['src'], files['dest'])
|
||||
|
||||
render('neutron_sudoers', '/etc/sudoers.d/neutron_sudoers', {},
|
||||
perms=0o440)
|
||||
|
||||
neutron_api_context = {
|
||||
'service_description': 'Neutron API server',
|
||||
'charm_name': 'neutron-api',
|
||||
'process_name': 'neutron-server',
|
||||
}
|
||||
|
||||
# NOTE(coreycb): Needs systemd support
|
||||
render('upstart/neutron-server.upstart', '/etc/init/neutron-server.conf',
|
||||
neutron_api_context, perms=0o644)
|
||||
|
||||
service_restart('neutron-server')
|
||||
|
1
hooks/zeromq-configuration-relation-changed
Symbolic link
1
hooks/zeromq-configuration-relation-changed
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
1
hooks/zeromq-configuration-relation-joined
Symbolic link
1
hooks/zeromq-configuration-relation-joined
Symbolic link
@ -0,0 +1 @@
|
||||
neutron_api_hooks.py
|
@ -34,6 +34,9 @@ requires:
|
||||
ha:
|
||||
interface: hacluster
|
||||
scope: container
|
||||
zeromq-configuration:
|
||||
interface: zeromq-configuration
|
||||
scope: container
|
||||
peers:
|
||||
cluster:
|
||||
interface: neutron-api-ha
|
||||
|
@ -1,3 +1,4 @@
|
||||
# icehouse
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
@ -11,7 +12,10 @@ state_path = /var/lib/neutron
|
||||
lock_path = $state_path/lock
|
||||
bind_host = {{ bind_host }}
|
||||
auth_strategy = keystone
|
||||
|
||||
{% if notifications == 'True' -%}
|
||||
notification_driver = neutron.openstack.common.notifier.rpc_notifier
|
||||
{% endif -%}
|
||||
api_workers = {{ workers }}
|
||||
rpc_workers = {{ workers }}
|
||||
|
||||
|
85
templates/juno/neutron.conf
Normal file
85
templates/juno/neutron.conf
Normal file
@ -0,0 +1,85 @@
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
## Restart trigger {{ restart_trigger }}
|
||||
###############################################################################
|
||||
[DEFAULT]
|
||||
verbose = {{ verbose }}
|
||||
debug = {{ debug }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
state_path = /var/lib/neutron
|
||||
lock_path = $state_path/lock
|
||||
bind_host = {{ bind_host }}
|
||||
auth_strategy = keystone
|
||||
notification_driver = neutron.openstack.common.notifier.rpc_notifier
|
||||
api_workers = {{ workers }}
|
||||
rpc_workers = {{ workers }}
|
||||
|
||||
router_distributed = {{ enable_dvr }}
|
||||
|
||||
l3_ha = {{ l3_ha }}
|
||||
{% if l3_ha -%}
|
||||
max_l3_agents_per_router = {{ max_l3_agents_per_router }}
|
||||
min_l3_agents_per_router = {{ min_l3_agents_per_router }}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_bind_port -%}
|
||||
bind_port = {{ neutron_bind_port }}
|
||||
{% else -%}
|
||||
bind_port = 9696
|
||||
{% endif -%}
|
||||
|
||||
{% if core_plugin -%}
|
||||
core_plugin = {{ core_plugin }}
|
||||
{% if neutron_plugin in ['ovs', 'ml2'] -%}
|
||||
service_plugins = neutron.services.l3_router.l3_router_plugin.L3RouterPlugin,neutron.services.firewall.fwaas_plugin.FirewallPlugin,neutron.services.loadbalancer.plugin.LoadBalancerPlugin,neutron.services.vpn.plugin.VPNDriverPlugin,neutron.services.metering.metering_plugin.MeteringPlugin
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_security_groups -%}
|
||||
allow_overlapping_ips = True
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
notify_nova_on_port_status_changes = True
|
||||
notify_nova_on_port_data_changes = True
|
||||
nova_url = {{ nova_url }}
|
||||
nova_region_name = {{ region }}
|
||||
{% if auth_host -%}
|
||||
nova_admin_username = {{ admin_user }}
|
||||
nova_admin_tenant_id = {{ admin_tenant_id }}
|
||||
nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
quota_items = network,subnet,port,security_group,security_group_rule
|
||||
{% endif -%}
|
||||
|
||||
[agent]
|
||||
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
|
||||
|
||||
[keystone_authtoken]
|
||||
signing_dir = {{ signing_dir }}
|
||||
{% if service_host -%}
|
||||
service_protocol = {{ service_protocol }}
|
||||
service_host = {{ service_host }}
|
||||
service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/section-database" %}
|
||||
|
||||
[service_providers]
|
||||
service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
|
||||
service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
|
||||
service_provider=FIREWALL:Iptables:neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
|
@ -1,3 +1,4 @@
|
||||
# kilo
|
||||
###############################################################################
|
||||
# [ WARNING ]
|
||||
# Configuration file maintained by Juju. Local changes may be overwritten.
|
||||
@ -8,13 +9,20 @@ verbose = {{ verbose }}
|
||||
debug = {{ debug }}
|
||||
use_syslog = {{ use_syslog }}
|
||||
state_path = /var/lib/neutron
|
||||
lock_path = $state_path/lock
|
||||
bind_host = {{ bind_host }}
|
||||
auth_strategy = keystone
|
||||
notification_driver = neutron.openstack.common.notifier.rpc_notifier
|
||||
api_workers = {{ workers }}
|
||||
rpc_workers = {{ workers }}
|
||||
|
||||
router_distributed = {{ enable_dvr }}
|
||||
|
||||
l3_ha = {{ l3_ha }}
|
||||
{% if l3_ha -%}
|
||||
max_l3_agents_per_router = {{ max_l3_agents_per_router }}
|
||||
min_l3_agents_per_router = {{ min_l3_agents_per_router }}
|
||||
{% endif -%}
|
||||
|
||||
{% if neutron_bind_port -%}
|
||||
bind_port = {{ neutron_bind_port }}
|
||||
{% else -%}
|
||||
@ -33,8 +41,6 @@ allow_overlapping_ips = True
|
||||
neutron_firewall_driver = neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver
|
||||
{% endif -%}
|
||||
|
||||
{% include "parts/rabbitmq" %}
|
||||
|
||||
notify_nova_on_port_status_changes = True
|
||||
notify_nova_on_port_data_changes = True
|
||||
nova_url = {{ nova_url }}
|
||||
@ -46,6 +52,8 @@ nova_admin_password = {{ admin_password }}
|
||||
nova_admin_auth_url = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}/v2.0
|
||||
{% endif -%}
|
||||
|
||||
{% include "section-zeromq" %}
|
||||
|
||||
[quotas]
|
||||
quota_driver = neutron.db.quota_db.DbQuotaDriver
|
||||
{% if neutron_security_groups -%}
|
||||
@ -56,7 +64,7 @@ quota_security_group_rule = {{ quota_security_group_rule }}
|
||||
quota_items = network,subnet,port
|
||||
{% endif -%}
|
||||
quota_network = {{ quota_network }}
|
||||
quota_subnet = {{ quota_subnet }}
|
||||
quota_subnet = {{ quota_subnet }}
|
||||
quota_port = {{ quota_port }}
|
||||
quota_vip = {{ quota_vip }}
|
||||
quota_pool = {{ quota_pool }}
|
||||
@ -68,23 +76,16 @@ quota_floatingip = {{ quota_floatingip }}
|
||||
[agent]
|
||||
root_helper = sudo /usr/bin/neutron-rootwrap /etc/neutron/rootwrap.conf
|
||||
|
||||
[keystone_authtoken]
|
||||
signing_dir = {{ signing_dir }}
|
||||
{% if service_host -%}
|
||||
service_protocol = {{ service_protocol }}
|
||||
service_host = {{ service_host }}
|
||||
service_port = {{ service_port }}
|
||||
auth_host = {{ auth_host }}
|
||||
auth_port = {{ auth_port }}
|
||||
auth_protocol = {{ auth_protocol }}
|
||||
admin_tenant_name = {{ admin_tenant_name }}
|
||||
admin_user = {{ admin_user }}
|
||||
admin_password = {{ admin_password }}
|
||||
{% endif -%}
|
||||
{% include "section-keystone-authtoken" %}
|
||||
|
||||
{% include "parts/section-database" %}
|
||||
|
||||
{% include "section-rabbitmq-oslo" %}
|
||||
|
||||
[service_providers]
|
||||
service_provider=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
|
||||
service_provider=VPN:openswan:neutron_vpnaas.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default
|
||||
service_provider=FIREWALL:Iptables:neutron_fwaas.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver:default
|
||||
|
||||
[oslo_concurrency]
|
||||
lock_path = $state_path/lock
|
||||
|
4
templates/neutron_sudoers
Normal file
4
templates/neutron_sudoers
Normal file
@ -0,0 +1,4 @@
|
||||
Defaults:neutron !requiretty
|
||||
|
||||
neutron ALL = (root) NOPASSWD: /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf *
|
||||
|
22
templates/upstart/neutron-server.upstart
Normal file
22
templates/upstart/neutron-server.upstart
Normal file
@ -0,0 +1,22 @@
|
||||
description "{{ service_description }}"
|
||||
author "Juju {{ charm_name }} Charm <juju@localhost>"
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [!2345]
|
||||
|
||||
respawn
|
||||
|
||||
chdir /var/run
|
||||
|
||||
pre-start script
|
||||
mkdir -p /var/run/neutron
|
||||
chown neutron:root /var/run/neutron
|
||||
end script
|
||||
|
||||
script
|
||||
[ -r /etc/default/{{ process_name }} ] && . /etc/default/{{ process_name }}
|
||||
[ -r "$NEUTRON_PLUGIN_CONFIG" ] && CONF_ARG="--config-file $NEUTRON_PLUGIN_CONFIG"
|
||||
exec start-stop-daemon --start --chuid neutron --exec /usr/local/bin/neutron-server -- \
|
||||
--config-file /etc/neutron/neutron.conf \
|
||||
--log-file /var/log/neutron/server.log $CONF_ARG
|
||||
end script
|
9
tests/16-basic-trusty-icehouse-git
Executable file
9
tests/16-basic-trusty-icehouse-git
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
"""Amulet tests on a basic neutron-api git deployment on trusty-icehouse."""
|
||||
|
||||
from basic_deployment import NeutronAPIBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = NeutronAPIBasicDeployment(series='trusty', git=True)
|
||||
deployment.run_tests()
|
12
tests/18-basic-trusty-juno-git
Executable file
12
tests/18-basic-trusty-juno-git
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
"""Amulet tests on a basic neutron-api git deployment on trusty-juno."""
|
||||
|
||||
from basic_deployment import NeutronAPIBasicDeployment
|
||||
|
||||
if __name__ == '__main__':
|
||||
deployment = NeutronAPIBasicDeployment(series='trusty',
|
||||
openstack='cloud:trusty-juno',
|
||||
source='cloud:trusty-updates/juno',
|
||||
git=True)
|
||||
deployment.run_tests()
|
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import amulet
|
||||
import yaml
|
||||
|
||||
from charmhelpers.contrib.openstack.amulet.deployment import (
|
||||
OpenStackAmuletDeployment
|
||||
@ -19,10 +20,12 @@ u = OpenStackAmuletUtils(ERROR)
|
||||
class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
"""Amulet tests on a basic neutron-api deployment."""
|
||||
|
||||
def __init__(self, series, openstack=None, source=None, stable=False):
|
||||
def __init__(self, series, openstack=None, source=None, git=False,
|
||||
stable=False):
|
||||
"""Deploy the entire test environment."""
|
||||
super(NeutronAPIBasicDeployment, self).__init__(series, openstack,
|
||||
source, stable)
|
||||
self.git = git
|
||||
self._add_services()
|
||||
self._add_relations()
|
||||
self._configure_services()
|
||||
@ -65,11 +68,29 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
|
||||
def _configure_services(self):
|
||||
"""Configure all of the services."""
|
||||
neutron_api_config = {}
|
||||
if self.git:
|
||||
branch = 'stable/' + self._get_openstack_release_string()
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository': 'git://git.openstack.org/openstack/requirements',
|
||||
'branch': branch},
|
||||
{'name': 'neutron',
|
||||
'repository': 'git://git.openstack.org/openstack/neutron',
|
||||
'branch': branch},
|
||||
],
|
||||
'directory': '/mnt/openstack-git',
|
||||
'http_proxy': 'http://squid.internal:3128',
|
||||
'https_proxy': 'https://squid.internal:3128',
|
||||
}
|
||||
neutron_api_config['openstack-origin-git'] = yaml.dump(openstack_origin_git)
|
||||
keystone_config = {'admin-password': 'openstack',
|
||||
'admin-token': 'ubuntutesting'}
|
||||
nova_cc_config = {'network-manager': 'Quantum',
|
||||
'quantum-security-groups': 'yes'}
|
||||
configs = {'keystone': keystone_config,
|
||||
configs = {'neutron-api': neutron_api_config,
|
||||
'keystone': keystone_config,
|
||||
'nova-cloud-controller': nova_cc_config}
|
||||
super(NeutronAPIBasicDeployment, self)._configure_services(configs)
|
||||
|
||||
@ -178,7 +199,6 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
'auth_host': id_ip,
|
||||
'auth_port': "35357",
|
||||
'auth_protocol': 'http',
|
||||
'https_keystone': "False",
|
||||
'private-address': id_ip,
|
||||
'service_host': id_ip,
|
||||
}
|
||||
@ -294,7 +314,7 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
'nova_admin_auth_url': nova_auth_url,
|
||||
},
|
||||
'keystone_authtoken': {
|
||||
'signing_dir': '/var/lib/neutron/keystone-signing',
|
||||
'signing_dir': '/var/cache/neutron',
|
||||
'service_protocol': ks_rel['service_protocol'],
|
||||
'service_host': ks_rel['service_host'],
|
||||
'service_port': ks_rel['service_port'],
|
||||
@ -355,6 +375,7 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
def test_services(self):
|
||||
"""Verify the expected services are running on the corresponding
|
||||
service units."""
|
||||
neutron_api_services = ['status neutron-server']
|
||||
neutron_services = ['status neutron-dhcp-agent',
|
||||
'status neutron-lbaas-agent',
|
||||
'status neutron-metadata-agent',
|
||||
@ -374,7 +395,8 @@ class NeutronAPIBasicDeployment(OpenStackAmuletDeployment):
|
||||
self.mysql_sentry: ['status mysql'],
|
||||
self.keystone_sentry: ['status keystone'],
|
||||
self.nova_cc_sentry: nova_cc_services,
|
||||
self.quantum_gateway_sentry: neutron_services
|
||||
self.quantum_gateway_sentry: neutron_services,
|
||||
self.neutron_api_sentry: neutron_api_services,
|
||||
}
|
||||
|
||||
ret = u.validate_services(commands)
|
||||
|
@ -15,6 +15,7 @@
|
||||
# along with charm-helpers. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import six
|
||||
from collections import OrderedDict
|
||||
from charmhelpers.contrib.amulet.deployment import (
|
||||
AmuletDeployment
|
||||
)
|
||||
@ -100,12 +101,34 @@ class OpenStackAmuletDeployment(AmuletDeployment):
|
||||
"""
|
||||
(self.precise_essex, self.precise_folsom, self.precise_grizzly,
|
||||
self.precise_havana, self.precise_icehouse,
|
||||
self.trusty_icehouse) = range(6)
|
||||
self.trusty_icehouse, self.trusty_juno, self.trusty_kilo) = range(8)
|
||||
releases = {
|
||||
('precise', None): self.precise_essex,
|
||||
('precise', 'cloud:precise-folsom'): self.precise_folsom,
|
||||
('precise', 'cloud:precise-grizzly'): self.precise_grizzly,
|
||||
('precise', 'cloud:precise-havana'): self.precise_havana,
|
||||
('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)]
|
||||
|
||||
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]
|
||||
|
@ -1,2 +1,4 @@
|
||||
import sys
|
||||
|
||||
sys.path.append('actions/')
|
||||
sys.path.append('hooks/')
|
||||
|
85
unit_tests/test_actions_git_reinstall.py
Normal file
85
unit_tests/test_actions_git_reinstall.py
Normal file
@ -0,0 +1,85 @@
|
||||
from mock import patch
|
||||
|
||||
with patch('charmhelpers.core.hookenv.config') as config:
|
||||
config.return_value = 'neutron'
|
||||
import neutron_api_utils as utils # noqa
|
||||
|
||||
import git_reinstall
|
||||
|
||||
from test_utils import (
|
||||
CharmTestCase
|
||||
)
|
||||
|
||||
TO_PATCH = [
|
||||
'config',
|
||||
]
|
||||
|
||||
|
||||
openstack_origin_git = \
|
||||
"""repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: stable/juno}
|
||||
- {name: neutron,
|
||||
repository: 'git://git.openstack.org/openstack/neutron',
|
||||
branch: stable/juno}"""
|
||||
|
||||
|
||||
class TestNeutronAPIActions(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestNeutronAPIActions, self).setUp(git_reinstall, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
|
||||
@patch.object(git_reinstall, 'action_set')
|
||||
@patch.object(git_reinstall, 'action_fail')
|
||||
@patch.object(git_reinstall, 'git_install')
|
||||
def test_git_reinstall(self, git_install, action_fail, action_set):
|
||||
self.test_config.set('openstack-origin-git', openstack_origin_git)
|
||||
|
||||
git_reinstall.git_reinstall()
|
||||
|
||||
git_install.assert_called_with(openstack_origin_git)
|
||||
self.assertTrue(git_install.called)
|
||||
self.assertFalse(action_set.called)
|
||||
self.assertFalse(action_fail.called)
|
||||
|
||||
@patch.object(git_reinstall, 'action_set')
|
||||
@patch.object(git_reinstall, 'action_fail')
|
||||
@patch.object(git_reinstall, 'git_install')
|
||||
@patch('charmhelpers.contrib.openstack.utils.config')
|
||||
def test_git_reinstall_not_configured(self, _config, git_install,
|
||||
action_fail, action_set):
|
||||
_config.return_value = None
|
||||
|
||||
git_reinstall.git_reinstall()
|
||||
|
||||
msg = 'openstack-origin-git is not configured'
|
||||
action_fail.assert_called_with(msg)
|
||||
self.assertFalse(git_install.called)
|
||||
self.assertFalse(action_set.called)
|
||||
|
||||
@patch.object(git_reinstall, 'action_set')
|
||||
@patch.object(git_reinstall, 'action_fail')
|
||||
@patch.object(git_reinstall, 'git_install')
|
||||
@patch('charmhelpers.contrib.openstack.utils.config')
|
||||
def test_git_reinstall_exception(self, _config, git_install,
|
||||
action_fail, action_set):
|
||||
_config.return_value = openstack_origin_git
|
||||
e = OSError('something bad happened')
|
||||
git_install.side_effect = e
|
||||
traceback = (
|
||||
"Traceback (most recent call last):\n"
|
||||
" File \"actions/git_reinstall.py\", line 33, in git_reinstall\n"
|
||||
" git_install(config(\'openstack-origin-git\'))\n"
|
||||
" File \"/usr/lib/python2.7/dist-packages/mock.py\", line 964, in __call__\n" # noqa
|
||||
" return _mock_self._mock_call(*args, **kwargs)\n"
|
||||
" File \"/usr/lib/python2.7/dist-packages/mock.py\", line 1019, in _mock_call\n" # noqa
|
||||
" raise effect\n"
|
||||
"OSError: something bad happened\n")
|
||||
|
||||
git_reinstall.git_reinstall()
|
||||
|
||||
msg = 'git-reinstall resulted in an unexpected error'
|
||||
action_fail.assert_called_with(msg)
|
||||
action_set.assert_called_with({'traceback': traceback})
|
@ -3,15 +3,131 @@ from mock import patch
|
||||
import neutron_api_context as context
|
||||
import charmhelpers
|
||||
TO_PATCH = [
|
||||
'config',
|
||||
'determine_api_port',
|
||||
'determine_apache_port',
|
||||
'log',
|
||||
'os_release',
|
||||
'relation_get',
|
||||
'relation_ids',
|
||||
'related_units',
|
||||
'config',
|
||||
'determine_api_port',
|
||||
'determine_apache_port'
|
||||
]
|
||||
|
||||
|
||||
class GeneralTests(CharmTestCase):
|
||||
def setUp(self):
|
||||
super(GeneralTests, self).setUp(context, TO_PATCH)
|
||||
self.relation_get.side_effect = self.test_relation.get
|
||||
self.config.side_effect = self.test_config.get
|
||||
|
||||
def test_l2population(self):
|
||||
self.test_config.set('l2-population', True)
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.assertEquals(context.get_l2population(), True)
|
||||
|
||||
def test_l2population_nonovs(self):
|
||||
self.test_config.set('l2-population', True)
|
||||
self.test_config.set('neutron-plugin', 'nsx')
|
||||
self.assertEquals(context.get_l2population(), False)
|
||||
|
||||
def test_get_overlay_network_type(self):
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.assertEquals(context.get_overlay_network_type(), 'gre')
|
||||
|
||||
def test_get_overlay_network_type_unsupported(self):
|
||||
self.test_config.set('overlay-network-type', 'tokenring')
|
||||
with self.assertRaises(Exception) as _exceptctxt:
|
||||
context.get_overlay_network_type()
|
||||
self.assertEqual(_exceptctxt.exception.message,
|
||||
'Unsupported overlay-network-type')
|
||||
|
||||
def test_get_l3ha(self):
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_l3ha(), True)
|
||||
|
||||
def test_get_l3ha_prejuno(self):
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'icehouse'
|
||||
self.assertEquals(context.get_l3ha(), False)
|
||||
|
||||
def test_get_l3ha_l2pop(self):
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', True)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_l3ha(), False)
|
||||
|
||||
def test_get_l3ha_badoverlay(self):
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'tokenring')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_l3ha(), False)
|
||||
|
||||
def test_get_dvr(self):
|
||||
self.test_config.set('enable-dvr', True)
|
||||
self.test_config.set('enable-l3ha', False)
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', True)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_dvr(), True)
|
||||
|
||||
def test_get_dvr_explicit_off(self):
|
||||
self.test_config.set('enable-dvr', False)
|
||||
self.test_config.set('enable-l3ha', False)
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', True)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_dvr(), False)
|
||||
|
||||
def test_get_dvr_prejuno(self):
|
||||
self.test_config.set('enable-dvr', True)
|
||||
self.test_config.set('enable-l3ha', False)
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', True)
|
||||
self.os_release.return_value = 'icehouse'
|
||||
self.assertEquals(context.get_dvr(), False)
|
||||
|
||||
def test_get_dvr_gre(self):
|
||||
self.test_config.set('enable-dvr', True)
|
||||
self.test_config.set('enable-l3ha', False)
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', True)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_dvr(), False)
|
||||
|
||||
def test_get_dvr_l3ha_on(self):
|
||||
self.test_config.set('enable-dvr', True)
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_dvr(), False)
|
||||
|
||||
def test_get_dvr_l2pop(self):
|
||||
self.test_config.set('enable-dvr', True)
|
||||
self.test_config.set('enable-l3ha', False)
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'juno'
|
||||
self.assertEquals(context.get_dvr(), False)
|
||||
|
||||
|
||||
class IdentityServiceContext(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -152,6 +268,8 @@ class NeutronCCContextTest(CharmTestCase):
|
||||
plugin.return_value = None
|
||||
ctxt_data = {
|
||||
'debug': True,
|
||||
'enable_dvr': False,
|
||||
'l3_ha': False,
|
||||
'external_network': 'bob',
|
||||
'neutron_bind_port': self.api_port,
|
||||
'verbose': True,
|
||||
@ -181,6 +299,8 @@ class NeutronCCContextTest(CharmTestCase):
|
||||
self.test_config.set('overlay-network-type', 'vxlan')
|
||||
ctxt_data = {
|
||||
'debug': True,
|
||||
'enable_dvr': False,
|
||||
'l3_ha': False,
|
||||
'external_network': 'bob',
|
||||
'neutron_bind_port': self.api_port,
|
||||
'verbose': True,
|
||||
@ -202,6 +322,43 @@ class NeutronCCContextTest(CharmTestCase):
|
||||
with patch.object(napi_ctxt, '_ensure_packages'):
|
||||
self.assertEquals(ctxt_data, napi_ctxt())
|
||||
|
||||
@patch.object(context.NeutronCCContext, 'network_manager')
|
||||
@patch.object(context.NeutronCCContext, 'plugin')
|
||||
@patch('__builtin__.__import__')
|
||||
def test_neutroncc_context_l3ha(self, _import, plugin, nm):
|
||||
plugin.return_value = None
|
||||
self.test_config.set('enable-l3ha', True)
|
||||
self.test_config.set('overlay-network-type', 'gre')
|
||||
self.test_config.set('neutron-plugin', 'ovs')
|
||||
self.test_config.set('l2-population', False)
|
||||
self.os_release.return_value = 'juno'
|
||||
ctxt_data = {
|
||||
'debug': True,
|
||||
'enable_dvr': False,
|
||||
'l3_ha': True,
|
||||
'external_network': 'bob',
|
||||
'neutron_bind_port': self.api_port,
|
||||
'verbose': True,
|
||||
'l2_population': False,
|
||||
'overlay_network_type': 'gre',
|
||||
'max_l3_agents_per_router': 2,
|
||||
'min_l3_agents_per_router': 2,
|
||||
'quota_floatingip': 50,
|
||||
'quota_health_monitors': -1,
|
||||
'quota_member': -1,
|
||||
'quota_network': 10,
|
||||
'quota_pool': 10,
|
||||
'quota_port': 50,
|
||||
'quota_router': 10,
|
||||
'quota_security_group': 10,
|
||||
'quota_security_group_rule': 100,
|
||||
'quota_subnet': 10,
|
||||
'quota_vip': 10,
|
||||
}
|
||||
napi_ctxt = context.NeutronCCContext()
|
||||
with patch.object(napi_ctxt, '_ensure_packages'):
|
||||
self.assertEquals(ctxt_data, napi_ctxt())
|
||||
|
||||
@patch.object(context.NeutronCCContext, 'network_manager')
|
||||
@patch.object(context.NeutronCCContext, 'plugin')
|
||||
@patch('__builtin__.__import__')
|
||||
|
@ -1,4 +1,5 @@
|
||||
from mock import MagicMock, patch, call
|
||||
import yaml
|
||||
from test_utils import CharmTestCase
|
||||
|
||||
|
||||
@ -32,14 +33,20 @@ TO_PATCH = [
|
||||
'determine_packages',
|
||||
'determine_ports',
|
||||
'do_openstack_upgrade',
|
||||
'dvr_router_present',
|
||||
'l3ha_router_present',
|
||||
'execd_preinstall',
|
||||
'filter_installed_packages',
|
||||
'get_dvr',
|
||||
'get_l3ha',
|
||||
'get_l2population',
|
||||
'get_overlay_network_type',
|
||||
'git_install',
|
||||
'is_relation_made',
|
||||
'log',
|
||||
'open_port',
|
||||
'openstack_upgrade_available',
|
||||
'os_requires_version',
|
||||
'relation_get',
|
||||
'relation_ids',
|
||||
'relation_set',
|
||||
@ -48,6 +55,8 @@ TO_PATCH = [
|
||||
'get_netmask_for_address',
|
||||
'get_address_in_network',
|
||||
'update_nrpe_config',
|
||||
'service_reload',
|
||||
'IdentityServiceContext',
|
||||
]
|
||||
NEUTRON_CONF_DIR = "/etc/neutron"
|
||||
|
||||
@ -56,6 +65,15 @@ NEUTRON_CONF = '%s/neutron.conf' % NEUTRON_CONF_DIR
|
||||
from random import randrange
|
||||
|
||||
|
||||
class DummyContext():
|
||||
|
||||
def __init__(self, return_value):
|
||||
self.return_value = return_value
|
||||
|
||||
def __call__(self):
|
||||
return self.return_value
|
||||
|
||||
|
||||
class NeutronAPIHooksTests(CharmTestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -73,7 +91,9 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
hooks.hooks.execute([
|
||||
'hooks/{}'.format(hookname)])
|
||||
|
||||
def test_install_hook(self):
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
def test_install_hook(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
_pkgs = ['foo', 'bar']
|
||||
_ports = [80, 81, 82]
|
||||
_port_calls = [call(port) for port in _ports]
|
||||
@ -90,9 +110,46 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
self.open_port.assert_has_calls(_port_calls)
|
||||
self.assertTrue(self.execd_preinstall.called)
|
||||
|
||||
@patch.object(utils, 'git_install_requested')
|
||||
def test_install_hook_git(self, git_requested):
|
||||
git_requested.return_value = True
|
||||
_pkgs = ['foo', 'bar']
|
||||
_ports = [80, 81, 82]
|
||||
_port_calls = [call(port) for port in _ports]
|
||||
self.determine_packages.return_value = _pkgs
|
||||
self.determine_ports.return_value = _ports
|
||||
repo = 'cloud:trusty-juno'
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository': 'git://git.openstack.org/openstack/requirements', # noqa
|
||||
'branch': 'stable/juno'},
|
||||
{'name': 'neutron',
|
||||
'repository': 'git://git.openstack.org/openstack/neutron',
|
||||
'branch': 'stable/juno'}
|
||||
],
|
||||
'directory': '/mnt/openstack-git',
|
||||
}
|
||||
projects_yaml = yaml.dump(openstack_origin_git)
|
||||
self.test_config.set('openstack-origin', repo)
|
||||
self.test_config.set('openstack-origin-git', projects_yaml)
|
||||
self._call_hook('install')
|
||||
self.assertTrue(self.execd_preinstall.called)
|
||||
self.configure_installation_source.assert_called_with(repo)
|
||||
self.apt_update.assert_called_with()
|
||||
self.apt_install.assert_has_calls([
|
||||
call(_pkgs, fatal=True),
|
||||
])
|
||||
self.git_install.assert_called_with(projects_yaml)
|
||||
self.open_port.assert_has_calls(_port_calls)
|
||||
|
||||
@patch.object(hooks, 'configure_https')
|
||||
def test_config_changed(self, conf_https):
|
||||
@patch.object(hooks, 'git_install_requested')
|
||||
def test_config_changed(self, git_requested, conf_https):
|
||||
git_requested.return_value = False
|
||||
self.openstack_upgrade_available.return_value = True
|
||||
self.dvr_router_present.return_value = False
|
||||
self.l3ha_router_present.return_value = False
|
||||
self.relation_ids.side_effect = self._fake_relids
|
||||
_n_api_rel_joined = self.patch('neutron_api_relation_joined')
|
||||
_n_plugin_api_rel_joined =\
|
||||
@ -100,16 +157,64 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
_amqp_rel_joined = self.patch('amqp_joined')
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
_id_cluster_joined = self.patch('cluster_joined')
|
||||
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
|
||||
self._call_hook('config-changed')
|
||||
self.assertTrue(_n_api_rel_joined.called)
|
||||
self.assertTrue(_n_plugin_api_rel_joined.called)
|
||||
self.assertTrue(_amqp_rel_joined.called)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
self.assertTrue(_id_cluster_joined.called)
|
||||
self.assertTrue(_zmq_joined.called)
|
||||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(self.do_openstack_upgrade.called)
|
||||
self.assertTrue(self.apt_install.called)
|
||||
|
||||
@patch.object(hooks, 'configure_https')
|
||||
@patch.object(hooks, 'git_install_requested')
|
||||
@patch.object(hooks, 'config_value_changed')
|
||||
def test_config_changed_git(self, config_val_changed, git_requested,
|
||||
configure_https):
|
||||
git_requested.return_value = True
|
||||
self.dvr_router_present.return_value = False
|
||||
self.l3ha_router_present.return_value = False
|
||||
self.relation_ids.side_effect = self._fake_relids
|
||||
_n_api_rel_joined = self.patch('neutron_api_relation_joined')
|
||||
_n_plugin_api_rel_joined =\
|
||||
self.patch('neutron_plugin_api_relation_joined')
|
||||
_amqp_rel_joined = self.patch('amqp_joined')
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
_id_cluster_joined = self.patch('cluster_joined')
|
||||
_zmq_joined = self.patch('zeromq_configuration_relation_joined')
|
||||
repo = 'cloud:trusty-juno'
|
||||
openstack_origin_git = {
|
||||
'repositories': [
|
||||
{'name': 'requirements',
|
||||
'repository':
|
||||
'git://git.openstack.org/openstack/requirements',
|
||||
'branch': 'stable/juno'},
|
||||
{'name': 'neutron',
|
||||
'repository': 'git://git.openstack.org/openstack/neutron',
|
||||
'branch': 'stable/juno'}
|
||||
],
|
||||
'directory': '/mnt/openstack-git',
|
||||
}
|
||||
projects_yaml = yaml.dump(openstack_origin_git)
|
||||
self.test_config.set('openstack-origin', repo)
|
||||
self.test_config.set('openstack-origin-git', projects_yaml)
|
||||
self._call_hook('config-changed')
|
||||
self.git_install.assert_called_with(projects_yaml)
|
||||
self.assertFalse(self.do_openstack_upgrade.called)
|
||||
self.assertTrue(self.apt_install.called)
|
||||
self.assertTrue(configure_https.called)
|
||||
self.assertTrue(self.update_nrpe_config.called)
|
||||
self.assertTrue(self.CONFIGS.write_all.called)
|
||||
self.assertTrue(_n_api_rel_joined.called)
|
||||
self.assertTrue(_n_plugin_api_rel_joined.called)
|
||||
self.assertTrue(_amqp_rel_joined.called)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
self.assertTrue(_zmq_joined.called)
|
||||
self.assertTrue(_id_cluster_joined.called)
|
||||
|
||||
def test_amqp_joined(self):
|
||||
self._call_hook('amqp-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
@ -272,11 +377,87 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_nol2(self):
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': False,
|
||||
'enable-l3ha': False,
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
'auth_protocol': None,
|
||||
'service_tenant': None,
|
||||
'service_port': None,
|
||||
'region': 'RegionOne',
|
||||
'service_password': None,
|
||||
'auth_port': None,
|
||||
'auth_host': None,
|
||||
'service_username': None,
|
||||
'service_host': None
|
||||
}
|
||||
self.get_dvr.return_value = False
|
||||
self.get_l3ha.return_value = False
|
||||
self.get_l2population.return_value = False
|
||||
self.get_overlay_network_type.return_value = 'vxlan'
|
||||
self._call_hook('neutron-plugin-api-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
relation_id=None,
|
||||
**_relation_data
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_dvr(self):
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': True,
|
||||
'enable-l3ha': False,
|
||||
'l2-population': True,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
'auth_protocol': None,
|
||||
'service_tenant': None,
|
||||
'service_port': None,
|
||||
'region': 'RegionOne',
|
||||
'service_password': None,
|
||||
'auth_port': None,
|
||||
'auth_host': None,
|
||||
'service_username': None,
|
||||
'service_host': None
|
||||
}
|
||||
self.get_dvr.return_value = True
|
||||
self.get_l3ha.return_value = False
|
||||
self.get_l2population.return_value = True
|
||||
self.get_overlay_network_type.return_value = 'vxlan'
|
||||
self._call_hook('neutron-plugin-api-relation-joined')
|
||||
self.relation_set.assert_called_with(
|
||||
relation_id=None,
|
||||
**_relation_data
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_l3ha(self):
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'enable-dvr': False,
|
||||
'enable-l3ha': True,
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'service_protocol': None,
|
||||
'auth_protocol': None,
|
||||
'service_tenant': None,
|
||||
'service_port': None,
|
||||
'region': 'RegionOne',
|
||||
'service_password': None,
|
||||
'auth_port': None,
|
||||
'auth_host': None,
|
||||
'service_username': None,
|
||||
'service_host': None
|
||||
}
|
||||
self.get_dvr.return_value = False
|
||||
self.get_l3ha.return_value = True
|
||||
self.get_l2population.return_value = False
|
||||
self.get_overlay_network_type.return_value = 'vxlan'
|
||||
self._call_hook('neutron-plugin-api-relation-joined')
|
||||
@ -286,13 +467,29 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
)
|
||||
|
||||
def test_neutron_plugin_api_relation_joined_w_mtu(self):
|
||||
self.IdentityServiceContext.return_value = \
|
||||
DummyContext(return_value={})
|
||||
self.test_config.set('network-device-mtu', 1500)
|
||||
_relation_data = {
|
||||
'neutron-security-groups': False,
|
||||
'l2-population': False,
|
||||
'overlay-network-type': 'vxlan',
|
||||
'network-device-mtu': 1500,
|
||||
'enable-l3ha': True,
|
||||
'enable-dvr': True,
|
||||
'service_protocol': None,
|
||||
'auth_protocol': None,
|
||||
'service_tenant': None,
|
||||
'service_port': None,
|
||||
'region': 'RegionOne',
|
||||
'service_password': None,
|
||||
'auth_port': None,
|
||||
'auth_host': None,
|
||||
'service_username': None,
|
||||
'service_host': None
|
||||
}
|
||||
self.get_dvr.return_value = True
|
||||
self.get_l3ha.return_value = True
|
||||
self.get_l2population.return_value = False
|
||||
self.get_overlay_network_type.return_value = 'vxlan'
|
||||
self._call_hook('neutron-plugin-api-relation-joined')
|
||||
@ -433,8 +630,9 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
self.relation_ids.side_effect = self._fake_relids
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
hooks.configure_https()
|
||||
self.check_call.assert_called_with(['a2ensite',
|
||||
'openstack_https_frontend'])
|
||||
calls = [call('a2dissite', 'openstack_https_frontend'),
|
||||
call('service', 'apache2', 'reload')]
|
||||
self.check_call.assert_called_has_calls(calls)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
|
||||
def test_configure_https_nohttps(self):
|
||||
@ -442,6 +640,7 @@ class NeutronAPIHooksTests(CharmTestCase):
|
||||
self.relation_ids.side_effect = self._fake_relids
|
||||
_id_rel_joined = self.patch('identity_joined')
|
||||
hooks.configure_https()
|
||||
self.check_call.assert_called_with(['a2dissite',
|
||||
'openstack_https_frontend'])
|
||||
calls = [call('a2dissite', 'openstack_https_frontend'),
|
||||
call('service', 'apache2', 'reload')]
|
||||
self.check_call.assert_called_has_calls(calls)
|
||||
self.assertTrue(_id_rel_joined.called)
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
from mock import MagicMock, patch
|
||||
from mock import MagicMock, patch, call
|
||||
from collections import OrderedDict
|
||||
from copy import deepcopy
|
||||
import charmhelpers.contrib.openstack.templating as templating
|
||||
@ -31,6 +31,15 @@ TO_PATCH = [
|
||||
'os_release',
|
||||
]
|
||||
|
||||
openstack_origin_git = \
|
||||
"""repositories:
|
||||
- {name: requirements,
|
||||
repository: 'git://git.openstack.org/openstack/requirements',
|
||||
branch: stable/juno}
|
||||
- {name: neutron,
|
||||
repository: 'git://git.openstack.org/openstack/neutron',
|
||||
branch: stable/juno}"""
|
||||
|
||||
|
||||
def _mock_npa(plugin, attr, net_manager=None):
|
||||
plugins = {
|
||||
@ -64,13 +73,17 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
port = nutils.api_port('neutron-server')
|
||||
self.assertEqual(port, nutils.API_PORTS['neutron-server'])
|
||||
|
||||
def test_determine_packages(self):
|
||||
@patch.object(nutils, 'git_install_requested')
|
||||
def test_determine_packages(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
pkg_list = nutils.determine_packages()
|
||||
expect = deepcopy(nutils.BASE_PACKAGES)
|
||||
expect.extend(['neutron-server', 'neutron-plugin-ml2'])
|
||||
self.assertItemsEqual(pkg_list, expect)
|
||||
|
||||
def test_determine_packages_kilo(self):
|
||||
@patch.object(nutils, 'git_install_requested')
|
||||
def test_determine_packages_kilo(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
self.get_os_codename_install_source.return_value = 'kilo'
|
||||
pkg_list = nutils.determine_packages()
|
||||
expect = deepcopy(nutils.BASE_PACKAGES)
|
||||
@ -159,7 +172,9 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
nutils.keystone_ca_cert_b64()
|
||||
self.assertTrue(self.b64encode.called)
|
||||
|
||||
def test_do_openstack_upgrade(self):
|
||||
@patch.object(nutils, 'git_install_requested')
|
||||
def test_do_openstack_upgrade(self, git_requested):
|
||||
git_requested.return_value = False
|
||||
self.config.side_effect = self.test_config.get
|
||||
self.test_config.set('openstack-origin', 'cloud:trusty-juno')
|
||||
self.os_release.side_effect = 'icehouse'
|
||||
@ -184,3 +199,87 @@ class TestNeutronAPIUtils(CharmTestCase):
|
||||
options=dpkg_opts,
|
||||
fatal=True)
|
||||
configs.set_release.assert_called_with(openstack_release='juno')
|
||||
|
||||
@patch.object(nutils, 'git_install_requested')
|
||||
@patch.object(nutils, 'git_clone_and_install')
|
||||
@patch.object(nutils, 'git_post_install')
|
||||
@patch.object(nutils, 'git_pre_install')
|
||||
def test_git_install(self, git_pre, git_post, git_clone_and_install,
|
||||
git_requested):
|
||||
projects_yaml = openstack_origin_git
|
||||
git_requested.return_value = True
|
||||
nutils.git_install(projects_yaml)
|
||||
self.assertTrue(git_pre.called)
|
||||
git_clone_and_install.assert_called_with(openstack_origin_git,
|
||||
core_project='neutron')
|
||||
self.assertTrue(git_post.called)
|
||||
|
||||
@patch.object(nutils, 'mkdir')
|
||||
@patch.object(nutils, 'write_file')
|
||||
@patch.object(nutils, 'add_user_to_group')
|
||||
@patch.object(nutils, 'add_group')
|
||||
@patch.object(nutils, 'adduser')
|
||||
def test_git_pre_install(self, adduser, add_group, add_user_to_group,
|
||||
write_file, mkdir):
|
||||
nutils.git_pre_install()
|
||||
adduser.assert_called_with('neutron', shell='/bin/bash',
|
||||
system_user=True)
|
||||
add_group.assert_called_with('neutron', system_group=True)
|
||||
add_user_to_group.assert_called_with('neutron', 'neutron')
|
||||
expected = [
|
||||
call('/etc/neutron', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/etc/neutron/rootwrap.d', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/etc/neutron/plugins', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/etc/neutron/plugins/ml2', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/var/lib/neutron', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/var/lib/neutron/lock', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
call('/var/log/neutron', owner='neutron',
|
||||
group='neutron', perms=0700, force=False),
|
||||
]
|
||||
self.assertEquals(mkdir.call_args_list, expected)
|
||||
expected = [
|
||||
call('/var/log/neutron/server.log', '', owner='neutron',
|
||||
group='neutron', perms=0600),
|
||||
]
|
||||
self.assertEquals(write_file.call_args_list, expected)
|
||||
|
||||
@patch.object(nutils, 'git_src_dir')
|
||||
@patch.object(nutils, 'service_restart')
|
||||
@patch.object(nutils, 'render')
|
||||
@patch('os.path.join')
|
||||
@patch('shutil.copyfile')
|
||||
def test_git_post_install(self, copyfile, join, render, service_restart,
|
||||
git_src_dir):
|
||||
projects_yaml = openstack_origin_git
|
||||
join.return_value = 'joined-string'
|
||||
nutils.git_post_install(projects_yaml)
|
||||
expected = [
|
||||
call('joined-string', '/etc/neutron/api-paste.ini'),
|
||||
call('joined-string', '/etc/neutron/rootwrap.d/debug.filters'),
|
||||
call('joined-string', '/etc/neutron/policy.json'),
|
||||
call('joined-string', '/etc/neutron/rootwrap.conf'),
|
||||
]
|
||||
copyfile.assert_has_calls(expected, any_order=True)
|
||||
neutron_api_context = {
|
||||
'service_description': 'Neutron API server',
|
||||
'charm_name': 'neutron-api',
|
||||
'process_name': 'neutron-server',
|
||||
}
|
||||
expected = [
|
||||
call('neutron_sudoers', '/etc/sudoers.d/neutron_sudoers', {},
|
||||
perms=0o440),
|
||||
call('upstart/neutron-server.upstart',
|
||||
'/etc/init/neutron-server.conf',
|
||||
neutron_api_context, perms=0o644),
|
||||
]
|
||||
self.assertEquals(render.call_args_list, expected)
|
||||
expected = [
|
||||
call('neutron-server'),
|
||||
]
|
||||
self.assertEquals(service_restart.call_args_list, expected)
|
||||
|
Loading…
x
Reference in New Issue
Block a user