[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)
(cherry picked from commit 28d5c8e96532b295610216db3a0b97103f6db590)
(cherry picked from commit 0b5ce0d378b1772e2bc9c3127232a163d6b91928)
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 8136e47..74f7c03 100644
--- a/neutron_tempest_plugin/config.py
+++ b/neutron_tempest_plugin/config.py
@@ -194,6 +194,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 "