Refactor codes.

This commit is contained in:
Hui Xiang 2014-09-30 17:17:06 +08:00
commit c1409bb2d6
7 changed files with 187 additions and 72 deletions

View File

@ -67,9 +67,9 @@ class NeutronCCContext(context.NeutronContext):
determine_api_port(api_port('neutron-server'))
for rid in relation_ids('neutron-api'):
for unit in related_units(rid):
ctxt['nova_url'] = relation_get(attribute='nova_url',
rid=rid,
unit=unit)
rdata = relation_get(rid=rid, unit=unit)
ctxt['nova_url'] = rdata.get('nova_url')
ctxt['restart_trigger'] = rdata.get('restart_trigger')
if ctxt['nova_url']:
return ctxt
return ctxt

View File

@ -18,7 +18,8 @@ from charmhelpers.core.hookenv import (
)
from charmhelpers.core.host import (
restart_on_change
restart_on_change,
service_restart,
)
from charmhelpers.fetch import (
@ -38,6 +39,7 @@ from charmhelpers.contrib.openstack.neutron import (
from neutron_api_utils import (
determine_packages,
determine_ports,
migrate_neutron_database,
register_configs,
restart_map,
NEUTRON_CONF,
@ -62,7 +64,9 @@ from charmhelpers.contrib.openstack.ip import (
from charmhelpers.contrib.network.ip import (
get_iface_for_address,
get_netmask_for_address,
get_ipv6_addr
get_address_in_network,
get_ipv6_addr,
is_ipv6
)
hooks = Hooks()
@ -92,9 +96,6 @@ def configure_https():
def install():
execd_preinstall()
configure_installation_source(config('openstack-origin'))
if config('prefer-ipv6'):
setup_ipv6()
apt_update()
apt_install(determine_packages(), fatal=True)
[open_port(port) for port in determine_ports()]
@ -140,6 +141,30 @@ def amqp_changed():
CONFIGS.write(NEUTRON_CONF)
def conditional_neutron_migration():
# This is an attempt to stop a race over the db migration between nova-cc
# and neutron-api by having the migration master decided by the presence
# of the neutron-api relation. In the long term this should only be done
# the neutron-api charm and nova-cc should play no hand in it
# * neutron-api refuses to run migrations until neutron-api relation is
# present
# * nova-cc refuses to run migration if neutron-api relations is present
clustered = relation_get('clustered')
if not relation_ids('neutron-api'):
log('Not running neutron database migration, no nova-cloud-controller'
'is present.')
else:
if clustered:
if is_leader(CLUSTER_RES):
migrate_neutron_database()
service_restart('neutron-server')
else:
log('Not running neutron database migration, not leader')
else:
migrate_neutron_database()
service_restart('neutron-server')
@hooks.hook('shared-db-relation-joined')
def db_joined():
if is_relation_made('pgsql-db'):
@ -178,6 +203,7 @@ def db_changed():
log('shared-db relation incomplete. Peer not ready?')
return
CONFIGS.write_all()
conditional_neutron_migration()
@hooks.hook('pgsql-db-relation-changed')
@ -186,6 +212,7 @@ def postgresql_neutron_db_changed():
plugin = config('neutron-plugin')
# DB config might have been moved to main neutron.conf in H?
CONFIGS.write(neutron_plugin_attribute(plugin, 'config'))
conditional_neutron_migration()
@hooks.hook('amqp-relation-broken',
@ -260,29 +287,29 @@ def neutron_plugin_api_relation_joined(rid=None):
relation_set(relation_id=rid, **relation_data)
@hooks.hook('cluster-relation-joined')
def cluster_joined(relation_id=None):
if config('prefer-ipv6'):
private_addr = get_ipv6_addr(exc_list=[config('vip')])[0]
else:
private_addr = unit_get('private-address')
address = get_address_in_network(config('os-internal-network'),
private_addr)
relation_set(relation_id=relation_id,
relation_settings={'private-address': address})
@hooks.hook('cluster-relation-changed',
'cluster-relation-departed')
@restart_on_change(restart_map(), stopstart=True)
def cluster_changed():
if config('prefer-ipv6'):
for rid in relation_ids('cluster'):
addr = get_ipv6_addr(exc_list=[config('vip')])[0]
relation_set(relation_id=rid,
relation_settings={'private-address': addr})
CONFIGS.write_all()
@hooks.hook('ha-relation-joined')
def ha_joined():
cluster_config = get_hacluster_config()
if config('prefer-ipv6'):
res_neutron_vip = 'ocf:heartbeat:IPv6addr'
vip_params = 'ipv6addr'
else:
res_neutron_vip = 'ocf:heartbeat:IPaddr2'
vip_params = 'ip'
resources = {
'res_neutron_haproxy': 'lsb:haproxy',
}
@ -291,6 +318,13 @@ def ha_joined():
}
vip_group = []
for vip in cluster_config['vip'].split():
if is_ipv6(vip):
res_neutron_vip = 'ocf:heartbeat:IPv6addr'
vip_params = 'ipv6addr'
else:
res_neutron_vip = 'ocf:heartbeat:IPaddr2'
vip_params = 'ip'
iface = get_iface_for_address(vip)
if iface is not None:
vip_key = 'res_neutron_{}_vip'.format(iface)

View File

@ -30,6 +30,7 @@ from charmhelpers.core.host import (
)
import neutron_api_context
import subprocess
TEMPLATES = 'templates/'
@ -208,18 +209,33 @@ def do_openstack_upgrade(configs):
# set CONFIGS to load templates from new release
configs.set_release(openstack_release=new_os_rel)
migrate_neutron_database()
def migrate_neutron_database():
'''Runs neutron-db-manage to init a new database or migrate existing'''
log('Migrating the neutron database.')
plugin = config('neutron-plugin')
cmd = ['neutron-db-manage',
'--config-file', NEUTRON_CONF,
'--config-file', neutron_plugin_attribute(plugin,
'config',
'neutron'),
'upgrade',
'head']
subprocess.check_output(cmd)
def setup_ipv6():
ubuntu_rel = float(lsb_release()['DISTRIB_RELEASE'])
if ubuntu_rel < 14.04:
if ubuntu_rel < 'trusty':
raise Exception("IPv6 is not supported for Ubuntu "
"versions less than Trusty 14.04")
# NOTE(xianghui): Need to install haproxy(1.5.3) from trusty-backports
# to support ipv6 address, so check is required to make sure not
# breaking other versions, IPv6 only support for >= Trusty
if ubuntu_rel == 14.04:
if ubuntu_rel == 'trusty':
add_source('deb http://archive.ubuntu.com/ubuntu trusty-backports'
' main')
apt_update()

View File

@ -1,6 +1,7 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
## Restart trigger {{ restart_trigger }}
###############################################################################
[DEFAULT]
verbose = {{ verbose }}

View File

@ -1,6 +1,5 @@
from test_utils import CharmTestCase
from test_utils import patch_open
from mock import patch, MagicMock
from mock import patch
import neutron_api_context as context
import charmhelpers
TO_PATCH = [
@ -13,7 +12,6 @@ TO_PATCH = [
]
@patch('charmhelpers.core.hookenv.config')
class IdentityServiceContext(CharmTestCase):
def setUp(self):
super(IdentityServiceContext, self).setUp(context, TO_PATCH)
@ -29,7 +27,7 @@ class IdentityServiceContext(CharmTestCase):
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
@patch.object(charmhelpers.contrib.openstack.context, 'log')
def test_ids_ctxt(self, _log, _rids, _runits, _rget, _ctxt_comp,
format_ipv6_addr, mock_config):
format_ipv6_addr):
_rids.return_value = 'rid1'
_runits.return_value = 'runit'
_ctxt_comp.return_value = True
@ -48,7 +46,7 @@ class IdentityServiceContext(CharmTestCase):
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
@patch.object(charmhelpers.contrib.openstack.context, 'log')
def test_ids_ctxt_no_rels(self, _log, _rids, mock_config):
def test_ids_ctxt_no_rels(self, _log, _rids):
_rids.return_value = []
ids_ctxt = context.IdentityServiceContext()
self.assertEquals(ids_ctxt(), None)
@ -60,6 +58,7 @@ class HAProxyContextTest(CharmTestCase):
super(HAProxyContextTest, self).setUp(context, TO_PATCH)
self.determine_api_port.return_value = 9686
self.determine_apache_port.return_value = 9686
self.api_port = 9696
def tearDown(self):
super(HAProxyContextTest, self).tearDown()
@ -69,7 +68,8 @@ class HAProxyContextTest(CharmTestCase):
def test_context_No_peers(self, _log, _rids):
_rids.return_value = []
hap_ctxt = context.HAProxyContext()
self.assertTrue('units' not in hap_ctxt())
with patch('__builtin__.__import__'):
self.assertTrue('units' not in hap_ctxt())
@patch.object(charmhelpers.contrib.openstack.context, 'config')
@patch.object(charmhelpers.contrib.openstack.context, 'local_unit')
@ -78,8 +78,10 @@ class HAProxyContextTest(CharmTestCase):
@patch.object(charmhelpers.contrib.openstack.context, 'related_units')
@patch.object(charmhelpers.contrib.openstack.context, 'relation_ids')
@patch.object(charmhelpers.contrib.openstack.context, 'log')
def test_context_peers(self, _log, _rids, _runits, _rget, _uget,
_lunit, _config):
@patch('__builtin__.__import__')
@patch('__builtin__.open')
def test_context_peers(self, _open, _import, _log, _rids, _runits, _rget,
_uget, _lunit, _config):
unit_addresses = {
'neutron-api-0': '10.10.10.10',
'neutron-api-1': '10.10.10.11',
@ -100,11 +102,10 @@ class HAProxyContextTest(CharmTestCase):
'service_ports': service_ports,
'neutron_bind_port': 9686,
}
with patch_open() as (_open, _file):
_file.write = MagicMock()
hap_ctxt = context.HAProxyContext()
self.assertEquals(hap_ctxt(), ctxt_data)
_file.write.assert_called_with('ENABLED=1\n')
_import().api_port.return_value = 9696
hap_ctxt = context.HAProxyContext()
self.assertEquals(hap_ctxt(), ctxt_data)
_open.assert_called_with('/etc/default/haproxy', 'w')
class NeutronAPIContextsTest(CharmTestCase):
@ -126,28 +127,32 @@ class NeutronAPIContextsTest(CharmTestCase):
@patch.object(context.NeutronCCContext, 'network_manager')
@patch.object(context.NeutronCCContext, 'plugin')
def test_neutroncc_context_no_setting(self, plugin, nm):
@patch('__builtin__.__import__')
def test_neutroncc_context_no_setting(self, _import, plugin, nm):
plugin.return_value = None
napi_ctxt = context.NeutronCCContext()
ctxt_data = {
'debug': True,
'external_network': 'bob',
'neutron_bind_port': self.api_port,
'verbose': True,
}
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')
def test_neutroncc_context_api_rel(self, plugin, nm):
@patch('__builtin__.__import__')
def test_neutroncc_context_api_rel(self, _import, plugin, nm):
nova_url = 'http://127.0.0.10'
plugin.return_value = None
self.related_units.return_value = ['unit1']
self.relation_ids.return_value = ['rid2']
self.test_relation.set({'nova_url': nova_url})
self.test_relation.set({'nova_url': nova_url,
'restart_trigger': 'bob'})
napi_ctxt = context.NeutronCCContext()
self.assertEquals(nova_url, napi_ctxt()['nova_url'])
self.assertEquals('bob', napi_ctxt()['restart_trigger'])
self.assertEquals(self.api_port, napi_ctxt()['neutron_bind_port'])
def test_neutroncc_context_manager(self):

View File

@ -13,6 +13,7 @@ utils.register_configs = MagicMock()
utils.restart_map = MagicMock()
import neutron_api_hooks as hooks
hooks.hooks._config_save = False
utils.register_configs = _reg
utils.restart_map = _map
@ -42,6 +43,8 @@ TO_PATCH = [
'unit_get',
'get_iface_for_address',
'get_netmask_for_address',
'migrate_neutron_database',
'service_restart',
]
NEUTRON_CONF_DIR = "/etc/neutron"
@ -50,7 +53,6 @@ NEUTRON_CONF = '%s/neutron.conf' % NEUTRON_CONF_DIR
from random import randrange
@patch('charmhelpers.core.hookenv.config')
class NeutronAPIHooksTests(CharmTestCase):
def setUp(self):
@ -68,7 +70,7 @@ class NeutronAPIHooksTests(CharmTestCase):
hooks.hooks.execute([
'hooks/{}'.format(hookname)])
def test_install_hook(self, mock_config):
def test_install_hook(self):
_pkgs = ['foo', 'bar']
_ports = [80, 81, 82]
_port_calls = [call(port) for port in _ports]
@ -86,7 +88,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertTrue(self.execd_preinstall.called)
@patch.object(hooks, 'configure_https')
def test_config_changed(self, conf_https, mock_config):
def test_config_changed(self, conf_https):
self.openstack_upgrade_available.return_value = True
self.relation_ids.side_effect = self._fake_relids
_n_api_rel_joined = self.patch('neutron_api_relation_joined')
@ -102,7 +104,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertTrue(self.CONFIGS.write_all.called)
self.assertTrue(self.do_openstack_upgrade.called)
def test_amqp_joined(self, mock_config):
def test_amqp_joined(self):
self._call_hook('amqp-relation-joined')
self.relation_set.assert_called_with(
username='neutron',
@ -110,16 +112,16 @@ class NeutronAPIHooksTests(CharmTestCase):
relation_id=None
)
def test_amqp_changed(self, mock_config):
def test_amqp_changed(self):
self.CONFIGS.complete_contexts.return_value = ['amqp']
self._call_hook('amqp-relation-changed')
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
def test_amqp_departed(self, mock_config):
def test_amqp_departed(self):
self._call_hook('amqp-relation-departed')
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
def test_db_joined(self, mock_config):
def test_db_joined(self):
self.is_relation_made.return_value = False
self.unit_get.return_value = 'myhostname'
self._call_hook('shared-db-relation-joined')
@ -129,7 +131,7 @@ class NeutronAPIHooksTests(CharmTestCase):
hostname='myhostname',
)
def test_db_joined_with_postgresql(self, mock_config):
def test_db_joined_with_postgresql(self):
self.is_relation_made.return_value = True
with self.assertRaises(Exception) as context:
@ -138,7 +140,7 @@ class NeutronAPIHooksTests(CharmTestCase):
'Attempting to associate a mysql database when there '
'is already associated a postgresql one')
def test_postgresql_db_joined(self, mock_config):
def test_postgresql_db_joined(self):
self.unit_get.return_value = 'myhostname'
self.is_relation_made.return_value = False
self._call_hook('pgsql-db-relation-joined')
@ -146,7 +148,7 @@ class NeutronAPIHooksTests(CharmTestCase):
database='neutron',
)
def test_postgresql_joined_with_db(self, mock_config):
def test_postgresql_joined_with_db(self):
self.is_relation_made.return_value = True
with self.assertRaises(Exception) as context:
@ -155,25 +157,29 @@ class NeutronAPIHooksTests(CharmTestCase):
'Attempting to associate a postgresql database when'
' there is already associated a mysql one')
def test_shared_db_changed(self, mock_config):
@patch.object(hooks, 'conditional_neutron_migration')
def test_shared_db_changed(self, cond_neutron_mig):
self.CONFIGS.complete_contexts.return_value = ['shared-db']
self._call_hook('shared-db-relation-changed')
self.assertTrue(self.CONFIGS.write_all.called)
cond_neutron_mig.assert_called_with()
def test_shared_db_changed_partial_ctxt(self, mock_config):
def test_shared_db_changed_partial_ctxt(self):
self.CONFIGS.complete_contexts.return_value = []
self._call_hook('shared-db-relation-changed')
self.assertFalse(self.CONFIGS.write_all.called)
def test_pgsql_db_changed(self, mock_config):
@patch.object(hooks, 'conditional_neutron_migration')
def test_pgsql_db_changed(self, cond_neutron_mig):
self._call_hook('pgsql-db-relation-changed')
self.assertTrue(self.CONFIGS.write.called)
cond_neutron_mig.assert_called_with()
def test_amqp_broken(self, mock_config):
def test_amqp_broken(self):
self._call_hook('amqp-relation-broken')
self.assertTrue(self.CONFIGS.write_all.called)
def test_identity_joined(self, mock_config):
def test_identity_joined(self):
self.canonical_url.return_value = 'http://127.0.0.1'
self.api_port.return_value = '9696'
self.test_config.set('region', 'region1')
@ -191,7 +197,7 @@ class NeutronAPIHooksTests(CharmTestCase):
relation_settings=_endpoints
)
def test_identity_changed_partial_ctxt(self, mock_config):
def test_identity_changed_partial_ctxt(self):
self.CONFIGS.complete_contexts.return_value = []
_api_rel_joined = self.patch('neutron_api_relation_joined')
self.relation_ids.side_effect = self._fake_relids
@ -199,7 +205,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertFalse(_api_rel_joined.called)
@patch.object(hooks, 'configure_https')
def test_identity_changed(self, conf_https, mock_config):
def test_identity_changed(self, conf_https):
self.CONFIGS.complete_contexts.return_value = ['identity-service']
_api_rel_joined = self.patch('neutron_api_relation_joined')
self.relation_ids.side_effect = self._fake_relids
@ -207,7 +213,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
self.assertTrue(_api_rel_joined.called)
def test_neutron_api_relation_no_id_joined(self, mock_config):
def test_neutron_api_relation_no_id_joined(self):
host = 'http://127.0.0.1'
port = 1234
_id_rel_joined = self.patch('identity_joined')
@ -235,7 +241,7 @@ class NeutronAPIHooksTests(CharmTestCase):
**_relation_data
)
def test_neutron_api_relation_joined(self, mock_config):
def test_neutron_api_relation_joined(self):
host = 'http://127.0.0.1'
port = 1234
self.canonical_url.return_value = host
@ -253,11 +259,11 @@ class NeutronAPIHooksTests(CharmTestCase):
**_relation_data
)
def test_neutron_api_relation_changed(self, mock_config):
def test_neutron_api_relation_changed(self):
self._call_hook('neutron-api-relation-changed')
self.assertTrue(self.CONFIGS.write.called_with(NEUTRON_CONF))
def test_neutron_plugin_api_relation_joined(self, mock_config):
def test_neutron_plugin_api_relation_joined(self):
_relation_data = {
'neutron-security-groups': False,
}
@ -267,12 +273,12 @@ class NeutronAPIHooksTests(CharmTestCase):
**_relation_data
)
def test_cluster_changed(self, mock_config):
def test_cluster_changed(self):
self._call_hook('cluster-relation-changed')
self.assertTrue(self.CONFIGS.write_all.called)
@patch.object(hooks, 'get_hacluster_config')
def test_ha_joined(self, _get_ha_config, mock_config):
def test_ha_joined(self, _get_ha_config):
_ha_config = {
'vip': '10.0.0.1',
'vip_cidr': '24',
@ -305,7 +311,7 @@ class NeutronAPIHooksTests(CharmTestCase):
)
@patch.object(hooks, 'get_hacluster_config')
def test_ha_joined_with_ipv6(self, _get_ha_config, mock_config):
def test_ha_joined_with_ipv6(self, _get_ha_config):
self.test_config.set('prefer-ipv6', 'True')
_ha_config = {
'vip': '2001:db8:1::1',
@ -340,7 +346,7 @@ class NeutronAPIHooksTests(CharmTestCase):
**_relation_data
)
def test_ha_changed(self, mock_config):
def test_ha_changed(self):
self.test_relation.set({
'clustered': 'true',
})
@ -352,7 +358,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertTrue(_n_api_rel_joined.called)
self.assertTrue(_id_rel_joined.called)
def test_ha_changed_not_leader(self, mock_config):
def test_ha_changed_not_leader(self):
self.test_relation.set({
'clustered': 'true',
})
@ -364,7 +370,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertFalse(_n_api_rel_joined.called)
self.assertFalse(_id_rel_joined.called)
def test_ha_changed_not_clustered(self, mock_config):
def test_ha_changed_not_clustered(self):
self.test_relation.set({
'clustered': None,
})
@ -376,7 +382,7 @@ class NeutronAPIHooksTests(CharmTestCase):
self.assertFalse(_n_api_rel_joined.called)
self.assertFalse(_id_rel_joined.called)
def test_configure_https(self, mock_config):
def test_configure_https(self):
self.CONFIGS.complete_contexts.return_value = ['https']
self.relation_ids.side_effect = self._fake_relids
_id_rel_joined = self.patch('identity_joined')
@ -385,7 +391,7 @@ class NeutronAPIHooksTests(CharmTestCase):
'openstack_https_frontend'])
self.assertTrue(_id_rel_joined.called)
def test_configure_https_nohttps(self, mock_config):
def test_configure_https_nohttps(self):
self.CONFIGS.complete_contexts.return_value = []
self.relation_ids.side_effect = self._fake_relids
_id_rel_joined = self.patch('identity_joined')
@ -393,3 +399,44 @@ class NeutronAPIHooksTests(CharmTestCase):
self.check_call.assert_called_with(['a2dissite',
'openstack_https_frontend'])
self.assertTrue(_id_rel_joined.called)
def test_conditional_neutron_migration_no_ncc_rel(self):
self.test_relation.set({
'clustered': 'false',
})
self.relation_ids.return_value = []
hooks.conditional_neutron_migration()
self.log.assert_called_with(
'Not running neutron database migration, no nova-cloud-controller'
'is present.'
)
def test_conditional_neutron_migration_ncc_rel_leader(self):
self.test_relation.set({
'clustered': 'true',
})
self.is_leader.return_value = True
hooks.conditional_neutron_migration()
self.migrate_neutron_database.assert_called_with()
self.service_restart.assert_called_with('neutron-server')
def test_conditional_neutron_migration_ncc_rel_notleader(self):
self.test_relation.set({
'clustered': 'true',
})
self.is_leader.return_value = False
hooks.conditional_neutron_migration()
self.assertFalse(self.migrate_neutron_database.called)
self.assertFalse(self.service_restart.called)
self.log.assert_called_with(
'Not running neutron database migration, not leader'
)
def test_conditional_neutron_migration_not_clustered(self):
self.test_relation.set({
'clustered': 'false',
})
self.relation_ids.return_value = ['nova-cc/o']
hooks.conditional_neutron_migration()
self.migrate_neutron_database.assert_called_with()
self.service_restart.assert_called_with('neutron-server')

View File

@ -5,7 +5,9 @@ import charmhelpers.contrib.openstack.templating as templating
templating.OSConfigRenderer = MagicMock()
import neutron_api_utils as nutils
with patch('charmhelpers.core.hookenv.config') as config:
config.return_value = 'neutron'
import neutron_api_utils as nutils
from test_utils import (
CharmTestCase,
@ -26,6 +28,7 @@ TO_PATCH = [
'log',
'neutron_plugin_attribute',
'os_release',
'subprocess',
]
@ -102,7 +105,7 @@ class TestNeutronAPIUtils(CharmTestCase):
(ML2CONF, {
'services': ['neutron-server'],
}),
(nutils.APACHE_CONF, {
(nutils.APACHE_24_CONF, {
'services': ['apache2'],
}),
(nutils.HAPROXY_CONF, {
@ -126,7 +129,7 @@ class TestNeutronAPIUtils(CharmTestCase):
confs = ['/etc/neutron/neutron.conf',
'/etc/default/neutron-server',
'/etc/neutron/plugins/ml2/ml2_conf.ini',
'/etc/apache2/sites-available/openstack_https_frontend',
'/etc/apache2/sites-available/openstack_https_frontend.conf',
'/etc/haproxy/haproxy.cfg']
self.assertItemsEqual(_regconfs.configs, confs)
@ -166,3 +169,12 @@ class TestNeutronAPIUtils(CharmTestCase):
self.configure_installation_source.assert_called_with(
'cloud:precise-havana'
)
def test_migrate_neutron_database(self):
nutils.migrate_neutron_database()
cmd = ['neutron-db-manage',
'--config-file', '/etc/neutron/neutron.conf',
'--config-file', '/etc/neutron/plugins/ml2/ml2_conf.ini',
'upgrade',
'head']
self.subprocess.check_output.assert_called_with(cmd)