From 05c4ff2065abee0b8c139330620735e0a0e32c6f Mon Sep 17 00:00:00 2001 From: Russell Bryant Date: Tue, 29 May 2012 16:04:16 -0400 Subject: [PATCH] Don't query nova-network on startup. Fix bug 999698. nova-compute requested network info for each instance on startup via rpc. If all services get (re)started at the same time, nova-network may not be available to take this request, resulting in a lost request. To combat this issue, get the network info from the cache in the database on startup. If by some chance this information is not correct, it will get fixed up by a periodic task. Change-Id: I0bbd475e078ac2a67c99c2be4711e86d617c609a --- nova/api/openstack/common.py | 10 ++-------- nova/api/openstack/compute/contrib/cloudpipe.py | 4 ++-- nova/compute/manager.py | 9 +++++---- nova/compute/utils.py | 6 ++++++ nova/network/api.py | 4 ++-- .../api/openstack/compute/contrib/test_cloudpipe.py | 14 +++++++------- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 3756f91..93b5a36 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -26,11 +26,11 @@ from xml.dom import minidom from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.compute import task_states +from nova.compute import utils as compute_utils from nova.compute import vm_states from nova import exception from nova import flags from nova import log as logging -from nova.network import model as network_model from nova import quota @@ -321,12 +321,6 @@ def get_networks_for_instance_from_nw_info(nw_info): return networks -def get_nw_info_for_instance(context, instance): - info_cache = instance['info_cache'] or {} - cached_nwinfo = info_cache.get('network_info') or [] - return network_model.NetworkInfo.hydrate(cached_nwinfo) - - def get_networks_for_instance(context, instance): """Returns a prepared nw_info list for passing into the view builders @@ -338,7 +332,7 @@ def get_networks_for_instance(context, instance): {'addr': '172.16.2.1', 'version': 4}]}, ...} """ - nw_info = get_nw_info_for_instance(context, instance) + nw_info = compute_utils.get_nw_info_for_instance(instance) return get_networks_for_instance_from_nw_info(nw_info) diff --git a/nova/api/openstack/compute/contrib/cloudpipe.py b/nova/api/openstack/compute/contrib/cloudpipe.py index b0d17ff..1d4c63d 100644 --- a/nova/api/openstack/compute/contrib/cloudpipe.py +++ b/nova/api/openstack/compute/contrib/cloudpipe.py @@ -16,13 +16,13 @@ import os -from nova.api.openstack import common from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova.auth import manager from nova.cloudpipe import pipelib from nova import compute +from nova.compute import utils as compute_utils from nova.compute import vm_states from nova import db from nova import exception @@ -91,7 +91,7 @@ class CloudpipeController(object): return rv rv['instance_id'] = instance['uuid'] rv['created_at'] = utils.isotime(instance['created_at']) - nw_info = common.get_nw_info_for_instance(elevated, instance) + nw_info = compute_utils.get_nw_info_for_instance(instance) if not nw_info: return rv vif = nw_info[0] diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 740102e..2a6bb19 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -68,6 +68,7 @@ from nova.openstack.common import excutils from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova import rpc +from nova.rpc import common as rpc_common from nova import utils from nova.virt import driver from nova import volume @@ -293,9 +294,9 @@ class ComputeManager(manager.SchedulerDependentManager): elif drv_state == power_state.RUNNING: # VMWareAPI drivers will raise an exception try: - net_info = self._get_instance_nw_info(context, instance) + net_info = compute_utils.get_nw_info_for_instance(instance) self.driver.ensure_filtering_rules_for_instance(instance, - self._legacy_nw_info(net_info)) + self._legacy_nw_info(net_info)) except NotImplementedError: LOG.warning(_('Hypervisor driver does not support ' 'firewall rules'), instance=instance) @@ -347,7 +348,7 @@ class ComputeManager(manager.SchedulerDependentManager): """This call passes straight through to the virtualization driver.""" return self.driver.refresh_provider_fw_rules(**kwargs) - def _get_instance_nw_info(self, context, instance): + def _get_instance_nw_info(self, context, instance, timeout=None): """Get a list of dictionaries of network data of an instance. Returns an empty list if stub_network flag is set.""" if FLAGS.stub_network: @@ -355,7 +356,7 @@ class ComputeManager(manager.SchedulerDependentManager): # get the network info from network network_info = self.network_api.get_instance_nw_info(context, - instance) + instance, timeout) return network_info def _legacy_nw_info(self, network_info): diff --git a/nova/compute/utils.py b/nova/compute/utils.py index f5f3c5f..7a2074c 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -104,3 +104,9 @@ def notify_about_instance_usage(context, instance, event_suffix, notifier_api.notify(context, 'compute.%s' % host, 'compute.instance.%s' % event_suffix, notifier_api.INFO, usage_info) + + +def get_nw_info_for_instance(instance): + info_cache = instance['info_cache'] or {} + cached_nwinfo = info_cache.get('network_info') or [] + return network_model.NetworkInfo.hydrate(cached_nwinfo) diff --git a/nova/network/api.py b/nova/network/api.py index fa95674..ff041c3 100644 --- a/nova/network/api.py +++ b/nova/network/api.py @@ -206,7 +206,7 @@ class API(base.Base): {'method': 'add_network_to_project', 'args': {'project_id': project_id}}) - def get_instance_nw_info(self, context, instance): + def get_instance_nw_info(self, context, instance, timeout=None): """Returns all network info related to an instance.""" args = {'instance_id': instance['id'], 'instance_uuid': instance['uuid'], @@ -215,7 +215,7 @@ class API(base.Base): 'project_id': instance['project_id']} nw_info = rpc.call(context, FLAGS.network_topic, {'method': 'get_instance_nw_info', - 'args': args}) + 'args': args}, timeout=timeout) return network_model.NetworkInfo.hydrate(nw_info) def validate_networks(self, context, requested_networks): diff --git a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py index f6e1fbc..c082e31 100644 --- a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py +++ b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py @@ -15,9 +15,9 @@ from lxml import etree -from nova.api.openstack import common from nova.api.openstack.compute.contrib import cloudpipe from nova.api.openstack import wsgi +from nova.compute import utils as compute_utils from nova import db from nova import flags from nova import test @@ -65,11 +65,11 @@ class CloudpipeTest(test.TestCase): def test_cloudpipe_list_no_network(self): - def common_get_nw_info_for_instance(context, instance): + def fake_get_nw_info_for_instance(instance): return {} - self.stubs.Set(common, "get_nw_info_for_instance", - common_get_nw_info_for_instance) + self.stubs.Set(compute_utils, "get_nw_info_for_instance", + fake_get_nw_info_for_instance) self.stubs.Set(self.controller.compute_api, "get_all", compute_api_get_all) req = fakes.HTTPRequest.blank('/v2/fake/os-cloudpipe') @@ -86,12 +86,12 @@ class CloudpipeTest(test.TestCase): return {'vpn_public_address': '127.0.0.1', 'vpn_public_port': 22} - def common_get_nw_info_for_instance(context, instance): + def fake_get_nw_info_for_instance(instance): return fake_network.fake_get_instance_nw_info(self.stubs, spectacular=True) - self.stubs.Set(common, "get_nw_info_for_instance", - common_get_nw_info_for_instance) + self.stubs.Set(compute_utils, "get_nw_info_for_instance", + fake_get_nw_info_for_instance) self.stubs.Set(self.controller.network_api, "get", network_api_get) self.stubs.Set(self.controller.compute_api, "get_all", -- 1.7.10.2