Single/Multinode VPNaaS Scenario Tests using Rally

(a) Refactored the code to work with the following cases
    1. Single node with DVR
    2. Single node without DVR
    3. Multinode with DVR
    4. Multinode without DVR
|-------------|-------------------------------------------------------|
|             |                Single Node/ Multinode Tests           |
| Scenarios   |-------------------------------------------------------|
|             | DVR | DVR+Concurrency | Non DVR | Non DVR+Concurrency |
|-------------|-----|-----------------|---------|---------------------|
| Vpn Basic   |  x  |      x          |    x    |         x           |
| Multi Tenant|  x  |      x          |    x    |         x           |
| Vpn Status  |  x  |      x          |    x    |         x           |
|-------------|-----|-----------------|---------|---------------------|

(b) Used the paramiko package to execute commands over ssh.

(c) Moved the README to devref

Depends-On: Id3f199d688d648f4618a6850d094e26ca6bb9a7f
Change-Id: I24d5a8435f06014fa9164bef518cac62bbb70ef9
This commit is contained in:
Aishwarya Thangappa 2016-02-11 14:31:32 -08:00
parent e6f643f2a1
commit 22205d681e
11 changed files with 982 additions and 539 deletions

View File

@ -34,7 +34,6 @@ VPNaaS Flavors
Info on the different Swan flavors, how they are different, and what Info on the different Swan flavors, how they are different, and what
Operating Systems support them. Operating Systems support them.
VPNaaS Internals VPNaaS Internals
----------------- -----------------
.. toctree:: .. toctree::
@ -42,6 +41,13 @@ VPNaaS Internals
multiple-local-subnets multiple-local-subnets
VPNaaS Rally Tests
--------------------
.. toctree::
:maxdepth: 3
vpnaas-rally-test
Testing Testing
------- -------
.. toctree:: .. toctree::
@ -54,7 +60,6 @@ Testing
Add notes about functional testing, with info on how Add notes about functional testing, with info on how
different reference drivers are tested. different reference drivers are tested.
Module Reference Module Reference
---------------- ----------------
.. toctree:: .. toctree::

View File

@ -0,0 +1,67 @@
===================
VPNaaS Rally Tests
===================
This contains the rally test codes for the Neutron VPN as a Service (VPNaaS) service. The tests
currently require rally to be installed via devstack or standalone. It is assumed that you
also have Neutron with the Neutron VPNaaS service installed.
These tests could also be run against a multinode openstack.
Please see /neutron-vpnaas/devstack/README.md for the required devstack configuration settings
for Neutron-VPNaaS.
Structure:
==========
1. plugins - Directory where you can add rally plugins. Almost everything in Rally is a plugin.
Contains base, common methods and actual scenario tests
2. rally-configs - Contains input configurations for the scenario tests
How to test:
============
Included in the repo are rally tests. For information on rally, please see the rally README :
https://github.com/openstack/rally/blob/master/README.rst
* Create a rally deployment for your cloud and make sure it is active.
rally deployment create --file=cloud_cred.json --name=MyCloud
You can also create a rally deployment from the environment variables.
rally deployment create --fromenv --name=MyCloud
* Create a folder structure as below
sudo mkdir /opt/rally
* Create a symbolic link to the plugins directory
cd /opt/rally
sudo ln -s /opt/stack/neutron-vpnaas/rally-jobs/plugins
* Run the tests. You can run the tests in various combinations.
(a) Single Node with DVR with admin credentials
(b) Single Node with DVR with non admin credentials
(c) Multi Node with DVR with admin credentials
(d) Multi Node with DVR with non admin credentials
(e) Single Node, Non DVR with admin credentials
(f) Multi Node, Non DVR with admin credentials
-> Create a args.json file with the correct credentials depending on whether it is a
single node or multinode cloud. A args_template.json file is available at
/opt/stack/neutron-vpnaas/rally-jobs/rally-configs/args_template.json for your reference.
-> Update the rally_config_dvr.yaml or rally_config_non_dvr.yaml file to change the
admin/non_admin credentials.
-> Use the appropriate config files to run either dvr or non_dvr tests.
With DVR:
rally task start /opt/stack/neutron-vpnaas/rally-jobs/rally-configs/rally_config_dvr.yaml
--task-args-file /opt/stack/neutron-vpnaas/rally-jobs/rally-configs/args.json
Non DVR:
rally task start /opt/stack/neutron-vpnaas/rally-jobs/rally-configs/rally_config_non_dvr.yaml
--task-args-file /opt/stack/neutron-vpnaas/rally-jobs/rally-configs/args.json
**Note:**
Non DVR scenario can only be run as admin as you need admin credentials to create
a non DVR router.
External Resources:
===================
For more information on the rally testing framework see: <https://github.com/openstack/rally>

View File

@ -1,36 +0,0 @@
Welcome!
========
This contains rally testing code for the Neutron VPN as a Service (VPNaaS) service. The tests
currently require rally to be installed via devstack or standalone. It is assumed that you
also have Neutron with the Neutron VPNaaS service installed.
Please see /neutron-vpnaas/devstack/README.md for the required devstack configuration settings
for Neutron-VPNaaS.
Structure:
==========
1. plugins - Directory where you can add rally plugins. Almost everything in Rally is a plugin.
Contains base, common methods and actual scenario tests
2. rally-configs - Contains input config for the scenario tests
How to test:
============
Included in the repo are rally tests. For information on rally, please see the rally README :
https://github.com/openstack/rally/blob/master/README.rst
* Create the folder structure as below
$> sudo mkdir /opt/rally
* Create a symbolic link to the plugin
$> cd /opt/rally
$> sudo ln -s /opt/stack/neutron-vpnaas/rally-jobs/plugins
* Run the tests
$> rally task start /opt/stack/neutron-vpnaas/rally-jobs/rally-configs/rally_config.yaml
External Resources:
===================
For more information on the rally testing framework see: <https://github.com/openstack/rally>

View File

@ -14,22 +14,20 @@
from neutron_vpnaas._i18n import _LI from neutron_vpnaas._i18n import _LI
from rally.common import log as logging from rally.common import log as logging
from rally.task import scenario from rally.task import scenario
from rally.task import types as types from rally.task import types as types
import vpn_base
import vpn_base
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class VpnBasicScenario(vpn_base.VpnBase): class TestVpnBasicScenario(vpn_base.VpnBase):
"""Rally scenarios for VPNaaS""" """Rally scenarios for VPNaaS"""
@types.set(image=types.ImageResourceType, @types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType) flavor=types.FlavorResourceType)
@scenario.configure() @scenario.configure()
def create_and_delete_vpn_connection( def create_and_delete_vpn_connection(self, **kwargs):
self, **kwargs):
"""Basic VPN connectivity scenario. """Basic VPN connectivity scenario.
1. Create 2 private networks, subnets and routers 1. Create 2 private networks, subnets and routers
@ -44,10 +42,10 @@ class VpnBasicScenario(vpn_base.VpnBase):
8. Create VPN service at each of the routers 8. Create VPN service at each of the routers
9. Create IPSEC site connections at both endpoints 9. Create IPSEC site connections at both endpoints
10. Verify that the ipsec-site-connection is ACTIVE (takes upto 30secs) 10. Verify that the ipsec-site-connection is ACTIVE (takes upto 30secs)
11. To verify the vpn connectivity, get into the first snat 11. To verify the vpn connectivity, get into the peer router's snat
namespace and start a tcpdump at the qg-xxxx interface namespace and start a tcpdump at the qg-xxxx interface
12. SSH into the second instance from the second qrouter namespace 12. SSH into the nova instance from the local qrouter namespace
and try to ping the first instance and try to ping the nova instance on the peer network.
14. Verify that the captured packets are encapsulated and encrypted. 14. Verify that the captured packets are encapsulated and encrypted.
15. Verify the connectivity in the reverse direction following the 15. Verify the connectivity in the reverse direction following the
steps 11 through 13 steps 11 through 13
@ -55,16 +53,17 @@ class VpnBasicScenario(vpn_base.VpnBase):
""" """
try: try:
self.setup() self.setup(**kwargs)
self.create_networks_and_servers(**kwargs) self.create_networks(**kwargs)
self.create_servers(**kwargs)
self.check_route() self.check_route()
self.ike_policy = self._create_ike_policy(**kwargs) self.ike_policy = self._create_ike_policy(**kwargs)
self.ipsec_policy = self._create_ipsec_policy(**kwargs) self.ipsec_policy = self._create_ipsec_policy(**kwargs)
self.create_vpn_services() self.create_vpn_services()
self.create_ipsec_site_connections(**kwargs) self.create_ipsec_site_connections(**kwargs)
self.assert_statuses(final_status='ACTIVE', **kwargs) self.assert_statuses(final_status='ACTIVE', **kwargs)
self.assert_vpn_connectivity() self.verify_vpn_connectivity(**kwargs)
LOG.info(_LI("VPN CONNECTIVITY TEST PASSED!!")) LOG.info(_LI("VPN CONNECTIVITY TEST PASSED!"))
finally: finally:
self.cleanup() self.cleanup()

View File

@ -12,17 +12,21 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron_vpnaas._i18n import _LI
from rally.common import log as logging
from rally.task import scenario from rally.task import scenario
from rally.task import types as types from rally.task import types as types
import vpn_base import vpn_base
LOG = logging.getLogger(__name__)
class TestVPNStatusScenario(vpn_base.VpnBase):
class TestVpnStatusScenario(vpn_base.VpnBase):
@types.set(image=types.ImageResourceType, @types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType) flavor=types.FlavorResourceType)
@scenario.configure() @scenario.configure()
def check_vpn_status( def check_vpn_status(self, **kwargs):
self, **kwargs):
"""Test VPN's status correctly after bringing router's status to """Test VPN's status correctly after bringing router's status to
DOWN and back to ACTIVE state DOWN and back to ACTIVE state
@ -45,8 +49,8 @@ class TestVPNStatusScenario(vpn_base.VpnBase):
""" """
try: try:
self.setup() self.setup(**kwargs)
self.create_networks_and_servers(**kwargs) self.create_networks(**kwargs)
self.check_route() self.check_route()
self.ike_policy = self._create_ike_policy(**kwargs) self.ike_policy = self._create_ike_policy(**kwargs)
self.ipsec_policy = self._create_ipsec_policy(**kwargs) self.ipsec_policy = self._create_ipsec_policy(**kwargs)
@ -59,6 +63,7 @@ class TestVPNStatusScenario(vpn_base.VpnBase):
self.update_router(self.router_ids[0], admin_state_up=True) self.update_router(self.router_ids[0], admin_state_up=True)
self.update_router(self.router_ids[1], admin_state_up=True) self.update_router(self.router_ids[1], admin_state_up=True)
self.assert_statuses(final_status='ACTIVE', **kwargs) self.assert_statuses(final_status='ACTIVE', **kwargs)
LOG.info(_LI("VPN STATUS TEST PASSED!"))
finally: finally:
self.cleanup() self.cleanup()

View File

@ -12,21 +12,24 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from neutron_vpnaas._i18n import _LI
from rally.common import log as logging
from rally.task import scenario from rally.task import scenario
from rally.task import types as types from rally.task import types as types
import vpn_base import vpn_base
LOG = logging.getLogger(__name__)
class VpnTenantScenario(vpn_base.VpnBase):
class TestVpnTenantScenario(vpn_base.VpnBase):
"""Rally scenarios for VPNaaS""" """Rally scenarios for VPNaaS"""
@types.set(image=types.ImageResourceType, @types.set(image=types.ImageResourceType,
flavor=types.FlavorResourceType) flavor=types.FlavorResourceType)
@scenario.configure() @scenario.configure()
def multitenants_vpn_test( def multitenants_vpn_test(self, **kwargs):
self, **kwargs): """Test VPN connectivity under two different tenants.
"""Basic VPN connectivity scenario.
1. Create 2 private networks with 2 different tenants, subnets, routers 1. Create 2 private networks with 2 different tenants, subnets, routers
2. Create public network, subnets and GW IPs on routers, if not present 2. Create public network, subnets and GW IPs on routers, if not present
@ -41,19 +44,19 @@ class VpnTenantScenario(vpn_base.VpnBase):
9. Create IPSEC site connections at both endpoints 9. Create IPSEC site connections at both endpoints
10. Verify that the vpn-service and ipsec-site-connection are ACTIVE 10. Verify that the vpn-service and ipsec-site-connection are ACTIVE
11. Cleanup the resources that are setup for this test 11. Cleanup the resources that are setup for this test
""" """
try: try:
self.setup(use_admin_client=True) self.setup(**kwargs)
self.create_tenant() self.create_tenants()
self.create_networks_and_servers(**kwargs) self.create_networks(**kwargs)
self.check_route() self.check_route()
self.ike_policy = self._create_ike_policy(**kwargs) self.ike_policy = self._create_ike_policy(**kwargs)
self.ipsec_policy = self._create_ipsec_policy(**kwargs) self.ipsec_policy = self._create_ipsec_policy(**kwargs)
self.create_vpn_services() self.create_vpn_services()
self.create_ipsec_site_connections(**kwargs) self.create_ipsec_site_connections(**kwargs)
self.assert_statuses(final_status='ACTIVE', **kwargs) self.assert_statuses(final_status='ACTIVE', **kwargs)
LOG.info(_LI("VPN TENANT TEST PASSED!"))
finally: finally:
self.cleanup() self.cleanup()

View File

@ -14,8 +14,8 @@
import concurrent.futures import concurrent.futures
import exceptions import exceptions
import multiprocessing
import re import re
import threading
import time import time
from oslo_utils import uuidutils from oslo_utils import uuidutils
@ -26,19 +26,35 @@ from rally.task import atomic
import vpn_utils import vpn_utils
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
LOCK = multiprocessing.RLock() LOCK = threading.RLock()
MAX_RESOURCES = 2 MAX_RESOURCES = 2
class VpnBase(rally_base.OpenStackScenario): class VpnBase(rally_base.OpenStackScenario):
def setup(self, use_admin_client=False): def setup(self, **kwargs):
"""Creates and initializes data structures to hold various resources """Create and initialize data structures to hold various resources"""
:param use_admin_client: Use admin client when it is set to True
""" with LOCK:
LOG.debug('SETUP RESOURCES')
self.neutron_admin_client = self.admin_clients("neutron")
if kwargs['use_admin_client']:
self.neutron_client = self.neutron_admin_client
self.keystone_client = self.admin_clients("keystone")
self.nova_client = self.admin_clients("nova")
else:
self.neutron_client = self.clients("neutron")
self.nova_client = self.clients("nova")
self.suffixes = [uuidutils.generate_uuid(),
uuidutils.generate_uuid()]
self.remote_key_files = ['rally_keypair_' + x
for x in self.suffixes]
self.local_key_files = ['/tmp/' + x for x in self.remote_key_files]
self.private_key_file = kwargs["private_key"]
self.keypairs = []
self.tenant_ids = [] self.tenant_ids = []
self.snat_namespaces = [] self.ns_controller_tuples = []
self.qrouter_namespaces = [] self.qrouterns_compute_tuples = []
self.router_ids = [] self.router_ids = []
self.rally_router_gw_ips = [] self.rally_router_gw_ips = []
self.rally_routers = [] self.rally_routers = []
@ -51,43 +67,114 @@ class VpnBase(rally_base.OpenStackScenario):
self.ipsec_site_connections = [] self.ipsec_site_connections = []
self.servers = [] self.servers = []
self.server_private_ips = [] self.server_private_ips = []
self.suffixes = [uuidutils.generate_uuid(), uuidutils.generate_uuid()] self.server_fips = []
self.tenant_names = map(lambda x: "rally_tenant_" + x, self.suffixes)
self.key_names = map(lambda x: "rally_keypair_" + x, self.suffixes)
self.key_file_paths = map(lambda x: '/tmp/' + x, self.key_names)
self.nova_client = self.clients("nova")
self.neutron_client = self.clients("neutron")
self.neutron_admin_client = self.admin_clients("neutron")
if use_admin_client is True:
self.neutron_client = self.admin_clients("neutron")
self.keystone_client = self.admin_clients("keystone")
self.nova_client = self.admin_clients("nova")
@atomic.action_timer("cleanup") def create_tenants(self):
def cleanup(self): """Create tenants"""
"""Cleans up all the resources"""
vpn_utils.delete_servers(self.nova_client, self.servers) for x in range(MAX_RESOURCES):
vpn_utils.delete_hosts_from_knownhosts_file(self.server_private_ips) tenant_id = vpn_utils.create_tenant(
vpn_utils.delete_key_files(self.key_file_paths) self.keystone_client, self.suffixes[x])
self._delete_ipsec_site_connections() with LOCK:
self._delete_vpn_services() self.tenant_ids.append(tenant_id)
self._delete_ipsec_policy()
self._delete_ike_policy() def create_networks(self, **kwargs):
vpn_utils.delete_network( """Create networks to test vpn connectivity"""
self.neutron_client, self.neutron_admin_client, self.rally_routers,
self.rally_networks, self.rally_subnets) for x in range(MAX_RESOURCES):
if self.tenant_ids: if self.tenant_ids:
vpn_utils.delete_tenant(self.keystone_client, router, network, subnet, cidr = vpn_utils.create_network(
self.tenant_ids) self.neutron_client, self.neutron_admin_client,
self.suffixes[x], tenant_id=self.tenant_ids[x],
DVR_flag=kwargs["DVR_flag"],
ext_net_name=kwargs["ext-net"])
else:
router, network, subnet, cidr = vpn_utils.create_network(
self.neutron_client, self.neutron_admin_client,
self.suffixes[x], DVR_flag=kwargs["DVR_flag"],
ext_net_name=kwargs["ext-net"])
with LOCK:
self.rally_cidrs.append(cidr)
self.rally_subnets.append(subnet)
self.rally_networks.append(network)
self.rally_routers.append(router)
self.router_ids.append(router["router"]['id'])
self.rally_router_gw_ips.append(
router["router"]["external_gateway_info"]
["external_fixed_ips"][0]["ip_address"])
if(kwargs["DVR_flag"]):
ns, controller = vpn_utils.wait_for_namespace_creation(
"snat-", router["router"]['id'],
kwargs['controller_creds'],
self.private_key_file,
kwargs['namespace_creation_timeout'])
else:
ns, controller = vpn_utils.wait_for_namespace_creation(
"qrouter-", router["router"]['id'],
kwargs['controller_creds'],
self.private_key_file,
kwargs['namespace_creation_timeout'])
with LOCK:
self.ns_controller_tuples.append((ns, controller))
def create_servers(self, **kwargs):
"""Create servers"""
for x in range(MAX_RESOURCES):
kwargs.update({
"nics":
[{"net-id": self.rally_networks[x]["network"]["id"]}],
"sec_group_suffix": self.suffixes[x],
"server_suffix": self.suffixes[x]
})
keypair = vpn_utils.create_keypair(
self.nova_client, self.suffixes[x])
server = vpn_utils.create_server(
self.nova_client, keypair, **kwargs)
vpn_utils.assert_server_status(server, **kwargs)
with LOCK:
self.servers.append(server)
self.keypairs.append(keypair)
self.server_private_ips.append(vpn_utils.get_server_ip(
self.nova_client, server.id, self.suffixes[x]))
if(kwargs["DVR_flag"]):
qrouter, compute = vpn_utils.wait_for_namespace_creation(
"qrouter-", self.router_ids[x],
kwargs['compute_creds'],
self.private_key_file,
kwargs['namespace_creation_timeout'])
vpn_utils.write_key_to_compute_node(
keypair, self.local_key_files[x],
self.remote_key_files[x], compute,
self.private_key_file)
with LOCK:
self.qrouterns_compute_tuples.append((qrouter, compute))
else:
vpn_utils.write_key_to_local_path(self.keypairs[x],
self.local_key_files[x])
fip = vpn_utils.add_floating_ip(self.nova_client, server)
with LOCK:
self.server_fips.append(fip)
def check_route(self):
"""Verify route exists between the router gateways"""
LOG.debug("VERIFY ROUTE EXISTS BETWEEN THE ROUTER GATEWAYS")
for tuple in self.ns_controller_tuples:
for ip in self.rally_router_gw_ips:
assert(vpn_utils.ping_router_gateway(
tuple, ip, self.private_key_file)), (
"PING TO IP " + ip + " FAILED")
@atomic.action_timer("_create_ike_policy") @atomic.action_timer("_create_ike_policy")
def _create_ike_policy(self, **kwargs): def _create_ike_policy(self, **kwargs):
"""Creates IKE policy """Create IKE policy
:return: IKE policy :return: IKE policy
""" """
LOG.debug("CREATING IKE_POLICY") LOG.debug('CREATING IKE_POLICY')
ike_policy = self.neutron_client.create_ikepolicy({ ike_policy = self.neutron_client.create_ikepolicy({
"ikepolicy": { "ikepolicy": {
"phase1_negotiation_mode": "phase1_negotiation_mode":
@ -107,11 +194,11 @@ class VpnBase(rally_base.OpenStackScenario):
@atomic.action_timer("_create_ipsec_policy") @atomic.action_timer("_create_ipsec_policy")
def _create_ipsec_policy(self, **kwargs): def _create_ipsec_policy(self, **kwargs):
"""Creates IPSEC policy """Create IPSEC policy
:return: IPSEC policy :return: IPSEC policy
""" """
LOG.debug("CREATING IPSEC_POLICY") LOG.debug('CREATING IPSEC_POLICY')
ipsec_policy = self.neutron_client.create_ipsecpolicy({ ipsec_policy = self.neutron_client.create_ipsecpolicy({
"ipsecpolicy": { "ipsecpolicy": {
"name": "rally_ipsecpolicy", "name": "rally_ipsecpolicy",
@ -131,16 +218,15 @@ class VpnBase(rally_base.OpenStackScenario):
return ipsec_policy return ipsec_policy
@atomic.action_timer("_create_vpn_service") @atomic.action_timer("_create_vpn_service")
def _create_vpn_service(self, rally_subnet, def _create_vpn_service(self, rally_subnet, rally_router, vpn_suffix=None):
rally_router, vpn_suffix=None): """Create VPN service endpoints
"""Creates VPN service endpoints
:param rally_subnet: local subnet :param rally_subnet: local subnet
:param rally_router: router endpoint :param rally_router: router endpoint
:param vpn_suffix: suffix name for vpn service :param vpn_suffix: suffix name for vpn service
:return: VPN service :return: VPN service
""" """
LOG.debug("CREATING VPN_SERVICE") LOG.debug('CREATING VPN_SERVICE')
vpn_service = self.neutron_client.create_vpnservice({ vpn_service = self.neutron_client.create_vpnservice({
"vpnservice": { "vpnservice": {
"subnet_id": rally_subnet["subnet"]["id"], "subnet_id": rally_subnet["subnet"]["id"],
@ -151,16 +237,24 @@ class VpnBase(rally_base.OpenStackScenario):
}) })
return vpn_service return vpn_service
def create_vpn_services(self):
"""Create VPN services"""
for x in range(MAX_RESOURCES):
vpn_service = self._create_vpn_service(
self.rally_subnets[x], self.rally_routers[x], self.suffixes[x])
with LOCK:
self.vpn_services.append(vpn_service)
@atomic.action_timer("_create_ipsec_site_connection") @atomic.action_timer("_create_ipsec_site_connection")
def _create_ipsec_site_connection(self, local_index, def _create_ipsec_site_connection(self, local_index, peer_index, **kwargs):
peer_index, **kwargs): """Create IPSEC site connection
"""Creates IPSEC site connection
:param local_index: parameter to point to the local end-point :param local_index: parameter to point to the local end-point
:param peer_index: parameter to point to the peer end-point :param peer_index: parameter to point to the peer end-point
:return: IPSEC site connection :return: IPSEC site connection
""" """
LOG.debug("CREATING IPSEC_SITE_CONNECTION") LOG.debug('CREATING IPSEC_SITE_CONNECTION')
ipsec_site_conn = self.neutron_client.create_ipsec_site_connection({ ipsec_site_conn = self.neutron_client.create_ipsec_site_connection({
"ipsec_site_connection": { "ipsec_site_connection": {
"psk": kwargs.get("secret", "secret"), "psk": kwargs.get("secret", "secret"),
@ -185,26 +279,31 @@ class VpnBase(rally_base.OpenStackScenario):
}) })
return ipsec_site_conn return ipsec_site_conn
def create_ipsec_site_connections(self, **kwargs):
"""Create IPSEC site connections"""
a = self._create_ipsec_site_connection(0, 1, **kwargs)
b = self._create_ipsec_site_connection(1, 0, **kwargs)
with LOCK:
self.ipsec_site_connections = [a, b]
def _get_resource(self, resource_tag, resource_id): def _get_resource(self, resource_tag, resource_id):
"""Gets the resource(vpn_service or ipsec_site_connection) """Get the resource(vpn_service or ipsec_site_connection)
:param resource_tag: "vpnservice" or "ipsec_site_connection" :param resource_tag: "vpnservice" or "ipsec_site_connection"
:param resource_id: id of the resource :param resource_id: id of the resource
:return: resource (vpn_service or ipsec_site_connection) :return: resource (vpn_service or ipsec_site_connection)
""" """
if resource_tag == "vpnservice": if resource_tag == "vpnservice":
vpn_service = self.neutron_client.show_vpnservice( vpn_service = self.neutron_client.show_vpnservice(resource_id)
resource_id)
if vpn_service: if vpn_service:
return vpn_service return vpn_service
elif resource_tag == 'ipsec_site_connection': elif resource_tag == 'ipsec_site_connection':
ipsec_site_conn = \ ipsec_site_conn = self.neutron_client.show_ipsec_site_connection(
self.neutron_client.show_ipsec_site_connection(
resource_id) resource_id)
if ipsec_site_conn: if ipsec_site_conn:
return ipsec_site_conn return ipsec_site_conn
@atomic.action_timer("_wait_for_status_change")
def _wait_for_status_change(self, resource, resource_tag, final_status, def _wait_for_status_change(self, resource, resource_tag, final_status,
wait_timeout=60, check_interval=1): wait_timeout=60, check_interval=1):
"""Wait for resource's status change """Wait for resource's status change
@ -220,10 +319,12 @@ class VpnBase(rally_base.OpenStackScenario):
change change
:return: resource :return: resource
""" """
LOG.debug('WAIT_FOR_%s_STATUS_CHANGE ', resource[resource_tag]['id'])
start_time = time.time() start_time = time.time()
while True: while True:
resource = self._get_resource(resource_tag, resource = self._get_resource(
resource[resource_tag]['id']) resource_tag, resource[resource_tag]['id'])
current_status = resource[resource_tag]['status'] current_status = resource[resource_tag]['status']
if current_status == final_status: if current_status == final_status:
return resource return resource
@ -231,9 +332,9 @@ class VpnBase(rally_base.OpenStackScenario):
if time.time() - start_time > wait_timeout: if time.time() - start_time > wait_timeout:
raise exceptions.Exception( raise exceptions.Exception(
"Timeout waiting for resource {} to change to {} status". "Timeout waiting for resource {} to change to {} status".
format(resource[resource_tag]['name'], final_status) format(resource[resource_tag]['name'], final_status))
)
@atomic.action_timer("wait_time_for_status_change")
def _assert_statuses(self, ipsec_site_conn, vpn_service, def _assert_statuses(self, ipsec_site_conn, vpn_service,
final_status, **kwargs): final_status, **kwargs):
"""Assert statuses of vpn_service and ipsec_site_connection """Assert statuses of vpn_service and ipsec_site_connection
@ -258,67 +359,106 @@ class VpnBase(rally_base.OpenStackScenario):
check_interval=5) check_interval=5)
LOG.debug("VPN SERVICE STATUS %s", vpn_service['vpnservice']['status']) LOG.debug("VPN SERVICE STATUS %s", vpn_service['vpnservice']['status'])
LOG.debug("IPSEC_SITE_CONNECTION STATUS: %s", LOG.debug("IPSEC_SITE_CONNECTION STATUS %s",
ipsec_site_conn['ipsec_site_connection']['status']) ipsec_site_conn['ipsec_site_connection']['status'])
self._validate_status(vpn_service, ipsec_site_conn, final_status) def assert_statuses(self, final_status, **kwargs):
"""Assert active statuses for VPN services and VPN connections
def _validate_status(self, vpn_service, ipsec_site_conn, final_status): :param final_status: the final status you expect the resource to be in
"""Validate the statuses of vpn_service, ipsec_site_connection and
evaluate the final_status
:param ipsec_site_conn: ipsec_site_connection of an instance
:param vpn_service: vpn_service of an instance
:param final_status: status of vpn and ipsec_site_connection instance
""" """
assert(final_status == vpn_service['vpnservice']['status']), ( LOG.debug("ASSERTING ACTIVE STATUSES FOR VPN-SERVICES AND "
"VPN SERVICE IS NOT IN %s STATE" % final_status) "IPSEC-SITE-CONNECTIONS")
assert(final_status == ipsec_site_conn['ipsec_site_connection'] for x in range(MAX_RESOURCES):
['status']), ("THE IPSEC SITE CONNECTION IS NOT IN %s STATE" self._assert_statuses(
% final_status) self.ipsec_site_connections[x], self.vpn_services[x],
final_status, **kwargs)
def _get_qg_interface(self, peer_index):
"""Get the qg- interface
:param peer_index: parameter to point to the local end-point
:return: qg-interface
"""
qg = vpn_utils.get_interfaces(
self.ns_controller_tuples[peer_index],
self.private_key_file)
p = re.compile(r"qg-\w+-\w+")
for line in qg:
m = p.search(line)
if m:
return m.group()
return None
@atomic.action_timer("_verify_vpn_connection") @atomic.action_timer("_verify_vpn_connection")
def _verify_vpn_connection(self, local_index, peer_index): def _verify_vpn_connectivity(self, local_index, peer_index, **kwargs):
"""Verifies the vpn connectivity between the endpoints """Verify the vpn connectivity between the endpoints
Get the qg- interface from the snat namespace corresponding to the
peer router and start a tcp dump. Concurrently, SSH into the nova
instance on the local subnet from the qrouter namespace and try
to ping the nova instance on the peer subnet. Inspect the captured
packets to see if they are encrypted.
:param local_index: parameter to point to the local end-point :param local_index: parameter to point to the local end-point
:param peer_index: parameter to point to the peer end-point :param peer_index: parameter to point to the peer end-point
:return: True or False :return: True if vpn connectivity test passes
False if the test fails
""" """
qg = vpn_utils.get_interfaces(self.snat_namespaces[peer_index]) qg_interface = self._get_qg_interface(peer_index)
if qg:
p = re.compile(r"qg-\w+-\w+")
m = p.search(qg)
if m:
qg_interface = m.group()
else:
qg_interface = None
if qg_interface: if qg_interface:
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as e: with concurrent.futures.ThreadPoolExecutor(max_workers=2) as e:
tcpdump_future = e.submit(vpn_utils.start_tcpdump, tcpdump_future = e.submit(vpn_utils.start_tcpdump,
self.snat_namespaces[peer_index], self.ns_controller_tuples[peer_index],
qg_interface) qg_interface, self.private_key_file)
ssh_future = e.submit(vpn_utils.ssh_and_ping_server, if(kwargs["DVR_flag"]):
ssh_future = e.submit(
vpn_utils.ssh_and_ping_server,
self.server_private_ips[local_index], self.server_private_ips[local_index],
self.server_private_ips[peer_index], self.server_private_ips[peer_index],
self.qrouter_namespaces[local_index], self.qrouterns_compute_tuples[local_index],
self.key_file_paths[local_index]) self.remote_key_files[local_index],
self.private_key_file)
else:
ssh_future = e.submit(
vpn_utils.ssh_and_ping_server_with_fip,
self.server_fips[local_index],
self.server_private_ips[peer_index],
self.local_key_files[local_index],
self.private_key_file)
assert(ssh_future.result()), "SSH/Ping failed" assert(ssh_future.result()), "SSH/Ping failed"
lines = tcpdump_future.result().split('\n') for line in tcpdump_future.result():
for line in lines:
if 'ESP' in line: if 'ESP' in line:
return True return True
return False return False
def verify_vpn_connectivity(self, **kwargs):
"""Verify VPN connectivity"""
LOG.debug("VERIFY THE VPN CONNECTIVITY")
with LOCK:
assert(self._verify_vpn_connectivity(
0, 1, **kwargs)), "VPN CONNECTION FAILED"
with LOCK:
assert(self._verify_vpn_connectivity(
1, 0, **kwargs)), "VPN CONNECTION FAILED"
def update_router(self, router_id, admin_state_up=False):
"""Update router's admin_state_up field
:param router_id: uuid of the router
:param admin_state_up: True or False
"""
LOG.debug('UPDATE ROUTER')
router_args = {'router': {'admin_state_up': admin_state_up}}
self.neutron_client.update_router(router_id, router_args)
@atomic.action_timer("_delete_ipsec_site_connection") @atomic.action_timer("_delete_ipsec_site_connection")
def _delete_ipsec_site_connections(self): def _delete_ipsec_site_connections(self):
"""Deletes IPSEC site connections""" """Delete IPSEC site connections"""
if self.ipsec_site_connections:
for site_conn in self.ipsec_site_connections: for site_conn in self.ipsec_site_connections:
if "rally" in (site_conn['ipsec_site_connection']['name']):
LOG.debug("DELETING IPSEC_SITE_CONNECTION %s", LOG.debug("DELETING IPSEC_SITE_CONNECTION %s",
site_conn['ipsec_site_connection']['id']) site_conn['ipsec_site_connection']['id'])
self.neutron_client.delete_ipsec_site_connection( self.neutron_client.delete_ipsec_site_connection(
@ -326,11 +466,9 @@ class VpnBase(rally_base.OpenStackScenario):
@atomic.action_timer("_delete_vpn_service") @atomic.action_timer("_delete_vpn_service")
def _delete_vpn_services(self): def _delete_vpn_services(self):
"""Deletes VPN service endpoints""" """Delete VPN service endpoints"""
if self.vpn_services:
for vpn_service in self.vpn_services: for vpn_service in self.vpn_services:
if "rally" in vpn_service['vpnservice']['name']:
LOG.debug("DELETING VPN_SERVICE %s", LOG.debug("DELETING VPN_SERVICE %s",
vpn_service['vpnservice']['id']) vpn_service['vpnservice']['id'])
self.neutron_client.delete_vpnservice( self.neutron_client.delete_vpnservice(
@ -338,127 +476,49 @@ class VpnBase(rally_base.OpenStackScenario):
@atomic.action_timer("_delete_ipsec_policy") @atomic.action_timer("_delete_ipsec_policy")
def _delete_ipsec_policy(self): def _delete_ipsec_policy(self):
"""Deletes IPSEC policy """Delete IPSEC policy"""
:param ipsec_policy: ipsec_policy object
:return:
"""
LOG.debug("DELETING IPSEC POLICY") LOG.debug("DELETING IPSEC POLICY")
if (self.ipsec_policy and if self.ipsec_policy:
"rally" in self.ipsec_policy['ipsecpolicy']['name']):
self.neutron_client.delete_ipsecpolicy( self.neutron_client.delete_ipsecpolicy(
self.ipsec_policy['ipsecpolicy']['id']) self.ipsec_policy['ipsecpolicy']['id'])
@atomic.action_timer("_delete_ike_policy") @atomic.action_timer("_delete_ike_policy")
def _delete_ike_policy(self): def _delete_ike_policy(self):
"""Deletes IKE policy """Delete IKE policy"""
:param ike_policy: ike_policy object LOG.debug('DELETING IKE POLICY')
:return: if self.ike_policy:
"""
LOG.debug("DELETING IKE POLICY")
if (self.ike_policy and
"rally" in self.ike_policy['ikepolicy']['name']):
self.neutron_client.delete_ikepolicy( self.neutron_client.delete_ikepolicy(
self.ike_policy['ikepolicy']['id']) self.ike_policy['ikepolicy']['id'])
def create_tenant(self): @atomic.action_timer("cleanup")
"""Creates tenant def cleanup(self):
"""Clean the resources"""
:param keystone_client: keystone_admin_client vpn_utils.delete_servers(self.nova_client, self.servers)
:param tenant_ids: append created tenant id into the list if self.server_fips:
:return: vpn_utils.delete_floating_ips(self.nova_client, self.server_fips)
""" vpn_utils.delete_keypairs(self.nova_client, self.keypairs)
with LOCK:
for x in range(MAX_RESOURCES):
self.tenant_ids.append((vpn_utils.create_tenant(
self.keystone_client,
self.tenant_names[x])).id)
def create_networks_and_servers(self, **kwargs): if self.qrouterns_compute_tuples:
with LOCK: vpn_utils.delete_hosts_from_knownhosts_file(
keypairs = [] self.server_private_ips, self.qrouterns_compute_tuples,
for x in range(MAX_RESOURCES): self.private_key_file)
if self.tenant_ids: vpn_utils.delete_keyfiles(
router, network, subnet, cidr = vpn_utils.create_network( self.local_key_files, self.remote_key_files,
self.neutron_client, self.neutron_admin_client, self.qrouterns_compute_tuples, self.private_key_file)
self.suffixes[x], self.tenant_ids[x])
else: else:
router, network, subnet, cidr = vpn_utils.create_network( vpn_utils.delete_hosts_from_knownhosts_file(
self.neutron_client, self.neutron_admin_client, self.server_private_ips)
self.suffixes[x]) vpn_utils.delete_keyfiles(self.local_key_files)
self.rally_cidrs.append(cidr)
self.rally_subnets.append(subnet)
self.rally_networks.append(network)
self.rally_routers.append(router)
self.router_ids.append(router["router"]['id'])
self.rally_router_gw_ips.append(
router["router"]["external_gateway_info"]
["external_fixed_ips"][0]["ip_address"])
self.snat_namespaces.append(
vpn_utils.wait_for_namespace_creation(
"snat-", router, **kwargs))
self.qrouter_namespaces.append(
vpn_utils.wait_for_namespace_creation(
"qrouter-", router, **kwargs))
keypairs.append(vpn_utils.create_keypair(
self.nova_client, self.key_names[x],
self.key_file_paths[x]))
kwargs.update({ self._delete_ipsec_site_connections()
"nics": self._delete_vpn_services()
[{"net-id": self.rally_networks[x]["network"]["id"]}], self._delete_ipsec_policy()
"sec_group_suffix": self.suffixes[x], self._delete_ike_policy()
"server_suffix": self.suffixes[x] vpn_utils.delete_networks(
}) self.neutron_client, self.neutron_admin_client, self.rally_routers,
server = vpn_utils.create_nova_vm( self.rally_networks, self.rally_subnets)
self.nova_client, keypairs[x], **kwargs) if self.tenant_ids:
self.server_private_ips.append(vpn_utils.get_server_ip( vpn_utils.delete_tenants(self.keystone_client, self.tenant_ids)
self.nova_client, server.id, self.suffixes[x]))
self.servers.append(server)
def check_route(self):
LOG.debug("VERIFYING THAT THERE IS A ROUTE BETWEEN ROUTER "
"GATEWAYS")
for ns in self.snat_namespaces:
for ip in self.rally_router_gw_ips:
assert(True == vpn_utils.ping(ns, ip)), (
"PING FAILED FROM NAMESPACE " + ns + " TO IP "
+ ip)
def update_router(self, router_id, admin_state_up=False):
"""Updates router
:param router_id: router id
:param admin_state_up: update 'admin_state_up' of the router
:return:
"""
req_body = {'router': {'admin_state_up': admin_state_up}}
self.neutron_client.update_router(router_id, req_body)
def create_vpn_services(self):
with LOCK:
for x in range(MAX_RESOURCES):
self.vpn_services.append(self._create_vpn_service(
self.rally_subnets[x], self.rally_routers[x],
self.suffixes[x]))
def create_ipsec_site_connections(self, **kwargs):
with LOCK:
self.ipsec_site_connections = [
self._create_ipsec_site_connection(0, 1, **kwargs),
self._create_ipsec_site_connection(1, 0, **kwargs)
]
def assert_statuses(self, final_status, **kwargs):
LOG.debug("ASSERTING ACTIVE STATUSES FOR VPN-SERVICES AND "
"VPN-CONNECTIONS")
for x in range(MAX_RESOURCES):
self._assert_statuses(self.ipsec_site_connections[x],
self.vpn_services[x], final_status, **kwargs)
def assert_vpn_connectivity(self):
LOG.debug("VERIFY THE VPN CONNECTIVITY")
with LOCK:
assert(self._verify_vpn_connection(0, 1)), "VPN CONNECTION FAILED"
assert(self._verify_vpn_connection(1, 0)), "VPN CONNECTION FAILED"

View File

@ -14,17 +14,11 @@
import exceptions import exceptions
import os import os
from oslo_config import cfg import paramiko
import socket
import stat import stat
import time import time
def noop(*args, **kwargs):
pass
cfg.CONF.register_cli_opts = noop
from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils as linux_utils
from rally.common import log as logging from rally.common import log as logging
from rally.plugins.openstack.wrappers import network as network_wrapper from rally.plugins.openstack.wrappers import network as network_wrapper
from rally.task import utils as task_utils from rally.task import utils as task_utils
@ -35,13 +29,71 @@ START_CIDR = "10.2.0.0/24"
EXT_NET_CIDR = "172.16.1.0/24" EXT_NET_CIDR = "172.16.1.0/24"
def create_network(neutron_client, neutron_admin_client, def execute_cmd_over_ssh(host, cmd, private_key):
network_suffix, tenant_id=None): """Run the given command over ssh
"""Creates neutron network, subnet, router
Using paramiko package, it creates a connection to the given host;
executes the required command on it and returns the output.
:param host: Dictionary of ip, username and password
:param cmd: Command to be run over ssh
:param private_key: path to private key file
:return: Output of the executed command
"""
LOG.debug('EXECUTE COMMAND <%s> OVER SSH', cmd)
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
k = paramiko.RSAKey.from_private_key_file(private_key)
try:
client.connect(host["ip"], username=host["username"], pkey=k)
except paramiko.BadHostKeyException as e:
raise exceptions.Exception(
"BADHOSTKEY EXCEPTION WHEN CONNECTING TO %s", host["ip"], e)
except paramiko.AuthenticationException as e:
raise exceptions.Exception(
"AUTHENTICATION EXCEPTION WHEN CONNECTING TO %s",
host["ip"], e)
except paramiko.SSHException as e:
raise exceptions.Exception(
"SSH EXCEPTION WHEN CONNECTING TO %s", host["ip"], e)
except socket.error as e:
raise exceptions.Exception(
"SOCKET ERROR WHEN CONNECTING TO %s", host["ip"], e)
LOG.debug("CONNECTED TO HOST <%s>", host["ip"])
try:
stdin, stdout, stderr = client.exec_command(cmd)
return stdout.read().splitlines()
except paramiko.SSHException as e:
raise exceptions.Exception(
"SSHEXCEPTION WHEN CONNECTING TO %s", host["ip"], e)
finally:
client.close()
def create_tenant(keystone_client, tenant_suffix):
"""Creates keystone tenant with a random name.
:param keystone_client: keystone client
:param tenant_suffix: suffix name for the tenant
:returns: uuid of the new tenant
"""
tenant_name = "rally_tenant_" + tenant_suffix
LOG.debug("CREATING NEW TENANT %s", tenant_name)
return keystone_client.tenants.create(tenant_name).id
def create_network(neutron_client, neutron_admin_client, network_suffix,
tenant_id=None, DVR_flag=True, ext_net_name=None):
"""Create neutron network, subnet, router
:param neutron_client: neutron client :param neutron_client: neutron client
:param neutron_admin_client: neutron_admin_client :param neutron_admin_client: neutron client with admin credentials
:param network_suffix: str, suffix name of the new network :param network_suffix: str, suffix name of the new network
:param tenant_id: uuid of the tenant
:param DVR_flag: True - creates a DVR router
False - creates a non DVR router
:param ext_net_name: external network that is to be used
:return: router, subnet, network, subnet_cidr :return: router, subnet, network, subnet_cidr
""" """
subnet_cidr = network_wrapper.generate_cidr(start_cidr=START_CIDR) subnet_cidr = network_wrapper.generate_cidr(start_cidr=START_CIDR)
@ -53,15 +105,13 @@ def create_network(neutron_client, neutron_admin_client,
network_args = {"name": network_name, network_args = {"name": network_name,
"router:external": is_external "router:external": is_external
} }
LOG.debug("ADDING NEW NETWORK: %s", network_name) if tenant_id:
if tenant_id is not None:
network_args["tenant_id"] = tenant_id network_args["tenant_id"] = tenant_id
LOG.debug("ADDING NEW NETWORK %s", network_name)
return neutron_client.create_network({"network": network_args}) return neutron_client.create_network({"network": network_args})
def _create_subnet(neutron_client, rally_network, network_suffix, cidr): def _create_subnet(neutron_client, rally_network, network_suffix, cidr):
"""Creates neutron subnet""" """Create neutron subnet"""
network_id = rally_network["network"]["id"] network_id = rally_network["network"]["id"]
subnet_name = "rally_subnet_" + network_suffix subnet_name = "rally_subnet_" + network_suffix
@ -70,19 +120,19 @@ def create_network(neutron_client, neutron_admin_client,
"network_id": network_id, "network_id": network_id,
"ip_version": SUBNET_IP_VERSION "ip_version": SUBNET_IP_VERSION
} }
LOG.debug("ADDING SUBNET: %s", subnet_name) if tenant_id:
if tenant_id is not None:
subnet_args["tenant_id"] = tenant_id subnet_args["tenant_id"] = tenant_id
LOG.debug("ADDING SUBNET %s", subnet_name)
return neutron_client.create_subnet({"subnet": subnet_args}) return neutron_client.create_subnet({"subnet": subnet_args})
def _create_router(neutron_client, ext_network_id, rally_subnet): def _create_router(neutron_client, ext_network_id, rally_subnet, dvr_flag):
"""Creates router, sets the external gateway and adds router interface """Create router, set the external gateway and add router interface
:param neutron_client: neutron_client :param neutron_client: neutron_client
:param ext_network_id: uuid of the external network :param ext_network_id: uuid of the external network
:param rally_subnet: subnet to add router interface :param rally_subnet: subnet to add router interface
:param dvr_flag: True - creates a DVR router
False - creates a non DVR router
:return: router :return: router
""" """
router_name = "rally_router_" + network_suffix router_name = "rally_router_" + network_suffix
@ -90,81 +140,134 @@ def create_network(neutron_client, neutron_admin_client,
router_args = {"name": router_name, router_args = {"name": router_name,
"external_gateway_info": gw_info "external_gateway_info": gw_info
} }
LOG.debug("ADDING ROUTER: %s", router_name) if not dvr_flag:
LOG.debug("ADDING ROUTER INTERFACE") router_args["distributed"] = dvr_flag
if tenant_id:
if tenant_id is not None:
router_args["tenant_id"] = 'tenant_id' router_args["tenant_id"] = 'tenant_id'
LOG.debug("ADDING ROUTER %s", router_name)
rally_router = neutron_client.create_router({"router": router_args})
rally_router = neutron_client.create_router( LOG.debug("[%s]: ADDING ROUTER INTERFACE")
{"router": router_args})
neutron_client.add_interface_router( neutron_client.add_interface_router(
rally_router['router']["id"], rally_router['router']["id"],
{"subnet_id": rally_subnet["subnet"]["id"]}) {"subnet_id": rally_subnet["subnet"]["id"]})
return rally_router return rally_router
def _get_external_network_id(): def _get_external_network_id(ext_net_name):
"""Fetches the external network id, if external network exists""" """Fetch the network id for the given external network, if it exists.
Else fetch the first external network present.
"""
for network in neutron_client.list_networks()['networks']: ext_nets = neutron_client.list_networks(
if network['router:external']: **{'router:external': True})['networks']
ext_network_id = network['id']
LOG.debug("EXTERNAL NETWORK ALREADY EXISTS") ext_nets_searched = [n for n in ext_nets if n['name'] == ext_net_name]
return ext_network_id if ext_nets_searched:
return ext_nets_searched[0]['id']
elif ext_nets:
return ext_nets[0]['id']
else:
return None
def _create_external_network(): def _create_external_network():
"""Creates external network and subnet""" """Creat external network and subnet"""
ext_net = _create_network(neutron_admin_client, "public", True) ext_net = _create_network(neutron_admin_client, "public", True)
_create_subnet(neutron_admin_client, ext_net, "public", EXT_NET_CIDR) _create_subnet(neutron_admin_client, ext_net, "public", EXT_NET_CIDR)
return ext_net['network']['id'] return ext_net['network']['id']
ext_network_id = _get_external_network_id() ext_network_id = _get_external_network_id(ext_net_name)
if not ext_network_id: if not ext_network_id:
ext_network_id = _create_external_network() ext_network_id = _create_external_network()
rally_network = _create_network(neutron_client, network_suffix) rally_network = _create_network(neutron_client, network_suffix)
rally_subnet = _create_subnet(neutron_client, rally_network, rally_subnet = _create_subnet(neutron_client, rally_network,
network_suffix, subnet_cidr) network_suffix, subnet_cidr)
rally_router = _create_router(neutron_client, ext_network_id, rally_subnet) rally_router = _create_router(neutron_client, ext_network_id,
rally_subnet, DVR_flag)
return rally_router, rally_network, rally_subnet, subnet_cidr return rally_router, rally_network, rally_subnet, subnet_cidr
def create_tenant(keystone_client, tenant): def create_keypair(nova_client, keypair_suffix):
"""Creates keystone tenant with random name.
:param tenant: create a tenant with random name
:returns:
"""
return keystone_client.tenants.create(tenant)
def delete_tenant(keystone_client, tenant):
"""Deletes keystone tenant
:returns: delete keystone tenant instance
"""
if tenant:
for id in tenant:
keystone_client.tenants.delete(id)
def create_keypair(nova_client, key_name, key_file_path):
"""Create keypair """Create keypair
:param nova_client: nova_client :param nova_client: nova_client
:param key_name: key_name :param keypair_suffix: sufix name for the keypair
:param key_file_path: path to key_file
:return: keypair :return: keypair
""" """
LOG.debug("ADDING NEW KEYPAIR") keypair_name = "rally_keypair_" + keypair_suffix
keypair = nova_client.keypairs.create(key_name) LOG.debug("CREATING A KEYPAIR %s", keypair_name)
f = open(key_file_path, 'w') keypair = nova_client.keypairs.create(keypair_name)
os.chmod(key_file_path, stat.S_IREAD | stat.S_IWRITE)
f.write(keypair.private_key)
f.close()
return keypair return keypair
def create_nova_vm(nova_client, keypair, **kwargs): def write_key_to_local_path(keypair, local_key_file):
"""Write the private key of the nova instance to a temp file
:param keypair: nova keypair
:param local_key_file: path to private key file
:return:
"""
with open(local_key_file, 'w') as f:
os.chmod(local_key_file, stat.S_IREAD | stat.S_IWRITE)
f.write(keypair.private_key)
def write_key_to_compute_node(keypair, local_path, remote_path, host,
private_key):
"""Write the private key of the nova instance to the compute node
First fetches the private key from the keypair and writes it to a
temporary file in the local machine. It then sftp's the file
to the compute host.
:param keypair: nova keypair
:param local_path: path to private key file of the nova instance in the
local machine
:param remote_path: path where the private key file has to be placed
in the remote machine
:param host: compute host credentials
:param private_key: path to your private key file
:return:
"""
LOG.debug("WRITING PRIVATE KEY TO COMPUTE NODE")
k = paramiko.RSAKey.from_private_key_file(private_key)
write_key_to_local_path(keypair, local_path)
try:
transport = paramiko.Transport(host['ip'], host['port'])
except paramiko.SSHException as e:
raise exceptions.Exception(
"PARAMIKO TRANSPORT FAILED. CHECK IF THE HOST IP %s AND PORT %s "
"ARE CORRECT %s", host['ip'], host['port'], e)
try:
transport.connect(
username=host['username'], pkey=k)
except paramiko.BadHostKeyException as e:
transport.close()
raise exceptions.Exception(
"BADHOSTKEY EXCEPTION WHEN CONNECTING TO %s", host["ip"], e)
except paramiko.AuthenticationException as e:
transport.close()
raise exceptions.Exception(
"AUTHENTICATION EXCEPTION WHEN CONNECTING TO %s",
host["ip"], e)
except paramiko.SSHException as e:
transport.close()
raise exceptions.Exception(
"SSH EXCEPTION WHEN CONNECTING TO %s", host["ip"], e)
LOG.debug("CONNECTED TO HOST <%s>", host["ip"])
try:
sftp_client = paramiko.SFTPClient.from_transport(transport)
sftp_client.put(local_path, remote_path)
except IOError as e:
raise exceptions.Exception("FILE PATH DOESN'T EXIST", e)
finally:
transport.close()
def create_server(nova_client, keypair, **kwargs):
"""Create nova instance """Create nova instance
:param nova_client: nova client :param nova_client: nova client
@ -172,10 +275,10 @@ def create_nova_vm(nova_client, keypair, **kwargs):
:return: new nova instance :return: new nova instance
""" """
# add sec-group # add sec-group
sec_group_suffix = "rally_secgroup_" + kwargs["sec_group_suffix"] sec_group_name = "rally_secgroup_" + kwargs["sec_group_suffix"]
LOG.debug("ADDING NEW SECURITY GROUP %s", sec_group_suffix) LOG.debug("ADDING NEW SECURITY GROUP %s", sec_group_name)
secgroup = nova_client.security_groups.create(sec_group_suffix, secgroup = nova_client.security_groups.create(sec_group_name,
sec_group_suffix) sec_group_name)
# add security rules for SSH and ICMP # add security rules for SSH and ICMP
nova_client.security_group_rules.create(secgroup.id, from_port=22, nova_client.security_group_rules.create(secgroup.id, from_port=22,
to_port=22, ip_protocol="tcp", cidr="0.0.0.0/0") to_port=22, ip_protocol="tcp", cidr="0.0.0.0/0")
@ -186,14 +289,23 @@ def create_nova_vm(nova_client, keypair, **kwargs):
# boot new nova instance # boot new nova instance
server_name = "rally_server_" + (kwargs["server_suffix"]) server_name = "rally_server_" + (kwargs["server_suffix"])
LOG.debug("BOOTING NEW INSTANCE: %s", server_name) LOG.debug("BOOTING NEW INSTANCE: %s", server_name)
LOG.debug("%s", kwargs["image"])
server = nova_client.servers.create(server_name, server = nova_client.servers.create(server_name,
image=kwargs["image"], image=kwargs["image"],
flavor=kwargs["flavor"], flavor=kwargs["flavor"],
key_name=keypair.name, key_name=keypair.name,
security_groups=[secgroup.id], security_groups=[secgroup.id],
nics=kwargs["nics"]) nics=kwargs["nics"])
return server
LOG.debug("WAITING FOR INSTANCE TO BECOME ACTIVE")
def assert_server_status(server, **kwargs):
"""Assert server status
:param server: nova server
"""
LOG.debug('WAITING FOR SERVER TO GO ACTIVE')
server = task_utils.wait_for( server = task_utils.wait_for(
server, server,
is_ready=task_utils.resource_is("ACTIVE"), is_ready=task_utils.resource_is("ACTIVE"),
@ -201,10 +313,7 @@ def create_nova_vm(nova_client, keypair, **kwargs):
timeout=kwargs["nova_server_boot_timeout"], timeout=kwargs["nova_server_boot_timeout"],
check_interval=5) check_interval=5)
LOG.debug("SERVER STATUS: %s", server.status) LOG.debug("SERVER STATUS: %s", server.status)
assert('ACTIVE' == server.status), ("THE INSTANCE IS NOT IN ACTIVE STATE")
assert('ACTIVE' == server.status), (
"THE INSTANCE IS NOT IN ACTIVE STATE")
return server
def get_server_ip(nova_client, server_id, network_suffix): def get_server_ip(nova_client, server_id, network_suffix):
@ -221,147 +330,199 @@ def get_server_ip(nova_client, server_id, network_suffix):
return server_ip return server_ip
def get_namespace(): def add_floating_ip(nova_client, server):
"""Get namespaces """Associates floating-ip to a server
:param nova_client: nova client
:param server: nova instance
:return: associated floating ip
"""
fip_list = nova_client.floating_ips.list()
for fip in fip_list:
if fip.instance_id is None:
floating_ip = fip
break
else:
LOG.debug("CREATING NEW FLOATING IP")
floating_ip = nova_client.floating_ips.create()
LOG.debug("ASSOCIATING FLOATING IP %s", floating_ip.ip)
nova_client.servers.add_floating_ip(server.id, floating_ip.ip)
return floating_ip
def get_namespace(host, private_key):
"""SSH into the host and get the namespaces
:param host : dictionary of controller/compute node credentials
{ip:x.x.x.x, username:xxx, password:xxx}
:param private_key: path to private key file
:return: namespaces :return: namespaces
""" """
LOG.debug("GET NAMESPACES USING 'ip netns'") LOG.debug("GET NAMESPACES")
cmd = ['ip', 'netns'] cmd = "sudo ip netns"
cmd = ip_lib.add_namespace_to_cmd(cmd) namespaces = execute_cmd_over_ssh(host, cmd, private_key)
try: LOG.debug("NAMESPACES %s", namespaces)
namespaces = linux_utils.execute(cmd)
except RuntimeError:
return None
LOG.debug("%s", namespaces)
return namespaces return namespaces
def wait_for_namespace_creation(namespace, rally_router, **kwargs): def wait_for_namespace_creation(namespace_tag, router_id, hosts, private_key,
"""Wait for namespace creation timeout=60):
"""Wait for the namespace creation
:param namespace: snat/qrouter namespace Get into each of the controllers/compute nodes and check which one contains
:param rally_router: rally_router the snat/qrouter namespace corresponding to rally_router. Sleep for a sec
and repeat until either the namespace is found or the namespace_creation_
time exceeded.
:param namespace_tag: which namespace ("snat_" or "qrouter_")
:param router_id: uuid of the rally_router
:param hosts: controllers or compute hosts
:param private_key: path to private key file
:param timeout: namespace creation time
:return: :return:
""" """
start_time = time.time() start_time = time.time()
while True: while True:
namespaces = get_namespace().split() for host in hosts:
namespaces = get_namespace(host, private_key)
for line in namespaces: for line in namespaces:
if line == (namespace + rally_router["router"]["id"]): if line == (namespace_tag + router_id):
namespace = line namespace_tag = line
return namespace return namespace_tag, host
time.sleep(1) time.sleep(1)
if time.time() - start_time > kwargs['namespace_creation_timeout']: if time.time() - start_time > timeout:
raise exceptions.Exception("Timeout while waiting for" raise exceptions.Exception("TIMEOUT WHILE WAITING FOR"
" namespaces to be created") " NAMESPACES TO BE CREATED")
def ping(namespace, ip): def ping(host, cmd, private_key):
"""Pings ip address from network namespace. """Execute ping command over ssh"""
ping_result = execute_cmd_over_ssh(host, cmd, private_key)
In order to ping it uses following cli command: if ping_result:
ip netns exec <namespace> ping -c 4 -q <ip> LOG.debug("PING RESULT %s", ping_result)
:param namespace: namespace
:param ip: ip to ping to
"""
LOG.debug("PING %s FROM THE NAMESPACE %s", ip, namespace)
count = 4
cmd = ['ping', '-w', 2 * count, '-c', count, ip]
cmd = ip_lib.add_namespace_to_cmd(cmd, namespace)
try:
ping_result = linux_utils.execute(cmd, run_as_root=True)
except RuntimeError:
return False
LOG.debug("%s", ping_result)
return True return True
else:
return False
def get_interfaces(namespace): def ping_router_gateway(namespace_controller_tuple, router_gw_ip, private_key):
"""Do an "ip a". """Ping the ip address from network namespace
In order to do "ip a" it uses following cli command: Get into controller's snat-namespaces and ping the peer router gateway ip.
ip netns exec <namespace> ip a | grep qg :param namespace_controller_tuple: namespace, controller tuple. (It's the
:param namespace: namespace controller that contains the namespace )
:param router_gw_ip: ip address to be pinged
:param private_key: path to private key file
:return: True if ping succeeds
False if ping fails
"""
namespace, controller = namespace_controller_tuple
LOG.debug("PING %s FROM THE NAMESPACE %s", router_gw_ip, namespace)
count = 4
cmd = "sudo ip netns exec {} ping -w {} -c {} {}".format(
namespace, 2 * count, count, router_gw_ip)
return ping(controller, cmd, private_key)
def get_interfaces(namespace_controller_tuple, private_key):
"""Get the interfaces
Get into the controller's snat namespace and list the interfaces.
:param namespace_controller_tuple: namespace, controller tuple(the
controller that contains the namespace).
:param private_key: path to private key file
:return: interfaces :return: interfaces
""" """
namespace, controller = namespace_controller_tuple
LOG.debug("GET THE INTERFACES BY USING 'ip a' FROM THE NAMESPACE %s", LOG.debug("GET THE INTERFACES BY USING 'ip a' FROM THE NAMESPACE %s",
namespace) namespace)
cmd = ['ip', 'a'] cmd = "sudo ip netns exec {} ip a".format(namespace)
cmd = ip_lib.add_namespace_to_cmd(cmd, namespace) interfaces = execute_cmd_over_ssh(controller, cmd, private_key)
try: LOG.debug("INTERFACES %s", interfaces)
interfaces = linux_utils.execute(cmd, run_as_root=True)
except RuntimeError:
return None
LOG.debug("%s", interfaces)
return interfaces return interfaces
def start_tcpdump(namespace, interface): def start_tcpdump(namespace_controller_tuple, interface, private_key):
"""Starts tcpdump at the given interface """Start the tcpdump at the given interface
In order to start a "tcpdump" it uses the following command: Get into the controller's snat namespace and start a tcp dump at the
ip netns exec <namespace> sudo tcpdump -i <interface> qg-interface.
:param namespace: namespace :param namespace_controller_tuple: namespace, controller tuple. (It's the
:param interface: interface controller that contains the namespace )
:return: tcpdump :param interface: interface in which tcpdump has to be run
:param private_key: path to private key file
:return: tcpdump output
""" """
LOG.debug("START THE TCPDUMP USING 'tcpdump -i <%s> FROM THE NAMESPACE" namespace, controller = namespace_controller_tuple
LOG.debug("START THE TCPDUMP USING 'tcpdump -i %s FROM THE NAMESPACE"
" %s", interface, namespace) " %s", interface, namespace)
cmd = ['timeout', '5', 'tcpdump', '-n', '-i', interface] cmd = ("sudo ip netns exec {} timeout 15 tcpdump -n -i {}"
cmd = ip_lib.add_namespace_to_cmd(cmd, namespace) .format(namespace, interface))
try: tcpdump = execute_cmd_over_ssh(controller, cmd, private_key)
tcpdump = linux_utils.execute(cmd, run_as_root=True, LOG.debug("TCPDUMP %s", tcpdump)
extra_ok_codes=[124])
except RuntimeError:
return None
LOG.debug("%s", tcpdump)
return tcpdump return tcpdump
def ssh_and_ping_server(ssh_server, ping_server, namespace, key_file_name): def ssh_and_ping_server(local_server, peer_server, ns_compute_tuple, keyfile,
"""SSH into the server from the namespace. private_key):
"""SSH and ping the nova instance from the namespace
In order to ssh it uses the following command: Get into the compute node's qrouter namespace and then ssh into the local
ip netns exec <namespace> ssh -i <path to keyfile> cirros@<server_ip> nova instance & ping the peer nova instance.
:param ssh_server: ip of the server to ssh into :param local_server: private ip of the server to ssh into
:param ping_server: ip of the server to ping to :param peer_server: private ip of the server to ping to
:param namespace: qrouter namespace :param ns_compute_tuple: namespace, compute tuple. (It's the
:param key_file_name: path to private key file compute node that contains the namespace )
:return: True/False :param keyfile: path to private key file of the nova instance
:param private_key: path to private key file
:return: True if ping succeeds
False if ping fails
""" """
namespace, compute_host = ns_compute_tuple
LOG.debug("SSH INTO SERVER %s AND PING THE PEER SERVER %s FROM THE" LOG.debug("SSH INTO SERVER %s AND PING THE PEER SERVER %s FROM THE"
" NAMESPACE %s", ssh_server, ping_server, namespace) " NAMESPACE %s", local_server, peer_server, namespace)
host = "cirros@" + ssh_server host = "cirros@" + local_server
count = 20 count = 20
cmd = ['ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'HashKnownHosts=no', cmd = ("sudo ip netns exec {} ssh -v -o StrictHostKeyChecking=no -o"
'-i', key_file_name, host, 'ping', '-w', 2 * count, '-c', count, "HashKnownHosts=no -i {} {} ping -w {} -c {} {}"
ping_server] .format(namespace, keyfile, host, 2 * count, count, peer_server))
cmd = ip_lib.add_namespace_to_cmd(cmd, namespace) return ping(compute_host, cmd, private_key)
try:
ping_result = linux_utils.execute(cmd, run_as_root=True)
except RuntimeError: def ssh_and_ping_server_with_fip(local_server, peer_server, keyfile,
return False private_key):
LOG.debug("%s", ping_result) """SSH into the local nova instance and ping the peer instance using fips
return True
:param local_server: fip of the server to ssh into
:param peer_server: private ip of the server to ping to
:param keyfile: path to private key file of the nova instance
:param private_key: path to private key file
:return: True if ping succeeds
False if ping fails
"""
LOG.debug("SSH INTO LOCAL SERVER %s AND PING THE PEER SERVER %s",
local_server.ip, peer_server)
count = 20
local_host = {"ip": "127.0.0.1", "username": None}
host = "cirros@" + local_server.ip
cmd = ("ssh -v -o StrictHostKeyChecking=no -o"
"HashKnownHosts=no -i {} {} ping -w {} -c {} {}"
.format(keyfile, host, 2 * count, count, peer_server))
return ping(local_host, cmd, private_key)
def delete_servers(nova_client, servers): def delete_servers(nova_client, servers):
"""Delete nova servers """Delete nova servers
It deletes the nova servers, associated security groups and keypairs. It deletes the nova servers, associated security groups.
:param nova_client: nova client :param nova_client: nova client
:param servers: nova instances to be deleted :param servers: nova instances to be deleted
:return: :return:
""" """
if servers:
for server in servers: for server in servers:
if "rally" in server.name:
sec_group_name = server.security_groups[0]['name']
server_key_name = server.key_name
LOG.debug("DELETING NOVA INSTANCE: %s", server.id) LOG.debug("DELETING NOVA INSTANCE: %s", server.id)
sec_group_id = server.security_groups[0]['name']
nova_client.servers.delete(server.id) nova_client.servers.delete(server.id)
LOG.debug("WAITING FOR INSTANCE TO GET DELETED") LOG.debug("WAITING FOR INSTANCE TO GET DELETED")
@ -369,19 +530,37 @@ def delete_servers(nova_client, servers):
server, update_resource=task_utils.get_from_manager()) server, update_resource=task_utils.get_from_manager())
for secgroup in nova_client.security_groups.list(): for secgroup in nova_client.security_groups.list():
if secgroup.name == sec_group_name: if secgroup.id == sec_group_id:
LOG.debug("DELETING SEC_GROUP: %s", sec_group_name) LOG.debug("DELETING SEC_GROUP: %s", sec_group_id)
nova_client.security_groups.delete(secgroup.id) nova_client.security_groups.delete(secgroup.id)
for key_pair in nova_client.keypairs.list():
if key_pair.name == server_key_name: def delete_floating_ips(nova_client, fips):
LOG.debug("DELETING KEY_PAIR: %s", server_key_name) """Delete floating ips
:param nova_client: nova client
:param fips: list of floating ips
:return:
"""
for fip in fips:
nova_client.floating_ips.delete(fip.id)
def delete_keypairs(nova_client, keypairs):
"""Delete key pairs
:param nova_client: nova client
:param keypairs: list of keypairs
:return
"""
for key_pair in keypairs:
LOG.debug("DELETING KEY_PAIR %s", key_pair.name)
nova_client.keypairs.delete(key_pair.id) nova_client.keypairs.delete(key_pair.id)
def delete_network(neutron_client, neutron_admin_client, def delete_networks(neutron_client, neutron_admin_client,
routers, networks, subnets): routers, networks, subnets):
"""Delete neutron network, subnets amd routers. """Delete neutron network, subnets amd routers
:param neutron_client: neutron client :param neutron_client: neutron client
:param neutron_admin_client: neutron_admin_client :param neutron_admin_client: neutron_admin_client
@ -391,14 +570,10 @@ def delete_network(neutron_client, neutron_admin_client,
:return :return
""" """
LOG.debug("DELETING RALLY ROUTER INTERFACES & GATEWAYS") LOG.debug("DELETING RALLY ROUTER INTERFACES & GATEWAYS")
if routers:
for router in routers: for router in routers:
if "rally" in router['router']['name']:
neutron_client.remove_gateway_router(router['router']['id']) neutron_client.remove_gateway_router(router['router']['id'])
router_name = router['router']['name'] router_name = router['router']['name']
subnet_name = ("rally_subnet_" + subnet_name = ("rally_subnet_" + router_name[13:len(router_name)])
router_name[13:len(router_name)])
if subnets:
for subnet in subnets: for subnet in subnets:
if subnet_name == subnet['subnet']['name']: if subnet_name == subnet['subnet']['name']:
neutron_client.remove_interface_router( neutron_client.remove_interface_router(
@ -406,49 +581,76 @@ def delete_network(neutron_client, neutron_admin_client,
{"subnet_id": subnet['subnet']['id']}) {"subnet_id": subnet['subnet']['id']})
LOG.debug("DELETING RALLY ROUTERS") LOG.debug("DELETING RALLY ROUTERS")
if routers:
for router in routers: for router in routers:
if "rally" in router['router']['name']:
neutron_client.delete_router(router['router']['id']) neutron_client.delete_router(router['router']['id'])
LOG.debug("DELETING RALLY NETWORKS") LOG.debug("DELETING RALLY NETWORKS")
if networks:
for network in networks: for network in networks:
if (network['network']['router:external'] and if (network['network']['router:external'] and
network['network']['name'] == "rally_network_public"): network['network']['name'] == "rally_network_public"):
external_network = network external_network = network
neutron_admin_client.delete_network( neutron_admin_client.delete_network(
external_network['network']["id"]) external_network['network']["id"])
if "rally_network" in network['network']['name']: elif network['network']['router:external']:
pass
else:
neutron_client.delete_network(network['network']['id']) neutron_client.delete_network(network['network']['id'])
def delete_key_files(key_file_paths): def delete_tenants(keystone_client, tenant_ids):
"""Deletes ssh key files """Delete keystone tenant
:param key_file_paths: paths to ssh key files :param keystone_client: keystone client
:param tenant_ids: list of tenants' uuids
:returns: delete keystone tenant instance
"""
LOG.debug('DELETE TENANTS')
for id in tenant_ids:
keystone_client.tenants.delete(id)
def delete_keyfiles(local_key_files, remote_key_files=None,
ns_compute_tuples=None, private_key=None):
"""Delete the SSH keyfiles from the compute and the local nodes
:param local_key_files: paths to ssh key files in local node
:param remote_key_files: paths to ssh key files in compute nodes
:param ns_compute_tuples: namespace, compute tuple. (It's the
compute node that contains the namespace )
:param private_key: path to private key file
:return: :return:
""" """
LOG.debug("DELETING RALLY KEY FILES") LOG.debug("DELETING RALLY KEY FILES FROM LOCAL MACHINE")
if key_file_paths: for key in local_key_files:
for path in key_file_paths: if os.path.exists(key):
if os.path.exists(path): os.remove(key)
os.remove(path)
if ns_compute_tuples:
LOG.debug("DELETING RALLY KEY FILES FROM COMPUTE HOSTS")
for key, ns_comp in zip(remote_key_files, ns_compute_tuples):
cmd = "sudo rm -f {}".format(key)
host = ns_comp[1]
execute_cmd_over_ssh(host, cmd, private_key)
def delete_hosts_from_knownhosts_file(hosts): def delete_hosts_from_knownhosts_file(hosts, ns_compute_tuples=None,
"""Removes the hosts from the knownhosts file private_key=None):
"""Remove the hosts from the knownhosts file
:param hosts: host ips to be removed from /root/.ssh/knownhosts :param hosts: host ips to be removed from /root/.ssh/knownhosts
:param ns_compute_tuples: namespace, compute tuple. (It's the
compute node that contains the namespace )
:param private_key: path to private key file
:return: :return:
""" """
if ns_compute_tuples:
LOG.debug("DELETES HOSTS FROM THE KNOWNHOSTS FILE") LOG.debug("DELETES HOSTS FROM THE KNOWNHOSTS FILE")
if hosts: for host, ns_comp in zip(hosts, ns_compute_tuples):
compute_host = ns_comp[1]
cmd = ("sudo ssh-keygen -f /root/.ssh/known_hosts -R"
" {}".format(host))
execute_cmd_over_ssh(compute_host, cmd, private_key)
else:
for host in hosts: for host in hosts:
cmd = ['ssh-keygen', '-f', "/root/.ssh/known_hosts", '-R', host] os.system("sudo ssh-keygen -f /root/.ssh/known_hosts -R"
cmd = ip_lib.add_namespace_to_cmd(cmd) " {}".format(host))
try:
linux_utils.execute(cmd, run_as_root=True)
except RuntimeError:
return False
return True

View File

@ -0,0 +1,17 @@
{
"image_name": "^cirros.*-disk$",
"private_key": "<path-to-private-key-file>",
"controller_creds": [
{
"ip": "x.x.x.x",
"username": "xxx"
}
],
"compute_creds": [
{
"ip": "x.x.x.x",
"username": "xxx",
"port": 22
}
]
}

View File

@ -1,6 +1,6 @@
{% set image_name = image_name or "cirros-0.3.3-x86_64-disk" %}
--- ---
VpnBasicScenario.create_and_delete_vpn_connection:
TestVpnBasicScenario.create_and_delete_vpn_connection:
- -
args: args:
flavor: flavor:
@ -19,8 +19,14 @@
secret: "secret" secret: "secret"
nova_server_boot_timeout: 60 * 6 nova_server_boot_timeout: 60 * 6
vpn_service_creation_timeout: 100 vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 400 ipsec_site_connection_creation_timeout: 180
namespace_creation_timeout: 60 namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: True
use_admin_client: False
ext-net: "ext-net"
runner: runner:
type: "constant" type: "constant"
@ -35,7 +41,7 @@
failure_rate: failure_rate:
max: 0 max: 0
TestVPNStatusScenario.check_vpn_status: TestVpnStatusScenario.check_vpn_status:
- -
args: args:
flavor: flavor:
@ -46,6 +52,12 @@
vpn_service_creation_timeout: 100 vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 400 ipsec_site_connection_creation_timeout: 400
namespace_creation_timeout: 60 namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: True
use_admin_client: False
ext-net: "ext-net"
runner: runner:
type: "constant" type: "constant"
@ -60,7 +72,7 @@
failure_rate: failure_rate:
max: 0 max: 0
VpnTenantScenario.multitenants_vpn_test: TestVpnTenantScenario.multitenants_vpn_test:
- -
args: args:
flavor: flavor:
@ -69,8 +81,14 @@
name: {{image_name}} name: {{image_name}}
nova_server_boot_timeout: 60 * 6 nova_server_boot_timeout: 60 * 6
vpn_service_creation_timeout: 100 vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 400 ipsec_site_connection_creation_timeout: 180
namespace_creation_timeout: 60 namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: True
use_admin_client: True
ext-net: "ext-net"
runner: runner:
type: "constant" type: "constant"

View File

@ -0,0 +1,103 @@
---
TestVpnBasicScenario.create_and_delete_vpn_connection:
-
args:
flavor:
name: "m1.tiny"
image:
name: {{image_name}}
phase1_negotiation_mode: "main"
auth_algorithm: "sha1"
encryption_algorithm: "aes-128"
pfs: "group5"
value: 7200
ike_version: "v1"
transform_protocol: "esp"
encapsulation_mode: "tunnel"
mtu: 1500
secret: "secret"
nova_server_boot_timeout: 60 * 6
vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 180
namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: False
use_admin_client: True
ext-net: "ext-net"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
sla:
failure_rate:
max: 0
TestVpnStatusScenario.check_vpn_status:
-
args:
flavor:
name: "m1.tiny"
image:
name: {{image_name}}
nova_server_boot_timeout: 60 * 6
vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 400
namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: False
use_admin_client: True
ext-net: "ext-net"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
sla:
failure_rate:
max: 0
TestVpnTenantScenario.multitenants_vpn_test:
-
args:
flavor:
name: "m1.tiny"
image:
name: {{image_name}}
nova_server_boot_timeout: 60 * 6
vpn_service_creation_timeout: 100
ipsec_site_connection_creation_timeout: 180
namespace_creation_timeout: 60
private_key: {{private_key}}
controller_creds: {{controller_creds}}
compute_creds: {{compute_creds}}
DVR_flag: False
use_admin_client: True
ext-net: "ext-net"
runner:
type: "constant"
times: 1
concurrency: 1
context:
users:
tenants: 1
users_per_tenant: 1
sla:
failure_rate:
max: 0