From f58351ade3fce34e5c7ab1306b12afca9ebb88d6 Mon Sep 17 00:00:00 2001 From: Janet Yu Date: Fri, 21 Aug 2015 14:50:48 -0700 Subject: [PATCH] NSXv3: Update backend during network update When a network is updated in Neutron, update the logical switch in NSX. Change-Id: I1baec7f5f44bde92b6a61c0f25c013eabaf832b3 --- .../plugins/vmware/nsxlib/v3/__init__.py | 20 +++++++++++ .../plugins/vmware/plugins/nsx_v3_plugin.py | 35 ++++++++++++++----- .../neutron/tests/unit/vmware/nsx_v3_mocks.py | 16 +++++++++ .../tests/unit/vmware/test_nsx_v3_plugin.py | 4 ++- 4 files changed, 66 insertions(+), 9 deletions(-) diff --git a/vmware_nsx/neutron/plugins/vmware/nsxlib/v3/__init__.py b/vmware_nsx/neutron/plugins/vmware/nsxlib/v3/__init__.py index 9c49e693fa..ca69083aff 100644 --- a/vmware_nsx/neutron/plugins/vmware/nsxlib/v3/__init__.py +++ b/vmware_nsx/neutron/plugins/vmware/nsxlib/v3/__init__.py @@ -53,6 +53,26 @@ def delete_logical_switch(lswitch_id): client.delete_resource(resource) +def get_logical_switch(logical_switch_id): + resource = "logical-switches/%s" % logical_switch_id + return client.get_resource(resource) + + +@utils.retry_upon_exception_nsxv3(nsx_exc.StaleRevision, + max_attempts=cfg.CONF.nsx_v3.retries) +def update_logical_switch(lswitch_id, name=None, admin_state=None): + resource = "logical-switches/%s" % lswitch_id + lswitch = get_logical_switch(lswitch_id) + if name is not None: + lswitch['display_name'] = name + if admin_state is not None: + if admin_state: + lswitch['admin_state'] = nsx_constants.ADMIN_STATE_UP + else: + lswitch['admin_state'] = nsx_constants.ADMIN_STATE_DOWN + return client.update_resource(resource, lswitch) + + def create_logical_port(lswitch_id, vif_uuid, tags, attachment_type=nsx_constants.ATTACHMENT_VIF, admin_state=True, name=None, address_bindings=None, diff --git a/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v3_plugin.py b/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v3_plugin.py index 4959eb056d..e8edf84916 100644 --- a/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v3_plugin.py +++ b/vmware_nsx/neutron/plugins/vmware/plugins/nsx_v3_plugin.py @@ -186,7 +186,6 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2, network[pnet.SEGMENTATION_ID] = bindings[0].vlan_id def create_network(self, context, network): - # TODO(jwy): Handle creating external network (--router:external) is_provider_net = any(attributes.is_attr_set(network['network'].get(f)) for f in (pnet.NETWORK_TYPE, pnet.PHYSICAL_NETWORK, @@ -216,8 +215,8 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2, with context.session.begin(subtransactions=True): # Create network in Neutron try: - network = super(NsxV3Plugin, self).create_network(context, - network) + created_net = super(NsxV3Plugin, self).create_network(context, + network) except Exception: with excutils.save_and_reraise_exception(): # Undo creation on the backend @@ -229,7 +228,7 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2, nsx_db.add_network_binding(context.session, net_id, net_type, physical_net, vlan_id) - return network + return created_net def delete_network(self, context, network_id): # First call DB operation for delete network as it will perform @@ -241,10 +240,30 @@ class NsxV3Plugin(db_base_plugin_v2.NeutronDbPluginV2, nsxlib.delete_logical_switch(network_id) return ret_val - def update_network(self, context, network_id, network): - # TODO(arosen) - call to backend - return super(NsxV3Plugin, self).update_network(context, network_id, - network) + def update_network(self, context, id, network): + original_net = super(NsxV3Plugin, self).get_network(context, id) + net_data = network['network'] + # Neutron does not support changing provider network values + pnet._raise_if_updates_provider_attributes(net_data) + updated_net = super(NsxV3Plugin, self).update_network(context, id, + network) + + if 'name' in net_data or 'admin_state_up' in net_data: + try: + nsxlib.update_logical_switch( + id, name=net_data.get('name'), + admin_state=net_data.get('admin_state_up')) + # Backend does not update the admin state of the ports on + # the switch when the switch's admin state changes. Do not + # update the admin state of the ports in neutron either. + except nsx_exc.ManagerError: + LOG.exception(_LE("Unable to update NSX backend, rolling " + "back changes on neutron")) + with excutils.save_and_reraise_exception(): + super(NsxV3Plugin, self).update_network( + context, id, {'network': original_net}) + + return updated_net def _build_address_bindings(self, port): address_bindings = [] diff --git a/vmware_nsx/neutron/tests/unit/vmware/nsx_v3_mocks.py b/vmware_nsx/neutron/tests/unit/vmware/nsx_v3_mocks.py index a87b804402..17ec7da012 100644 --- a/vmware_nsx/neutron/tests/unit/vmware/nsx_v3_mocks.py +++ b/vmware_nsx/neutron/tests/unit/vmware/nsx_v3_mocks.py @@ -69,6 +69,22 @@ def create_logical_switch(display_name, transport_zone_id, tags, return make_fake_switch() +def get_logical_switch(lswitch_id): + return make_fake_switch(switch_uuid=lswitch_id) + + +def update_logical_switch(lswitch_id, name=None, admin_state=None): + lswitch = get_logical_switch(lswitch_id) + if name is not None: + lswitch['display_name'] = name + if admin_state is not None: + if admin_state: + lswitch['admin_state'] = nsx_constants.ADMIN_STATE_UP + else: + lswitch['admin_state'] = nsx_constants.ADMIN_STATE_DOWN + return lswitch + + def create_logical_port(lswitch_id, vif_uuid, tags, attachment_type=nsx_constants.ATTACHMENT_VIF, admin_state=True, name=None, address_bindings=None, diff --git a/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v3_plugin.py b/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v3_plugin.py index 8c20d1bfd6..c8f839877d 100644 --- a/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v3_plugin.py +++ b/vmware_nsx/neutron/tests/unit/vmware/test_nsx_v3_plugin.py @@ -39,9 +39,11 @@ class NsxPluginV3TestCase(test_plugin.NeutronDbPluginV2TestCase): # white-box testing on the plugin class # TODO(salv-orlando): supply unit tests for nsxlib.v3 nsxlib.create_logical_switch = nsx_v3_mocks.create_logical_switch + nsxlib.delete_logical_switch = mock.Mock() + nsxlib.get_logical_switch = nsx_v3_mocks.get_logical_switch + nsxlib.update_logical_switch = nsx_v3_mocks.update_logical_switch nsxlib.create_logical_port = nsx_v3_mocks.create_logical_port nsxlib.delete_logical_port = mock.Mock() - nsxlib.delete_logical_switch = mock.Mock() nsxlib.get_logical_port = nsx_v3_mocks.get_logical_port nsxlib.update_logical_port = nsx_v3_mocks.update_logical_port