Allow multiple ports to exist with the same name 51/7151/4
authorschillinge <ablu@mail.uni-paderborn.de>
Wed, 30 Jan 2019 16:48:27 +0000 (17:48 +0100)
committerschillinge <ablu@mail.uni-paderborn.de>
Tue, 5 Feb 2019 14:17:11 +0000 (15:17 +0100)
Ports in OpenStack may very well have identical names. In fact this is
almost guaranteed when deploying network services with multiple identical
VNFs.

Change-Id: Iba196e64be329c376eca9f34c7b2cbcdfd569a3e
Signed-off-by: schillinge <ablu@mail.uni-paderborn.de>
src/emuvim/api/openstack/compute.py
src/emuvim/api/openstack/openstack_dummies/neutron_dummy_api.py
src/emuvim/api/openstack/openstack_dummies/nova_dummy_api.py
src/emuvim/test/unittests/test_openstack.py

index 405fa6f..4d6517e 100755 (executable)
@@ -687,12 +687,6 @@ class OpenstackCompute(object):
         :return: Returns the created port.
         :rtype: :class:`heat.resources.port`
         """
-        port = self.find_port_by_name_or_id(name)
-        if port is not None and not stack_operation:
-            LOG.warning(
-                "Creating port with name %s failed, as it already exists" % name)
-            raise Exception("Port with name %s already exists." % name)
-        LOG.debug("Creating port with name %s" % name)
         port = Port(name)
         if not stack_operation:
             self.ports[port.id] = port
@@ -708,12 +702,19 @@ class OpenstackCompute(object):
         :return: Returns the port reference if it was found or None
         :rtype: :class:`heat.resources.port`
         """
+        # find by id
         if name_or_id in self.ports:
             return self.ports[name_or_id]
-        for port in self.ports.values():
-            if port.name == name_or_id or port.template_name == name_or_id:
-                return port
-
+        # find by name
+        matching_ports = filter(
+            lambda port: port.name == name_or_id or port.template_name == name_or_id,
+            self.ports.values()
+        )
+        matching_ports_count = len(matching_ports)
+        if matching_ports_count == 1:
+            return matching_ports[0]
+        if matching_ports_count > 1:
+            raise RuntimeError("Ambiguous port name %s" % name_or_id)
         return None
 
     def delete_port(self, name_or_id):
index e094f0e..13698bd 100755 (executable)
@@ -816,10 +816,6 @@ class NeutronCreatePort(Resource):
                 num_ports = len(self.api.compute.ports)
                 name = "port:cp%s:man:%s" % (num_ports, str(uuid.uuid4()))
 
-            if self.api.compute.find_port_by_name_or_id(name):
-                return Response("Port with name %s already exists.\n" %
-                                name, status=500, mimetype='application/json')
-
             port = self.api.compute.create_port(name)
 
             port.net_name = net.name
index e12fb05..12a9cc2 100755 (executable)
@@ -246,10 +246,10 @@ class NovaListServersApi(Resource):
 
             if networks is not None:
                 for net in networks:
-                    port = self.api.compute.find_port_by_name_or_id(
-                        net.get('port', ""))
+                    port_name_or_id = net.get('port', "")
+                    port = self.api.compute.find_port_by_name_or_id(port_name_or_id)
                     if port is not None:
-                        server.port_names.append(port.name)
+                        server.port_names.append(port_name_or_id)
                     else:
                         return Response(
                             "Currently only networking by port is supported.", status=400)
index 93d7f4a..5540247 100755 (executable)
@@ -610,18 +610,26 @@ class testRestApi(ApiBaseOpenStack):
             url, data=createportdata, headers=headers)
         self.assertEqual(createportresponse.status_code, 201)
         print(createportresponse.content)
-        self.assertEqual(json.loads(createportresponse.content)[
-                         "port"]["name"], "new_port")
+        createport = json.loads(createportresponse.content)["port"]
+        self.assertEqual(createport["name"], "new_port")
         print(" ")
 
         print('->>>>>>> test Neutron Create Port With Existing Name ->>>>>>>>>>>>>>>')
         print('->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>')
         url = "http://0.0.0.0:19696/v2.0/ports"
-        createportwithexistingnamedata = '{"port": {"name": "new_port", "network_id": "%s"} }' % (
-            json.loads(createnetworkresponse.content)["network"]["id"])
-        createportwithexistingnameresponse = requests.post(
+        network_id = json.loads(createnetworkresponse.content)["network"]["id"]
+        createportwithexistingnamedata = '{"port": {"name": "duplicate_port_name", "network_id": "%s"} }' % network_id
+        createportwithexistingnameresponse1 = requests.post(
+            url, data=createportwithexistingnamedata, headers=headers)
+        createportwithexistingnameresponse2 = requests.post(
             url, data=createportwithexistingnamedata, headers=headers)
-        self.assertEqual(createportwithexistingnameresponse.status_code, 500)
+        createportwithexistingname1 = json.loads(createportwithexistingnameresponse1.content)["port"]
+        createportwithexistingname2 = json.loads(createportwithexistingnameresponse2.content)["port"]
+        self.assertEqual(createportwithexistingnameresponse1.status_code, 201)
+        self.assertEqual(createportwithexistingnameresponse2.status_code, 201)
+        self.assertEqual(createportwithexistingname1["name"], "duplicate_port_name")
+        self.assertEqual(createportwithexistingname2["name"], "duplicate_port_name")
+        self.assertNotEqual(createportwithexistingname1["id"], createportwithexistingname2["id"], "Duplicate port should have different id")
         print(" ")
 
         print('->>>>>>> test Neutron Create Port Without Name ->>>>>>>>>>>>>>>')