[gnuoy,r=james-page] Add support for Neutron DVR
When Neutron DVR is enabled, nova-compute nodes must run the metadata-api service for instances on the local hypervisor.
This commit is contained in:
commit
857b5d9ce4
@ -393,6 +393,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 = []
|
||||
|
||||
|
@ -21,6 +21,7 @@ from charmhelpers.core.host import (
|
||||
|
||||
from charmhelpers.fetch import (
|
||||
apt_install,
|
||||
apt_purge,
|
||||
apt_update,
|
||||
filter_installed_packages,
|
||||
)
|
||||
@ -324,6 +325,18 @@ 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)
|
||||
else:
|
||||
apt_purge('nova-api-metadata', fatal=True)
|
||||
CONFIGS.write(NOVA_CONF)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
hooks.execute(sys.argv)
|
||||
|
@ -39,6 +39,7 @@ from charmhelpers.contrib.openstack.utils import (
|
||||
|
||||
from nova_compute_context import (
|
||||
CloudComputeContext,
|
||||
MetadataServiceContext,
|
||||
NovaComputeLibvirtContext,
|
||||
NovaComputeCephContext,
|
||||
NeutronComputeContext,
|
||||
@ -94,6 +95,7 @@ BASE_RESOURCE_MAP = {
|
||||
service='nova',
|
||||
config_file=NOVA_CONF),
|
||||
InstanceConsoleContext(),
|
||||
MetadataServiceContext(),
|
||||
HostIPContext()],
|
||||
},
|
||||
}
|
||||
@ -203,6 +205,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
|
||||
|
||||
|
||||
@ -271,6 +275,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
|
||||
|
||||
@ -488,3 +494,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
|
||||
|
@ -38,6 +38,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
|
||||
|
@ -26,6 +26,11 @@ libvirt_use_virtio_for_bridges=False
|
||||
libvirt_disk_prefix=vd
|
||||
{% 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
|
||||
|
@ -233,3 +233,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'})
|
||||
|
@ -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')
|
||||
|
@ -24,7 +24,8 @@ TO_PATCH = [
|
||||
'relation_ids',
|
||||
'relation_get',
|
||||
'mkdir',
|
||||
'install_alternative'
|
||||
'install_alternative',
|
||||
'MetadataServiceContext',
|
||||
]
|
||||
|
||||
OVS_PKGS = [
|
||||
@ -41,8 +42,10 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
super(NovaComputeUtilsTests, self).setUp(utils, TO_PATCH)
|
||||
self.config.side_effect = self.test_config.get
|
||||
|
||||
@patch.object(utils, 'enable_nova_metadata')
|
||||
@patch.object(utils, 'network_manager')
|
||||
def test_determine_packages_nova_network(self, net_man):
|
||||
def test_determine_packages_nova_network(self, net_man, en_meta):
|
||||
en_meta.return_value = False
|
||||
net_man.return_value = 'flatdhcpmanager'
|
||||
self.relation_ids.return_value = []
|
||||
result = utils.determine_packages()
|
||||
@ -53,9 +56,11 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
]
|
||||
self.assertEquals(ex, result)
|
||||
|
||||
@patch.object(utils, 'enable_nova_metadata')
|
||||
@patch.object(utils, 'neutron_plugin')
|
||||
@patch.object(utils, 'network_manager')
|
||||
def test_determine_packages_quantum(self, net_man, n_plugin):
|
||||
def test_determine_packages_quantum(self, net_man, n_plugin, en_meta):
|
||||
en_meta.return_value = False
|
||||
self.neutron_plugin_attribute.return_value = OVS_PKGS
|
||||
net_man.return_value = 'quantum'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -64,9 +69,11 @@ class NovaComputeUtilsTests(CharmTestCase):
|
||||
ex = utils.BASE_PACKAGES + OVS_PKGS_FLAT + ['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_quantum_ceph(self, net_man, n_plugin):
|
||||
def test_determine_packages_quantum_ceph(self, net_man, n_plugin, en_meta):
|
||||
en_meta.return_value = False
|
||||
self.neutron_plugin_attribute.return_value = OVS_PKGS
|
||||
net_man.return_value = 'quantum'
|
||||
n_plugin.return_value = 'ovs'
|
||||
@ -76,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')
|
||||
@ -172,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
|
||||
@ -375,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)
|
||||
|
Loading…
Reference in New Issue
Block a user