]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Rename L2 Switch/Gateway related methods for VMware NSX plugin
authorarmando-migliaccio <armamig@gmail.com>
Thu, 16 Jan 2014 21:06:30 +0000 (13:06 -0800)
committerarmando-migliaccio <armamig@gmail.com>
Fri, 21 Feb 2014 22:16:07 +0000 (14:16 -0800)
Yet another another step for the renaming/refactoring
of nvplib and related modules. This is about l2 switches
and l2 gateways.

Partial-implements blueprint nicira-plugin-renaming

Change-Id: I35c2b20a33ed8f2df4334c335f91472f7b822f8e

18 files changed:
neutron/plugins/nicira/NeutronPlugin.py
neutron/plugins/nicira/NeutronServicePlugin.py
neutron/plugins/nicira/common/nsx_utils.py
neutron/plugins/nicira/common/sync.py
neutron/plugins/nicira/common/utils.py
neutron/plugins/nicira/dhcp_meta/lsnmanager.py
neutron/plugins/nicira/nsxlib/l2gateway.py [new file with mode: 0644]
neutron/plugins/nicira/nsxlib/router.py
neutron/plugins/nicira/nsxlib/switch.py [new file with mode: 0644]
neutron/plugins/nicira/nvplib.py
neutron/tests/unit/nicira/nsxlib/test_l2gateway.py [new file with mode: 0644]
neutron/tests/unit/nicira/nsxlib/test_lsn.py [moved from neutron/tests/unit/nicira/test_lsn_lib.py with 100% similarity]
neutron/tests/unit/nicira/nsxlib/test_router.py
neutron/tests/unit/nicira/nsxlib/test_switch.py [new file with mode: 0644]
neutron/tests/unit/nicira/test_dhcpmeta.py
neutron/tests/unit/nicira/test_nicira_plugin.py
neutron/tests/unit/nicira/test_nsx_utils.py
neutron/tests/unit/nicira/test_nvplib.py

index df1674595232f4555bdacfc616b77fd21a65934f..9d3d629fb2440a83387c33cdca8eb969a5c53a8b 100644 (file)
@@ -76,8 +76,10 @@ from neutron.plugins.nicira import dhcpmeta_modes
 from neutron.plugins.nicira.extensions import maclearning as mac_ext
 from neutron.plugins.nicira.extensions import nvp_networkgw as networkgw
 from neutron.plugins.nicira.extensions import nvp_qos as ext_qos
+from neutron.plugins.nicira.nsxlib import l2gateway as l2gwlib
 from neutron.plugins.nicira.nsxlib import queue as queuelib
 from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
 from neutron.plugins.nicira import NvpApiClient
 from neutron.plugins.nicira import nvplib
 
@@ -411,17 +413,17 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
 
     def _nvp_create_port_helper(self, cluster, ls_uuid, port_data,
                                 do_port_security=True):
-        return nvplib.create_lport(cluster, ls_uuid, port_data['tenant_id'],
-                                   port_data['id'], port_data['name'],
-                                   port_data['device_id'],
-                                   port_data['admin_state_up'],
-                                   port_data['mac_address'],
-                                   port_data['fixed_ips'],
-                                   port_data[psec.PORTSECURITY],
-                                   port_data[ext_sg.SECURITYGROUPS],
-                                   port_data.get(ext_qos.QUEUE),
-                                   port_data.get(mac_ext.MAC_LEARNING),
-                                   port_data.get(addr_pair.ADDRESS_PAIRS))
+        return switchlib.create_lport(cluster, ls_uuid, port_data['tenant_id'],
+                                      port_data['id'], port_data['name'],
+                                      port_data['device_id'],
+                                      port_data['admin_state_up'],
+                                      port_data['mac_address'],
+                                      port_data['fixed_ips'],
+                                      port_data[psec.PORTSECURITY],
+                                      port_data[ext_sg.SECURITYGROUPS],
+                                      port_data.get(ext_qos.QUEUE),
+                                      port_data.get(mac_ext.MAC_LEARNING),
+                                      port_data.get(addr_pair.ADDRESS_PAIRS))
 
     def _handle_create_port_exception(self, context, port_id,
                                       ls_uuid, lp_uuid):
@@ -430,8 +432,8 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             # created on NVP. Should this command fail the original
             # exception will be raised.
             if lp_uuid:
-                # Remove orphaned port from NVP
-                nvplib.delete_port(self.cluster, ls_uuid, lp_uuid)
+                # Remove orphaned port from NSX
+                switchlib.delete_port(self.cluster, ls_uuid, lp_uuid)
             # rollback the neutron-nvp port mapping
             nicira_db.delete_neutron_nsx_port_mapping(context.session,
                                                       port_id)
@@ -465,9 +467,9 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 context.session, port_data['id'],
                 selected_lswitch['uuid'], lport['uuid'])
             if port_data['device_owner'] not in self.port_special_owners:
-                nvplib.plug_interface(self.cluster, selected_lswitch['uuid'],
-                                      lport['uuid'], "VifAttachment",
-                                      port_data['id'])
+                switchlib.plug_interface(
+                    self.cluster, selected_lswitch['uuid'],
+                    lport['uuid'], "VifAttachment", port_data['id'])
             LOG.debug(_("_nvp_create_port completed for port %(name)s "
                         "on network %(network_id)s. The new port id is "
                         "%(id)s."), port_data)
@@ -487,9 +489,9 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 LOG.warning(msg)
                 if selected_lswitch and lport:
                     try:
-                        nvplib.delete_port(self.cluster,
-                                           selected_lswitch['uuid'],
-                                           lport['uuid'])
+                        switchlib.delete_port(self.cluster,
+                                              selected_lswitch['uuid'],
+                                              lport['uuid'])
                     except q_exc.NotFound:
                         LOG.debug(_("NSX Port %s already gone"), lport['uuid'])
 
@@ -503,18 +505,16 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                         "external networks. Port %s will be down."),
                       port_data['network_id'])
             return
-        nvp_switch_id, nvp_port_id = nsx_utils.get_nsx_switch_and_port_id(
+        nsx_switch_id, nsx_port_id = nsx_utils.get_nsx_switch_and_port_id(
             context.session, self.cluster, port_data['id'])
-        if not nvp_port_id:
+        if not nsx_port_id:
             LOG.debug(_("Port '%s' was already deleted on NVP platform"), id)
             return
         # TODO(bgh): if this is a bridged network and the lswitch we just got
         # back will have zero ports after the delete we should garbage collect
         # the lswitch.
         try:
-            nvplib.delete_port(self.cluster,
-                               nvp_switch_id,
-                               nvp_port_id)
+            switchlib.delete_port(self.cluster, nsx_switch_id, nsx_port_id)
             LOG.debug(_("_nvp_delete_port completed for port %(port_id)s "
                         "on network %(net_id)s"),
                       {'port_id': port_data['id'],
@@ -716,7 +716,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             nicira_db.add_neutron_nsx_port_mapping(
                 context.session, port_data['id'],
                 selected_lswitch['uuid'], lport['uuid'])
-            nvplib.plug_l2_gw_service(
+            l2gwlib.plug_l2_gw_service(
                 self.cluster,
                 port_data['network_id'],
                 lport['uuid'],
@@ -725,9 +725,9 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         except Exception:
             with excutils.save_and_reraise_exception():
                 if lport:
-                    nvplib.delete_port(self.cluster,
-                                       selected_lswitch['uuid'],
-                                       lport['uuid'])
+                    switchlib.delete_port(self.cluster,
+                                          selected_lswitch['uuid'],
+                                          lport['uuid'])
         LOG.debug(_("_nvp_create_l2_gw_port completed for port %(name)s "
                     "on network %(network_id)s. The new port id "
                     "is %(id)s."), port_data)
@@ -864,14 +864,14 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
                 # The tag must therefore be added.
                 tags = main_ls['tags']
                 tags.append({'tag': 'True', 'scope': 'multi_lswitch'})
-                nvplib.update_lswitch(cluster,
-                                      main_ls['uuid'],
-                                      main_ls['display_name'],
-                                      network['tenant_id'],
-                                      tags=tags)
+                switchlib.update_lswitch(cluster,
+                                         main_ls['uuid'],
+                                         main_ls['display_name'],
+                                         network['tenant_id'],
+                                         tags=tags)
             transport_zone_config = self._convert_to_nvp_transport_zones(
                 cluster, network, bindings=network_bindings)
-            selected_lswitch = nvplib.create_lswitch(
+            selected_lswitch = switchlib.create_lswitch(
                 cluster, network.id, network.tenant_id,
                 "%s-ext-%s" % (network.name, len(lswitches)),
                 transport_zone_config)
@@ -983,7 +983,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         net_data['id'] = str(uuid.uuid4())
         if (not attr.is_attr_set(external) or
             attr.is_attr_set(external) and not external):
-            lswitch = nvplib.create_lswitch(
+            lswitch = switchlib.create_lswitch(
                 self.cluster, net_data['id'],
                 tenant_id, net_data.get('name'),
                 transport_zone_config,
@@ -1074,7 +1074,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         # Do not go to NVP for external networks
         if not external:
             try:
-                nvplib.delete_networks(self.cluster, id, lswitch_ids)
+                switchlib.delete_networks(self.cluster, id, lswitch_ids)
                 LOG.debug(_("delete_network completed for tenant: %s"),
                           context.tenant_id)
             except q_exc.NotFound:
@@ -1292,34 +1292,35 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             self._process_port_queue_mapping(context, ret_port,
                                              port_queue_id)
             LOG.warn(_("Update port request: %s"), port)
-            nvp_switch_id, nvp_port_id = nsx_utils.get_nsx_switch_and_port_id(
+            nsx_switch_id, nsx_port_id = nsx_utils.get_nsx_switch_and_port_id(
                 context.session, self.cluster, id)
-            if nvp_port_id:
+            if nsx_port_id:
                 try:
-                    nvplib.update_port(self.cluster,
-                                       nvp_switch_id,
-                                       nvp_port_id, id, tenant_id,
-                                       ret_port['name'], ret_port['device_id'],
-                                       ret_port['admin_state_up'],
-                                       ret_port['mac_address'],
-                                       ret_port['fixed_ips'],
-                                       ret_port[psec.PORTSECURITY],
-                                       ret_port[ext_sg.SECURITYGROUPS],
-                                       ret_port[ext_qos.QUEUE],
-                                       ret_port.get(mac_ext.MAC_LEARNING),
-                                       ret_port.get(addr_pair.ADDRESS_PAIRS))
+                    switchlib.update_port(
+                        self.cluster,
+                        nsx_switch_id, nsx_port_id, id, tenant_id,
+                        ret_port['name'],
+                        ret_port['device_id'],
+                        ret_port['admin_state_up'],
+                        ret_port['mac_address'],
+                        ret_port['fixed_ips'],
+                        ret_port[psec.PORTSECURITY],
+                        ret_port[ext_sg.SECURITYGROUPS],
+                        ret_port[ext_qos.QUEUE],
+                        ret_port.get(mac_ext.MAC_LEARNING),
+                        ret_port.get(addr_pair.ADDRESS_PAIRS))
 
                     # Update the port status from nvp. If we fail here hide it
                     # since the port was successfully updated but we were not
                     # able to retrieve the status.
-                    ret_port['status'] = nvplib.get_port_status(
+                    ret_port['status'] = switchlib.get_port_status(
                         self.cluster, ret_port['network_id'],
-                        nvp_port_id)
+                        nsx_port_id)
                 # FIXME(arosen) improve exception handling.
                 except Exception:
                     ret_port['status'] = constants.PORT_STATUS_ERROR
                     LOG.exception(_("Unable to update port id: %s."),
-                                  nvp_port_id)
+                                  nsx_port_id)
 
             # If nvp_port_id is not in database or in nvp put in error state.
             else:
@@ -1688,15 +1689,15 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             context.session, self.cluster, router_id)
         if port_id:
             port_data = self._get_port(context, port_id)
-            nvp_switch_id, nvp_port_id = nsx_utils.get_nsx_switch_and_port_id(
+            nsx_switch_id, nsx_port_id = nsx_utils.get_nsx_switch_and_port_id(
                 context.session, self.cluster, port_id)
             # Unplug current attachment from lswitch port
-            nvplib.plug_interface(self.cluster, nvp_switch_id,
-                                  nvp_port_id, "NoAttachment")
+            switchlib.plug_interface(self.cluster, nsx_switch_id,
+                                     nsx_port_id, "NoAttachment")
             # Create logical router port and plug patch attachment
             self._create_and_attach_router_port(
                 self.cluster, context, nsx_router_id, port_data,
-                "PatchAttachment", nvp_port_id, subnet_ids=[subnet_id])
+                "PatchAttachment", nsx_port_id, subnet_ids=[subnet_id])
         subnet = self._get_subnet(context, subnet_id)
         # If there is an external gateway we need to configure the SNAT rule.
         # Fetch router from DB
@@ -2013,20 +2014,20 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
             if not device.get('interface_name'):
                 device['interface_name'] = self.cluster.default_interface_name
         try:
-            nvp_res = nvplib.create_l2_gw_service(self.cluster, tenant_id,
-                                                  gw_data['name'], devices)
-            nvp_uuid = nvp_res.get('uuid')
+            nsx_res = l2gwlib.create_l2_gw_service(
+                self.cluster, tenant_id, gw_data['name'], devices)
+            nsx_uuid = nsx_res.get('uuid')
         except NvpApiClient.Conflict:
             raise nvp_exc.NvpL2GatewayAlreadyInUse(gateway=gw_data['name'])
         except NvpApiClient.NvpApiException:
             err_msg = _("Unable to create l2_gw_service for: %s") % gw_data
             LOG.exception(err_msg)
             raise nvp_exc.NvpPluginException(err_msg=err_msg)
-        gw_data['id'] = nvp_uuid
+        gw_data['id'] = nsx_uuid
         return super(NvpPluginV2, self).create_network_gateway(context,
                                                                network_gateway)
 
-    def delete_network_gateway(self, context, id):
+    def delete_network_gateway(self, context, gateway_id):
         """Remove a layer-2 network gateway.
 
         Remove the gateway service from NVP platform and corresponding data
@@ -2036,8 +2037,9 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         self._ensure_default_network_gateway()
         with context.session.begin(subtransactions=True):
             try:
-                super(NvpPluginV2, self).delete_network_gateway(context, id)
-                nvplib.delete_l2_gw_service(self.cluster, id)
+                super(NvpPluginV2, self).delete_network_gateway(
+                    context, gateway_id)
+                l2gwlib.delete_l2_gw_service(self.cluster, gateway_id)
             except NvpApiClient.ResourceNotFound:
                 # Do not cause a 500 to be returned to the user if
                 # the corresponding NVP resource does not exist
@@ -2067,7 +2069,7 @@ class NvpPluginV2(addr_pair_db.AllowedAddressPairsMixin,
         name = network_gateway[networkgw.RESOURCE_NAME].get('name')
         if name:
             try:
-                nvplib.update_l2_gw_service(self.cluster, id, name)
+                l2gwlib.update_l2_gw_service(self.cluster, id, name)
             except NvpApiClient.NvpApiException:
                 # Consider backend failures as non-fatal, but still warn
                 # because this might indicate something dodgy is going on
index da0c7c2a92bc3d5957958698cd49463c33a0a379..379bc52b29ea37a9ef277ab94210838117ce4463 100644 (file)
@@ -37,6 +37,7 @@ from neutron.plugins.nicira.dbexts import vcns_models
 from neutron.plugins.nicira.extensions import servicerouter as sr
 from neutron.plugins.nicira import NeutronPlugin
 from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
 from neutron.plugins.nicira import NvpApiClient
 from neutron.plugins.nicira import nvplib
 from neutron.plugins.nicira.vshield.common import (
@@ -109,12 +110,12 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
         # load the vCNS driver
         self._load_vcns_drivers()
 
-        # nvplib's create_lswitch needs to be replaced in order to proxy
+        # switchlib's create_lswitch needs to be replaced in order to proxy
         # logical switch create requests to vcns
         self._set_create_lswitch_proxy()
 
     def _set_create_lswitch_proxy(self):
-        NeutronPlugin.nvplib.create_lswitch = self._proxy_create_lswitch
+        NeutronPlugin.switchlib.create_lswitch = self._proxy_create_lswitch
 
     def _proxy_create_lswitch(self, *args, **kwargs):
         name, tz_config, tags = (
@@ -412,7 +413,7 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
                                           lrouter, lswitch):
         # create logic switch port
         try:
-            ls_port = nvplib.create_lport(
+            ls_port = switchlib.create_lport(
                 self.cluster, lswitch['uuid'], tenant_id,
                 '', '', lrouter['uuid'], True)
         except NvpApiClient.NvpApiException:
@@ -433,7 +434,8 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
         except NvpApiClient.NvpApiException:
             msg = (_("Unable to create port on NVP logical router %s") % name)
             LOG.exception(msg)
-            nvplib.delete_port(self.cluster, lswitch['uuid'], ls_port['uuid'])
+            switchlib.delete_port(
+                self.cluster, lswitch['uuid'], ls_port['uuid'])
             raise q_exc.NeutronException(message=msg)
 
         # attach logic router port to switch port
@@ -443,7 +445,8 @@ class NvpAdvancedPlugin(sr_db.ServiceRouter_mixin,
                 'PatchAttachment', ls_port['uuid'], None)
         except NvpApiClient.NvpApiException as e:
             # lr_port should have been deleted
-            nvplib.delete_port(self.cluster, lswitch['uuid'], ls_port['uuid'])
+            switchlib.delete_port(
+                self.cluster, lswitch['uuid'], ls_port['uuid'])
             raise e
 
     def _create_lrouter(self, context, router, nexthop):
index 208b2ea745fb92c531e81861fc5d6067a8efafb9..50dcadf4f2f17f7dedd0dcaac1078c83afad99bf 100644 (file)
@@ -19,8 +19,8 @@ from neutron.openstack.common import log
 from neutron.plugins.nicira.dbexts import nicira_db
 from neutron.plugins.nicira import nsx_cluster
 from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
 from neutron.plugins.nicira import NvpApiClient
-from neutron.plugins.nicira import nvplib
 
 
 LOG = log.getLogger(__name__)
@@ -37,9 +37,9 @@ def fetch_nsx_switches(session, cluster, neutron_net_id):
     """
     nsx_switch_ids = get_nsx_switch_ids(session, cluster, neutron_net_id)
     if len(nsx_switch_ids) > 1:
-        lswitches = nvplib.get_lswitches(cluster, neutron_net_id)
+        lswitches = switchlib.get_lswitches(cluster, neutron_net_id)
     else:
-        lswitches = [nvplib.get_lswitch_by_id(
+        lswitches = [switchlib.get_lswitch_by_id(
             cluster, nsx_switch_ids[0])]
     return lswitches
 
@@ -56,7 +56,7 @@ def get_nsx_switch_ids(session, cluster, neutron_network_id):
         # Find logical switches from backend.
         # This is a rather expensive query, but it won't be executed
         # more than once for each network in Neutron's lifetime
-        nsx_switches = nvplib.get_lswitches(cluster, neutron_network_id)
+        nsx_switches = switchlib.get_lswitches(cluster, neutron_network_id)
         if not nsx_switches:
             LOG.warn(_("Unable to find NSX switches for Neutron network %s"),
                      neutron_network_id)
@@ -91,38 +91,38 @@ def get_nsx_switch_and_port_id(session, cluster, neutron_port_id):
     the backend logical switch identifier is equal to the neutron
     network identifier.
     """
-    nvp_switch_id, nvp_port_id = nicira_db.get_nsx_switch_and_port_id(
+    nsx_switch_id, nsx_port_id = nicira_db.get_nsx_switch_and_port_id(
         session, neutron_port_id)
-    if not nvp_switch_id:
+    if not nsx_switch_id:
         # Find logical switch for port from backend
         # This is a rather expensive query, but it won't be executed
         # more than once for each port in Neutron's lifetime
-        nvp_ports = nvplib.query_lswitch_lports(
+        nsx_ports = switchlib.query_lswitch_lports(
             cluster, '*', relations='LogicalSwitchConfig',
             filters={'tag': neutron_port_id,
                      'tag_scope': 'q_port_id'})
         # Only one result expected
         # NOTE(salv-orlando): Not handling the case where more than one
         # port is found with the same neutron port tag
-        if not nvp_ports:
-            LOG.warn(_("Unable to find NVP port for Neutron port %s"),
+        if not nsx_ports:
+            LOG.warn(_("Unable to find NSX port for Neutron port %s"),
                      neutron_port_id)
             # This method is supposed to return a tuple
             return None, None
-        nvp_port = nvp_ports[0]
-        nvp_switch_id = (nvp_port['_relations']
+        nsx_port = nsx_ports[0]
+        nsx_switch_id = (nsx_port['_relations']
                          ['LogicalSwitchConfig']['uuid'])
-        if nvp_port_id:
+        if nsx_port_id:
             # Mapping already exists. Delete before recreating
             nicira_db.delete_neutron_nsx_port_mapping(
                 session, neutron_port_id)
         else:
-            nvp_port_id = nvp_port['uuid']
+            nsx_port_id = nsx_port['uuid']
         # (re)Create DB mapping
         nicira_db.add_neutron_nsx_port_mapping(
             session, neutron_port_id,
-            nvp_switch_id, nvp_port_id)
-    return nvp_switch_id, nvp_port_id
+            nsx_switch_id, nsx_port_id)
+    return nsx_switch_id, nsx_port_id
 
 
 def create_nsx_cluster(cluster_opts, concurrent_connections, nsx_gen_timeout):
index dbbedf61cef6961bfb7023c99286ebbaccc67a63..4db520adf77b1da0bb7eb4b0f51764791633139d 100644 (file)
@@ -28,6 +28,7 @@ from neutron.openstack.common import timeutils
 from neutron.plugins.nicira.common import exceptions as nvp_exc
 from neutron.plugins.nicira.common import nsx_utils
 from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
 from neutron.plugins.nicira import NvpApiClient
 from neutron.plugins.nicira import nvplib
 
@@ -383,7 +384,7 @@ class NvpSynchronizer():
                 ls_uuid, lp_uuid = nsx_utils.get_nsx_switch_and_port_id(
                     context.session, self._cluster, neutron_port_data['id'])
                 if lp_uuid:
-                    lswitchport = nvplib.get_port(
+                    lswitchport = switchlib.get_port(
                         self._cluster, ls_uuid, lp_uuid,
                         relations='LogicalPortStatus')
             except (exceptions.PortNotFoundOnNetwork):
index 273ec97b216bc560c2e819d317a5978211b0cfec..48773f63f06b300e50e189497d7621178b6dcbd5 100644 (file)
@@ -15,6 +15,8 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+import hashlib
+
 from neutron.api.v2.attributes import is_attr_set
 from neutron.openstack.common import log
 from neutron.version import version_info
@@ -32,9 +34,24 @@ def get_tags(**kwargs):
     return tags
 
 
+def device_id_to_vm_id(device_id, obfuscate=False):
+    # device_id can be longer than 40 characters, for example
+    # a device_id for a dhcp port is like the following:
+    #
+    # dhcp83b5fdeb-e3b4-5e18-ac5f-55161...80747326-47d7-46c2-a87a-cf6d5194877c
+    #
+    # To fit it into an NSX tag we need to hash it, however device_id
+    # used for ports associated to VM's are small enough so let's skip the
+    # hashing
+    if len(device_id) > MAX_DISPLAY_NAME_LEN or obfuscate:
+        return hashlib.sha1(device_id).hexdigest()
+    else:
+        return device_id
+
+
 def check_and_truncate(display_name):
     if is_attr_set(display_name) and len(display_name) > MAX_DISPLAY_NAME_LEN:
         LOG.debug(_("Specified name:'%s' exceeds maximum length. "
-                    "It will be truncated on NVP"), display_name)
+                    "It will be truncated on NSX"), display_name)
         return display_name[:MAX_DISPLAY_NAME_LEN]
     return display_name or ''
index 4c2bd34804f429cc8a0d8e12321919b9e55b5004..02dd81a5d64ad0d421762cfa9a6fdc6b59587cfe 100644 (file)
@@ -24,6 +24,7 @@ from neutron.plugins.nicira.common import exceptions as p_exc
 from neutron.plugins.nicira.dbexts import lsn_db
 from neutron.plugins.nicira.dhcp_meta import constants as const
 from neutron.plugins.nicira.nsxlib import lsn as lsn_api
+from neutron.plugins.nicira.nsxlib import switch as switch_api
 from neutron.plugins.nicira import nvplib as nsxlib
 
 LOG = logging.getLogger(__name__)
@@ -161,13 +162,13 @@ class LsnManager(object):
             self.lsn_port_delete(context, lsn_id, lsn_port_id)
             if mac_address == const.METADATA_MAC:
                 try:
-                    lswitch_port_id = nsxlib.get_port_by_neutron_tag(
+                    lswitch_port_id = switch_api.get_port_by_neutron_tag(
                         self.cluster, network_id,
                         const.METADATA_PORT_ID)['uuid']
-                    nsxlib.delete_port(
+                    switch_api.delete_port(
                         self.cluster, network_id, lswitch_port_id)
                 except (n_exc.PortNotFoundOnNetwork,
-                        nsxlib.NvpApiClient.NvpApiException):
+                        switch_api.NvpApiClient.NvpApiException):
                     LOG.warn(_("Metadata port not found while attempting "
                                "to delete it from network %s"), network_id)
         else:
@@ -179,7 +180,7 @@ class LsnManager(object):
         """Connect network to LSN via specified port and port_data."""
         try:
             lsn_id = None
-            lswitch_port_id = nsxlib.get_port_by_neutron_tag(
+            lswitch_port_id = switch_api.get_port_by_neutron_tag(
                 self.cluster, network_id, port_id)['uuid']
             lsn_id = self.lsn_get(context, network_id)
             lsn_port_id = self.lsn_port_create(context, lsn_id, port_data)
@@ -211,7 +212,7 @@ class LsnManager(object):
         tenant_id = subnet['tenant_id']
         lswitch_port_id = None
         try:
-            lswitch_port_id = nsxlib.create_lport(
+            lswitch_port_id = switch_api.create_lport(
                 self.cluster, network_id, tenant_id,
                 const.METADATA_PORT_ID, const.METADATA_PORT_NAME,
                 const.METADATA_DEVICE_ID, True)['uuid']
@@ -226,7 +227,8 @@ class LsnManager(object):
                     self.cluster, lsn_id, lsn_port_id, lswitch_port_id)
             except p_exc.LsnConfigurationConflict:
                 self.lsn_port_delete(self.cluster, lsn_id, lsn_port_id)
-                nsxlib.delete_port(self.cluster, network_id, lswitch_port_id)
+                switch_api.delete_port(
+                    self.cluster, network_id, lswitch_port_id)
                 raise p_exc.PortConfigurationError(
                     net_id=network_id, lsn_id=lsn_id, port_id=lsn_port_id)
 
diff --git a/neutron/plugins/nicira/nsxlib/l2gateway.py b/neutron/plugins/nicira/nsxlib/l2gateway.py
new file mode 100644 (file)
index 0000000..db6fe2c
--- /dev/null
@@ -0,0 +1,109 @@
+# Copyright 2014 VMware, Inc.
+# All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+import json
+
+from neutron.openstack.common import log
+from neutron.plugins.nicira.common import utils
+from neutron.plugins.nicira.nvplib import _build_uri_path
+from neutron.plugins.nicira.nvplib import _plug_interface
+from neutron.plugins.nicira.nvplib import do_request
+from neutron.plugins.nicira.nvplib import get_all_query_pages
+
+HTTP_GET = "GET"
+HTTP_POST = "POST"
+HTTP_DELETE = "DELETE"
+HTTP_PUT = "PUT"
+
+GWSERVICE_RESOURCE = "gateway-service"
+
+LOG = log.getLogger(__name__)
+
+
+def create_l2_gw_service(cluster, tenant_id, display_name, devices):
+    """Create a NSX Layer-2 Network Gateway Service.
+
+        :param cluster: The target NSX cluster
+        :param tenant_id: Identifier of the Openstack tenant for which
+        the gateway service.
+        :param display_name: Descriptive name of this gateway service
+        :param devices: List of transport node uuids (and network
+        interfaces on them) to use for the network gateway service
+        :raise NvpApiException: if there is a problem while communicating
+        with the NSX controller
+    """
+    # NOTE(salvatore-orlando): This is a little confusing, but device_id in
+    # NSX is actually the identifier a physical interface on the gateway
+    # device, which in the Neutron API is referred as interface_name
+    gateways = [{"transport_node_uuid": device['id'],
+                 "device_id": device['interface_name'],
+                 "type": "L2Gateway"} for device in devices]
+    gwservice_obj = {
+        "display_name": utils.check_and_truncate(display_name),
+        "tags": utils.get_tags(os_tid=tenant_id),
+        "gateways": gateways,
+        "type": "L2GatewayServiceConfig"
+    }
+    return do_request(
+        "POST", _build_uri_path(GWSERVICE_RESOURCE),
+        json.dumps(gwservice_obj), cluster=cluster)
+
+
+def plug_l2_gw_service(cluster, lswitch_id, lport_id,
+                       gateway_id, vlan_id=None):
+    """Plug a Layer-2 Gateway Attachment object in a logical port."""
+    att_obj = {'type': 'L2GatewayAttachment',
+               'l2_gateway_service_uuid': gateway_id}
+    if vlan_id:
+        att_obj['vlan_id'] = vlan_id
+    return _plug_interface(cluster, lswitch_id, lport_id, att_obj)
+
+
+def get_l2_gw_service(cluster, gateway_id):
+    return do_request(
+        "GET", _build_uri_path(GWSERVICE_RESOURCE,
+                               resource_id=gateway_id),
+        cluster=cluster)
+
+
+def get_l2_gw_services(cluster, tenant_id=None,
+                       fields=None, filters=None):
+    actual_filters = dict(filters or {})
+    if tenant_id:
+        actual_filters['tag'] = tenant_id
+        actual_filters['tag_scope'] = 'os_tid'
+    return get_all_query_pages(
+        _build_uri_path(GWSERVICE_RESOURCE,
+                        filters=actual_filters),
+        cluster)
+
+
+def update_l2_gw_service(cluster, gateway_id, display_name):
+    # TODO(salvatore-orlando): Allow updates for gateways too
+    gwservice_obj = get_l2_gw_service(cluster, gateway_id)
+    if not display_name:
+        # Nothing to update
+        return gwservice_obj
+    gwservice_obj["display_name"] = utils.check_and_truncate(display_name)
+    return do_request("PUT", _build_uri_path(GWSERVICE_RESOURCE,
+                                             resource_id=gateway_id),
+                      json.dumps(gwservice_obj), cluster=cluster)
+
+
+def delete_l2_gw_service(cluster, gateway_id):
+    do_request("DELETE", _build_uri_path(GWSERVICE_RESOURCE,
+                                         resource_id=gateway_id),
+               cluster=cluster)
index b76b6325457e79cbe85c98815462b5660516765a..97b9adc5a65384cde98cc879a9f2ad31d15c2d31 100644 (file)
@@ -19,13 +19,13 @@ from neutron.openstack.common import jsonutils
 from neutron.openstack.common import log
 from neutron.plugins.nicira.common import exceptions as nvp_exc
 from neutron.plugins.nicira.common import utils
+from neutron.plugins.nicira.nsxlib.switch import get_port
 from neutron.plugins.nicira.nsxlib.versioning import DEFAULT_VERSION
 from neutron.plugins.nicira.nsxlib.versioning import versioned
 from neutron.plugins.nicira import NvpApiClient
 from neutron.plugins.nicira.nvplib import _build_uri_path
 from neutron.plugins.nicira.nvplib import do_request
 from neutron.plugins.nicira.nvplib import get_all_query_pages
-from neutron.plugins.nicira.nvplib import get_port
 
 HTTP_GET = "GET"
 HTTP_POST = "POST"
diff --git a/neutron/plugins/nicira/nsxlib/switch.py b/neutron/plugins/nicira/nsxlib/switch.py
new file mode 100644 (file)
index 0000000..f7b77b0
--- /dev/null
@@ -0,0 +1,379 @@
+# Copyright 2014 VMware, Inc.
+# All Rights Reserved
+#
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    not use this file except in compliance with the License. You may obtain
+#    a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+#    Unless required by applicable law or agreed to in writing, software
+#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+#    License for the specific language governing permissions and limitations
+#    under the License.
+#
+
+import json
+
+from neutron.common import constants
+from neutron.common import exceptions as exception
+from neutron.openstack.common import log
+from neutron.plugins.nicira.common import exceptions as nvp_exc
+from neutron.plugins.nicira.common import utils
+from neutron.plugins.nicira import NvpApiClient
+from neutron.plugins.nicira.nvplib import _build_uri_path
+from neutron.plugins.nicira.nvplib import _plug_interface
+from neutron.plugins.nicira.nvplib import do_request
+from neutron.plugins.nicira.nvplib import get_all_query_pages
+
+HTTP_GET = "GET"
+HTTP_POST = "POST"
+HTTP_DELETE = "DELETE"
+HTTP_PUT = "PUT"
+
+LSWITCH_RESOURCE = "lswitch"
+LSWITCHPORT_RESOURCE = "lport/%s" % LSWITCH_RESOURCE
+
+LOG = log.getLogger(__name__)
+
+
+def _configure_extensions(lport_obj, mac_address, fixed_ips,
+                          port_security_enabled, security_profiles,
+                          queue_id, mac_learning_enabled,
+                          allowed_address_pairs):
+    lport_obj['allowed_address_pairs'] = []
+    if port_security_enabled:
+        for fixed_ip in fixed_ips:
+            ip_address = fixed_ip.get('ip_address')
+            if ip_address:
+                lport_obj['allowed_address_pairs'].append(
+                    {'mac_address': mac_address, 'ip_address': ip_address})
+        # add address pair allowing src_ip 0.0.0.0 to leave
+        # this is required for outgoing dhcp request
+        lport_obj["allowed_address_pairs"].append(
+            {"mac_address": mac_address,
+             "ip_address": "0.0.0.0"})
+    lport_obj['security_profiles'] = list(security_profiles or [])
+    lport_obj['queue_uuid'] = queue_id
+    if mac_learning_enabled is not None:
+        lport_obj["mac_learning"] = mac_learning_enabled
+        lport_obj["type"] = "LogicalSwitchPortConfig"
+    for address_pair in list(allowed_address_pairs or []):
+        lport_obj['allowed_address_pairs'].append(
+            {'mac_address': address_pair['mac_address'],
+             'ip_address': address_pair['ip_address']})
+
+
+def get_lswitch_by_id(cluster, lswitch_id):
+    try:
+        lswitch_uri_path = _build_uri_path(
+            LSWITCH_RESOURCE, lswitch_id,
+            relations="LogicalSwitchStatus")
+        return do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
+    except exception.NotFound:
+        # FIXME(salv-orlando): this should not raise a neutron exception
+        raise exception.NetworkNotFound(net_id=lswitch_id)
+
+
+def get_lswitches(cluster, neutron_net_id):
+
+    def lookup_switches_by_tag():
+        # Fetch extra logical switches
+        lswitch_query_path = _build_uri_path(
+            LSWITCH_RESOURCE,
+            fields="uuid,display_name,tags,lport_count",
+            relations="LogicalSwitchStatus",
+            filters={'tag': neutron_net_id,
+                     'tag_scope': 'quantum_net_id'})
+        return get_all_query_pages(lswitch_query_path, cluster)
+
+    lswitch_uri_path = _build_uri_path(LSWITCH_RESOURCE, neutron_net_id,
+                                       relations="LogicalSwitchStatus")
+    results = []
+    try:
+        ls = do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
+        results.append(ls)
+        for tag in ls['tags']:
+            if (tag['scope'] == "multi_lswitch" and
+                tag['tag'] == "True"):
+                results.extend(lookup_switches_by_tag())
+    except exception.NotFound:
+        # This is legit if the neutron network was created using
+        # a post-Havana version of the plugin
+        results.extend(lookup_switches_by_tag())
+    if results:
+        return results
+    else:
+        raise exception.NetworkNotFound(net_id=neutron_net_id)
+
+
+def create_lswitch(cluster, neutron_net_id, tenant_id, display_name,
+                   transport_zones_config,
+                   shared=None,
+                   **kwargs):
+    # The tag scope adopts a slightly different naming convention for
+    # historical reasons
+    lswitch_obj = {"display_name": utils.check_and_truncate(display_name),
+                   "transport_zones": transport_zones_config,
+                   "tags": utils.get_tags(os_tid=tenant_id,
+                                          quantum_net_id=neutron_net_id)}
+    # TODO(salv-orlando): Now that we have async status synchronization
+    # this tag is perhaps not needed anymore
+    if shared:
+        lswitch_obj["tags"].append({"tag": "true",
+                                    "scope": "shared"})
+    if "tags" in kwargs:
+        lswitch_obj["tags"].extend(kwargs["tags"])
+    uri = _build_uri_path(LSWITCH_RESOURCE)
+    lswitch = do_request(HTTP_POST, uri, json.dumps(lswitch_obj),
+                         cluster=cluster)
+    LOG.debug(_("Created logical switch: %s"), lswitch['uuid'])
+    return lswitch
+
+
+def update_lswitch(cluster, lswitch_id, display_name,
+                   tenant_id=None, **kwargs):
+    uri = _build_uri_path(LSWITCH_RESOURCE, resource_id=lswitch_id)
+    lswitch_obj = {"display_name": utils.check_and_truncate(display_name),
+                   "tags": utils.get_tags(os_tid=tenant_id)}
+    if "tags" in kwargs:
+        lswitch_obj["tags"].extend(kwargs["tags"])
+    try:
+        return do_request(HTTP_PUT, uri, json.dumps(lswitch_obj),
+                          cluster=cluster)
+    except exception.NotFound as e:
+        LOG.error(_("Network not found, Error: %s"), str(e))
+        raise exception.NetworkNotFound(net_id=lswitch_id)
+
+
+def delete_network(cluster, net_id, lswitch_id):
+    delete_networks(cluster, net_id, [lswitch_id])
+
+
+#TODO(salvatore-orlando): Simplify and harmonize
+def delete_networks(cluster, net_id, lswitch_ids):
+    for ls_id in lswitch_ids:
+        path = "/ws.v1/lswitch/%s" % ls_id
+        try:
+            do_request(HTTP_DELETE, path, cluster=cluster)
+        except exception.NotFound as e:
+            LOG.error(_("Network not found, Error: %s"), str(e))
+            raise exception.NetworkNotFound(net_id=ls_id)
+
+
+def query_lswitch_lports(cluster, ls_uuid, fields="*",
+                         filters=None, relations=None):
+    # Fix filter for attachments
+    if filters and "attachment" in filters:
+        filters['attachment_vif_uuid'] = filters["attachment"]
+        del filters['attachment']
+    uri = _build_uri_path(LSWITCHPORT_RESOURCE, parent_resource_id=ls_uuid,
+                          fields=fields, filters=filters, relations=relations)
+    return do_request(HTTP_GET, uri, cluster=cluster)['results']
+
+
+def delete_port(cluster, switch, port):
+    uri = "/ws.v1/lswitch/" + switch + "/lport/" + port
+    try:
+        do_request(HTTP_DELETE, uri, cluster=cluster)
+    except exception.NotFound:
+        LOG.exception(_("Port or Network not found"))
+        raise exception.PortNotFoundOnNetwork(
+            net_id=switch, port_id=port)
+    except NvpApiClient.NvpApiException:
+        raise exception.NeutronException()
+
+
+def get_ports(cluster, networks=None, devices=None, tenants=None):
+    vm_filter_obsolete = ""
+    vm_filter = ""
+    tenant_filter = ""
+    # This is used when calling delete_network. Neutron checks to see if
+    # the network has any ports.
+    if networks:
+        # FIXME (Aaron) If we get more than one network_id this won't work
+        lswitch = networks[0]
+    else:
+        lswitch = "*"
+    if devices:
+        for device_id in devices:
+            vm_filter_obsolete = '&'.join(
+                ["tag_scope=vm_id",
+                 "tag=%s" % utils.device_id_to_vm_id(device_id,
+                                                     obfuscate=True),
+                 vm_filter_obsolete])
+            vm_filter = '&'.join(
+                ["tag_scope=vm_id",
+                 "tag=%s" % utils.device_id_to_vm_id(device_id),
+                 vm_filter])
+    if tenants:
+        for tenant in tenants:
+            tenant_filter = '&'.join(
+                ["tag_scope=os_tid",
+                 "tag=%s" % tenant,
+                 tenant_filter])
+
+    nsx_lports = {}
+    lport_fields_str = ("tags,admin_status_enabled,display_name,"
+                        "fabric_status_up")
+    try:
+        lport_query_path_obsolete = (
+            "/ws.v1/lswitch/%s/lport?fields=%s&%s%stag_scope=q_port_id"
+            "&relations=LogicalPortStatus" %
+            (lswitch, lport_fields_str, vm_filter_obsolete, tenant_filter))
+        lport_query_path = (
+            "/ws.v1/lswitch/%s/lport?fields=%s&%s%stag_scope=q_port_id"
+            "&relations=LogicalPortStatus" %
+            (lswitch, lport_fields_str, vm_filter, tenant_filter))
+        try:
+            # NOTE(armando-migliaccio): by querying with obsolete tag first
+            # current deployments won't take the performance hit of a double
+            # call. In release L-** or M-**, we might want to swap the calls
+            # as it's likely that ports with the new tag would outnumber the
+            # ones with the old tag
+            ports = get_all_query_pages(lport_query_path_obsolete, cluster)
+            if not ports:
+                ports = get_all_query_pages(lport_query_path, cluster)
+        except exception.NotFound:
+            LOG.warn(_("Lswitch %s not found in NSX"), lswitch)
+            ports = None
+
+        if ports:
+            for port in ports:
+                for tag in port["tags"]:
+                    if tag["scope"] == "q_port_id":
+                        nsx_lports[tag["tag"]] = port
+    except Exception:
+        err_msg = _("Unable to get ports")
+        LOG.exception(err_msg)
+        raise nvp_exc.NvpPluginException(err_msg=err_msg)
+    return nsx_lports
+
+
+def get_port_by_neutron_tag(cluster, lswitch_uuid, neutron_port_id):
+    """Get port by neutron tag.
+
+    Returns the NSX UUID of the logical port with tag q_port_id equal to
+    neutron_port_id or None if the port is not Found.
+    """
+    uri = _build_uri_path(LSWITCHPORT_RESOURCE,
+                          parent_resource_id=lswitch_uuid,
+                          fields='uuid',
+                          filters={'tag': neutron_port_id,
+                                   'tag_scope': 'q_port_id'})
+    LOG.debug(_("Looking for port with q_port_id tag '%(neutron_port_id)s' "
+                "on: '%(lswitch_uuid)s'"),
+              {'neutron_port_id': neutron_port_id,
+               'lswitch_uuid': lswitch_uuid})
+    res = do_request(HTTP_GET, uri, cluster=cluster)
+    num_results = len(res["results"])
+    if num_results >= 1:
+        if num_results > 1:
+            LOG.warn(_("Found '%(num_ports)d' ports with "
+                       "q_port_id tag: '%(neutron_port_id)s'. "
+                       "Only 1 was expected."),
+                     {'num_ports': num_results,
+                      'neutron_port_id': neutron_port_id})
+        return res["results"][0]
+
+
+def get_port(cluster, network, port, relations=None):
+    LOG.info(_("get_port() %(network)s %(port)s"),
+             {'network': network, 'port': port})
+    uri = "/ws.v1/lswitch/" + network + "/lport/" + port + "?"
+    if relations:
+        uri += "relations=%s" % relations
+    try:
+        return do_request(HTTP_GET, uri, cluster=cluster)
+    except exception.NotFound as e:
+        LOG.error(_("Port or Network not found, Error: %s"), str(e))
+        raise exception.PortNotFoundOnNetwork(
+            port_id=port, net_id=network)
+
+
+def update_port(cluster, lswitch_uuid, lport_uuid, neutron_port_id, tenant_id,
+                display_name, device_id, admin_status_enabled,
+                mac_address=None, fixed_ips=None, port_security_enabled=None,
+                security_profiles=None, queue_id=None,
+                mac_learning_enabled=None, allowed_address_pairs=None):
+    lport_obj = dict(
+        admin_status_enabled=admin_status_enabled,
+        display_name=utils.check_and_truncate(display_name),
+        tags=utils.get_tags(os_tid=tenant_id,
+                            q_port_id=neutron_port_id,
+                            vm_id=utils.device_id_to_vm_id(device_id)))
+
+    _configure_extensions(lport_obj, mac_address, fixed_ips,
+                          port_security_enabled, security_profiles,
+                          queue_id, mac_learning_enabled,
+                          allowed_address_pairs)
+
+    path = "/ws.v1/lswitch/" + lswitch_uuid + "/lport/" + lport_uuid
+    try:
+        result = do_request(HTTP_PUT, path, json.dumps(lport_obj),
+                            cluster=cluster)
+        LOG.debug(_("Updated logical port %(result)s "
+                    "on logical switch %(uuid)s"),
+                  {'result': result['uuid'], 'uuid': lswitch_uuid})
+        return result
+    except exception.NotFound as e:
+        LOG.error(_("Port or Network not found, Error: %s"), str(e))
+        raise exception.PortNotFoundOnNetwork(
+            port_id=lport_uuid, net_id=lswitch_uuid)
+
+
+def create_lport(cluster, lswitch_uuid, tenant_id, neutron_port_id,
+                 display_name, device_id, admin_status_enabled,
+                 mac_address=None, fixed_ips=None, port_security_enabled=None,
+                 security_profiles=None, queue_id=None,
+                 mac_learning_enabled=None, allowed_address_pairs=None):
+    """Creates a logical port on the assigned logical switch."""
+    display_name = utils.check_and_truncate(display_name)
+    lport_obj = dict(
+        admin_status_enabled=admin_status_enabled,
+        display_name=display_name,
+        tags=utils.get_tags(os_tid=tenant_id,
+                            q_port_id=neutron_port_id,
+                            vm_id=utils.device_id_to_vm_id(device_id))
+    )
+
+    _configure_extensions(lport_obj, mac_address, fixed_ips,
+                          port_security_enabled, security_profiles,
+                          queue_id, mac_learning_enabled,
+                          allowed_address_pairs)
+
+    path = _build_uri_path(LSWITCHPORT_RESOURCE,
+                           parent_resource_id=lswitch_uuid)
+    result = do_request(HTTP_POST, path, json.dumps(lport_obj),
+                        cluster=cluster)
+
+    LOG.debug(_("Created logical port %(result)s on logical switch %(uuid)s"),
+              {'result': result['uuid'], 'uuid': lswitch_uuid})
+    return result
+
+
+def get_port_status(cluster, lswitch_id, port_id):
+    """Retrieve the operational status of the port."""
+    try:
+        r = do_request(HTTP_GET,
+                       "/ws.v1/lswitch/%s/lport/%s/status" %
+                       (lswitch_id, port_id), cluster=cluster)
+    except exception.NotFound as e:
+        LOG.error(_("Port not found, Error: %s"), str(e))
+        raise exception.PortNotFoundOnNetwork(
+            port_id=port_id, net_id=lswitch_id)
+    if r['link_status_up'] is True:
+        return constants.PORT_STATUS_ACTIVE
+    else:
+        return constants.PORT_STATUS_DOWN
+
+
+def plug_interface(cluster, lswitch_id, port, port_type, attachment=None):
+    """Plug a VIF Attachment object in a logical port."""
+    lport_obj = {}
+    if attachment:
+        lport_obj["vif_uuid"] = attachment
+
+    lport_obj["type"] = port_type
+    return _plug_interface(cluster, lswitch_id, port, lport_obj)
index 3c5987063e085e2684565c36ca9af6d748211d8d..9c31132459d2024078dd09069bf2b01f6ed6e79d 100644 (file)
@@ -20,7 +20,6 @@
 # @author: Aaron Rosen, Nicira Networks, Inc.
 
 
-import hashlib
 import json
 
 #FIXME(danwent): I'd like this file to get to the point where it has
@@ -42,10 +41,10 @@ HTTP_DELETE = "DELETE"
 HTTP_PUT = "PUT"
 # Prefix to be used for all NVP API calls
 URI_PREFIX = "/ws.v1"
-# Resources exposed by NVP API
+
 LSWITCH_RESOURCE = "lswitch"
 LSWITCHPORT_RESOURCE = "lport/%s" % LSWITCH_RESOURCE
-GWSERVICE_RESOURCE = "gateway-service"
+
 # Current neutron version
 NEUTRON_VERSION = version_info.release_string()
 
@@ -54,27 +53,6 @@ NEUTRON_VERSION = version_info.release_string()
 # limit be raised in future versions
 MAX_PAGE_SIZE = 5000
 
-# TODO(bgh): it would be more efficient to use a bitmap
-taken_context_ids = []
-
-# XXX Only cache default for now
-_lqueue_cache = {}
-
-
-def device_id_to_vm_id(device_id, obfuscate=False):
-    # device_id can be longer than 40 characters, for example
-    # a device_id for a dhcp port is like the following:
-    #
-    # dhcp83b5fdeb-e3b4-5e18-ac5f-55161...80747326-47d7-46c2-a87a-cf6d5194877c
-    #
-    # To fit it into an NVP tag we need to hash it, however device_id
-    # used for ports associated to VM's are small enough so let's skip the
-    # hashing
-    if len(device_id) > utils.MAX_DISPLAY_NAME_LEN or obfuscate:
-        return hashlib.sha1(device_id).hexdigest()
-    else:
-        return device_id
-
 
 def _build_uri_path(resource,
                     resource_id=None,
@@ -160,411 +138,6 @@ def get_all_query_pages(path, c):
     return result_list
 
 
-# -------------------------------------------------------------------
-# Network functions
-# -------------------------------------------------------------------
-def get_lswitch_by_id(cluster, lswitch_id):
-    try:
-        lswitch_uri_path = _build_uri_path(
-            LSWITCH_RESOURCE, lswitch_id,
-            relations="LogicalSwitchStatus")
-        return do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
-    except exception.NotFound:
-        # FIXME(salv-orlando): this should not raise a neutron exception
-        raise exception.NetworkNotFound(net_id=lswitch_id)
-
-
-def get_lswitches(cluster, neutron_net_id):
-
-    def lookup_switches_by_tag():
-        # Fetch extra logical switches
-        lswitch_query_path = _build_uri_path(
-            LSWITCH_RESOURCE,
-            fields="uuid,display_name,tags,lport_count",
-            relations="LogicalSwitchStatus",
-            filters={'tag': neutron_net_id,
-                     'tag_scope': 'quantum_net_id'})
-        return get_all_query_pages(lswitch_query_path, cluster)
-
-    lswitch_uri_path = _build_uri_path(LSWITCH_RESOURCE, neutron_net_id,
-                                       relations="LogicalSwitchStatus")
-    results = []
-    try:
-        ls = do_request(HTTP_GET, lswitch_uri_path, cluster=cluster)
-        results.append(ls)
-        for tag in ls['tags']:
-            if (tag['scope'] == "multi_lswitch" and
-                tag['tag'] == "True"):
-                results.extend(lookup_switches_by_tag())
-    except exception.NotFound:
-        # This is legit if the neutron network was created using
-        # a post-Havana version of the plugin
-        results.extend(lookup_switches_by_tag())
-    if results:
-        return results
-    else:
-        raise exception.NetworkNotFound(net_id=neutron_net_id)
-
-
-def create_lswitch(cluster, neutron_net_id, tenant_id, display_name,
-                   transport_zones_config,
-                   shared=None,
-                   **kwargs):
-    # The tag scope adopts a slightly different naming convention for
-    # historical reasons
-    lswitch_obj = {"display_name": utils.check_and_truncate(display_name),
-                   "transport_zones": transport_zones_config,
-                   "tags": [{"tag": tenant_id, "scope": "os_tid"},
-                            {"tag": neutron_net_id, "scope": "quantum_net_id"},
-                            {"tag": NEUTRON_VERSION, "scope": "quantum"}]}
-    # TODO(salv-orlando): Now that we have async status synchronization
-    # this tag is perhaps not needed anymore
-    if shared:
-        lswitch_obj["tags"].append({"tag": "true",
-                                    "scope": "shared"})
-    if "tags" in kwargs:
-        lswitch_obj["tags"].extend(kwargs["tags"])
-    uri = _build_uri_path(LSWITCH_RESOURCE)
-    lswitch = do_request(HTTP_POST, uri, json.dumps(lswitch_obj),
-                         cluster=cluster)
-    LOG.debug(_("Created logical switch: %s"), lswitch['uuid'])
-    return lswitch
-
-
-def update_lswitch(cluster, lswitch_id, display_name,
-                   tenant_id=None, **kwargs):
-    uri = _build_uri_path(LSWITCH_RESOURCE, resource_id=lswitch_id)
-    lswitch_obj = {"display_name": utils.check_and_truncate(display_name),
-                   "tags": [{"tag": tenant_id, "scope": "os_tid"},
-                            {"tag": NEUTRON_VERSION, "scope": "quantum"}]}
-    if "tags" in kwargs:
-        lswitch_obj["tags"].extend(kwargs["tags"])
-    try:
-        return do_request(HTTP_PUT, uri, json.dumps(lswitch_obj),
-                          cluster=cluster)
-    except exception.NotFound as e:
-        LOG.error(_("Network not found, Error: %s"), str(e))
-        raise exception.NetworkNotFound(net_id=lswitch_id)
-
-
-def create_l2_gw_service(cluster, tenant_id, display_name, devices):
-    """Create a NVP Layer-2 Network Gateway Service.
-
-        :param cluster: The target NVP cluster
-        :param tenant_id: Identifier of the Openstack tenant for which
-        the gateway service.
-        :param display_name: Descriptive name of this gateway service
-        :param devices: List of transport node uuids (and network
-        interfaces on them) to use for the network gateway service
-        :raise NvpApiException: if there is a problem while communicating
-        with the NVP controller
-    """
-    tags = [{"tag": tenant_id, "scope": "os_tid"},
-            {"tag": NEUTRON_VERSION, "scope": "quantum"}]
-    # NOTE(salvatore-orlando): This is a little confusing, but device_id in
-    # NVP is actually the identifier a physical interface on the gateway
-    # device, which in the Neutron API is referred as interface_name
-    gateways = [{"transport_node_uuid": device['id'],
-                 "device_id": device['interface_name'],
-                 "type": "L2Gateway"} for device in devices]
-    gwservice_obj = {
-        "display_name": utils.check_and_truncate(display_name),
-        "tags": tags,
-        "gateways": gateways,
-        "type": "L2GatewayServiceConfig"
-    }
-    return do_request(
-        "POST", _build_uri_path(GWSERVICE_RESOURCE),
-        json.dumps(gwservice_obj), cluster=cluster)
-
-
-def delete_l2_gw_service(cluster, gateway_id):
-    do_request("DELETE", _build_uri_path(GWSERVICE_RESOURCE,
-                                         resource_id=gateway_id),
-               cluster=cluster)
-
-
-def get_l2_gw_service(cluster, gateway_id):
-    return do_request(
-        "GET", _build_uri_path(GWSERVICE_RESOURCE,
-                               resource_id=gateway_id),
-        cluster=cluster)
-
-
-def get_l2_gw_services(cluster, tenant_id=None,
-                       fields=None, filters=None):
-    actual_filters = dict(filters or {})
-    if tenant_id:
-        actual_filters['tag'] = tenant_id
-        actual_filters['tag_scope'] = 'os_tid'
-    return get_all_query_pages(
-        _build_uri_path(GWSERVICE_RESOURCE,
-                        filters=actual_filters),
-        cluster)
-
-
-def update_l2_gw_service(cluster, gateway_id, display_name):
-    # TODO(salvatore-orlando): Allow updates for gateways too
-    gwservice_obj = get_l2_gw_service(cluster, gateway_id)
-    if not display_name:
-        # Nothing to update
-        return gwservice_obj
-    gwservice_obj["display_name"] = utils.check_and_truncate(display_name)
-    return do_request("PUT", _build_uri_path(GWSERVICE_RESOURCE,
-                                             resource_id=gateway_id),
-                      json.dumps(gwservice_obj), cluster=cluster)
-
-
-def delete_network(cluster, net_id, lswitch_id):
-    delete_networks(cluster, net_id, [lswitch_id])
-
-
-#TODO(salvatore-orlando): Simplify and harmonize
-def delete_networks(cluster, net_id, lswitch_ids):
-    for ls_id in lswitch_ids:
-        path = "/ws.v1/lswitch/%s" % ls_id
-        try:
-            do_request(HTTP_DELETE, path, cluster=cluster)
-        except exception.NotFound as e:
-            LOG.error(_("Network not found, Error: %s"), str(e))
-            raise exception.NetworkNotFound(net_id=ls_id)
-
-
-def query_lswitch_lports(cluster, ls_uuid, fields="*",
-                         filters=None, relations=None):
-    # Fix filter for attachments
-    if filters and "attachment" in filters:
-        filters['attachment_vif_uuid'] = filters["attachment"]
-        del filters['attachment']
-    uri = _build_uri_path(LSWITCHPORT_RESOURCE, parent_resource_id=ls_uuid,
-                          fields=fields, filters=filters, relations=relations)
-    return do_request(HTTP_GET, uri, cluster=cluster)['results']
-
-
-def delete_port(cluster, switch, port):
-    uri = "/ws.v1/lswitch/" + switch + "/lport/" + port
-    try:
-        do_request(HTTP_DELETE, uri, cluster=cluster)
-    except exception.NotFound:
-        LOG.exception(_("Port or Network not found"))
-        raise exception.PortNotFoundOnNetwork(
-            net_id=switch, port_id=port)
-    except NvpApiClient.NvpApiException:
-        raise exception.NeutronException()
-
-
-def get_ports(cluster, networks=None, devices=None, tenants=None):
-    vm_filter_obsolete = ""
-    vm_filter = ""
-    tenant_filter = ""
-    # This is used when calling delete_network. Neutron checks to see if
-    # the network has any ports.
-    if networks:
-        # FIXME (Aaron) If we get more than one network_id this won't work
-        lswitch = networks[0]
-    else:
-        lswitch = "*"
-    if devices:
-        for device_id in devices:
-            vm_filter_obsolete = '&'.join(
-                ["tag_scope=vm_id",
-                 "tag=%s" % device_id_to_vm_id(device_id, obfuscate=True),
-                 vm_filter_obsolete])
-            vm_filter = '&'.join(
-                ["tag_scope=vm_id",
-                 "tag=%s" % device_id_to_vm_id(device_id),
-                 vm_filter])
-    if tenants:
-        for tenant in tenants:
-            tenant_filter = '&'.join(
-                ["tag_scope=os_tid",
-                 "tag=%s" % tenant,
-                 tenant_filter])
-
-    nvp_lports = {}
-    lport_fields_str = ("tags,admin_status_enabled,display_name,"
-                        "fabric_status_up")
-    try:
-        lport_query_path_obsolete = (
-            "/ws.v1/lswitch/%s/lport?fields=%s&%s%stag_scope=q_port_id"
-            "&relations=LogicalPortStatus" %
-            (lswitch, lport_fields_str, vm_filter_obsolete, tenant_filter))
-        lport_query_path = (
-            "/ws.v1/lswitch/%s/lport?fields=%s&%s%stag_scope=q_port_id"
-            "&relations=LogicalPortStatus" %
-            (lswitch, lport_fields_str, vm_filter, tenant_filter))
-        try:
-            # NOTE(armando-migliaccio): by querying with obsolete tag first
-            # current deployments won't take the performance hit of a double
-            # call. In release L-** or M-**, we might want to swap the calls
-            # as it's likely that ports with the new tag would outnumber the
-            # ones with the old tag
-            ports = get_all_query_pages(lport_query_path_obsolete, cluster)
-            if not ports:
-                ports = get_all_query_pages(lport_query_path, cluster)
-        except exception.NotFound:
-            LOG.warn(_("Lswitch %s not found in NVP"), lswitch)
-            ports = None
-
-        if ports:
-            for port in ports:
-                for tag in port["tags"]:
-                    if tag["scope"] == "q_port_id":
-                        nvp_lports[tag["tag"]] = port
-    except Exception:
-        err_msg = _("Unable to get ports")
-        LOG.exception(err_msg)
-        raise nvp_exc.NvpPluginException(err_msg=err_msg)
-    return nvp_lports
-
-
-def get_port_by_neutron_tag(cluster, lswitch_uuid, neutron_port_id):
-    """Get port by neutron tag.
-
-    Returns the NVP UUID of the logical port with tag q_port_id equal to
-    neutron_port_id or None if the port is not Found.
-    """
-    uri = _build_uri_path(LSWITCHPORT_RESOURCE,
-                          parent_resource_id=lswitch_uuid,
-                          fields='uuid',
-                          filters={'tag': neutron_port_id,
-                                   'tag_scope': 'q_port_id'})
-    LOG.debug(_("Looking for port with q_port_id tag '%(neutron_port_id)s' "
-                "on: '%(lswitch_uuid)s'"),
-              {'neutron_port_id': neutron_port_id,
-               'lswitch_uuid': lswitch_uuid})
-    res = do_request(HTTP_GET, uri, cluster=cluster)
-    num_results = len(res["results"])
-    if num_results >= 1:
-        if num_results > 1:
-            LOG.warn(_("Found '%(num_ports)d' ports with "
-                       "q_port_id tag: '%(neutron_port_id)s'. "
-                       "Only 1 was expected."),
-                     {'num_ports': num_results,
-                      'neutron_port_id': neutron_port_id})
-        return res["results"][0]
-
-
-def get_port(cluster, network, port, relations=None):
-    LOG.info(_("get_port() %(network)s %(port)s"),
-             {'network': network, 'port': port})
-    uri = "/ws.v1/lswitch/" + network + "/lport/" + port + "?"
-    if relations:
-        uri += "relations=%s" % relations
-    try:
-        return do_request(HTTP_GET, uri, cluster=cluster)
-    except exception.NotFound as e:
-        LOG.error(_("Port or Network not found, Error: %s"), str(e))
-        raise exception.PortNotFoundOnNetwork(
-            port_id=port, net_id=network)
-
-
-def _configure_extensions(lport_obj, mac_address, fixed_ips,
-                          port_security_enabled, security_profiles,
-                          queue_id, mac_learning_enabled,
-                          allowed_address_pairs):
-    lport_obj['allowed_address_pairs'] = []
-    if port_security_enabled:
-        for fixed_ip in fixed_ips:
-            ip_address = fixed_ip.get('ip_address')
-            if ip_address:
-                lport_obj['allowed_address_pairs'].append(
-                    {'mac_address': mac_address, 'ip_address': ip_address})
-        # add address pair allowing src_ip 0.0.0.0 to leave
-        # this is required for outgoing dhcp request
-        lport_obj["allowed_address_pairs"].append(
-            {"mac_address": mac_address,
-             "ip_address": "0.0.0.0"})
-    lport_obj['security_profiles'] = list(security_profiles or [])
-    lport_obj['queue_uuid'] = queue_id
-    if mac_learning_enabled is not None:
-        lport_obj["mac_learning"] = mac_learning_enabled
-        lport_obj["type"] = "LogicalSwitchPortConfig"
-    for address_pair in list(allowed_address_pairs or []):
-        lport_obj['allowed_address_pairs'].append(
-            {'mac_address': address_pair['mac_address'],
-             'ip_address': address_pair['ip_address']})
-
-
-def update_port(cluster, lswitch_uuid, lport_uuid, neutron_port_id, tenant_id,
-                display_name, device_id, admin_status_enabled,
-                mac_address=None, fixed_ips=None, port_security_enabled=None,
-                security_profiles=None, queue_id=None,
-                mac_learning_enabled=None, allowed_address_pairs=None):
-    lport_obj = dict(
-        admin_status_enabled=admin_status_enabled,
-        display_name=utils.check_and_truncate(display_name),
-        tags=[dict(scope='os_tid', tag=tenant_id),
-              dict(scope='q_port_id', tag=neutron_port_id),
-              dict(scope='vm_id', tag=device_id_to_vm_id(device_id)),
-              dict(scope='quantum', tag=NEUTRON_VERSION)])
-
-    _configure_extensions(lport_obj, mac_address, fixed_ips,
-                          port_security_enabled, security_profiles,
-                          queue_id, mac_learning_enabled,
-                          allowed_address_pairs)
-
-    path = "/ws.v1/lswitch/" + lswitch_uuid + "/lport/" + lport_uuid
-    try:
-        result = do_request(HTTP_PUT, path, json.dumps(lport_obj),
-                            cluster=cluster)
-        LOG.debug(_("Updated logical port %(result)s "
-                    "on logical switch %(uuid)s"),
-                  {'result': result['uuid'], 'uuid': lswitch_uuid})
-        return result
-    except exception.NotFound as e:
-        LOG.error(_("Port or Network not found, Error: %s"), str(e))
-        raise exception.PortNotFoundOnNetwork(
-            port_id=lport_uuid, net_id=lswitch_uuid)
-
-
-def create_lport(cluster, lswitch_uuid, tenant_id, neutron_port_id,
-                 display_name, device_id, admin_status_enabled,
-                 mac_address=None, fixed_ips=None, port_security_enabled=None,
-                 security_profiles=None, queue_id=None,
-                 mac_learning_enabled=None, allowed_address_pairs=None):
-    """Creates a logical port on the assigned logical switch."""
-    display_name = utils.check_and_truncate(display_name)
-    lport_obj = dict(
-        admin_status_enabled=admin_status_enabled,
-        display_name=display_name,
-        tags=[dict(scope='os_tid', tag=tenant_id),
-              dict(scope='q_port_id', tag=neutron_port_id),
-              dict(scope='vm_id', tag=device_id_to_vm_id(device_id)),
-              dict(scope='quantum', tag=NEUTRON_VERSION)],
-    )
-
-    _configure_extensions(lport_obj, mac_address, fixed_ips,
-                          port_security_enabled, security_profiles,
-                          queue_id, mac_learning_enabled,
-                          allowed_address_pairs)
-
-    path = _build_uri_path(LSWITCHPORT_RESOURCE,
-                           parent_resource_id=lswitch_uuid)
-    result = do_request(HTTP_POST, path, json.dumps(lport_obj),
-                        cluster=cluster)
-
-    LOG.debug(_("Created logical port %(result)s on logical switch %(uuid)s"),
-              {'result': result['uuid'], 'uuid': lswitch_uuid})
-    return result
-
-
-def get_port_status(cluster, lswitch_id, port_id):
-    """Retrieve the operational status of the port."""
-    try:
-        r = do_request(HTTP_GET,
-                       "/ws.v1/lswitch/%s/lport/%s/status" %
-                       (lswitch_id, port_id), cluster=cluster)
-    except exception.NotFound as e:
-        LOG.error(_("Port not found, Error: %s"), str(e))
-        raise exception.PortNotFoundOnNetwork(
-            port_id=port_id, net_id=lswitch_id)
-    if r['link_status_up'] is True:
-        return constants.PORT_STATUS_ACTIVE
-    else:
-        return constants.PORT_STATUS_DOWN
-
-
 def _plug_interface(cluster, lswitch_id, lport_id, att_obj):
     uri = _build_uri_path(LSWITCHPORT_RESOURCE, lport_id, lswitch_id,
                           is_attachment=True)
@@ -572,25 +145,6 @@ def _plug_interface(cluster, lswitch_id, lport_id, att_obj):
                       cluster=cluster)
 
 
-def plug_l2_gw_service(cluster, lswitch_id, lport_id,
-                       gateway_id, vlan_id=None):
-    """Plug a Layer-2 Gateway Attachment object in a logical port."""
-    att_obj = {'type': 'L2GatewayAttachment',
-               'l2_gateway_service_uuid': gateway_id}
-    if vlan_id:
-        att_obj['vlan_id'] = vlan_id
-    return _plug_interface(cluster, lswitch_id, lport_id, att_obj)
-
-
-def plug_interface(cluster, lswitch_id, port, type, attachment=None):
-    """Plug a VIF Attachment object in a logical port."""
-    lport_obj = {}
-    if attachment:
-        lport_obj["vif_uuid"] = attachment
-
-    lport_obj["type"] = type
-    return _plug_interface(cluster, lswitch_id, port, lport_obj)
-
 #------------------------------------------------------------------------------
 # Security Profile convenience functions.
 #------------------------------------------------------------------------------
diff --git a/neutron/tests/unit/nicira/nsxlib/test_l2gateway.py b/neutron/tests/unit/nicira/nsxlib/test_l2gateway.py
new file mode 100644 (file)
index 0000000..ab3c279
--- /dev/null
@@ -0,0 +1,147 @@
+# Copyright (c) 2014 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from neutron.plugins.nicira.nsxlib import l2gateway as l2gwlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
+from neutron.plugins.nicira import nvplib
+from neutron.tests.unit.nicira.test_nvplib import NsxlibNegativeBaseTestCase
+from neutron.tests.unit.nicira.test_nvplib import NvplibTestCase
+from neutron.tests.unit import test_api_v2
+
+_uuid = test_api_v2._uuid
+
+
+class L2GatewayNegativeTestCase(NsxlibNegativeBaseTestCase):
+
+    def test_create_l2_gw_service_on_failure(self):
+        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+                          l2gwlib.create_l2_gw_service,
+                          self.fake_cluster,
+                          'fake-tenant',
+                          'fake-gateway',
+                          [{'id': _uuid(),
+                           'interface_name': 'xxx'}])
+
+    def test_delete_l2_gw_service_on_failure(self):
+        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+                          l2gwlib.delete_l2_gw_service,
+                          self.fake_cluster,
+                          'fake-gateway')
+
+    def test_get_l2_gw_service_on_failure(self):
+        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+                          l2gwlib.get_l2_gw_service,
+                          self.fake_cluster,
+                          'fake-gateway')
+
+    def test_update_l2_gw_service_on_failure(self):
+        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
+                          l2gwlib.update_l2_gw_service,
+                          self.fake_cluster,
+                          'fake-gateway',
+                          'pluto')
+
+
+class L2GatewayTestCase(NvplibTestCase):
+
+    def _create_gw_service(self, node_uuid, display_name,
+                           tenant_id='fake_tenant'):
+        return l2gwlib.create_l2_gw_service(self.fake_cluster,
+                                            tenant_id,
+                                            display_name,
+                                            [{'id': node_uuid,
+                                              'interface_name': 'xxx'}])
+
+    def test_create_l2_gw_service(self):
+        display_name = 'fake-gateway'
+        node_uuid = _uuid()
+        response = self._create_gw_service(node_uuid, display_name)
+        self.assertEqual(response.get('type'), 'L2GatewayServiceConfig')
+        self.assertEqual(response.get('display_name'), display_name)
+        gateways = response.get('gateways', [])
+        self.assertEqual(len(gateways), 1)
+        self.assertEqual(gateways[0]['type'], 'L2Gateway')
+        self.assertEqual(gateways[0]['device_id'], 'xxx')
+        self.assertEqual(gateways[0]['transport_node_uuid'], node_uuid)
+
+    def test_update_l2_gw_service(self):
+        display_name = 'fake-gateway'
+        new_display_name = 'still-fake-gateway'
+        node_uuid = _uuid()
+        res1 = self._create_gw_service(node_uuid, display_name)
+        gw_id = res1['uuid']
+        res2 = l2gwlib.update_l2_gw_service(
+            self.fake_cluster, gw_id, new_display_name)
+        self.assertEqual(res2['display_name'], new_display_name)
+
+    def test_get_l2_gw_service(self):
+        display_name = 'fake-gateway'
+        node_uuid = _uuid()
+        gw_id = self._create_gw_service(node_uuid, display_name)['uuid']
+        response = l2gwlib.get_l2_gw_service(self.fake_cluster, gw_id)
+        self.assertEqual(response.get('type'), 'L2GatewayServiceConfig')
+        self.assertEqual(response.get('display_name'), display_name)
+        self.assertEqual(response.get('uuid'), gw_id)
+
+    def test_list_l2_gw_service(self):
+        gw_ids = []
+        for name in ('fake-1', 'fake-2'):
+            gw_ids.append(self._create_gw_service(_uuid(), name)['uuid'])
+        results = l2gwlib.get_l2_gw_services(self.fake_cluster)
+        self.assertEqual(len(results), 2)
+        self.assertEqual(sorted(gw_ids), sorted([r['uuid'] for r in results]))
+
+    def test_list_l2_gw_service_by_tenant(self):
+        gw_ids = [self._create_gw_service(
+                  _uuid(), name, tenant_id=name)['uuid']
+                  for name in ('fake-1', 'fake-2')]
+        results = l2gwlib.get_l2_gw_services(self.fake_cluster,
+                                             tenant_id='fake-1')
+        self.assertEqual(len(results), 1)
+        self.assertEqual(results[0]['uuid'], gw_ids[0])
+
+    def test_delete_l2_gw_service(self):
+        display_name = 'fake-gateway'
+        node_uuid = _uuid()
+        gw_id = self._create_gw_service(node_uuid, display_name)['uuid']
+        l2gwlib.delete_l2_gw_service(self.fake_cluster, gw_id)
+        results = l2gwlib.get_l2_gw_services(self.fake_cluster)
+        self.assertEqual(len(results), 0)
+
+    def test_plug_l2_gw_port_attachment(self):
+        tenant_id = 'pippo'
+        node_uuid = _uuid()
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(
+            self.fake_cluster, _uuid(), tenant_id,
+            'fake-switch', transport_zones_config)
+        gw_id = self._create_gw_service(node_uuid, 'fake-gw')['uuid']
+        lport = switchlib.create_lport(
+            self.fake_cluster, lswitch['uuid'], tenant_id, _uuid(),
+            'fake-gw-port', gw_id, True)
+        l2gwlib.plug_l2_gw_service(
+            self.fake_cluster, lswitch['uuid'],
+            lport['uuid'], gw_id)
+        uri = nvplib._build_uri_path(nvplib.LSWITCHPORT_RESOURCE,
+                                     lport['uuid'],
+                                     lswitch['uuid'],
+                                     is_attachment=True)
+        resp_obj = nvplib.do_request("GET", uri,
+                                     cluster=self.fake_cluster)
+        self.assertIn('LogicalPortAttachment', resp_obj)
+        self.assertEqual(resp_obj['LogicalPortAttachment']['type'],
+                         'L2GatewayAttachment')
index 59a9e74d6172de4e011b81c46bc3cd121f4b9292..47f3ee2148ca251e95e7c1806a2c1488337aa6c7 100644 (file)
@@ -20,6 +20,7 @@ from neutron.common import exceptions
 from neutron.openstack.common import uuidutils
 from neutron.plugins.nicira.common import exceptions as nvp_exc
 from neutron.plugins.nicira.nsxlib import router as routerlib
+from neutron.plugins.nicira.nsxlib import switch as switchlib
 from neutron.plugins.nicira import NvpApiClient
 from neutron.plugins.nicira import nvplib
 from neutron.tests.unit.nicira.test_nvplib import NsxlibNegativeBaseTestCase
@@ -688,13 +689,13 @@ class TestLogicalRouters(NvplibTestCase):
         tenant_id = 'pippo'
         transport_zones_config = [{'zone_uuid': _uuid(),
                                    'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        _uuid(),
-                                        tenant_id, 'fake-switch',
-                                        transport_zones_config)
-        lport = nvplib.create_lport(self.fake_cluster, lswitch['uuid'],
-                                    tenant_id, 'xyz',
-                                    'name', 'device_id', True)
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           _uuid(),
+                                           tenant_id, 'fake-switch',
+                                           transport_zones_config)
+        lport = switchlib.create_lport(self.fake_cluster, lswitch['uuid'],
+                                       tenant_id, 'xyz',
+                                       'name', 'device_id', True)
         lrouter = routerlib.create_lrouter(self.fake_cluster,
                                            uuidutils.generate_uuid(),
                                            tenant_id,
diff --git a/neutron/tests/unit/nicira/nsxlib/test_switch.py b/neutron/tests/unit/nicira/nsxlib/test_switch.py
new file mode 100644 (file)
index 0000000..573a06b
--- /dev/null
@@ -0,0 +1,289 @@
+# Copyright (c) 2014 VMware, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import hashlib
+import mock
+
+from neutron.common import constants
+from neutron.common import exceptions
+from neutron.plugins.nicira.common import utils
+from neutron.plugins.nicira.nsxlib import switch as switchlib
+from neutron.tests.unit.nicira.test_nvplib import NvplibTestCase
+from neutron.tests.unit import test_api_v2
+
+_uuid = test_api_v2._uuid
+
+
+class LogicalSwitchesTestCase(NvplibTestCase):
+
+    def test_create_and_get_lswitches_single(self):
+        tenant_id = 'pippo'
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           _uuid(),
+                                           tenant_id,
+                                           'fake-switch',
+                                           transport_zones_config)
+        res_lswitch = switchlib.get_lswitches(self.fake_cluster,
+                                              lswitch['uuid'])
+        self.assertEqual(len(res_lswitch), 1)
+        self.assertEqual(res_lswitch[0]['uuid'],
+                         lswitch['uuid'])
+
+    def test_create_and_get_lswitches_single_name_exceeds_40_chars(self):
+        tenant_id = 'pippo'
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           tenant_id,
+                                           _uuid(),
+                                           '*' * 50,
+                                           transport_zones_config)
+        res_lswitch = switchlib.get_lswitches(self.fake_cluster,
+                                              lswitch['uuid'])
+        self.assertEqual(len(res_lswitch), 1)
+        self.assertEqual(res_lswitch[0]['uuid'], lswitch['uuid'])
+        self.assertEqual(res_lswitch[0]['display_name'], '*' * 40)
+
+    def test_create_and_get_lswitches_multiple(self):
+        tenant_id = 'pippo'
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        network_id = _uuid()
+        main_lswitch = switchlib.create_lswitch(
+            self.fake_cluster, network_id,
+            tenant_id, 'fake-switch', transport_zones_config,
+            tags=[{'scope': 'multi_lswitch', 'tag': 'True'}])
+        # Create secondary lswitch
+        second_lswitch = switchlib.create_lswitch(
+            self.fake_cluster, network_id,
+            tenant_id, 'fake-switch-2', transport_zones_config)
+        res_lswitch = switchlib.get_lswitches(self.fake_cluster,
+                                              network_id)
+        self.assertEqual(len(res_lswitch), 2)
+        switch_uuids = [ls['uuid'] for ls in res_lswitch]
+        self.assertIn(main_lswitch['uuid'], switch_uuids)
+        self.assertIn(second_lswitch['uuid'], switch_uuids)
+        for ls in res_lswitch:
+            if ls['uuid'] == main_lswitch['uuid']:
+                main_ls = ls
+            else:
+                second_ls = ls
+        main_ls_tags = self._build_tag_dict(main_ls['tags'])
+        second_ls_tags = self._build_tag_dict(second_ls['tags'])
+        self.assertIn('multi_lswitch', main_ls_tags)
+        self.assertNotIn('multi_lswitch', second_ls_tags)
+        self.assertIn('quantum_net_id', main_ls_tags)
+        self.assertIn('quantum_net_id', second_ls_tags)
+        self.assertEqual(main_ls_tags['quantum_net_id'],
+                         network_id)
+        self.assertEqual(second_ls_tags['quantum_net_id'],
+                         network_id)
+
+    def test_update_lswitch(self):
+        new_name = 'new-name'
+        new_tags = [{'scope': 'new_tag', 'tag': 'xxx'}]
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           _uuid(),
+                                           'pippo',
+                                           'fake-switch',
+                                           transport_zones_config)
+        switchlib.update_lswitch(self.fake_cluster, lswitch['uuid'],
+                                 new_name, tags=new_tags)
+        res_lswitch = switchlib.get_lswitches(self.fake_cluster,
+                                              lswitch['uuid'])
+        self.assertEqual(len(res_lswitch), 1)
+        self.assertEqual(res_lswitch[0]['display_name'], new_name)
+        switch_tags = self._build_tag_dict(res_lswitch[0]['tags'])
+        self.assertIn('new_tag', switch_tags)
+        self.assertEqual(switch_tags['new_tag'], 'xxx')
+
+    def test_update_non_existing_lswitch_raises(self):
+        self.assertRaises(exceptions.NetworkNotFound,
+                          switchlib.update_lswitch,
+                          self.fake_cluster, 'whatever',
+                          'foo', 'bar')
+
+    def test_delete_networks(self):
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           _uuid(),
+                                           'pippo',
+                                           'fake-switch',
+                                           transport_zones_config)
+        switchlib.delete_networks(self.fake_cluster, lswitch['uuid'],
+                                  [lswitch['uuid']])
+        self.assertRaises(exceptions.NotFound,
+                          switchlib.get_lswitches,
+                          self.fake_cluster,
+                          lswitch['uuid'])
+
+    def test_delete_non_existing_lswitch_raises(self):
+        self.assertRaises(exceptions.NetworkNotFound,
+                          switchlib.delete_networks,
+                          self.fake_cluster, 'whatever', ['whatever'])
+
+
+class LogicalPortsTestCase(NvplibTestCase):
+
+    def _create_switch_and_port(self, tenant_id='pippo',
+                                neutron_port_id='whatever',
+                                name='name', device_id='device_id'):
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(self.fake_cluster,
+                                           _uuid(), tenant_id, 'fake-switch',
+                                           transport_zones_config)
+        lport = switchlib.create_lport(self.fake_cluster, lswitch['uuid'],
+                                       tenant_id, neutron_port_id,
+                                       name, device_id, True)
+        return lswitch, lport
+
+    def test_create_and_get_port(self):
+        lswitch, lport = self._create_switch_and_port()
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'])
+        self.assertEqual(lport['uuid'], lport_res['uuid'])
+        # Try again with relation
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'],
+                                       relations='LogicalPortStatus')
+        self.assertEqual(lport['uuid'], lport_res['uuid'])
+
+    def test_plug_interface(self):
+        lswitch, lport = self._create_switch_and_port()
+        switchlib.plug_interface(self.fake_cluster, lswitch['uuid'],
+                                 lport['uuid'], 'VifAttachment', 'fake')
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'])
+        self.assertEqual(lport['uuid'], lport_res['uuid'])
+
+    def test_get_port_by_tag(self):
+        lswitch, lport = self._create_switch_and_port()
+        lport2 = switchlib.get_port_by_neutron_tag(self.fake_cluster,
+                                                   lswitch['uuid'],
+                                                   'whatever')
+        self.assertIsNotNone(lport2)
+        self.assertEqual(lport['uuid'], lport2['uuid'])
+
+    def test_get_port_by_tag_not_found_returns_None(self):
+        tenant_id = 'pippo'
+        neutron_port_id = 'whatever'
+        transport_zones_config = [{'zone_uuid': _uuid(),
+                                   'transport_type': 'stt'}]
+        lswitch = switchlib.create_lswitch(
+            self.fake_cluster, tenant_id, _uuid(),
+            'fake-switch', transport_zones_config)
+        lport = switchlib.get_port_by_neutron_tag(
+            self.fake_cluster, lswitch['uuid'], neutron_port_id)
+        self.assertIsNone(lport)
+
+    def test_get_port_status(self):
+        lswitch, lport = self._create_switch_and_port()
+        status = switchlib.get_port_status(
+            self.fake_cluster, lswitch['uuid'], lport['uuid'])
+        self.assertEqual(constants.PORT_STATUS_ACTIVE, status)
+
+    def test_get_port_status_non_existent_raises(self):
+        self.assertRaises(exceptions.PortNotFoundOnNetwork,
+                          switchlib.get_port_status,
+                          self.fake_cluster,
+                          'boo', 'boo')
+
+    def test_update_port(self):
+        lswitch, lport = self._create_switch_and_port()
+        switchlib.update_port(
+            self.fake_cluster, lswitch['uuid'], lport['uuid'],
+            'neutron_port_id', 'pippo2', 'new_name', 'device_id', False)
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'])
+        self.assertEqual(lport['uuid'], lport_res['uuid'])
+        self.assertEqual('new_name', lport_res['display_name'])
+        self.assertEqual('False', lport_res['admin_status_enabled'])
+        port_tags = self._build_tag_dict(lport_res['tags'])
+        self.assertIn('os_tid', port_tags)
+        self.assertIn('q_port_id', port_tags)
+        self.assertIn('vm_id', port_tags)
+
+    def test_create_port_device_id_less_than_40_chars(self):
+        lswitch, lport = self._create_switch_and_port()
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'])
+        port_tags = self._build_tag_dict(lport_res['tags'])
+        self.assertEqual('device_id', port_tags['vm_id'])
+
+    def test_create_port_device_id_more_than_40_chars(self):
+        dev_id = "this_is_a_very_long_device_id_with_lots_of_characters"
+        lswitch, lport = self._create_switch_and_port(device_id=dev_id)
+        lport_res = switchlib.get_port(self.fake_cluster,
+                                       lswitch['uuid'], lport['uuid'])
+        port_tags = self._build_tag_dict(lport_res['tags'])
+        self.assertNotEqual(len(dev_id), len(port_tags['vm_id']))
+
+    def test_get_ports_with_obsolete_and_new_vm_id_tag(self):
+        def obsolete(device_id, obfuscate=False):
+            return hashlib.sha1(device_id).hexdigest()
+
+        with mock.patch.object(utils, 'device_id_to_vm_id', new=obsolete):
+            dev_id1 = "short-dev-id-1"
+            _, lport1 = self._create_switch_and_port(device_id=dev_id1)
+        dev_id2 = "short-dev-id-2"
+        _, lport2 = self._create_switch_and_port(device_id=dev_id2)
+
+        lports = switchlib.get_ports(self.fake_cluster, None, [dev_id1])
+        port_tags = self._build_tag_dict(lports['whatever']['tags'])
+        self.assertNotEqual(dev_id1, port_tags['vm_id'])
+
+        lports = switchlib.get_ports(self.fake_cluster, None, [dev_id2])
+        port_tags = self._build_tag_dict(lports['whatever']['tags'])
+        self.assertEqual(dev_id2, port_tags['vm_id'])
+
+    def test_update_non_existent_port_raises(self):
+        self.assertRaises(exceptions.PortNotFoundOnNetwork,
+                          switchlib.update_port, self.fake_cluster,
+                          'boo', 'boo', 'boo', 'boo', 'boo', 'boo', False)
+
+    def test_delete_port(self):
+        lswitch, lport = self._create_switch_and_port()
+        switchlib.delete_port(self.fake_cluster,
+                              lswitch['uuid'], lport['uuid'])
+        self.assertRaises(exceptions.PortNotFoundOnNetwork,
+                          switchlib.get_port, self.fake_cluster,
+                          lswitch['uuid'], lport['uuid'])
+
+    def test_delete_non_existent_port_raises(self):
+        lswitch = self._create_switch_and_port()[0]
+        self.assertRaises(exceptions.PortNotFoundOnNetwork,
+                          switchlib.delete_port, self.fake_cluster,
+                          lswitch['uuid'], 'bad_port_uuid')
+
+    def test_query_lswitch_ports(self):
+        lswitch, lport = self._create_switch_and_port()
+        switch_port_uuids = [
+            switchlib.create_lport(
+                self.fake_cluster, lswitch['uuid'], 'pippo', 'qportid-%s' % k,
+                'port-%s' % k, 'deviceid-%s' % k, True)['uuid']
+            for k in range(2)]
+        switch_port_uuids.append(lport['uuid'])
+        ports = switchlib.query_lswitch_lports(
+            self.fake_cluster, lswitch['uuid'])
+        self.assertEqual(len(ports), 3)
+        for res_port in ports:
+            self.assertIn(res_port['uuid'], switch_port_uuids)
index 0be43af5a51cd70937ba01cf03b1551232392c57..0adce9215ca2c1e7de6c2bd37c0c78f4d745f7c5 100644 (file)
@@ -435,7 +435,8 @@ class LsnManagerTestCase(base.BaseTestCase):
         self.mock_lsn_api.lsn_port_create.return_value = self.lsn_port_id
         with mock.patch.object(
             self.manager, 'lsn_get', return_value=self.lsn_id):
-            with mock.patch.object(lsn_man.nsxlib, 'get_port_by_neutron_tag'):
+            with mock.patch.object(lsn_man.switch_api,
+                                   'get_port_by_neutron_tag'):
                 expected = self.manager.lsn_port_dhcp_setup(
                     mock.ANY, mock.ANY, mock.ANY, mock.ANY, subnet_config=sub)
                 self.assertEqual(
@@ -453,7 +454,8 @@ class LsnManagerTestCase(base.BaseTestCase):
             self.assertEqual(1, f.call_count)
 
     def test_lsn_port_dhcp_setup_with_not_found(self):
-        with mock.patch.object(lsn_man.nsxlib, 'get_port_by_neutron_tag') as f:
+        with mock.patch.object(lsn_man.switch_api,
+                               'get_port_by_neutron_tag') as f:
             f.side_effect = n_exc.NotFound
             self.assertRaises(p_exc.PortConfigurationError,
                               self.manager.lsn_port_dhcp_setup,
@@ -462,7 +464,7 @@ class LsnManagerTestCase(base.BaseTestCase):
     def test_lsn_port_dhcp_setup_with_conflict(self):
         self.mock_lsn_api.lsn_port_plug_network.side_effect = (
             p_exc.LsnConfigurationConflict(lsn_id=self.lsn_id))
-        with mock.patch.object(lsn_man.nsxlib, 'get_port_by_neutron_tag'):
+        with mock.patch.object(lsn_man.switch_api, 'get_port_by_neutron_tag'):
             with mock.patch.object(self.manager, 'lsn_port_delete') as g:
                 self.assertRaises(p_exc.PortConfigurationError,
                                   self.manager.lsn_port_dhcp_setup,
@@ -558,7 +560,7 @@ class LsnManagerTestCase(base.BaseTestCase):
             'network_id': self.net_id,
             'tenant_id': self.tenant_id
         }
-        with mock.patch.object(lsn_man.nsxlib, 'create_lport') as f:
+        with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
             f.return_value = {'uuid': self.port_id}
             self.manager.lsn_port_metadata_setup(mock.ANY, self.lsn_id, subnet)
             self.assertEqual(1, self.mock_lsn_api.lsn_port_create.call_count)
@@ -572,7 +574,7 @@ class LsnManagerTestCase(base.BaseTestCase):
             'network_id': self.net_id,
             'tenant_id': self.tenant_id
         }
-        with mock.patch.object(lsn_man.nsxlib, 'create_lport') as f:
+        with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
             f.side_effect = n_exc.NotFound
             self.assertRaises(p_exc.PortConfigurationError,
                               self.manager.lsn_port_metadata_setup,
@@ -585,8 +587,8 @@ class LsnManagerTestCase(base.BaseTestCase):
             'network_id': self.net_id,
             'tenant_id': self.tenant_id
         }
-        with mock.patch.object(lsn_man.nsxlib, 'create_lport') as f:
-            with mock.patch.object(lsn_man.nsxlib, 'delete_port') as g:
+        with mock.patch.object(lsn_man.switch_api, 'create_lport') as f:
+            with mock.patch.object(lsn_man.switch_api, 'delete_port') as g:
                 f.return_value = {'uuid': self.port_id}
                 self.mock_lsn_api.lsn_port_plug_network.side_effect = (
                     p_exc.LsnConfigurationConflict(lsn_id=self.lsn_id))
@@ -611,8 +613,9 @@ class LsnManagerTestCase(base.BaseTestCase):
 
     def test_lsn_port_dispose_meta_mac(self):
         self.mac = constants.METADATA_MAC
-        with mock.patch.object(lsn_man.nsxlib, 'get_port_by_neutron_tag') as f:
-            with mock.patch.object(lsn_man.nsxlib, 'delete_port') as g:
+        with mock.patch.object(lsn_man.switch_api,
+                               'get_port_by_neutron_tag') as f:
+            with mock.patch.object(lsn_man.switch_api, 'delete_port') as g:
                 f.return_value = {'uuid': self.port_id}
                 self._test_lsn_port_dispose_with_values(
                     self.lsn_id, self.lsn_port_id, 1)
index de67969127b753b9d8fab74d44c5643c12143ab3..12269abba3ce1eb506e1f65331e8b3b873515e8e 100644 (file)
@@ -197,8 +197,8 @@ class TestNiciraPortsV2(NiciraPluginV2TestCase,
                 with self.port(subnet=sub):
                     with self.port(subnet=sub):
                         plugin = manager.NeutronManager.get_plugin()
-                        ls = nvplib.get_lswitches(plugin.cluster,
-                                                  net['network']['id'])
+                        ls = nsxlib.switch.get_lswitches(plugin.cluster,
+                                                         net['network']['id'])
                         self.assertEqual(len(ls), 2)
 
     def test_update_port_delete_ip(self):
@@ -236,7 +236,7 @@ class TestNiciraPortsV2(NiciraPluginV2TestCase,
         self.assertFalse(self.fc._fake_lswitch_lport_dict)
 
     def test_create_port_nvp_error_no_orphan_left(self):
-        with mock.patch.object(nvplib, 'create_lport',
+        with mock.patch.object(nsxlib.switch, 'create_lport',
                                side_effect=NvpApiClient.NvpApiException):
             with self.network() as net:
                 net_id = net['network']['id']
@@ -1473,7 +1473,7 @@ class TestNiciraNetworkGateway(NiciraPluginV2TestCase,
 
     def test_update_network_gateway_with_name_calls_backend(self):
         with mock.patch.object(
-            nvplib, 'update_l2_gw_service') as mock_update_gw:
+            nsxlib.l2gateway, 'update_l2_gw_service') as mock_update_gw:
             with self._network_gateway(name='cavani') as nw_gw:
                 nw_gw_id = nw_gw[self.resource]['id']
                 self._update(nvp_networkgw.COLLECTION_NAME, nw_gw_id,
@@ -1483,7 +1483,7 @@ class TestNiciraNetworkGateway(NiciraPluginV2TestCase,
 
     def test_update_network_gateway_without_name_does_not_call_backend(self):
         with mock.patch.object(
-            nvplib, 'update_l2_gw_service') as mock_update_gw:
+            nsxlib.l2gateway, 'update_l2_gw_service') as mock_update_gw:
             with self._network_gateway(name='something') as nw_gw:
                 nw_gw_id = nw_gw[self.resource]['id']
                 self._update(nvp_networkgw.COLLECTION_NAME, nw_gw_id,
@@ -1510,7 +1510,7 @@ class TestNiciraNetworkGateway(NiciraPluginV2TestCase,
         def raise_nvp_api_exc(*args, **kwargs):
             raise NvpApiClient.NvpApiException
 
-        with mock.patch.object(nvplib,
+        with mock.patch.object(nsxlib.l2gateway,
                                'create_l2_gw_service',
                                new=raise_nvp_api_exc):
             res = self._create_network_gateway(
@@ -1519,7 +1519,7 @@ class TestNiciraNetworkGateway(NiciraPluginV2TestCase,
             self.assertEqual(500, res.status_int)
 
     def test_create_network_gateway_nvp_error_returns_409(self):
-        with mock.patch.object(nvplib,
+        with mock.patch.object(nsxlib.l2gateway,
                                'create_l2_gw_service',
                                side_effect=NvpApiClient.Conflict):
             res = self._create_network_gateway(
index 6262fdc3d584e5be8ca03f3859ef645ae9d266df..2f3954de8bc388f0c7f0a777a4ab34d8ab8534a7 100644 (file)
@@ -102,7 +102,8 @@ class NsxUtilsTestCase(base.BaseTestCase):
         exp_lp_uuid = uuidutils.generate_uuid()
         ret_value = None, exp_lp_uuid
         self._mock_port_mapping_db_calls(ret_value)
-        with mock.patch(nicira_method('query_lswitch_lports'),
+        with mock.patch(nicira_method('query_lswitch_lports',
+                                      module_name='nsxlib.switch'),
                         return_value=[{'uuid': exp_lp_uuid,
                                        '_relations': {
                                            'LogicalSwitchConfig': {
@@ -117,7 +118,8 @@ class NsxUtilsTestCase(base.BaseTestCase):
         exp_lp_uuid = uuidutils.generate_uuid()
         ret_value = None, None
         self._mock_port_mapping_db_calls(ret_value)
-        with mock.patch(nicira_method('query_lswitch_lports'),
+        with mock.patch(nicira_method('query_lswitch_lports',
+                                      module_name='nsxlib.switch'),
                         return_value=[{'uuid': exp_lp_uuid,
                                        '_relations': {
                                            'LogicalSwitchConfig': {
@@ -130,7 +132,8 @@ class NsxUtilsTestCase(base.BaseTestCase):
         # mappings are not found both in the db and the backend
         ret_value = None, None
         self._mock_port_mapping_db_calls(ret_value)
-        with mock.patch(nicira_method('query_lswitch_lports'),
+        with mock.patch(nicira_method('query_lswitch_lports',
+                                      module_name='nsxlib.switch'),
                         return_value=[]):
             self._verify_get_nsx_switch_and_port_id(None, None)
 
@@ -146,7 +149,8 @@ class NsxUtilsTestCase(base.BaseTestCase):
         # found for a given network identifier
         exp_ls_uuids = [uuidutils.generate_uuid()]
         self._mock_network_mapping_db_calls(None)
-        with mock.patch(nicira_method('get_lswitches'),
+        with mock.patch(nicira_method('get_lswitches',
+                                      module_name='nsxlib.switch'),
                         return_value=[{'uuid': uuid}
                                       for uuid in exp_ls_uuids]):
             self._verify_get_nsx_switch_ids(exp_ls_uuids)
@@ -155,7 +159,8 @@ class NsxUtilsTestCase(base.BaseTestCase):
         # This test verifies that the function returns None if the mappings
         # are not found both in the db and in the backend
         self._mock_network_mapping_db_calls(None)
-        with mock.patch(nicira_method('get_lswitches'),
+        with mock.patch(nicira_method('get_lswitches',
+                                      module_name='nsxlib.switch'),
                         return_value=[]):
             self._verify_get_nsx_switch_ids(None)
 
index 740197d3d18b9087d8758c17ddd841119e166923..e08c4289b7bca07a8a95077bd1baeceebee17417 100644 (file)
 #
 # @author: Salvatore Orlando, VMware
 
-import hashlib
 import mock
 
-from neutron.common import constants
 from neutron.common import exceptions
 from neutron.plugins.nicira.common import config  # noqa
 from neutron.plugins.nicira.common import exceptions as nvp_exc
@@ -104,247 +102,6 @@ class NsxlibNegativeBaseTestCase(base.BaseTestCase):
         self.addCleanup(self.mock_nvpapi.stop)
 
 
-class L2GatewayNegativeTestCase(NsxlibNegativeBaseTestCase):
-
-    def test_create_l2_gw_service_on_failure(self):
-        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
-                          nvplib.create_l2_gw_service,
-                          self.fake_cluster,
-                          'fake-tenant',
-                          'fake-gateway',
-                          [{'id': _uuid(),
-                           'interface_name': 'xxx'}])
-
-    def test_delete_l2_gw_service_on_failure(self):
-        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
-                          nvplib.delete_l2_gw_service,
-                          self.fake_cluster,
-                          'fake-gateway')
-
-    def test_get_l2_gw_service_on_failure(self):
-        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
-                          nvplib.get_l2_gw_service,
-                          self.fake_cluster,
-                          'fake-gateway')
-
-    def test_update_l2_gw_service_on_failure(self):
-        self.assertRaises(nvplib.NvpApiClient.NvpApiException,
-                          nvplib.update_l2_gw_service,
-                          self.fake_cluster,
-                          'fake-gateway',
-                          'pluto')
-
-
-class TestNvplibL2Gateway(NvplibTestCase):
-
-    def _create_gw_service(self, node_uuid, display_name,
-                           tenant_id='fake_tenant'):
-        return nvplib.create_l2_gw_service(self.fake_cluster,
-                                           tenant_id,
-                                           display_name,
-                                           [{'id': node_uuid,
-                                             'interface_name': 'xxx'}])
-
-    def test_create_l2_gw_service(self):
-        display_name = 'fake-gateway'
-        node_uuid = _uuid()
-        response = self._create_gw_service(node_uuid, display_name)
-        self.assertEqual(response.get('type'), 'L2GatewayServiceConfig')
-        self.assertEqual(response.get('display_name'), display_name)
-        gateways = response.get('gateways', [])
-        self.assertEqual(len(gateways), 1)
-        self.assertEqual(gateways[0]['type'], 'L2Gateway')
-        self.assertEqual(gateways[0]['device_id'], 'xxx')
-        self.assertEqual(gateways[0]['transport_node_uuid'], node_uuid)
-
-    def test_update_l2_gw_service(self):
-        display_name = 'fake-gateway'
-        new_display_name = 'still-fake-gateway'
-        node_uuid = _uuid()
-        res1 = self._create_gw_service(node_uuid, display_name)
-        gw_id = res1['uuid']
-        res2 = nvplib.update_l2_gw_service(self.fake_cluster, gw_id,
-                                           new_display_name)
-        self.assertEqual(res2['display_name'], new_display_name)
-
-    def test_get_l2_gw_service(self):
-        display_name = 'fake-gateway'
-        node_uuid = _uuid()
-        gw_id = self._create_gw_service(node_uuid, display_name)['uuid']
-        response = nvplib.get_l2_gw_service(self.fake_cluster, gw_id)
-        self.assertEqual(response.get('type'), 'L2GatewayServiceConfig')
-        self.assertEqual(response.get('display_name'), display_name)
-        self.assertEqual(response.get('uuid'), gw_id)
-
-    def test_list_l2_gw_service(self):
-        gw_ids = []
-        for name in ('fake-1', 'fake-2'):
-            gw_ids.append(self._create_gw_service(_uuid(), name)['uuid'])
-        results = nvplib.get_l2_gw_services(self.fake_cluster)
-        self.assertEqual(len(results), 2)
-        self.assertEqual(sorted(gw_ids), sorted([r['uuid'] for r in results]))
-
-    def test_list_l2_gw_service_by_tenant(self):
-        gw_ids = [self._create_gw_service(
-                  _uuid(), name, tenant_id=name)['uuid']
-                  for name in ('fake-1', 'fake-2')]
-        results = nvplib.get_l2_gw_services(self.fake_cluster,
-                                            tenant_id='fake-1')
-        self.assertEqual(len(results), 1)
-        self.assertEqual(results[0]['uuid'], gw_ids[0])
-
-    def test_delete_l2_gw_service(self):
-        display_name = 'fake-gateway'
-        node_uuid = _uuid()
-        gw_id = self._create_gw_service(node_uuid, display_name)['uuid']
-        nvplib.delete_l2_gw_service(self.fake_cluster, gw_id)
-        results = nvplib.get_l2_gw_services(self.fake_cluster)
-        self.assertEqual(len(results), 0)
-
-    def test_plug_l2_gw_port_attachment(self):
-        tenant_id = 'pippo'
-        node_uuid = _uuid()
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster, _uuid(), tenant_id,
-                                        'fake-switch', transport_zones_config)
-        gw_id = self._create_gw_service(node_uuid, 'fake-gw')['uuid']
-        lport = nvplib.create_lport(self.fake_cluster,
-                                    lswitch['uuid'],
-                                    tenant_id,
-                                    _uuid(),
-                                    'fake-gw-port',
-                                    gw_id,
-                                    True)
-        nvplib.plug_l2_gw_service(self.fake_cluster,
-                                  lswitch['uuid'],
-                                  lport['uuid'],
-                                  gw_id)
-        uri = nvplib._build_uri_path(nvplib.LSWITCHPORT_RESOURCE,
-                                     lport['uuid'],
-                                     lswitch['uuid'],
-                                     is_attachment=True)
-        resp_obj = nvplib.do_request("GET", uri,
-                                     cluster=self.fake_cluster)
-        self.assertIn('LogicalPortAttachment', resp_obj)
-        self.assertEqual(resp_obj['LogicalPortAttachment']['type'],
-                         'L2GatewayAttachment')
-
-
-class TestNvplibLogicalSwitches(NvplibTestCase):
-
-    def test_create_and_get_lswitches_single(self):
-        tenant_id = 'pippo'
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        _uuid(),
-                                        tenant_id,
-                                        'fake-switch',
-                                        transport_zones_config)
-        res_lswitch = nvplib.get_lswitches(self.fake_cluster,
-                                           lswitch['uuid'])
-        self.assertEqual(len(res_lswitch), 1)
-        self.assertEqual(res_lswitch[0]['uuid'],
-                         lswitch['uuid'])
-
-    def test_create_and_get_lswitches_single_name_exceeds_40_chars(self):
-        tenant_id = 'pippo'
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        tenant_id,
-                                        _uuid(),
-                                        '*' * 50,
-                                        transport_zones_config)
-        res_lswitch = nvplib.get_lswitches(self.fake_cluster,
-                                           lswitch['uuid'])
-        self.assertEqual(len(res_lswitch), 1)
-        self.assertEqual(res_lswitch[0]['uuid'], lswitch['uuid'])
-        self.assertEqual(res_lswitch[0]['display_name'], '*' * 40)
-
-    def test_create_and_get_lswitches_multiple(self):
-        tenant_id = 'pippo'
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        network_id = _uuid()
-        main_lswitch = nvplib.create_lswitch(
-            self.fake_cluster, network_id,
-            tenant_id, 'fake-switch', transport_zones_config,
-            tags=[{'scope': 'multi_lswitch', 'tag': 'True'}])
-        # Create secondary lswitch
-        second_lswitch = nvplib.create_lswitch(
-            self.fake_cluster, network_id,
-            tenant_id, 'fake-switch-2', transport_zones_config)
-        res_lswitch = nvplib.get_lswitches(self.fake_cluster,
-                                           network_id)
-        self.assertEqual(len(res_lswitch), 2)
-        switch_uuids = [ls['uuid'] for ls in res_lswitch]
-        self.assertIn(main_lswitch['uuid'], switch_uuids)
-        self.assertIn(second_lswitch['uuid'], switch_uuids)
-        for ls in res_lswitch:
-            if ls['uuid'] == main_lswitch['uuid']:
-                main_ls = ls
-            else:
-                second_ls = ls
-        main_ls_tags = self._build_tag_dict(main_ls['tags'])
-        second_ls_tags = self._build_tag_dict(second_ls['tags'])
-        self.assertIn('multi_lswitch', main_ls_tags)
-        self.assertNotIn('multi_lswitch', second_ls_tags)
-        self.assertIn('quantum_net_id', main_ls_tags)
-        self.assertIn('quantum_net_id', second_ls_tags)
-        self.assertEqual(main_ls_tags['quantum_net_id'],
-                         network_id)
-        self.assertEqual(second_ls_tags['quantum_net_id'],
-                         network_id)
-
-    def test_update_lswitch(self):
-        new_name = 'new-name'
-        new_tags = [{'scope': 'new_tag', 'tag': 'xxx'}]
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        _uuid(),
-                                        'pippo',
-                                        'fake-switch',
-                                        transport_zones_config)
-        nvplib.update_lswitch(self.fake_cluster, lswitch['uuid'],
-                              new_name, tags=new_tags)
-        res_lswitch = nvplib.get_lswitches(self.fake_cluster,
-                                           lswitch['uuid'])
-        self.assertEqual(len(res_lswitch), 1)
-        self.assertEqual(res_lswitch[0]['display_name'], new_name)
-        switch_tags = self._build_tag_dict(res_lswitch[0]['tags'])
-        self.assertIn('new_tag', switch_tags)
-        self.assertEqual(switch_tags['new_tag'], 'xxx')
-
-    def test_update_non_existing_lswitch_raises(self):
-        self.assertRaises(exceptions.NetworkNotFound,
-                          nvplib.update_lswitch,
-                          self.fake_cluster, 'whatever',
-                          'foo', 'bar')
-
-    def test_delete_networks(self):
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        _uuid(),
-                                        'pippo',
-                                        'fake-switch',
-                                        transport_zones_config)
-        nvplib.delete_networks(self.fake_cluster, lswitch['uuid'],
-                               [lswitch['uuid']])
-        self.assertRaises(exceptions.NotFound,
-                          nvplib.get_lswitches,
-                          self.fake_cluster,
-                          lswitch['uuid'])
-
-    def test_delete_non_existing_lswitch_raises(self):
-        self.assertRaises(exceptions.NetworkNotFound,
-                          nvplib.delete_networks,
-                          self.fake_cluster, 'whatever', ['whatever'])
-
-
 class TestNvplibSecurityProfile(NvplibTestCase):
 
     def test_create_and_get_security_profile(self):
@@ -448,154 +205,6 @@ class TestNvplibSecurityProfile(NvplibTestCase):
                           self.fake_cluster, 'whatever')
 
 
-class TestNvplibLogicalPorts(NvplibTestCase):
-
-    def _create_switch_and_port(self, tenant_id='pippo',
-                                neutron_port_id='whatever',
-                                name='name', device_id='device_id'):
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster,
-                                        _uuid(), tenant_id, 'fake-switch',
-                                        transport_zones_config)
-        lport = nvplib.create_lport(self.fake_cluster, lswitch['uuid'],
-                                    tenant_id, neutron_port_id,
-                                    name, device_id, True)
-        return lswitch, lport
-
-    def test_create_and_get_port(self):
-        lswitch, lport = self._create_switch_and_port()
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'])
-        self.assertEqual(lport['uuid'], lport_res['uuid'])
-        # Try again with relation
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'],
-                                    relations='LogicalPortStatus')
-        self.assertEqual(lport['uuid'], lport_res['uuid'])
-
-    def test_plug_interface(self):
-        lswitch, lport = self._create_switch_and_port()
-        nvplib.plug_interface(self.fake_cluster, lswitch['uuid'],
-                              lport['uuid'], 'VifAttachment', 'fake')
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'])
-        self.assertEqual(lport['uuid'], lport_res['uuid'])
-
-    def test_get_port_by_tag(self):
-        lswitch, lport = self._create_switch_and_port()
-        lport2 = nvplib.get_port_by_neutron_tag(self.fake_cluster,
-                                                lswitch['uuid'],
-                                                'whatever')
-        self.assertIsNotNone(lport2)
-        self.assertEqual(lport['uuid'], lport2['uuid'])
-
-    def test_get_port_by_tag_not_found_returns_None(self):
-        tenant_id = 'pippo'
-        neutron_port_id = 'whatever'
-        transport_zones_config = [{'zone_uuid': _uuid(),
-                                   'transport_type': 'stt'}]
-        lswitch = nvplib.create_lswitch(self.fake_cluster, tenant_id, _uuid(),
-                                        'fake-switch', transport_zones_config)
-        lport = nvplib.get_port_by_neutron_tag(self.fake_cluster,
-                                               lswitch['uuid'],
-                                               neutron_port_id)
-        self.assertIsNone(lport)
-
-    def test_get_port_status(self):
-        lswitch, lport = self._create_switch_and_port()
-        status = nvplib.get_port_status(self.fake_cluster,
-                                        lswitch['uuid'],
-                                        lport['uuid'])
-        self.assertEqual(constants.PORT_STATUS_ACTIVE, status)
-
-    def test_get_port_status_non_existent_raises(self):
-        self.assertRaises(exceptions.PortNotFoundOnNetwork,
-                          nvplib.get_port_status,
-                          self.fake_cluster,
-                          'boo', 'boo')
-
-    def test_update_port(self):
-        lswitch, lport = self._create_switch_and_port()
-        nvplib.update_port(
-            self.fake_cluster, lswitch['uuid'], lport['uuid'],
-            'neutron_port_id', 'pippo2', 'new_name', 'device_id', False)
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'])
-        self.assertEqual(lport['uuid'], lport_res['uuid'])
-        self.assertEqual('new_name', lport_res['display_name'])
-        self.assertEqual('False', lport_res['admin_status_enabled'])
-        port_tags = self._build_tag_dict(lport_res['tags'])
-        self.assertIn('os_tid', port_tags)
-        self.assertIn('q_port_id', port_tags)
-        self.assertIn('vm_id', port_tags)
-
-    def test_create_port_device_id_less_than_40_chars(self):
-        lswitch, lport = self._create_switch_and_port()
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'])
-        port_tags = self._build_tag_dict(lport_res['tags'])
-        self.assertEqual('device_id', port_tags['vm_id'])
-
-    def test_create_port_device_id_more_than_40_chars(self):
-        dev_id = "this_is_a_very_long_device_id_with_lots_of_characters"
-        lswitch, lport = self._create_switch_and_port(device_id=dev_id)
-        lport_res = nvplib.get_port(self.fake_cluster,
-                                    lswitch['uuid'], lport['uuid'])
-        port_tags = self._build_tag_dict(lport_res['tags'])
-        self.assertNotEqual(len(dev_id), len(port_tags['vm_id']))
-
-    def test_get_ports_with_obsolete_and_new_vm_id_tag(self):
-        def obsolete(device_id, obfuscate=False):
-            return hashlib.sha1(device_id).hexdigest()
-
-        with mock.patch.object(nvplib, 'device_id_to_vm_id', new=obsolete):
-            dev_id1 = "short-dev-id-1"
-            _, lport1 = self._create_switch_and_port(device_id=dev_id1)
-        dev_id2 = "short-dev-id-2"
-        _, lport2 = self._create_switch_and_port(device_id=dev_id2)
-
-        lports = nvplib.get_ports(self.fake_cluster, None, [dev_id1])
-        port_tags = self._build_tag_dict(lports['whatever']['tags'])
-        self.assertNotEqual(dev_id1, port_tags['vm_id'])
-
-        lports = nvplib.get_ports(self.fake_cluster, None, [dev_id2])
-        port_tags = self._build_tag_dict(lports['whatever']['tags'])
-        self.assertEqual(dev_id2, port_tags['vm_id'])
-
-    def test_update_non_existent_port_raises(self):
-        self.assertRaises(exceptions.PortNotFoundOnNetwork,
-                          nvplib.update_port, self.fake_cluster,
-                          'boo', 'boo', 'boo', 'boo', 'boo', 'boo', False)
-
-    def test_delete_port(self):
-        lswitch, lport = self._create_switch_and_port()
-        nvplib.delete_port(self.fake_cluster,
-                           lswitch['uuid'], lport['uuid'])
-        self.assertRaises(exceptions.PortNotFoundOnNetwork,
-                          nvplib.get_port, self.fake_cluster,
-                          lswitch['uuid'], lport['uuid'])
-
-    def test_delete_non_existent_port_raises(self):
-        lswitch = self._create_switch_and_port()[0]
-        self.assertRaises(exceptions.PortNotFoundOnNetwork,
-                          nvplib.delete_port, self.fake_cluster,
-                          lswitch['uuid'], 'bad_port_uuid')
-
-    def test_query_lswitch_ports(self):
-        lswitch, lport = self._create_switch_and_port()
-        switch_port_uuids = [
-            nvplib.create_lport(
-                self.fake_cluster, lswitch['uuid'], 'pippo', 'qportid-%s' % k,
-                'port-%s' % k, 'deviceid-%s' % k, True)['uuid']
-            for k in range(2)]
-        switch_port_uuids.append(lport['uuid'])
-        ports = nvplib.query_lswitch_lports(self.fake_cluster, lswitch['uuid'])
-        self.assertEqual(len(ports), 3)
-        for res_port in ports:
-            self.assertIn(res_port['uuid'], switch_port_uuids)
-
-
 class TestNvplibClusterManagement(NvplibTestCase):
 
     def test_get_cluster_version(self):