Merge "Fix interface-attach removes existing interfaces from db"

This commit is contained in:
Jenkins 2013-11-14 06:26:08 +00:00 committed by Gerrit Code Review
commit 79d0ce6171
3 changed files with 81 additions and 5 deletions

View File

@ -191,7 +191,6 @@ class API(base.Base):
raise exception.PortLimitExceeded()
raise
@refresh_cache
def allocate_for_instance(self, context, instance, **kwargs):
"""Allocate network resources for the instance.
@ -416,14 +415,12 @@ class API(base.Base):
LOG.exception(_("Failed to delete neutron port %(portid)s")
% {'portid': port})
@refresh_cache
def allocate_port_for_instance(self, context, instance, port_id,
network_id=None, requested_ip=None):
"""Allocate a port for the instance."""
return self.allocate_for_instance(context, instance,
requested_networks=[(network_id, requested_ip, port_id)])
@refresh_cache
def deallocate_port_for_instance(self, context, instance, port_id):
"""Remove a specified port from the instance.
@ -454,6 +451,7 @@ class API(base.Base):
update_cells=False)
return result
@refresh_cache
def _get_instance_nw_info(self, context, instance, networks=None):
LOG.debug(_('get_instance_nw_info() for %s'),
instance['display_name'])
@ -973,11 +971,15 @@ class API(base.Base):
return network, ovs_interfaceid
def _build_network_info_model(self, context, instance, networks=None):
# Note(arosen): on interface-attach networks only contains the
# network that the interface is being attached to.
search_opts = {'tenant_id': instance['project_id'],
'device_id': instance['uuid'], }
client = neutronv2.get_client(context, admin=True)
data = client.list_ports(**search_opts)
ports = data.get('ports', [])
nw_info = network_model.NetworkInfo()
if networks is None:
# retrieve networks from info_cache to get correct nic order
network_cache = self.conductor_api.instance_get_by_uuid(
@ -990,12 +992,31 @@ class API(base.Base):
# ensure ports are in preferred network order, and filter out
# those not attached to one of the provided list of networks
else:
# Unfortunately, this is sometimes in unicode and sometimes not
if isinstance(instance['info_cache']['network_info'], unicode):
ifaces = jsonutils.loads(
instance['info_cache']['network_info'])
else:
ifaces = instance['info_cache']['network_info']
# Include existing interfaces so they are not removed from the db.
# Needed when interfaces are added to existing instances.
for iface in ifaces:
nw_info.append(network_model.VIF(
id=iface['id'],
address=iface['address'],
network=iface['network'],
type=iface['type'],
ovs_interfaceid=iface['ovs_interfaceid'],
devname=iface['devname']))
net_ids = [n['id'] for n in networks]
ports = [port for port in ports if port['network_id'] in net_ids]
_ensure_requested_network_ordering(lambda x: x['network_id'],
ports, net_ids)
nw_info = network_model.NetworkInfo()
for port in ports:
network_IPs = self._nw_info_get_ips(client, port)
subnets = self._nw_info_get_subnets(context, port, network_IPs)

View File

@ -164,6 +164,7 @@ class TestNeutronSecurityGroups(
self._create_network()
fake_instance = {'project_id': 'fake_tenant',
'availability_zone': 'zone_one',
'info_cache': {'network_info': []},
'security_groups': [],
'uuid': str(uuid.uuid4()),
'display_name': 'test_instance'}

View File

@ -512,11 +512,64 @@ class TestNeutronv2(TestNeutronv2Base):
admin=True).MultipleTimes().AndReturn(
self.moxed_client)
self.mox.ReplayAll()
self.instance['info_cache'] = {'network_info': []}
nw_inf = api.get_instance_nw_info(self.context,
self.instance,
networks=self.nets1)
self._verify_nw_info(nw_inf, 0)
def test_get_instance_nw_info_with_nets_and_info_cache(self):
# This tests that adding an interface to an instance does not
# remove the first instance from the instance.
api = neutronapi.API()
self.mox.StubOutWithMock(api.db, 'instance_info_cache_update')
api.db.instance_info_cache_update(
mox.IgnoreArg(),
self.instance['uuid'], mox.IgnoreArg())
self.moxed_client.list_ports(
tenant_id=self.instance['project_id'],
device_id=self.instance['uuid']).AndReturn(
{'ports': self.port_data1})
port_data = self.port_data1
for ip in port_data[0]['fixed_ips']:
self.moxed_client.list_floatingips(
fixed_ip_address=ip['ip_address'],
port_id=port_data[0]['id']).AndReturn(
{'floatingips': self.float_data1})
self.moxed_client.list_subnets(
id=mox.SameElementsAs(['my_subid1'])).AndReturn(
{'subnets': self.subnet_data1})
self.moxed_client.list_ports(
network_id='my_netid1',
device_owner='network:dhcp').AndReturn(
{'ports': self.dhcp_port_data1})
neutronv2.get_client(mox.IgnoreArg(),
admin=True).MultipleTimes().AndReturn(
self.moxed_client)
self.mox.ReplayAll()
network_model = model.Network(id='network_id',
bridge='br-int',
injected='injected',
label='fake_network',
tenant_name='fake_tenant')
self.instance['info_cache'] = {
'network_info': [{'id': 'port_id',
'address': 'mac_address',
'network': network_model,
'type': 'ovs',
'ovs_interfaceid': 'ovs_interfaceid',
'devname': 'devname'}]}
nw_inf = api.get_instance_nw_info(self.context,
self.instance,
networks=self.nets1)
self.assertEqual(2, len(nw_inf))
for k, v in self.instance['info_cache']['network_info'][0].iteritems():
self.assertEqual(nw_inf[0][k], v)
# remove first inf and verify that the second interface is correct
del nw_inf[0]
self._verify_nw_info(nw_inf, 0)
def test_get_instance_nw_info_without_subnet(self):
# Test get instance_nw_info for a port without subnet.
api = neutronapi.API()
@ -1584,7 +1637,8 @@ class TestNeutronv2(TestNeutronv2Base):
def test_build_network_info_model(self):
api = neutronapi.API()
fake_inst = {'project_id': 'fake', 'uuid': 'uuid'}
fake_inst = {'project_id': 'fake', 'uuid': 'uuid',
'info_cache': {'network_info': []}}
fake_ports = [
{'id': 'port0',
'network_id': 'net-id',