[bgpvpn] Bring in L2/L3 VPN endpoints tests

Closes-Bug: PRODX-11809
Closes-Bug: PRODX-11810
Change-Id: Iac179b592e579916fc36bef79b1a007528a07f36
(cherry picked from commit 35829e1bec9aa92a3cf90d371892dc900d6364ad)
(cherry picked from commit 7227eec12b83854694c22b7eb7ae37379931f5c0)
(cherry picked from commit 3e5d783f9d34cb9cc093a3dd451ec8aa559cb597)
(cherry picked from commit ef22edabe140965c19dcee18d7b10f98ede28326)
diff --git a/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_advanced.py b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_advanced.py
new file mode 100644
index 0000000..c7b2f8f
--- /dev/null
+++ b/neutron_tempest_plugin/bgpvpn/scenario/test_bgpvpn_advanced.py
@@ -0,0 +1,267 @@
+# Copyright 2021 Mirantis, 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.
+
+from oslo_log import log as logging
+from tempest.common import compute
+from tempest.common import utils
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import decorators
+import testtools
+
+from neutron_tempest_plugin.bgpvpn import base
+from neutron_tempest_plugin.bgpvpn.scenario import manager
+
+CONF = config.CONF
+LOG = logging.getLogger(__name__)
+
+
+class TestBGPVPNAdvanced(base.BaseBgpvpnTest, manager.NetworkScenarioTest):
+    def setUp(self):
+        super(TestBGPVPNAdvanced, self).setUp()
+        self.security_group = self._create_security_group(
+            tenant_id=self.bgpvpn_client.tenant_id
+        )
+
+    @decorators.idempotent_id("734213fb-8213-487d-9fe3-c8ff31758e18")
+    @utils.services("compute", "network")
+    @testtools.skipUnless(
+        CONF.bgpvpn.l2vpn_endpoint and CONF.bgpvpn.route_target,
+        "Required ip address of L2 endpoint and route target.",
+    )
+    def test_bgpvpn_l2vpn_endpoint(self):
+        """This test checks L2VPN connectivity.
+
+        1. Create network with respective subnet
+        2. Start up server
+        4. Associate network to a given L2 BGPVPN
+        5. Create router and connect it to network
+        6. Give a FIP to server
+        7. Check that server can ping l2vpn vtep/endpoint
+        """
+
+        self._create_networks_and_subnets(
+            subnet_cidr=CONF.bgpvpn.l2vpn_endpoint
+        )
+        self._create_server()
+        self._create_bgpvpn(
+            type="l2",
+            rts=CONF.bgpvpn.route_target,
+            vni=CONF.bgpvpn.route_target.split(":")[1],
+        )
+        self._associate_all_nets_to_bgpvpn()
+        self._associate_fip_and_check_bgpvpn(
+            CONF.bgpvpn.l2vpn_endpoint.split("/")[0]
+        )
+
+    @decorators.idempotent_id("124fe1bd-e18a-4482-9c52-855c81a58cd2")
+    @utils.services("compute", "network")
+    @testtools.skipUnless(
+        CONF.bgpvpn.l3vpn_endpoint and CONF.bgpvpn.route_target,
+        "Required ip address of L3 endpoint and route target.",
+    )
+    def test_bgpvpn_l3vpn_endpoint(self):
+        """This test checks L3VPN connectivity.
+
+        1. Create network with respective subnet
+        2. Start up server
+        4. Associate network to a given L3 BGPVPN
+        5. Create router and connect it to network
+        6. Give a FIP to server
+        7. Check that server can ping l3vpn endpoint
+        """
+
+        self._create_networks_and_subnets(
+            subnet_cidr=CONF.bgpvpn.l3vpn_subnet_cidr
+        )
+        self._create_server()
+        self._create_bgpvpn(rts=CONF.bgpvpn.route_target)
+        self._associate_all_nets_to_bgpvpn()
+        self._associate_fip_and_check_bgpvpn(
+            CONF.bgpvpn.l3vpn_endpoint.split("/")[0]
+        )
+
+    def _create_networks_and_subnets(
+        self, name="bgp", subnet_cidr=None, port_security=True
+    ):
+        self.network = self._create_network(
+            namestart=name, port_security_enabled=port_security
+        )
+        self.subnet = self._create_subnet_with_cidr(
+            self.network, cidr=subnet_cidr, ip_version=4
+        )
+        self._reserve_ip_address(subnet_cidr.split("/")[0], self.os_primary)
+
+    def _create_subnet_with_cidr(
+        self, network, subnets_client=None, namestart="subnet-bgp", **kwargs
+    ):
+        if not subnets_client:
+            subnets_client = self.subnets_client
+        subnet = dict(
+            name=data_utils.rand_name(namestart),
+            network_id=network["id"],
+            tenant_id=network["tenant_id"],
+            **kwargs
+        )
+        result = subnets_client.create_subnet(**subnet)
+        self.assertIsNotNone(result, "Unable to allocate tenant network")
+        subnet = result["subnet"]
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            subnets_client.delete_subnet,
+            subnet["id"],
+        )
+        return subnet
+
+    def _create_fip_router(
+        self, client=None, public_network_id=None, subnet_id=None
+    ):
+        router = self._create_router(client, namestart="router-")
+        router_id = router["id"]
+        if public_network_id is None:
+            public_network_id = CONF.network.public_network_id
+        if client is None:
+            client = self.routers_client
+        kwargs = {"external_gateway_info": {"network_id": public_network_id}}
+        router = client.update_router(router_id, **kwargs)["router"]
+        if subnet_id is not None:
+            client.add_router_interface(router_id, subnet_id=subnet_id)
+            self.addCleanup(
+                test_utils.call_and_ignore_notfound_exc,
+                client.remove_router_interface,
+                router_id,
+                subnet_id=subnet_id,
+            )
+        return router
+
+    def _create_router_and_associate_fip(self, subnet):
+        router = self._create_fip_router(subnet_id=subnet["id"])
+        self.server_fip = self.create_floating_ip(
+            self.server, external_network_id=CONF.network.public_network_id
+        )
+        return router
+
+    def _reserve_ip_address(self, ip_address, clients):
+        create_port_kwargs = {
+            "fixed_ips": [{"ip_address": ip_address}],
+            "namestart": "port-endpoint",
+        }
+        self._create_port(
+            network_id=self.network["id"],
+            client=clients.ports_client,
+            **create_port_kwargs
+        )
+
+    def _create_server(self, name="server-bgp", port_security=True):
+        self.keypair = self.create_keypair()
+        security_group_name = self.security_group["name"]
+        clients = self.os_primary
+
+        security_groups = {}
+        if port_security:
+            security_groups = {
+                "security_groups": [{"name": security_group_name}]
+            }
+
+        create_server_kwargs = {
+            "key_name": self.keypair["name"],
+            "networks": [{"uuid": self.network["id"]}],
+            **security_groups,
+        }
+        body, _ = compute.create_test_server(
+            clients, wait_until="ACTIVE", name=name, **create_server_kwargs
+        )
+        self.addCleanup(
+            waiters.wait_for_server_termination,
+            clients.servers_client,
+            body["id"],
+        )
+        self.addCleanup(
+            test_utils.call_and_ignore_notfound_exc,
+            clients.servers_client.delete_server,
+            body["id"],
+        )
+        self.server = clients.servers_client.show_server(body["id"])["server"]
+        LOG.debug(
+            "Created server: %s with status: %s",
+            self.server["id"],
+            self.server["status"],
+        )
+
+    def _create_bgpvpn(
+        self,
+        name="test-bgpvpn",
+        type="l3",
+        rts=None,
+        import_rts=None,
+        export_rts=None,
+        vni=None,
+    ):
+        import_rts = import_rts or []
+        export_rts = export_rts or []
+        self.bgpvpn = self.create_bgpvpn(
+            self.bgpvpn_admin_client,
+            tenant_id=self.bgpvpn_client.tenant_id,
+            name=name,
+            route_targets=rts,
+            export_targets=export_rts,
+            import_targets=import_rts,
+            type=type,
+            vni=vni,
+        )
+        return self.bgpvpn
+
+    def _associate_all_nets_to_bgpvpn(self, bgpvpn=None):
+        bgpvpn = bgpvpn or self.bgpvpn
+        self.bgpvpn_client.create_network_association(
+            bgpvpn["id"], self.network["id"]
+        )
+        LOG.debug("BGPVPN network associations completed")
+
+    def _setup_ssh_client(self, server):
+        server_fip = self.server_fip["floating_ip_address"]
+        private_key = self.keypair["private_key"]
+        ssh_client = self.get_remote_client(
+            server_fip, private_key=private_key
+        )
+        return ssh_client
+
+    def _check_bgpvpn(self, from_server=None, to_server_ip=None):
+        from_server = from_server or self.server
+        from_server_ip = self.server_fip["floating_ip_address"]
+        ssh_client = self._setup_ssh_client(from_server)
+        msg = "Timed out waiting for {ip} to become reachable".format(
+            ip=to_server_ip
+        )
+        try:
+            result = self._check_remote_connectivity(
+                ssh_client, to_server_ip, True
+            )
+            self.assertTrue(result, msg)
+        except Exception:
+            LOG.exception(
+                "Error validating connectivity to %s "
+                "from VM with IP address %s: %s",
+                to_server_ip,
+                from_server_ip,
+                msg,
+            )
+            raise
+
+    def _associate_fip_and_check_bgpvpn(self, to_server_ip=None):
+        self.router = self._create_router_and_associate_fip(self.subnet)
+        self._check_bgpvpn(to_server_ip=to_server_ip)
diff --git a/neutron_tempest_plugin/config.py b/neutron_tempest_plugin/config.py
index 4fad1fa..e5d7eb7 100644
--- a/neutron_tempest_plugin/config.py
+++ b/neutron_tempest_plugin/config.py
@@ -184,6 +184,22 @@
                default=200,
                help=("Maximum number for the range of "
                      "assigned number for distinguishers.")),
+    cfg.StrOpt('l3vpn_endpoint',
+               default=None,
+               help=("IP Address/Mask, which will be used to "
+                     "test the l3vpn connectivity.")),
+    cfg.StrOpt('l3vpn_subnet_cidr',
+               default="192.168.0.254/24",
+               help=("IP Address/Mask, which will be used as private network"
+                     "test the l3vpn connectivity.")),
+    cfg.StrOpt('l2vpn_endpoint',
+               default=None,
+               help=("IP Address/Mask, which will be used to "
+                     "test the l2vpn connectivity.")),
+    cfg.StrOpt('route_target',
+               default=None,
+               help=("Route-target (RT) extended community attributes "
+                     "identify the VPN membership of routes.")),
 ]
 
 bgpvpn_group = cfg.OptGroup(name="bgpvpn", title=("Networking-Bgpvpn Service "