Add hybrid topology tests V2

Add hybrid topology that checks connection for BM to BM
in same and different networks via Logical Router.

Related-Prod: PRODX-51686
Change-Id: I69c7c92e2a658ff8c06591e2929c9802637e7ae2
diff --git a/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy_hybrid.py b/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy_hybrid.py
index b5577a5..3edeb38 100644
--- a/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy_hybrid.py
+++ b/ironic_tempest_plugin/tests/scenario/test_baremetal_multitenancy_hybrid.py
@@ -32,9 +32,7 @@
 class BaremetalMultitenancyHybridBase(
         baremetal_manager.BaremetalScenarioTest,
         base.BaseAdminNetworkTest):
-    """Check hybrid topology same network type
-
-    Use default tenant network type everywhere
+    """Check hybrid topology with BM for different net types
 
     ---- fip network -----
                        |
@@ -51,31 +49,37 @@
     """
 
     credentials = ['primary', 'admin', 'system_admin']
+
+    netA_types = CONF.baremetal.hybrid_topology_netA_network_types
+    netB_types = CONF.baremetal.hybrid_topology_netB_network_types
+
     netA_type = "geneve"
     netB_type = "geneve"
 
+    min_nodes = 1
+
     @classmethod
     def skip_checks(cls):
         super(BaremetalMultitenancyHybridBase, cls).skip_checks()
-        neta_types = CONF.baremetal.hybrid_topology_netA_network_types
-        netb_types = CONF.baremetal.hybrid_topology_netB_network_types
         if not CONF.baremetal.use_provision_network:
             msg = 'Ironic/Neutron tenant isolation is not configured.'
             raise cls.skipException(msg)
         if (CONF.baremetal.available_nodes is not None
-                and CONF.baremetal.available_nodes < 2):
+                and CONF.baremetal.available_nodes < cls.min_nodes):
             msg = ('Not enough baremetal nodes, %d configured, test requires '
-                   'a minimum of 2') % CONF.baremetal.available_nodes
+                   'a minimum of %d') % (CONF.baremetal.available_nodes,
+                                         cls.min_nodes)
             raise cls.skipException(msg)
+
         if not CONF.baremetal_feature_enabled.hybrid_topology:
             msg = 'Hybrid topology not supported'
             raise cls.skipException(msg)
 
-        if cls.netA_type not in neta_types:
+        if cls.netA_type not in cls.netA_types:
             msg = 'Hybrid topology netA type %s not supported.' % cls.netA_type
             raise cls.skipException(msg)
 
-        if cls.netB_type not in netb_types:
+        if cls.netB_type not in cls.netB_types:
             msg = 'Hybrid topology netB type %s not supported.' % cls.netB_type
             raise cls.skipException(msg)
 
@@ -874,3 +878,287 @@
     @decorators.idempotent_id('5aabaa14-cbed-45f6-a0ea-13952ab3f2a6')
     def test_connectivity_vmb1_vmb2(self):
         self._test_connectivity_vmb1_vmb2()
+
+
+class BaremetalMultitenancyHybridBaseBM(
+        BaremetalMultitenancyHybridBase):
+    """Check hybrid topology with BM for different net types
+
+    ---- fip network -----
+                       |
+                     ( r1 ) ------- netB --------
+                       |              |       |
+    --------- netA ------------    (bmB1)   (bmB2)
+            |        |              fipB1
+          (bmA1)   (bmA2)
+         fipbmA
+
+    * Test can ping fips fipbmA, fipA1, fipB1
+    * Test each VM can reach other VMs via FIPs
+    * Test each VM can reach othe VMs via private IPs
+    """
+
+    credentials = ['primary', 'admin', 'system_admin']
+
+    netA_types = CONF.baremetal.hybrid_topology_bm_netA_network_types
+    netB_types = CONF.baremetal.hybrid_topology_bm_netB_network_types
+
+    netA_type = "geneve"
+    netB_type = "geneve"
+
+    min_nodes = 4
+
+    @classmethod
+    def resource_setup(cls):
+        netA_cidr = netaddr.IPNetwork("192.168.10.0/24")
+        netB_cidr = netaddr.IPNetwork("192.168.11.0/24")
+        cls.ext_net_id = CONF.network.public_network_id
+        cls.ping_timeout = 60
+        netA_kwargs = {"port_security_enabled": False}
+        if cls.netA_type:
+            netA_kwargs["provider:network_type"] = cls.netA_type
+
+        cls.netA = cls.create_network(**netA_kwargs)
+        cls.subnetA = cls.create_subnet(cls.netA, cidr=netA_cidr)
+        cls.r1 = cls.create_router(external_network_id=cls.ext_net_id,
+                                   admin_state_up=True)
+
+        cls.create_router_interface(cls.r1['id'], cls.subnetA['id'])
+        cls.addClassCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            cls.routers_client.remove_router_interface,
+            cls.r1['id'], subnet_id=cls.subnetA['id'])
+
+        netB_kwargs = {"port_security_enabled": False}
+        if cls.netB_type:
+            netB_kwargs["provider:network_type"] = cls.netB_type
+        cls.netB = cls.create_network(**netB_kwargs)
+        cls.subnetB = cls.create_subnet(cls.netB, cidr=netB_cidr)
+
+        cls.create_router_interface(cls.r1['id'], cls.subnetB['id'])
+        cls.addClassCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            cls.routers_client.remove_router_interface,
+            cls.r1['id'], subnet_id=cls.subnetB['id'])
+
+        cls.keypair = cls.create_keypair()
+
+        cls.bmA1, cls.bmA1_ip, cls.bmA1_fip = cls.create_server(
+            key_name=cls.keypair['name'],
+            flavor=None,
+            net_id=cls.netA['id'],
+            fip=True
+        )
+
+        cls.bmA2, cls.bmA2_ip, cls.bmA2_fip = cls.create_server(
+            key_name=cls.keypair['name'],
+            flavor=None,
+            net_id=cls.netA['id'],
+            fip=False
+        )
+        cls.bmB1, cls.bmB1_ip, cls.bmB1_fip = cls.create_server(
+            key_name=cls.keypair['name'],
+            flavor=None,
+            net_id=cls.netB['id'],
+            fip=True
+        )
+
+        cls.bmB2, cls.bmB2_ip, cls.bmB2_fip = cls.create_server(
+            key_name=cls.keypair['name'],
+            flavor=None,
+            net_id=cls.netB['id'],
+            fip=False
+        )
+
+        # Make sure latest VM with FIP booted so we can assume
+        # Previous VMs are booted as well.
+        cls.wait_for_ssh(
+            cls.bmB2_fip,
+            private_key=cls.keypair['private_key'])
+
+    def _test_connectivity_fip_bma1(self):
+        self.assertTrue(
+            self.ping_ip_address(
+                self.bmA1_fip, should_succeed=True),
+            "Can't reach bmA1 FIP")
+
+    def _test_connectivity_fip_bmb1(self):
+        self.assertTrue(
+            self.ping_ip_address(
+                self.bmB1_fip, should_succeed=True),
+            "Can't reach bmB1 FIP")
+
+    def _test_connectivity_bma1_bma2(self):
+        self.verify_l3_connectivity(
+            self.bmA1_fip, self.keypair['private_key'],
+            self.bmA2_ip, conn_expected=True, timeout=self.ping_timeout)
+
+    def _test_connectivity_bma1_bmb1(self):
+        self.verify_l3_connectivity(
+            self.bmA1_fip, self.keypair['private_key'],
+            self.bmB1_ip, conn_expected=True, timeout=self.ping_timeout)
+
+    def _test_connectivity_bma1_bmb1_fip(self):
+        self.verify_l3_connectivity(
+            self.bmA1_fip, self.keypair['private_key'],
+            self.bmB2_fip, conn_expected=True, timeout=self.ping_timeout)
+
+    def _test_connectivity_bma1_bmb2(self):
+        self.verify_l3_connectivity(
+            self.bmA1_fip, self.keypair['private_key'],
+            self.bmB2_ip, conn_expected=True, timeout=self.ping_timeout)
+
+
+class BaremetalMultitenancyHybridBaseBMGeneveGeneve(
+        BaremetalMultitenancyHybridBaseBM):
+
+    netA_type = "geneve"
+    netB_type = "geneve"
+
+    @decorators.idempotent_id('1048b5dd-4936-479b-b857-65e277e42487')
+    def test_connectivity_fip_bma1(self):
+        self._test_connectivity_fip_bma1()
+
+    @decorators.idempotent_id('e0bc9ca8-cfe4-4f23-ba5b-25b7b3bbcedb')
+    def test_connectivity_fip_bmb1(self):
+        self.test_connectivity_fip_bmb1()
+
+    @decorators.idempotent_id('ad18f0eb-c520-4b2b-85af-f3d31c2158c6')
+    def test_connectivity_bma1_bma2(self):
+        self._test_connectivity_bma1_bma2()
+
+    @decorators.idempotent_id('b761b537-faf0-4246-b02d-fd569e0b3646')
+    def test_connectivity_bma1_bmb1(self):
+        self._test_connectivity_bma1_bmb1()
+
+    @decorators.idempotent_id('4de9301c-7877-4556-bee9-1906267bf870')
+    def test_connectivity_bma1_bmb1_fip(self):
+        self._test_connectivity_bma1_bmb1_fip()
+
+    @decorators.idempotent_id('dcfb3d59-fdd2-48ac-89ef-bf268cf70ab9')
+    def test_connectivity_bma1_bmb2(self):
+        self._test_connectivity_bma1_bmb2()
+
+
+class BaremetalMultitenancyHybridBaseBMVxlanVxlan(
+        BaremetalMultitenancyHybridBaseBM):
+
+    netA_type = "vxlan"
+    netB_type = "vxlan"
+
+    @decorators.idempotent_id('91cd5a65-a0c4-442b-958a-5054b27f79f2')
+    def test_connectivity_fip_bma1(self):
+        self._test_connectivity_fip_bma1()
+
+    @decorators.idempotent_id('0eb319f2-4829-446b-976e-ee38e56e0cb3')
+    def test_connectivity_fip_bmb1(self):
+        self.test_connectivity_fip_bmb1()
+
+    @decorators.idempotent_id('ddb0b827-f471-41f2-a09b-386105d79953')
+    def test_connectivity_bma1_bma2(self):
+        self._test_connectivity_bma1_bma2()
+
+    @decorators.idempotent_id('5465aa4a-88fa-44d5-b164-4a8fda34bb1b')
+    def test_connectivity_bma1_bmb1(self):
+        self._test_connectivity_bma1_bmb1()
+
+    @decorators.idempotent_id('1a02d1ac-b4bf-41f3-8905-6dc6daf16446')
+    def test_connectivity_bma1_bmb1_fip(self):
+        self._test_connectivity_bma1_bmb1_fip()
+
+    @decorators.idempotent_id('b275c501-078d-4a43-afe4-2b79db785285')
+    def test_connectivity_bma1_bmb2(self):
+        self._test_connectivity_bma1_bmb2()
+
+
+class BaremetalMultitenancyHybridBaseBMVlanVlan(
+        BaremetalMultitenancyHybridBaseBM):
+
+    netA_type = "vlan"
+    netB_type = "vlan"
+
+    @decorators.idempotent_id('1885d783-4112-4d36-ae8c-ac379b892cf8')
+    def test_connectivity_fip_bma1(self):
+        self._test_connectivity_fip_bma1()
+
+    @decorators.idempotent_id('80efbc42-d677-41d8-9116-e1c33ddd86ac')
+    def test_connectivity_fip_bmb1(self):
+        self.test_connectivity_fip_bmb1()
+
+    @decorators.idempotent_id('59e0870e-cede-4533-8494-c7c0a5e8fa62')
+    def test_connectivity_bma1_bma2(self):
+        self._test_connectivity_bma1_bma2()
+
+    @decorators.idempotent_id('eb8f9328-fae5-4af1-8fad-b881f6590751')
+    def test_connectivity_bma1_bmb1(self):
+        self._test_connectivity_bma1_bmb1()
+
+    @decorators.idempotent_id('0f38d7be-bba8-4ef0-aa7e-3d6dca4aba05')
+    def test_connectivity_bma1_bmb1_fip(self):
+        self._test_connectivity_bma1_bmb1_fip()
+
+    @decorators.idempotent_id('7516e2e7-0aa5-408d-b275-2281a5dd018e')
+    def test_connectivity_bma1_bmb2(self):
+        self._test_connectivity_bma1_bmb2()
+
+
+class BaremetalMultitenancyHybridBaseBMGeneveVLAN(
+        BaremetalMultitenancyHybridBaseBM):
+
+    netA_type = "geneve"
+    netB_type = "vlan"
+
+    @decorators.idempotent_id('da3d8f9e-33e6-46d0-a71e-e1f19553488e')
+    def test_connectivity_fip_bma1(self):
+        self._test_connectivity_fip_bma1()
+
+    @decorators.idempotent_id('30916aea-0c85-4d04-b66d-0734d8f3cfcc')
+    def test_connectivity_fip_bmb1(self):
+        self.test_connectivity_fip_bmb1()
+
+    @decorators.idempotent_id('638ef9e6-d3aa-42e8-89ed-e61b4d19ef42')
+    def test_connectivity_bma1_bma2(self):
+        self._test_connectivity_bma1_bma2()
+
+    @decorators.idempotent_id('82741d99-7fd2-4d74-b06c-7975f312a31c')
+    def test_connectivity_bma1_bmb1(self):
+        self._test_connectivity_bma1_bmb1()
+
+    @decorators.idempotent_id('dc3095a5-0202-46cd-a6fa-06ecae97c0ed')
+    def test_connectivity_bma1_bmb1_fip(self):
+        self._test_connectivity_bma1_bmb1_fip()
+
+    @decorators.idempotent_id('dc4b022c-0425-4386-9f54-212ec68883e5')
+    def test_connectivity_bma1_bmb2(self):
+        self._test_connectivity_bma1_bmb2()
+
+
+class BaremetalMultitenancyHybridBaseBMGeneveVXLAN(
+        BaremetalMultitenancyHybridBaseBM):
+
+    netA_type = "geneve"
+    netB_type = "vxlan"
+
+    @decorators.idempotent_id('4699004c-781f-4ebf-b210-60cbdfa31637')
+    def test_connectivity_fip_bma1(self):
+        self._test_connectivity_fip_bma1()
+
+    @decorators.idempotent_id('3f72193a-d0b0-4baf-b42c-d1427266f7b7')
+    def test_connectivity_fip_bmb1(self):
+        self.test_connectivity_fip_bmb1()
+
+    @decorators.idempotent_id('81c0ad1c-546d-4e3e-ae79-fcb6044c4b99')
+    def test_connectivity_bma1_bma2(self):
+        self._test_connectivity_bma1_bma2()
+
+    @decorators.idempotent_id('31f3b6d0-6dd7-4971-9a6a-e30a9a8e7985')
+    def test_connectivity_bma1_bmb1(self):
+        self._test_connectivity_bma1_bmb1()
+
+    @decorators.idempotent_id('4169ddd5-ac1f-4227-8058-635621cee4c1')
+    def test_connectivity_bma1_bmb1_fip(self):
+        self._test_connectivity_bma1_bmb1_fip()
+
+    @decorators.idempotent_id('388a695f-c289-4d09-878b-1dc7d2b822ac')
+    def test_connectivity_bma1_bmb2(self):
+        self._test_connectivity_bma1_bmb2()