Convert network API to use InfoCache object
This converts the db.info_cache_update() call in network/api to use objects. The save() method has been extended to support what we need for cells. Converting to the object allows us to ditch the conductor_api kwarg on some methods. Related to blueprint unified-object-model Change-Id: I1722c03d20511d67acc0a8947de1d4273dc78597
This commit is contained in:
@@ -140,8 +140,8 @@ class InstanceMetadata():
|
||||
|
||||
# get network info, and the rendered network template
|
||||
if network_info is None:
|
||||
network_info = network.API().get_instance_nw_info(ctxt, instance,
|
||||
conductor_api=capi)
|
||||
network_info = network.API().get_instance_nw_info(ctxt,
|
||||
instance)
|
||||
|
||||
self.network_config = None
|
||||
cfg = netutils.get_injected_network_template(network_info)
|
||||
|
||||
@@ -854,7 +854,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
instance = self.conductor_api.instance_get_by_uuid(
|
||||
context, instance['uuid'])
|
||||
network_info = self.network_api.get_instance_nw_info(context,
|
||||
instance, conductor_api=self.conductor_api)
|
||||
instance)
|
||||
return network_info
|
||||
|
||||
def _legacy_nw_info(self, network_info):
|
||||
@@ -3556,8 +3556,9 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
|
||||
def detach_interface(self, context, instance, port_id):
|
||||
"""Detach an network adapter from an instance."""
|
||||
network_info = self.network_api.get_instance_nw_info(
|
||||
context.elevated(), instance, conductor_api=self.conductor_api)
|
||||
# FIXME(comstud): Why does this need elevated context?
|
||||
network_info = self._get_instance_nw_info(context.elevated(),
|
||||
instance)
|
||||
legacy_nwinfo = self._legacy_nw_info(network_info)
|
||||
condemned = None
|
||||
for (network, mapping) in legacy_nwinfo:
|
||||
|
||||
@@ -21,13 +21,13 @@
|
||||
import functools
|
||||
import inspect
|
||||
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova.compute import flavors
|
||||
from nova.db import base
|
||||
from nova import exception
|
||||
from nova.network import floating_ips
|
||||
from nova.network import model as network_model
|
||||
from nova.network import rpcapi as network_rpcapi
|
||||
from nova.objects import instance_info_cache as info_cache_obj
|
||||
from nova.openstack.common import log as logging
|
||||
from nova import policy
|
||||
from nova import utils
|
||||
@@ -57,38 +57,27 @@ def refresh_cache(f):
|
||||
raise Exception(msg)
|
||||
|
||||
update_instance_cache_with_nw_info(self, context, instance,
|
||||
nw_info=res, conductor_api=kwargs.get('conductor_api'))
|
||||
nw_info=res)
|
||||
|
||||
# return the original function's return value
|
||||
return res
|
||||
return wrapper
|
||||
|
||||
|
||||
def update_instance_cache_with_nw_info(api, context, instance,
|
||||
nw_info=None, conductor_api=None,
|
||||
def update_instance_cache_with_nw_info(api, context, instance, nw_info=None,
|
||||
update_cells=True):
|
||||
try:
|
||||
if not isinstance(nw_info, network_model.NetworkInfo):
|
||||
nw_info = None
|
||||
if not nw_info:
|
||||
nw_info = api._get_instance_nw_info(context, instance)
|
||||
# update cache
|
||||
cache = {'network_info': nw_info.json()}
|
||||
if conductor_api:
|
||||
rv = conductor_api.instance_info_cache_update(context,
|
||||
instance,
|
||||
cache)
|
||||
else:
|
||||
rv = api.db.instance_info_cache_update(context,
|
||||
instance['uuid'],
|
||||
cache)
|
||||
if update_cells:
|
||||
cells_api = cells_rpcapi.CellsAPI()
|
||||
try:
|
||||
cells_api.instance_info_cache_update_at_top(context, rv)
|
||||
except Exception:
|
||||
LOG.exception(_("Failed to notify cells of instance info "
|
||||
"cache update"))
|
||||
# NOTE(comstud): The save() method actually handles updating or
|
||||
# creating the instance. We don't need to retrieve the object
|
||||
# from the DB first.
|
||||
ic = info_cache_obj.InstanceInfoCache.new(context,
|
||||
instance['uuid'])
|
||||
ic.network_info = nw_info
|
||||
ic.save(update_cells=update_cells)
|
||||
except Exception:
|
||||
LOG.exception(_('Failed storing info cache'), instance=instance)
|
||||
|
||||
@@ -378,7 +367,7 @@ class API(base.Base):
|
||||
self.db.network_associate(context, project, network_id, True)
|
||||
|
||||
@wrap_check_policy
|
||||
def get_instance_nw_info(self, context, instance, conductor_api=None):
|
||||
def get_instance_nw_info(self, context, instance):
|
||||
"""Returns all network info related to an instance."""
|
||||
result = self._get_instance_nw_info(context, instance)
|
||||
# NOTE(comstud): Don't update API cell with new info_cache every
|
||||
@@ -386,8 +375,7 @@ class API(base.Base):
|
||||
# of info_cache causes too many cells messages. Healing the API
|
||||
# will happen separately.
|
||||
update_instance_cache_with_nw_info(self, context, instance,
|
||||
result, conductor_api,
|
||||
update_cells=False)
|
||||
result, update_cells=False)
|
||||
return result
|
||||
|
||||
def _get_instance_nw_info(self, context, instance):
|
||||
|
||||
@@ -396,14 +396,13 @@ class API(base.Base):
|
||||
"""Return the port for the client given the port id."""
|
||||
return neutronv2.get_client(context).show_port(port_id)
|
||||
|
||||
def get_instance_nw_info(self, context, instance, conductor_api=None,
|
||||
networks=None):
|
||||
def get_instance_nw_info(self, context, instance, networks=None):
|
||||
"""Return network information for specified instance
|
||||
and update cache.
|
||||
"""
|
||||
result = self._get_instance_nw_info(context, instance, networks)
|
||||
update_instance_info_cache(self, context, instance, result,
|
||||
conductor_api)
|
||||
update_cells=False)
|
||||
return result
|
||||
|
||||
def _get_instance_nw_info(self, context, instance, networks=None):
|
||||
|
||||
@@ -12,16 +12,22 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.cells import opts as cells_opts
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova.objects import base
|
||||
from nova.objects import utils
|
||||
from nova.openstack.common import log as logging
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InstanceInfoCache(base.NovaObject):
|
||||
VERSION = '1.1'
|
||||
VERSION = '1.2'
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: Converted network_info to store the model.
|
||||
# Version 1.2: Added new() and update_cells kwarg to save().
|
||||
|
||||
fields = {
|
||||
'instance_uuid': str,
|
||||
@@ -41,6 +47,21 @@ class InstanceInfoCache(base.NovaObject):
|
||||
info_cache._context = context
|
||||
return info_cache
|
||||
|
||||
@classmethod
|
||||
def new(cls, context, instance_uuid):
|
||||
"""Create an InfoCache object that can be used to create the DB
|
||||
entry for the first time.
|
||||
|
||||
When save()ing this object, the info_cache_update() DB call
|
||||
will properly handle creating it if it doesn't exist already.
|
||||
"""
|
||||
info_cache = cls()
|
||||
info_cache.instance_uuid = instance_uuid
|
||||
info_cache.network_info = None
|
||||
info_cache._context = context
|
||||
# Leave the fields dirty
|
||||
return info_cache
|
||||
|
||||
@base.remotable_classmethod
|
||||
def get_by_instance_uuid(cls, context, instance_uuid):
|
||||
db_obj = db.instance_info_cache_get(context, instance_uuid)
|
||||
@@ -49,10 +70,24 @@ class InstanceInfoCache(base.NovaObject):
|
||||
instance_uuid=instance_uuid)
|
||||
return InstanceInfoCache._from_db_object(context, cls(), db_obj)
|
||||
|
||||
@staticmethod
|
||||
def _info_cache_cells_update(ctxt, info_cache):
|
||||
cell_type = cells_opts.get_cell_type()
|
||||
if cell_type != 'compute':
|
||||
return
|
||||
cells_api = cells_rpcapi.CellsAPI()
|
||||
try:
|
||||
cells_api.instance_info_cache_update_at_top(ctxt, info_cache)
|
||||
except Exception:
|
||||
LOG.exception(_("Failed to notify cells of instance info "
|
||||
"cache update"))
|
||||
|
||||
@base.remotable
|
||||
def save(self, context):
|
||||
def save(self, context, update_cells=True):
|
||||
if 'network_info' in self.obj_what_changed():
|
||||
nw_info_json = self._attr_network_info_to_primitive()
|
||||
db.instance_info_cache_update(context, self.instance_uuid,
|
||||
{'network_info': nw_info_json})
|
||||
self.obj_reset_changes()
|
||||
rv = db.instance_info_cache_update(context, self.instance_uuid,
|
||||
{'network_info': nw_info_json})
|
||||
if update_cells and rv:
|
||||
self._info_cache_cells_update(context, rv)
|
||||
self.obj_reset_changes()
|
||||
|
||||
@@ -4415,8 +4415,7 @@ class ComputeTestCase(BaseTestCase):
|
||||
self.compute.conductor_api.instance_get_by_uuid(
|
||||
self.context, fake_instance['uuid']).AndReturn(fake_instance)
|
||||
self.compute.network_api.get_instance_nw_info(self.context,
|
||||
fake_instance, conductor_api=self.compute.conductor_api
|
||||
).AndReturn(fake_nw_info)
|
||||
fake_instance).AndReturn(fake_nw_info)
|
||||
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@@ -7699,7 +7698,7 @@ class ComputeAPITestCase(BaseTestCase):
|
||||
|
||||
def test_detach_interface(self):
|
||||
nwinfo, port_id = self.test_attach_interface()
|
||||
self.stubs.Set(self.compute.network_api, 'get_instance_nw_info',
|
||||
self.stubs.Set(self.compute, '_get_instance_nw_info',
|
||||
lambda *a, **k: nwinfo)
|
||||
self.stubs.Set(self.compute.network_api,
|
||||
'deallocate_port_for_instance',
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from nova.cells import opts as cells_opts
|
||||
from nova.cells import rpcapi as cells_rpcapi
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
@@ -44,18 +46,49 @@ class _TestInstanceInfoCacheObject(object):
|
||||
instance_info_cache.InstanceInfoCache.get_by_instance_uuid,
|
||||
ctxt, 'fake-uuid')
|
||||
|
||||
def test_save(self):
|
||||
def test_new(self):
|
||||
ctxt = context.get_admin_context()
|
||||
obj = instance_info_cache.InstanceInfoCache.new(ctxt,
|
||||
'fake-uuid')
|
||||
self.assertEqual(set(['instance_uuid', 'network_info']),
|
||||
obj.obj_what_changed())
|
||||
self.assertEqual('fake-uuid', obj.instance_uuid)
|
||||
self.assertEqual(None, obj.network_info)
|
||||
|
||||
def _save_helper(self, cell_type, update_cells):
|
||||
obj = instance_info_cache.InstanceInfoCache()
|
||||
cells_api = cells_rpcapi.CellsAPI()
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
self.mox.StubOutWithMock(db, 'instance_info_cache_update')
|
||||
self.mox.StubOutWithMock(cells_opts, 'get_cell_type')
|
||||
self.mox.StubOutWithMock(cells_rpcapi, 'CellsAPI',
|
||||
use_mock_anything=True)
|
||||
self.mox.StubOutWithMock(cells_api,
|
||||
'instance_info_cache_update_at_top')
|
||||
nwinfo = network_model.NetworkInfo.hydrate([{'address': 'foo'}])
|
||||
db.instance_info_cache_update(ctxt, 'fake-uuid',
|
||||
{'network_info': nwinfo.json()})
|
||||
db.instance_info_cache_update(
|
||||
ctxt, 'fake-uuid',
|
||||
{'network_info': nwinfo.json()}).AndReturn('foo')
|
||||
if update_cells:
|
||||
cells_opts.get_cell_type().AndReturn(cell_type)
|
||||
if cell_type == 'compute':
|
||||
cells_rpcapi.CellsAPI().AndReturn(cells_api)
|
||||
cells_api.instance_info_cache_update_at_top(ctxt, 'foo')
|
||||
self.mox.ReplayAll()
|
||||
obj = instance_info_cache.InstanceInfoCache()
|
||||
obj._context = ctxt
|
||||
obj.instance_uuid = 'fake-uuid'
|
||||
obj.network_info = nwinfo
|
||||
obj.save()
|
||||
obj.save(update_cells=update_cells)
|
||||
|
||||
def test_save_with_update_cells_and_compute_cell(self):
|
||||
self._save_helper('compute', True)
|
||||
|
||||
def test_save_with_update_cells_and_non_compute_cell(self):
|
||||
self._save_helper(None, True)
|
||||
|
||||
def test_save_without_update_cells(self):
|
||||
self._save_helper(None, False)
|
||||
|
||||
|
||||
class TestInstanceInfoCacheObject(test_objects._LocalTest,
|
||||
|
||||
@@ -290,8 +290,7 @@ class MetadataTestCase(test.TestCase):
|
||||
|
||||
network_api.API.get_instance_nw_info(
|
||||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
conductor_api=mox.IgnoreArg()).AndReturn(network_info_from_api)
|
||||
mox.IgnoreArg()).AndReturn(network_info_from_api)
|
||||
|
||||
self.mox.StubOutWithMock(netutils, "get_injected_network_template")
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
from oslo.config import cfg
|
||||
|
||||
from nova import conductor
|
||||
from nova import context
|
||||
from nova import network
|
||||
from nova.network import linux_net
|
||||
@@ -421,12 +420,10 @@ class IptablesFirewallDriver(FirewallDriver):
|
||||
# and should be the only one making
|
||||
# making rpc calls.
|
||||
nw_api = network.API()
|
||||
capi = conductor.API()
|
||||
for instance in rule['grantee_group']['instances']:
|
||||
nw_info = nw_api.get_instance_nw_info(
|
||||
ctxt,
|
||||
instance,
|
||||
conductor_api=capi)
|
||||
instance)
|
||||
|
||||
ips = [ip['address']
|
||||
for ip in nw_info.fixed_ips()
|
||||
|
||||
Reference in New Issue
Block a user