From 32e0feea2d1b9b55c69ab768312a86b33a09ba5b Mon Sep 17 00:00:00 2001 From: Aaron Rosen Date: Mon, 11 Feb 2013 12:49:56 -0800 Subject: Provide way to pass rxtx factor to quantum This patch adds a config option quantum_extension_sync_interval which by default is set to 600 seconds. After 600 seconds the next time nova needs to create a resource in quantum it will requery quantum for the extensions that it has loaded. Hopefully in Havana something smarter will be implemented rather than using time sync. I believe a better way to implement this would be to have each compute host keep a pool of persistant sockets open to quantum for it to communicate over. Resync'ing then would only happen if the connection to quantum broke because quantum needs to be restarted in order to change the extensions it is using Implemenets blueprint pass-rxtx-factor-to-quantum Change-Id: I001cfaf348a3f0c8144c0226559752555c486db0 --- nova/network/quantumv2/api.py | 32 ++++++++++++++++++++++++++++++++ nova/tests/network/test_quantumv2.py | 26 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index ee4ceb9cd..f3388f2ab 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -16,7 +16,10 @@ # # vim: tabstop=4 shiftwidth=4 softtabstop=4 +import time + from nova import conductor +from nova import context from nova.db import base from nova import exception from nova.network import api as network_api @@ -59,6 +62,10 @@ quantum_opts = [ cfg.StrOpt('quantum_ovs_bridge', default='br-int', help='Name of Integration Bridge used by Open vSwitch'), + cfg.IntOpt('quantum_extension_sync_interval', + default=600, + help='Number of seconds before querying quantum for' + ' extensions'), ] CONF = cfg.CONF @@ -77,6 +84,11 @@ class API(base.Base): conductor_api = conductor.API() + def __init__(self): + super(API, self).__init__() + self.last_quantum_extension_sync = None + self.extensions = {} + def setup_networks_on_host(self, context, instance, host=None, teardown=False): """Setup or teardown the network structures.""" @@ -188,6 +200,9 @@ class API(base.Base): instance=instance['display_name']) mac_address = available_macs.pop() port_req_body['port']['mac_address'] = mac_address + + self._populate_quantum_extension_values(instance, + port_req_body) created_port_ids.append( quantum.create_port(port_req_body)['port']['id']) except Exception: @@ -214,6 +229,23 @@ class API(base.Base): return self.get_instance_nw_info(context, instance, networks=nets, conductor_api=kwargs.get('conductor_api')) + def _refresh_quantum_extensions_cache(self): + if (not self.last_quantum_extension_sync or + ((time.time() - self.last_quantum_extension_sync) + >= CONF.quantum_extension_sync_interval)): + quantum = quantumv2.get_client(context.get_admin_context()) + extensions_list = quantum.list_extensions()['extensions'] + self.last_quantum_extension_sync = time.time() + self.extensions.clear() + self.extensions = dict((ext['name'], ext) + for ext in extensions_list) + + def _populate_quantum_extension_values(self, instance, port_req_body): + self._refresh_quantum_extensions_cache() + if 'nvp-qos' in self.extensions: + rxtx_factor = instance['instance_type'].get('rxtx_factor') + port_req_body['port']['rxtx_factor'] = rxtx_factor + def deallocate_for_instance(self, context, instance, **kwargs): """Deallocate all network resources related to the instance.""" LOG.debug(_('deallocate_for_instance() for %s'), diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index f3f306694..91d609914 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -354,9 +354,28 @@ class TestQuantumv2(test.TestCase): self.assertEquals('my_mac%s' % id_suffix, nw_inf[0]['address']) self.assertEquals(0, len(nw_inf[0]['network']['subnets'])) + def test_refresh_quantum_extensions_cache(self): + api = quantumapi.API() + self.moxed_client.list_extensions().AndReturn( + {'extensions': [{'name': 'nvp-qos'}]}) + self.mox.ReplayAll() + api._refresh_quantum_extensions_cache() + self.assertEquals({'nvp-qos': {'name': 'nvp-qos'}}, api.extensions) + + def test_populate_quantum_extension_values_rxtx_factor(self): + api = quantumapi.API() + self.moxed_client.list_extensions().AndReturn( + {'extensions': [{'name': 'nvp-qos'}]}) + self.mox.ReplayAll() + instance = {'instance_type': {'rxtx_factor': 1}} + port_req_body = {'port': {}} + api._populate_quantum_extension_values(instance, port_req_body) + self.assertEquals(port_req_body['port']['rxtx_factor'], 1) + def _stub_allocate_for_instance(self, net_idx=1, **kwargs): api = quantumapi.API() self.mox.StubOutWithMock(api, 'get_instance_nw_info') + self.mox.StubOutWithMock(api, '_populate_quantum_extension_values') # Net idx is 1-based for compatibility with existing unit tests nets = self.nets[net_idx - 1] ports = {} @@ -428,6 +447,9 @@ class TestQuantumv2(test.TestCase): if macs: port_req_body['port']['mac_address'] = macs.pop() res_port = {'port': {'id': 'fake'}} + api._populate_quantum_extension_values( + self.instance, port_req_body).AndReturn(None) + self.moxed_client.create_port( MyComparator(port_req_body)).AndReturn(res_port) @@ -547,6 +569,7 @@ class TestQuantumv2(test.TestCase): In this case, the code should delete the first created port. """ api = quantumapi.API() + self.mox.StubOutWithMock(api, '_populate_quantum_extension_values') self.moxed_client.list_networks( tenant_id=self.instance['project_id'], shared=False).AndReturn( @@ -565,6 +588,9 @@ class TestQuantumv2(test.TestCase): }, } port = {'id': 'portid_' + network['id']} + + api._populate_quantum_extension_values( + self.instance, port_req_body).AndReturn(None) if index == 0: self.moxed_client.create_port( MyComparator(port_req_body)).AndReturn({'port': port}) -- cgit