[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 "