From f92c1ddcef8b033957692b9b0728aee567d52de0 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Thu, 8 Nov 2012 14:41:59 -0500 Subject: Add support for backdoor_port to be returned with a rpc call. This adds an rpc call for compute and network that will return the eventlet_backdoor port for the service. Change-Id: I95fdb5ca9bce9f3128300e3b5601fb2b2fc5e82f Signed-off-by: Matthew Treinish --- nova/common/eventlet_backdoor.py | 8 +++++--- nova/compute/api.py | 4 ++++ nova/compute/manager.py | 6 +++++- nova/compute/rpcapi.py | 5 +++++ nova/manager.py | 1 + nova/network/api.py | 3 +++ nova/network/manager.py | 4 ++++ nova/network/rpcapi.py | 3 +++ nova/service.py | 11 ++++++++++- nova/tests/compute/test_compute.py | 30 ++++++++++++++++++++++++++++++ nova/tests/compute/test_rpcapi.py | 3 +++ nova/tests/network/test_api.py | 12 ++++++++++++ nova/tests/network/test_manager.py | 13 +++++++++++++ nova/tests/network/test_rpcapi.py | 3 +++ 14 files changed, 101 insertions(+), 5 deletions(-) diff --git a/nova/common/eventlet_backdoor.py b/nova/common/eventlet_backdoor.py index 4620d76ac..b407171c4 100644 --- a/nova/common/eventlet_backdoor.py +++ b/nova/common/eventlet_backdoor.py @@ -64,7 +64,7 @@ backdoor_locals = { def initialize_if_enabled(): if CONF.backdoor_port is None: - return + return None # NOTE(johannes): The standard sys.displayhook will print the value of # the last expression and set it to __builtin__._, which overwrites @@ -76,6 +76,8 @@ def initialize_if_enabled(): pprint.pprint(val) sys.displayhook = displayhook - eventlet.spawn(eventlet.backdoor.backdoor_server, - eventlet.listen(('localhost', CONF.backdoor_port)), + sock = eventlet.listen(('localhost', CONF.backdoor_port)) + port = sock.getsockname()[1] + eventlet.spawn(eventlet.backdoor.backdoor_server, sock, locals=backdoor_locals) + return port diff --git a/nova/compute/api.py b/nova/compute/api.py index 092ea6b39..bbf6b8f94 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -1804,6 +1804,10 @@ class API(base.Base): """Retrieve diagnostics for the given instance.""" return self.compute_rpcapi.get_diagnostics(context, instance=instance) + def get_backdoor_port(self, context, host): + """Retrieve backdoor port""" + return self.compute_rpcapi.get_backdoor_port(context, host) + @wrap_check_policy @check_instance_lock @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.RESCUED]) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 9011196b2..047676f43 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -265,7 +265,7 @@ class ComputeVirtAPI(virtapi.VirtAPI): class ComputeManager(manager.SchedulerDependentManager): """Manages the running instances from creation to destruction.""" - RPC_API_VERSION = '2.16' + RPC_API_VERSION = '2.17' def __init__(self, compute_driver=None, *args, **kwargs): """Load configuration options and connect to the hypervisor.""" @@ -422,6 +422,10 @@ class ComputeManager(manager.SchedulerDependentManager): except exception.NotFound: return power_state.NOSTATE + def get_backdoor_port(self, context): + """Return backdoor port for eventlet_backdoor""" + return self.backdoor_port + def get_console_topic(self, context): """Retrieves the console host for a project on this host. diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index b159756af..8d86c7336 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -144,6 +144,7 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): 2.14 - Remove aggregate_id, add aggregate to add_aggregate_host 2.15 - Remove aggregate_id, add aggregate to remove_aggregate_host 2.16 - Add instance_type to resize_instance + 2.17 - Add get_backdoor_port() ''' # @@ -550,6 +551,10 @@ class ComputeAPI(nova.openstack.common.rpc.proxy.RpcProxy): instance=instance_p), topic=_compute_topic(self.topic, ctxt, None, instance)) + def get_backdoor_port(self, ctxt, host): + return self.call(ctxt, self.make_msg('get_backdoor_port'), + topic=_compute_topic(self.topic, ctxt, host, None)) + def publish_service_capabilities(self, ctxt): self.fanout_cast(ctxt, self.make_msg('publish_service_capabilities')) diff --git a/nova/manager.py b/nova/manager.py index 2aff3d04e..100e0757c 100644 --- a/nova/manager.py +++ b/nova/manager.py @@ -140,6 +140,7 @@ class Manager(base.Base): host = CONF.host self.host = host self.load_plugins() + self.backdoor_port = None super(Manager, self).__init__(db_driver) def load_plugins(self): diff --git a/nova/network/api.py b/nova/network/api.py index e4fd38b13..11941a928 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -124,6 +124,9 @@ class API(base.Base): return self.network_rpcapi.get_floating_ips_by_fixed_address(context, fixed_address) + def get_backdoor_port(self, context): + return self.network_rpcapi.get_backdoor_port(context) + def get_instance_id_by_floating_address(self, context, address): # NOTE(tr3buchet): i hate this return self.network_rpcapi.get_instance_id_by_floating_address(context, diff --git a/nova/network/manager.py b/nova/network/manager.py index cf7b6109d..c1d70e078 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -1284,6 +1284,10 @@ class NetworkManager(manager.SchedulerDependentManager): network = self._get_network_by_id(context, network_id) self._allocate_fixed_ips(context, instance_id, host, [network]) + def get_backdoor_port(self, context): + """Return backdoor port for eventlet_backdoor""" + return self.backdoor_port + @wrap_check_policy def remove_fixed_ip_from_instance(self, context, instance_id, host, address): diff --git a/nova/network/rpcapi.py b/nova/network/rpcapi.py index b7e9cd70b..e8a02f6f5 100644 --- a/nova/network/rpcapi.py +++ b/nova/network/rpcapi.py @@ -104,6 +104,9 @@ class NetworkAPI(rpc_proxy.RpcProxy): 'get_instance_id_by_floating_address', address=address)) + def get_backdoor_port(self, ctxt): + return self.call(ctxt, self.make_msg('get_backdoor_port')) + def get_vifs_by_instance(self, ctxt, instance_id): # NOTE(vish): When the db calls are converted to store network # data by instance_uuid, this should pass uuid instead. diff --git a/nova/service.py b/nova/service.py index 45bdf7ec0..15d1ca887 100644 --- a/nova/service.py +++ b/nova/service.py @@ -111,7 +111,7 @@ class Launcher(object): """ self._services = [] - eventlet_backdoor.initialize_if_enabled() + self.backdoor_port = eventlet_backdoor.initialize_if_enabled() @staticmethod def run_server(server): @@ -131,6 +131,8 @@ class Launcher(object): :returns: None """ + if self.backdoor_port is not None: + server.backdoor_port = self.backdoor_port gt = eventlet.spawn(self.run_server, server) self._services.append(gt) @@ -382,6 +384,7 @@ class Service(object): self.periodic_fuzzy_delay = periodic_fuzzy_delay self.saved_args, self.saved_kwargs = args, kwargs self.timers = [] + self.backdoor_port = None def start(self): vcs_string = version.version_string_with_vcs() @@ -400,6 +403,9 @@ class Service(object): self.manager.pre_start_hook() + if self.backdoor_port is not None: + self.manager.backdoor_port = self.backdoor_port + self.conn = rpc.create_connection(new=True) LOG.debug(_("Creating Consumer connection for Service %s") % self.topic) @@ -578,6 +584,7 @@ class WSGIService(object): port=self.port) # Pull back actual port used self.port = self.server.port + self.backdoor_port = None def _get_manager(self): """Initialize a Manager object appropriate for this service. @@ -612,6 +619,8 @@ class WSGIService(object): if self.manager: self.manager.init_host() self.manager.pre_start_hook() + if self.backdoor_port is not None: + self.manager.backdoor_port = self.backdoor_port self.server.start() if self.manager: self.manager.post_start_hook() diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 3b2c00b32..868adf4b2 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -4695,6 +4695,23 @@ class ComputeAPITestCase(BaseTestCase): db.instance_destroy(self.context, instance['uuid']) + def test_get_backdoor_port(self): + """Test api call to get backdoor_port""" + fake_backdoor_port = 59697 + + self.mox.StubOutWithMock(rpc, 'call') + + rpc_msg = {'method': 'get_backdoor_port', + 'args': {}, + 'version': compute_rpcapi.ComputeAPI.BASE_RPC_API_VERSION} + rpc.call(self.context, 'compute.fake_host', rpc_msg, + None).AndReturn(fake_backdoor_port) + + self.mox.ReplayAll() + + port = self.compute_api.get_backdoor_port(self.context, 'fake_host') + self.assertEqual(port, fake_backdoor_port) + def test_console_output(self): fake_instance = {'uuid': 'fake_uuid', 'host': 'fake_compute_host'} @@ -5145,6 +5162,19 @@ class ComputeAPIAggrTestCase(BaseTestCase): self.context, aggr['id'], 'invalid_host') +class ComputeBackdoorPortTestCase(BaseTestCase): + """This is for unit test coverage of backdoor port rpc""" + + def setUp(self): + super(ComputeBackdoorPortTestCase, self).setUp() + self.context = context.get_admin_context() + self.compute.backdoor_port = 59697 + + def test_get_backdoor_port(self): + port = self.compute.get_backdoor_port(self.context) + self.assertEqual(port, self.compute.backdoor_port) + + class ComputeAggrTestCase(BaseTestCase): """This is for unit coverage of aggregate-related methods defined in nova.compute.manager.""" diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py index 5cce9a4d9..82537560b 100644 --- a/nova/tests/compute/test_rpcapi.py +++ b/nova/tests/compute/test_rpcapi.py @@ -174,6 +174,9 @@ class ComputeRpcAPITestCase(test.TestCase): self._test_compute_api('host_power_action', 'call', action='action', host='host') + def test_get_backdoor_port(self): + self._test_compute_api('get_backdoor_port', 'call', host='host') + def test_inject_file(self): self._test_compute_api('inject_file', 'cast', instance=self.fake_instance, path='path', file_contents='fc') diff --git a/nova/tests/network/test_api.py b/nova/tests/network/test_api.py index bfc9dc878..b091777f1 100644 --- a/nova/tests/network/test_api.py +++ b/nova/tests/network/test_api.py @@ -197,3 +197,15 @@ class ApiTestCase(test.TestCase): instance = {'uuid': FAKE_UUID} result = self.network_api._is_multi_host(self.context, instance) self.assertEqual(is_multi_host, result) + + def test_get_backdoor_port(self): + backdoor_port = 59697 + + def fake_get_backdoor_port(ctxt): + return backdoor_port + + self.stubs.Set(self.network_api.network_rpcapi, 'get_backdoor_port', + fake_get_backdoor_port) + + port = self.network_api.get_backdoor_port(self.context) + self.assertEqual(port, backdoor_port) diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index 698ce8f59..8c472e939 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -1524,6 +1524,19 @@ class RPCAllocateTestCase(test.TestCase): self.assertEqual(rval, address) +class BackdoorPortTestCase(test.TestCase): + """Tests nova.network.manager.get_backdoor_port""" + def setUp(self): + super(BackdoorPortTestCase, self).setUp() + self.manager = network_manager.NetworkManager() + self.manager.backdoor_port = 59697 + self.context = context.RequestContext('fake', 'fake') + + def test_backdoor_port(self): + port = self.manager.get_backdoor_port(self.context) + self.assertEqual(port, self.manager.backdoor_port) + + class TestFloatingIPManager(network_manager.FloatingIP, network_manager.NetworkManager): """Dummy manager that implements FloatingIP""" diff --git a/nova/tests/network/test_rpcapi.py b/nova/tests/network/test_rpcapi.py index b0c3572ea..3d8e4235c 100644 --- a/nova/tests/network/test_rpcapi.py +++ b/nova/tests/network/test_rpcapi.py @@ -121,6 +121,9 @@ class NetworkRpcAPITestCase(test.TestCase): self._test_network_api('get_instance_id_by_floating_address', rpc_method='call', address='w.x.y.z') + def test_get_backdoor_port(self): + self._test_network_api('get_backdoor_port', rpc_method='call') + def test_get_vifs_by_instance(self): self._test_network_api('get_vifs_by_instance', rpc_method='call', instance_id='fake_id') -- cgit