Merge "NSX|V: Support add/remove dvs for VLAN provider networks"

This commit is contained in:
Zuul 2017-10-29 12:42:05 +00:00 committed by Gerrit Code Review
commit de74d22fb7
3 changed files with 84 additions and 18 deletions

View File

@ -81,6 +81,11 @@ def add_neutron_nsx_network_mapping(session, neutron_id, nsx_switch_id,
return mapping
def delete_neutron_nsx_network_mapping(session, neutron_id):
return (session.query(nsx_models.NeutronNsxNetworkMapping).
filter_by(neutron_id=neutron_id).delete())
def add_neutron_nsx_port_mapping(session, neutron_id,
nsx_switch_id, nsx_port_id):
session.begin(subtransactions=True)

View File

@ -1496,21 +1496,21 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
return
providernet._raise_if_updates_provider_attributes(attrs)
def _update_vlan_network_dvs_ids(self, network, new_physical_network,
az_dvs):
def _update_vlan_network_dvs_ids(self, context, network,
new_physical_network, az_dvs):
"""Update the dvs ids of a vlan provider network
The new values will be added to the current ones.
No support for removing dvs-ids.
The new values will replace the old ones.
Actions done in this function:
- Create a backend network for each new dvs
- Delete the backend networks for the old ones.
- Return the relevant information in order to later also update
the spoofguard policy, qos, network object and DB
Returns:
- dvs_list_changed True/False
- dvs_pg_mappings - mapping of the new elements dvs->moref
- dvs_pg_mappings - updated mapping of the elements dvs->moref
"""
dvs_pg_mappings = {}
@ -1518,15 +1518,32 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
network[pnet.PHYSICAL_NETWORK], az_dvs))
new_dvs_ids = set(self._get_dvs_ids(
new_physical_network, az_dvs))
additinal_dvs_ids = new_dvs_ids - current_dvs_ids
additional_dvs_ids = new_dvs_ids - current_dvs_ids
removed_dvs_ids = current_dvs_ids - new_dvs_ids
if not additinal_dvs_ids:
if not additional_dvs_ids and not removed_dvs_ids:
# no changes in the list of DVS
return False, dvs_pg_mappings
# create all the new ones
for dvs_id in additinal_dvs_ids:
self._convert_to_transport_zones_dict(network)
# get the current mapping as in the DB
db_mapping = nsx_db.get_nsx_network_mappings(
context.session, network['id'])
for db_map in db_mapping:
dvs_pg_mappings[db_map.dvs_id] = db_map.nsx_id
# delete old backend networks
for dvs_id in removed_dvs_ids:
nsx_id = dvs_pg_mappings.get(dvs_id)
if nsx_id:
#Note(asarfaty) This may fail if there is a vm deployed, but
# since the delete is done offline we will not catch it here
self._delete_backend_network(nsx_id, dvs_id)
del dvs_pg_mappings[dvs_id]
# create all the new backend networks
for dvs_id in additional_dvs_ids:
try:
self._convert_to_transport_zones_dict(network)
net_moref = self._create_vlan_network_at_backend(
dvs_id=dvs_id,
net_data=network)
@ -1585,12 +1602,12 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
c_utils.NsxVNetworkTypes.VLAN):
(updated_morefs,
new_dvs_pg_mappings) = self._update_vlan_network_dvs_ids(
context,
orig_net,
net_attrs[pnet.PHYSICAL_NETWORK],
az_dvs)
if updated_morefs:
new_dvs = list(new_dvs_pg_mappings.values())
net_morefs.extend(new_dvs)
net_morefs = list(new_dvs_pg_mappings.values())
with db_api.context_manager.writer.using(context):
net_res = super(NsxVPluginV2, self).update_network(context, id,
@ -1602,16 +1619,21 @@ class NsxVPluginV2(addr_pair_db.AllowedAddressPairsMixin,
self._process_l3_update(context, net_res, net_attrs)
self._extend_network_dict_provider(context, net_res)
if updated_morefs:
# delete old mapping before recreating all
nsx_db.delete_neutron_nsx_network_mapping(
session=context.session, neutron_id=id)
# Save netmoref to dvs id mappings for VLAN network
# type for future access.
all_dvs = net_res.get(pnet.PHYSICAL_NETWORK)
dvs_ids = []
for dvs_id, netmoref in six.iteritems(new_dvs_pg_mappings):
nsx_db.add_neutron_nsx_network_mapping(
session=context.session,
neutron_id=id,
nsx_switch_id=netmoref,
dvs_id=dvs_id)
all_dvs = '%s, %s' % (all_dvs, dvs_id)
dvs_ids.append(dvs_id)
all_dvs = ', '.join(sorted(dvs_ids))
net_res[pnet.PHYSICAL_NETWORK] = all_dvs
vlan_id = net_res.get(pnet.SEGMENTATION_ID)
nsxv_db.update_network_binding_phy_uuid(

View File

@ -502,7 +502,7 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
# physical network attribute.
self.assertEqual(2, vlan_net_call.call_count)
def test_update_vlan_network_with_multiple_dvs(self):
def test_update_vlan_network_add_dvs(self):
name = 'multi-dvs-vlan-net'
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
pnet.SEGMENTATION_ID: 100,
@ -510,7 +510,7 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
p = directory.get_plugin()
with mock.patch.object(
p, '_create_vlan_network_at_backend',
# Return three netmorefs as side effect
# Return 3 netmorefs as side effect
side_effect=[_uuid(), _uuid(), _uuid()]) as vlan_net_call:
with self.network(name=name,
providernet_args=providernet_args,
@ -524,7 +524,8 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
self.assertEqual('dvs-1, dvs-2',
net['network'][pnet.PHYSICAL_NETWORK])
# Add another dvs
data = {'network': {pnet.PHYSICAL_NETWORK: 'dvs-3'}}
data = {'network': {pnet.PHYSICAL_NETWORK:
'dvs-1, dvs-2, dvs-3'}}
req = self.new_update_request('networks', data,
net['network']['id'])
res = self.deserialize('json', req.get_response(self.api))
@ -539,7 +540,6 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
res['network'][pnet.PHYSICAL_NETWORK])
# update again - with no real change
data = {'network': {pnet.PHYSICAL_NETWORK: 'dvs-3'}}
req = self.new_update_request('networks', data,
net['network']['id'])
res = self.deserialize('json', req.get_response(self.api))
@ -547,6 +547,45 @@ class TestNetworksV2(test_plugin.TestNetworksV2, NsxVPluginV2TestCase):
self.assertEqual('dvs-1, dvs-2, dvs-3',
res['network'][pnet.PHYSICAL_NETWORK])
def test_update_vlan_network_remove_dvs(self):
name = 'multi-dvs-vlan-net'
providernet_args = {pnet.NETWORK_TYPE: 'vlan',
pnet.SEGMENTATION_ID: 100,
pnet.PHYSICAL_NETWORK: 'dvs-1, dvs-2'}
p = directory.get_plugin()
with mock.patch.object(
p, '_create_vlan_network_at_backend',
# Return 2 netmorefs as side effect
side_effect=[_uuid(), _uuid()]) as vlan_net_call,\
mock.patch.object(
p, '_delete_backend_network') as del_net:
with self.network(name=name,
providernet_args=providernet_args,
arg_list=(pnet.NETWORK_TYPE,
pnet.SEGMENTATION_ID,
pnet.PHYSICAL_NETWORK)) as net:
# _create_vlan_network_at_backend is expected to be called
# 2 times since we have 2 DVS IDs in the physical
# network attribute.
self.assertEqual(2, vlan_net_call.call_count)
self.assertEqual('dvs-1, dvs-2',
net['network'][pnet.PHYSICAL_NETWORK])
# Keep only dvs-1 (Remove dvs-2)
data = {'network': {pnet.PHYSICAL_NETWORK: 'dvs-1'}}
req = self.new_update_request('networks', data,
net['network']['id'])
res = self.deserialize('json', req.get_response(self.api))
self.assertEqual(2, vlan_net_call.call_count)
del_net.assert_called_once()
self.assertEqual('dvs-1',
res['network'][pnet.PHYSICAL_NETWORK])
# make sure it is updates also in the DB
req = self.new_show_request('networks', net['network']['id'])
res = self.deserialize('json', req.get_response(self.api))
self.assertEqual('dvs-1',
res['network'][pnet.PHYSICAL_NETWORK])
def test_get_dvs_ids_for_multiple_dvs_vlan_network(self):
p = directory.get_plugin()
default_dvs = 'fake_dvs_id'