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:
parent
e6f643f2a1
commit
22205d681e
@ -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::
|
||||||
|
67
doc/source/devref/vpnaas-rally-test.rst
Normal file
67
doc/source/devref/vpnaas-rally-test.rst
Normal 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>
|
@ -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>
|
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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,68 +26,155 @@ 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
|
|
||||||
"""
|
|
||||||
self.tenant_ids = []
|
|
||||||
self.snat_namespaces = []
|
|
||||||
self.qrouter_namespaces = []
|
|
||||||
self.router_ids = []
|
|
||||||
self.rally_router_gw_ips = []
|
|
||||||
self.rally_routers = []
|
|
||||||
self.rally_networks = []
|
|
||||||
self.rally_subnets = []
|
|
||||||
self.rally_cidrs = []
|
|
||||||
self.ike_policy = None
|
|
||||||
self.ipsec_policy = None
|
|
||||||
self.vpn_services = []
|
|
||||||
self.ipsec_site_connections = []
|
|
||||||
self.servers = []
|
|
||||||
self.server_private_ips = []
|
|
||||||
self.suffixes = [uuidutils.generate_uuid(), uuidutils.generate_uuid()]
|
|
||||||
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")
|
with LOCK:
|
||||||
def cleanup(self):
|
LOG.debug('SETUP RESOURCES')
|
||||||
"""Cleans up all the 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.ns_controller_tuples = []
|
||||||
|
self.qrouterns_compute_tuples = []
|
||||||
|
self.router_ids = []
|
||||||
|
self.rally_router_gw_ips = []
|
||||||
|
self.rally_routers = []
|
||||||
|
self.rally_networks = []
|
||||||
|
self.rally_subnets = []
|
||||||
|
self.rally_cidrs = []
|
||||||
|
self.ike_policy = None
|
||||||
|
self.ipsec_policy = None
|
||||||
|
self.vpn_services = []
|
||||||
|
self.ipsec_site_connections = []
|
||||||
|
self.servers = []
|
||||||
|
self.server_private_ips = []
|
||||||
|
self.server_fips = []
|
||||||
|
|
||||||
vpn_utils.delete_servers(self.nova_client, self.servers)
|
def create_tenants(self):
|
||||||
vpn_utils.delete_hosts_from_knownhosts_file(self.server_private_ips)
|
"""Create tenants"""
|
||||||
vpn_utils.delete_key_files(self.key_file_paths)
|
|
||||||
self._delete_ipsec_site_connections()
|
for x in range(MAX_RESOURCES):
|
||||||
self._delete_vpn_services()
|
tenant_id = vpn_utils.create_tenant(
|
||||||
self._delete_ipsec_policy()
|
self.keystone_client, self.suffixes[x])
|
||||||
self._delete_ike_policy()
|
with LOCK:
|
||||||
vpn_utils.delete_network(
|
self.tenant_ids.append(tenant_id)
|
||||||
self.neutron_client, self.neutron_admin_client, self.rally_routers,
|
|
||||||
self.rally_networks, self.rally_subnets)
|
def create_networks(self, **kwargs):
|
||||||
if self.tenant_ids:
|
"""Create networks to test vpn connectivity"""
|
||||||
vpn_utils.delete_tenant(self.keystone_client,
|
|
||||||
self.tenant_ids)
|
for x in range(MAX_RESOURCES):
|
||||||
|
if self.tenant_ids:
|
||||||
|
router, network, subnet, cidr = vpn_utils.create_network(
|
||||||
|
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
|
||||||
@ -214,16 +313,18 @@ class VpnBase(rally_base.OpenStackScenario):
|
|||||||
:param resource: resource whose status has to be checked
|
:param resource: resource whose status has to be checked
|
||||||
:param final_status: desired final status of the resource
|
:param final_status: desired final status of the resource
|
||||||
:param resource_tag: to identify the resource as vpnservice or
|
:param resource_tag: to identify the resource as vpnservice or
|
||||||
ipsec_site_connection
|
ipsec_site_connection
|
||||||
:param wait_timeout: timeout value in seconds
|
:param wait_timeout: timeout value in seconds
|
||||||
:param check_interval: time to sleep before each check for the status
|
:param check_interval: time to sleep before each check for the status
|
||||||
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,207 +359,166 @@ 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:
|
if qg_interface:
|
||||||
p = re.compile(r"qg-\w+-\w+")
|
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as e:
|
||||||
m = p.search(qg)
|
tcpdump_future = e.submit(vpn_utils.start_tcpdump,
|
||||||
if m:
|
self.ns_controller_tuples[peer_index],
|
||||||
qg_interface = m.group()
|
qg_interface, self.private_key_file)
|
||||||
else:
|
if(kwargs["DVR_flag"]):
|
||||||
qg_interface = None
|
ssh_future = e.submit(
|
||||||
|
vpn_utils.ssh_and_ping_server,
|
||||||
|
self.server_private_ips[local_index],
|
||||||
|
self.server_private_ips[peer_index],
|
||||||
|
self.qrouterns_compute_tuples[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)
|
||||||
|
|
||||||
if qg_interface:
|
assert(ssh_future.result()), "SSH/Ping failed"
|
||||||
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as e:
|
for line in tcpdump_future.result():
|
||||||
tcpdump_future = e.submit(vpn_utils.start_tcpdump,
|
if 'ESP' in line:
|
||||||
self.snat_namespaces[peer_index],
|
return True
|
||||||
qg_interface)
|
|
||||||
ssh_future = e.submit(vpn_utils.ssh_and_ping_server,
|
|
||||||
self.server_private_ips[local_index],
|
|
||||||
self.server_private_ips[peer_index],
|
|
||||||
self.qrouter_namespaces[local_index],
|
|
||||||
self.key_file_paths[local_index])
|
|
||||||
assert(ssh_future.result()), "SSH/Ping failed"
|
|
||||||
lines = tcpdump_future.result().split('\n')
|
|
||||||
for line in lines:
|
|
||||||
if 'ESP' in line:
|
|
||||||
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:
|
LOG.debug("DELETING IPSEC_SITE_CONNECTION %s",
|
||||||
if "rally" in (site_conn['ipsec_site_connection']['name']):
|
site_conn['ipsec_site_connection']['id'])
|
||||||
LOG.debug("DELETING IPSEC_SITE_CONNECTION %s",
|
self.neutron_client.delete_ipsec_site_connection(
|
||||||
site_conn['ipsec_site_connection']['id'])
|
site_conn['ipsec_site_connection']['id'])
|
||||||
self.neutron_client.delete_ipsec_site_connection(
|
|
||||||
site_conn['ipsec_site_connection']['id'])
|
|
||||||
|
|
||||||
@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:
|
LOG.debug("DELETING VPN_SERVICE %s",
|
||||||
if "rally" in vpn_service['vpnservice']['name']:
|
vpn_service['vpnservice']['id'])
|
||||||
LOG.debug("DELETING VPN_SERVICE %s",
|
self.neutron_client.delete_vpnservice(
|
||||||
vpn_service['vpnservice']['id'])
|
vpn_service['vpnservice']['id'])
|
||||||
self.neutron_client.delete_vpnservice(
|
|
||||||
vpn_service['vpnservice']['id'])
|
|
||||||
|
|
||||||
@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:
|
vpn_utils.delete_hosts_from_knownhosts_file(
|
||||||
router, network, subnet, cidr = vpn_utils.create_network(
|
self.server_private_ips)
|
||||||
self.neutron_client, self.neutron_admin_client,
|
vpn_utils.delete_keyfiles(self.local_key_files)
|
||||||
self.suffixes[x])
|
|
||||||
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"
|
|
||||||
|
@ -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,167 +330,237 @@ 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:
|
||||||
for line in namespaces:
|
namespaces = get_namespace(host, private_key)
|
||||||
if line == (namespace + rally_router["router"]["id"]):
|
for line in namespaces:
|
||||||
namespace = line
|
if line == (namespace_tag + router_id):
|
||||||
return namespace
|
namespace_tag = line
|
||||||
|
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
|
return True
|
||||||
:param ip: ip to ping to
|
else:
|
||||||
"""
|
|
||||||
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
|
return False
|
||||||
LOG.debug("%s", ping_result)
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
LOG.debug("DELETING NOVA INSTANCE: %s", server.id)
|
||||||
if "rally" in server.name:
|
sec_group_id = server.security_groups[0]['name']
|
||||||
sec_group_name = server.security_groups[0]['name']
|
nova_client.servers.delete(server.id)
|
||||||
server_key_name = server.key_name
|
|
||||||
|
|
||||||
LOG.debug("DELETING NOVA INSTANCE: %s", server.id)
|
LOG.debug("WAITING FOR INSTANCE TO GET DELETED")
|
||||||
nova_client.servers.delete(server.id)
|
task_utils.wait_for_delete(
|
||||||
|
server, update_resource=task_utils.get_from_manager())
|
||||||
|
|
||||||
LOG.debug("WAITING FOR INSTANCE TO GET DELETED")
|
for secgroup in nova_client.security_groups.list():
|
||||||
task_utils.wait_for_delete(
|
if secgroup.id == sec_group_id:
|
||||||
server, update_resource=task_utils.get_from_manager())
|
LOG.debug("DELETING SEC_GROUP: %s", sec_group_id)
|
||||||
|
nova_client.security_groups.delete(secgroup.id)
|
||||||
for secgroup in nova_client.security_groups.list():
|
|
||||||
if secgroup.name == sec_group_name:
|
|
||||||
LOG.debug("DELETING SEC_GROUP: %s", sec_group_name)
|
|
||||||
nova_client.security_groups.delete(secgroup.id)
|
|
||||||
|
|
||||||
for key_pair in nova_client.keypairs.list():
|
|
||||||
if key_pair.name == server_key_name:
|
|
||||||
LOG.debug("DELETING KEY_PAIR: %s", server_key_name)
|
|
||||||
nova_client.keypairs.delete(key_pair.id)
|
|
||||||
|
|
||||||
|
|
||||||
def delete_network(neutron_client, neutron_admin_client,
|
def delete_floating_ips(nova_client, fips):
|
||||||
|
"""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)
|
||||||
|
|
||||||
|
|
||||||
|
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,64 +570,87 @@ 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:
|
neutron_client.remove_gateway_router(router['router']['id'])
|
||||||
if "rally" in router['router']['name']:
|
router_name = router['router']['name']
|
||||||
neutron_client.remove_gateway_router(router['router']['id'])
|
subnet_name = ("rally_subnet_" + router_name[13:len(router_name)])
|
||||||
router_name = router['router']['name']
|
for subnet in subnets:
|
||||||
subnet_name = ("rally_subnet_" +
|
if subnet_name == subnet['subnet']['name']:
|
||||||
router_name[13:len(router_name)])
|
neutron_client.remove_interface_router(
|
||||||
if subnets:
|
router['router']['id'],
|
||||||
for subnet in subnets:
|
{"subnet_id": subnet['subnet']['id']})
|
||||||
if subnet_name == subnet['subnet']['name']:
|
|
||||||
neutron_client.remove_interface_router(
|
|
||||||
router['router']['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:
|
neutron_client.delete_router(router['router']['id'])
|
||||||
if "rally" in router['router']['name']:
|
|
||||||
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"])
|
elif network['network']['router:external']:
|
||||||
if "rally_network" in network['network']['name']:
|
pass
|
||||||
neutron_client.delete_network(network['network']['id'])
|
else:
|
||||||
|
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:
|
||||||
"""
|
"""
|
||||||
LOG.debug("DELETES HOSTS FROM THE KNOWNHOSTS FILE")
|
if ns_compute_tuples:
|
||||||
if hosts:
|
LOG.debug("DELETES HOSTS FROM THE KNOWNHOSTS FILE")
|
||||||
|
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
|
|
||||||
|
17
rally-jobs/rally-configs/args_template.json
Normal file
17
rally-jobs/rally-configs/args_template.json
Normal 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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -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"
|
103
rally-jobs/rally-configs/rally_config_non_dvr.yaml
Normal file
103
rally-jobs/rally-configs/rally_config_non_dvr.yaml
Normal 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
|
Loading…
Reference in New Issue
Block a user