From ac4a3a440b9706f71763dbf111e2dbfdc655f27e Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 4 Feb 2015 16:31:09 +0000 Subject: [PATCH 1/3] Enable a nova metadata agent if running in DVR mode --- hooks/nova_compute_context.py | 13 +++++++++++++ hooks/nova_compute_hooks.py | 10 ++++++++++ hooks/nova_compute_utils.py | 11 +++++++++++ templates/juno/nova.conf | 5 +++++ 4 files changed, 39 insertions(+) diff --git a/hooks/nova_compute_context.py b/hooks/nova_compute_context.py index c4d7e582..20c3a2ce 100644 --- a/hooks/nova_compute_context.py +++ b/hooks/nova_compute_context.py @@ -383,6 +383,19 @@ class InstanceConsoleContext(context.OSContextGenerator): return ctxt +class MetadataServiceContext(context.OSContextGenerator): + + def __call__(self): + ctxt = {} + for rid in relation_ids('neutron-plugin'): + for unit in related_units(rid): + rdata = relation_get(rid=rid, unit=unit) + if 'metadata-shared-secret' in rdata: + ctxt['metadata_shared_secret'] = \ + rdata['metadata-shared-secret'] + return ctxt + + class NeutronComputeContext(context.NeutronContext): interfaces = [] diff --git a/hooks/nova_compute_hooks.py b/hooks/nova_compute_hooks.py index e42b630c..a27edbe5 100755 --- a/hooks/nova_compute_hooks.py +++ b/hooks/nova_compute_hooks.py @@ -317,6 +317,16 @@ def update_nrpe_config(): nrpe_setup.write() +@hooks.hook('neutron-plugin-relation-changed') +@restart_on_change(restart_map()) +def neutron_plugin_changed(): + settings = relation_get() + if 'metadata-shared-secret' in settings: + apt_update() + apt_install('nova-api-metadata', fatal=True) + CONFIGS.write(NOVA_CONF) + + def main(): try: hooks.execute(sys.argv) diff --git a/hooks/nova_compute_utils.py b/hooks/nova_compute_utils.py index 4fd3ad65..e0060d80 100644 --- a/hooks/nova_compute_utils.py +++ b/hooks/nova_compute_utils.py @@ -38,6 +38,7 @@ from charmhelpers.contrib.openstack.utils import ( from nova_compute_context import ( CloudComputeContext, + MetadataServiceContext, NovaComputeLibvirtContext, NovaComputeCephContext, NeutronComputeContext, @@ -93,6 +94,7 @@ BASE_RESOURCE_MAP = { service='nova', config_file=NOVA_CONF), InstanceConsoleContext(), + MetadataServiceContext(), HostIPContext()], }, } @@ -200,6 +202,8 @@ def resource_map(): } resource_map.update(CEPH_RESOURCES) + if enable_nova_metadata(): + resource_map[NOVA_CONF]['services'].append('nova-api-metadata') return resource_map @@ -268,6 +272,8 @@ def determine_packages(): except KeyError: log('Unsupported virt-type configured: %s' % virt_type) raise + if enable_nova_metadata(): + packages.append('nova-api-metadata') return packages @@ -479,3 +485,8 @@ def assert_charm_supports_ipv6(): if lsb_release()['DISTRIB_CODENAME'].lower() < "trusty": raise Exception("IPv6 is not supported in the charms for Ubuntu " "versions less than Trusty 14.04") + +def enable_nova_metadata(): + ctxt = MetadataServiceContext()() + return 'metadata_shared_secret' in ctxt + diff --git a/templates/juno/nova.conf b/templates/juno/nova.conf index c0272aea..452122f0 100644 --- a/templates/juno/nova.conf +++ b/templates/juno/nova.conf @@ -31,6 +31,11 @@ my_ip = {{ host_ip }} glance_api_servers = {{ glance_api_servers }} {% endif -%} +{% if metadata_shared_secret -%} +neutron_metadata_proxy_shared_secret = {{ metadata_shared_secret }} +service_neutron_metadata_proxy=True +{% endif -%} + {% if console_vnc_type -%} vnc_enabled = True novnc_enabled = True From f8ae3bfca524dc4a7250ff18563574839fa17c8e Mon Sep 17 00:00:00 2001 From: Liam Young Date: Wed, 25 Feb 2015 15:02:09 +0000 Subject: [PATCH 2/3] Add more unit tests --- unit_tests/test_nova_compute_contexts.py | 8 +++++ unit_tests/test_nova_compute_hooks.py | 9 ++++++ unit_tests/test_nova_compute_utils.py | 40 +++++++++++++++++++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/unit_tests/test_nova_compute_contexts.py b/unit_tests/test_nova_compute_contexts.py index 956d28b2..fb179cac 100644 --- a/unit_tests/test_nova_compute_contexts.py +++ b/unit_tests/test_nova_compute_contexts.py @@ -228,3 +228,11 @@ class NovaComputeContextTests(CharmTestCase): self.assertEquals( {'host_ip': '172.24.0.79'}, host_ip()) self.unit_get.assert_called_with('private-address') + + def test_metadata_service_ctxt(self): + self.relation_ids.return_value = 'neutron-plugin:0' + self.related_units.return_value = 'neutron-openvswitch/0' + self.test_relation.set({'metadata-shared-secret': 'shared_secret'}) + metadatactxt = context.MetadataServiceContext() + self.assertEqual(metadatactxt(), {'metadata_shared_secret': + 'shared_secret'}) diff --git a/unit_tests/test_nova_compute_hooks.py b/unit_tests/test_nova_compute_hooks.py index b01d8169..6236970b 100644 --- a/unit_tests/test_nova_compute_hooks.py +++ b/unit_tests/test_nova_compute_hooks.py @@ -378,3 +378,12 @@ class NovaComputeRelationsTests(CharmTestCase): call('/etc/nova/nova.conf'), ] self.assertEquals(ex, configs.write.call_args_list) + + @patch.object(hooks, 'CONFIGS') + def test_neutron_plugin_changed(self, configs): + self.relation_get.return_value = {'metadata-shared-secret': + 'sharedsecret'} + hooks.neutron_plugin_changed() + self.assertTrue(self.apt_update.called) + self.apt_install.assert_called_with('nova-api-metadata', fatal=True) + configs.write.assert_called_with('/etc/nova/nova.conf') diff --git a/unit_tests/test_nova_compute_utils.py b/unit_tests/test_nova_compute_utils.py index 76de28e7..c6217db4 100644 --- a/unit_tests/test_nova_compute_utils.py +++ b/unit_tests/test_nova_compute_utils.py @@ -24,7 +24,8 @@ TO_PATCH = [ 'relation_ids', 'relation_get', 'mkdir', - 'install_alternative' + 'install_alternative', + 'MetadataServiceContext', ] OVS_PKGS = [ @@ -82,6 +83,18 @@ class NovaComputeUtilsTests(CharmTestCase): ['ceph-common', 'nova-compute-kvm']) self.assertEquals(ex, result) + @patch.object(utils, 'enable_nova_metadata') + @patch.object(utils, 'neutron_plugin') + @patch.object(utils, 'network_manager') + def test_determine_packages_metadata(self, net_man, n_plugin, en_meta): + en_meta.return_value = True + self.neutron_plugin_attribute.return_value = OVS_PKGS + net_man.return_value = 'bob' + n_plugin.return_value = 'ovs' + self.relation_ids.return_value = [] + result = utils.determine_packages() + self.assertTrue('nova-api-metadata' in result) + @patch.object(utils, 'network_manager') def test_resource_map_nova_network_no_multihost(self, net_man): self.skipTest('skipped until contexts are properly mocked') @@ -178,6 +191,17 @@ class NovaComputeUtilsTests(CharmTestCase): result = utils.resource_map() self.assertTrue('/etc/neutron/neutron.conf' not in result) + @patch.object(utils, 'enable_nova_metadata') + @patch.object(utils, 'neutron_plugin') + @patch.object(utils, 'network_manager') + def test_resource_map_metadata(self, net_man, _plugin, _metadata): + _metadata.return_value = True + net_man.return_value = 'bob' + _plugin.return_value = 'ovs' + self.relation_ids.return_value = [] + result = utils.resource_map()['/etc/nova/nova.conf']['services'] + self.assertTrue('nova-api-metadata' in result) + def fake_user(self, username='foo'): user = MagicMock() user.pw_dir = '/home/' + username @@ -381,3 +405,17 @@ class NovaComputeUtilsTests(CharmTestCase): 'secret-set-value', '--secret', compute_context.CEPH_SECRET_UUID, '--base64', key]) + + def test_enable_nova_metadata(self): + class DummyContext(): + + def __init__(self, return_value): + self.return_value = return_value + + def __call__(self): + return self.return_value + + self.MetadataServiceContext.return_value = \ + DummyContext(return_value={'metadata_shared_secret': + 'sharedsecret'}) + self.assertEqual(utils.enable_nova_metadata(), True) From 1ab0d31e5c11fa58c3ce28ab02e61109ffa647fc Mon Sep 17 00:00:00 2001 From: Liam Young Date: Mon, 2 Mar 2015 14:55:03 +0000 Subject: [PATCH 3/3] Purge metadata pkg when not in dvr mode --- hooks/nova_compute_hooks.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hooks/nova_compute_hooks.py b/hooks/nova_compute_hooks.py index 947ec9f7..952f4938 100755 --- a/hooks/nova_compute_hooks.py +++ b/hooks/nova_compute_hooks.py @@ -21,6 +21,7 @@ from charmhelpers.core.host import ( from charmhelpers.fetch import ( apt_install, + apt_purge, apt_update, filter_installed_packages, ) @@ -331,6 +332,8 @@ def neutron_plugin_changed(): if 'metadata-shared-secret' in settings: apt_update() apt_install('nova-api-metadata', fatal=True) + else: + apt_purge('nova-api-metadata', fatal=True) CONFIGS.write(NOVA_CONF)