summaryrefslogtreecommitdiffstats
path: root/sdnvpn
diff options
context:
space:
mode:
authornikoskarandreas <nick@intracom-telecom.com>2018-11-06 17:31:11 +0200
committernikoskarandreas <nick@intracom-telecom.com>2018-12-11 11:38:24 +0200
commitba1eb0716b966256ed9ff1f160df0422a7b04776 (patch)
treeff1c01211f61c36316e4b34eccc87453e1a72f55 /sdnvpn
parent63ea4922aa8340e2d6ffde0cce3ddff775900f15 (diff)
Using heat orchestrator for sdnvpn - test case 8
Heat orchestrator and the use of Heat Orchestrator Templates is introduced in sdnvpn test cases. The deployment of the nodes and networks under test is performed as a stack with the use of the heat api and the use of the other apis is kept to as little as possible. The scenarios that are executed are the same as in the orginal test cases. This is the implementation of sdnvpn test case 8: Test floating IP and router assoc coexistence JIRA: SDNVPN-219 Change-Id: I8a61d40e9decf4297b8714c93ce77ba05f033b66 Signed-off-by: nikoskarandreas <nick@intracom-telecom.com>
Diffstat (limited to 'sdnvpn')
-rw-r--r--sdnvpn/artifacts/testcase_8bis.yaml173
-rw-r--r--sdnvpn/artifacts/testcase_8bis_upd.yaml17
-rw-r--r--sdnvpn/lib/openstack_utils.py18
-rw-r--r--sdnvpn/lib/utils.py18
-rw-r--r--sdnvpn/test/functest/config.yaml24
-rw-r--r--sdnvpn/test/functest/testcase_8bis.py176
6 files changed, 417 insertions, 9 deletions
diff --git a/sdnvpn/artifacts/testcase_8bis.yaml b/sdnvpn/artifacts/testcase_8bis.yaml
new file mode 100644
index 0000000..94853c3
--- /dev/null
+++ b/sdnvpn/artifacts/testcase_8bis.yaml
@@ -0,0 +1,173 @@
+heat_template_version: 2013-05-23
+
+description: >
+ Template for SDNVPN testcase 8
+ Test floating IP and router assoc coexistence
+
+parameters:
+ flavor:
+ type: string
+ description: flavor for the servers to be created
+ constraints:
+ - custom_constraint: nova.flavor
+ image_n:
+ type: string
+ description: image for the servers to be created
+ constraints:
+ - custom_constraint: glance.image
+ av_zone_1:
+ type: string
+ description: availability zone 1
+
+ external_nw:
+ type: string
+ description: the external network
+ net_1_name:
+ type: string
+ description: network 1
+ subnet_1_name:
+ type: string
+ description: subnet 1 name
+ subnet_1_cidr:
+ type: string
+ description: subnet 1 cidr
+ router_1_name:
+ type: string
+ description: router 1 cidr
+ net_2_name:
+ type: string
+ description: network 2
+ subnet_2_name:
+ type: string
+ description: subnet 2 name
+ subnet_2_cidr:
+ type: string
+ description: subnet 1 cidr
+
+ secgroup_name:
+ type: string
+ description: security group name
+ secgroup_descr:
+ type: string
+ description: security group slogan
+
+ instance_1_name:
+ type: string
+ description: instance name
+ instance_2_name:
+ type: string
+ description: instance name
+
+ ping_count:
+ type: string
+ description: ping count for user data script
+ default: 10
+
+resources:
+ router_1:
+ type: OS::Neutron::Router
+ properties:
+ name: { get_param: router_1_name }
+ external_gateway_info:
+ network: { get_param: external_nw }
+
+ net_1:
+ type: OS::Neutron::Net
+ properties:
+ name: { get_param: net_1_name }
+ subnet_1:
+ type: OS::Neutron::Subnet
+ properties:
+ name: { get_param: subnet_1_name }
+ network: { get_resource: net_1 }
+ cidr: { get_param: subnet_1_cidr }
+ routerinterface_1:
+ type: OS::Neutron::RouterInterface
+ properties:
+ router_id: { get_resource: router_1 }
+ subnet_id: { get_resource: subnet_1 }
+
+ net_2:
+ type: OS::Neutron::Net
+ properties:
+ name: { get_param: net_2_name }
+ subnet_2:
+ type: OS::Neutron::Subnet
+ properties:
+ name: { get_param: subnet_2_name }
+ network: { get_resource: net_2 }
+ cidr: { get_param: subnet_2_cidr }
+
+ sec_group:
+ type: OS::Neutron::SecurityGroup
+ properties:
+ name: { get_param: secgroup_name }
+ description: { get_param: secgroup_descr }
+ rules:
+ - protocol: icmp
+ remote_ip_prefix: 0.0.0.0/0
+ - protocol: tcp
+ port_range_min: 22
+ port_range_max: 22
+ remote_ip_prefix: 0.0.0.0/0
+
+ vm1:
+ type: OS::Nova::Server
+ depends_on: [ vm2 ]
+ properties:
+ name: { get_param: instance_1_name }
+ image: { get_param: image_n }
+ flavor: { get_param: flavor }
+ availability_zone: { get_param: av_zone_1 }
+ security_groups:
+ - { get_resource: sec_group }
+ networks:
+ - subnet: { get_resource: subnet_1 }
+ config_drive: True
+ user_data_format: RAW
+ user_data:
+ str_replace:
+ template: |
+ #!/bin/sh
+ set $IP_VM2
+ while true; do
+ for i do
+ ip=$i
+ ping -c $COUNT $ip 2>&1 >/dev/null
+ RES=$?
+ if [ \"Z$RES\" = \"Z0\" ] ; then
+ echo ping $ip OK
+ else echo ping $ip KO
+ fi
+ done
+ sleep 1
+ done
+ params:
+ $IP_VM2: { get_attr: [vm2, addresses, { get_resource: net_1}, 0, addr] }
+ $COUNT: { get_param: ping_count }
+ vm2:
+ type: OS::Nova::Server
+ properties:
+ name: { get_param: instance_2_name }
+ image: { get_param: image_n }
+ flavor: { get_param: flavor }
+ availability_zone: { get_param: av_zone_1 }
+ security_groups:
+ - { get_resource: sec_group }
+ networks:
+ - subnet: { get_resource: subnet_2 }
+
+
+outputs:
+ router_1_o:
+ description: the id of network 1
+ value: { get_attr: [router_1, show, id] }
+ net_2_o:
+ description: the id of network 2
+ value: { get_attr: [net_2, show, id] }
+ vm1_o:
+ description: the deployed vm resource
+ value: { get_attr: [vm1, show, name] }
+ vm2_o:
+ description: the deployed vm resource
+ value: { get_attr: [vm2, show, name] }
diff --git a/sdnvpn/artifacts/testcase_8bis_upd.yaml b/sdnvpn/artifacts/testcase_8bis_upd.yaml
new file mode 100644
index 0000000..4661e8a
--- /dev/null
+++ b/sdnvpn/artifacts/testcase_8bis_upd.yaml
@@ -0,0 +1,17 @@
+heat_template_version: 2013-05-23
+
+resources:
+ fip_1:
+ type: OS::Neutron::FloatingIP
+ properties:
+ floating_network: { get_param: external_nw }
+ fip_1_assoc:
+ type: OS::Neutron::FloatingIPAssociation
+ properties:
+ floatingip_id: { get_resource: fip_1 }
+ port_id: {get_attr: [vm1, addresses, {get_resource: net_1}, 0, port]}
+
+outputs:
+ fip_1_o:
+ description: the floating IP for vm1
+ value: { get_attr: [fip_1, show, floating_ip_address] }
diff --git a/sdnvpn/lib/openstack_utils.py b/sdnvpn/lib/openstack_utils.py
index d377c33..5fc1e49 100644
--- a/sdnvpn/lib/openstack_utils.py
+++ b/sdnvpn/lib/openstack_utils.py
@@ -1404,15 +1404,6 @@ def delete_user(keystone_client, user_id):
# *********************************************
# HEAT
# *********************************************
-def get_resource(conn, stack_id, resource):
- try:
- resource = conn.orchestration.resources(stack_id, id=resource).next()
- return resource
- except Exception as e:
- logger.error("Error [get_resource(orchestration)]: %s" % e)
- return None
-
-
def create_stack(conn, **kwargs):
try:
stack = conn.orchestration.create_stack(**kwargs)
@@ -1426,6 +1417,15 @@ def create_stack(conn, **kwargs):
return None
+def update_stack(conn, stack_id, **kwargs):
+ try:
+ conn.orchestration.update_stack(stack_id, **kwargs)
+ return True
+ except Exception as e:
+ logger.error("Error [update_stack(orchestration)]: %s" % e)
+ return False
+
+
def delete_stack(conn, stack_id):
try:
conn.orchestration.delete_stack(stack_id)
diff --git a/sdnvpn/lib/utils.py b/sdnvpn/lib/utils.py
index eb245c5..4c35edc 100644
--- a/sdnvpn/lib/utils.py
+++ b/sdnvpn/lib/utils.py
@@ -14,6 +14,7 @@ import time
import requests
import re
import subprocess
+import yaml
from concurrent.futures import ThreadPoolExecutor
from openstack.exceptions import ResourceNotFound, NotFoundException
from requests.auth import HTTPBasicAuth
@@ -1150,3 +1151,20 @@ def get_vms_from_stack_outputs(conn, stack_id, vm_stack_output_keys):
if vm is not None:
vms.append(vm)
return vms
+
+
+def merge_yaml(y1, y2):
+ """ Merge two yaml HOT into one
+
+ The parameters, resources and outputs sections are merged.
+
+ :param y1: the first yaml
+ :param y2: the second yaml
+ :return y: merged yaml
+ """
+ d1 = yaml.load(y1)
+ d2 = yaml.load(y2)
+ for key in ('parameters', 'resources', 'outputs'):
+ if key in d2:
+ d1[key].update(d2[key])
+ return yaml.dump(d1, default_flow_style=False)
diff --git a/sdnvpn/test/functest/config.yaml b/sdnvpn/test/functest/config.yaml
index 3ff35c5..3d2fd8b 100644
--- a/sdnvpn/test/functest/config.yaml
+++ b/sdnvpn/test/functest/config.yaml
@@ -242,6 +242,30 @@ testcases:
targets: '88:88'
route_distinguishers: '18:18'
+ sdnvpn.test.functest.testcase_8bis:
+ enabled: true
+ order: 21
+ description: "Test floating IP and router assoc coexistence \
+ same as test case 8"
+ image_name: sdnvpn-image
+ stack_name: stack-8bis
+ hot_file_name: artifacts/testcase_8bis.yaml
+ hot_update_file_name: artifacts/testcase_8bis_upd.yaml
+ heat_parameters:
+ instance_1_name: sdnvpn-8-1
+ instance_2_name: sdnvpn-8-2
+ net_1_name: sdnvpn-8-1
+ subnet_1_name: sdnvpn-8-1-subnet
+ subnet_1_cidr: 10.10.10.0/24
+ router_1_name: sdnvpn-8-1-router
+ net_2_name: sdnvpn-8-2
+ subnet_2_name: sdnvpn-8-2-subnet
+ subnet_2_cidr: 10.10.20.0/24
+ secgroup_name: sdnvpn-sg
+ secgroup_descr: Security group for SDNVPN test cases
+ targets: '88:88'
+ route_distinguishers: '18:18'
+
sdnvpn.test.functest.testcase_9:
enabled: true
order: 9
diff --git a/sdnvpn/test/functest/testcase_8bis.py b/sdnvpn/test/functest/testcase_8bis.py
new file mode 100644
index 0000000..d850020
--- /dev/null
+++ b/sdnvpn/test/functest/testcase_8bis.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+#
+# Copyright (c) 2017 All rights reserved
+# This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Test whether router assoc can coexist with floating IP
+# - Create VM1 in net1 with a subnet which is connected to a router
+# which is connected with the gateway
+# - Create VM2 in net2 with a subnet without a router attached.
+# - Create bgpvpn with iRT=eRT
+# - Assoc the router of net1 with bgpvpn and assoc net 2 with the bgpvpn
+# - Try to ping from one VM to the other
+# - Assign a floating IP to the VM in the router assoc network
+# - Ping it the floating ip
+
+import logging
+import sys
+import pkg_resources
+
+from sdnvpn.lib import config as sdnvpn_config
+from sdnvpn.lib import openstack_utils as os_utils
+from sdnvpn.lib import utils as test_utils
+from sdnvpn.lib.results import Results
+
+
+logger = logging.getLogger(__name__)
+
+COMMON_CONFIG = sdnvpn_config.CommonConfig()
+TESTCASE_CONFIG = sdnvpn_config.TestcaseConfig(
+ 'sdnvpn.test.functest.testcase_8bis')
+
+
+def main():
+ conn = os_utils.get_os_connection()
+ results = Results(COMMON_CONFIG.line_length, conn)
+
+ results.add_to_summary(0, "=")
+ results.add_to_summary(2, "STATUS", "SUBTEST")
+ results.add_to_summary(0, "=")
+
+ # neutron client is needed as long as bgpvpn heat module
+ # is not yet installed by default in apex (APEX-618)
+ neutron_client = os_utils.get_neutron_client()
+
+ image_ids = []
+ bgpvpn_ids = []
+
+ try:
+ image_id = os_utils.create_glance_image(
+ conn, TESTCASE_CONFIG.image_name,
+ COMMON_CONFIG.image_path, disk=COMMON_CONFIG.image_format,
+ container='bare', public='public')
+ image_ids = [image_id]
+
+ compute_nodes = test_utils.assert_and_get_compute_nodes(conn)
+ az_1 = "nova:" + compute_nodes[0]
+ # spawning the VMs on the same compute because fib flow (21) entries
+ # are not created properly if vm1 and vm2 are attached to two
+ # different computes
+
+ file_path = pkg_resources.resource_filename(
+ 'sdnvpn', TESTCASE_CONFIG.hot_file_name)
+ templ = open(file_path, 'r').read()
+ logger.debug("Template is read: '%s'" % templ)
+ env = test_utils.get_heat_environment(TESTCASE_CONFIG, COMMON_CONFIG)
+ logger.debug("Environment is read: '%s'" % env)
+
+ env['name'] = TESTCASE_CONFIG.stack_name
+ env['parameters']['external_nw'] = os_utils.get_external_net(conn)
+ env['template'] = templ
+ env['parameters']['image_n'] = TESTCASE_CONFIG.image_name
+ env['parameters']['av_zone_1'] = az_1
+
+ stack_id = os_utils.create_stack(conn, **env)
+ if stack_id is None:
+ logger.error('Stack create start failed')
+ raise SystemError('Stack create start failed')
+
+ test_utils.wait_stack_for_status(conn, stack_id, 'CREATE_COMPLETE')
+
+ router_1_output = os_utils.get_output(conn, stack_id, 'router_1_o')
+ router_1_id = router_1_output['output_value']
+ net_2_output = os_utils.get_output(conn, stack_id, 'net_2_o')
+ network_2_id = net_2_output['output_value']
+
+ vm_stack_output_keys = ['vm1_o', 'vm2_o']
+ vms = test_utils.get_vms_from_stack_outputs(conn,
+ stack_id,
+ vm_stack_output_keys)
+
+ logger.debug("Entering base test case with stack '%s'" % stack_id)
+
+ # TODO: check if ODL fixed bug
+ # https://jira.opendaylight.org/browse/NETVIRT-932
+ results.record_action('Create VPN with eRT==iRT')
+ vpn_name = 'sdnvpn-8'
+ kwargs = {
+ 'import_targets': TESTCASE_CONFIG.targets,
+ 'export_targets': TESTCASE_CONFIG.targets,
+ 'route_distinguishers': TESTCASE_CONFIG.route_distinguishers,
+ 'name': vpn_name
+ }
+ bgpvpn = test_utils.create_bgpvpn(neutron_client, **kwargs)
+ bgpvpn_id = bgpvpn['bgpvpn']['id']
+ logger.debug("VPN created details: %s" % bgpvpn)
+ bgpvpn_ids.append(bgpvpn_id)
+
+ msg = ("Associate router '%s' and net '%s' to the VPN."
+ % (TESTCASE_CONFIG.heat_parameters['router_1_name'],
+ TESTCASE_CONFIG.heat_parameters['net_2_name']))
+ results.record_action(msg)
+ results.add_to_summary(0, "-")
+
+ test_utils.create_router_association(
+ neutron_client, bgpvpn_id, router_1_id)
+ test_utils.create_network_association(
+ neutron_client, bgpvpn_id, network_2_id)
+
+ test_utils.wait_for_bgp_router_assoc(
+ neutron_client, bgpvpn_id, router_1_id)
+ test_utils.wait_for_bgp_net_assoc(
+ neutron_client, bgpvpn_id, network_2_id)
+
+ results.get_ping_status(vms[0], vms[1], expected="PASS", timeout=200)
+ results.add_to_summary(0, "=")
+
+ msg = "Assign a Floating IP to %s - using stack update" % vms[0].name
+ results.record_action(msg)
+
+ file_path = pkg_resources.resource_filename(
+ 'sdnvpn', TESTCASE_CONFIG.hot_update_file_name)
+ templ_update = open(file_path, 'r').read()
+ logger.debug("Update template is read: '%s'" % templ_update)
+ templ = test_utils.merge_yaml(templ, templ_update)
+
+ env['name'] = TESTCASE_CONFIG.stack_name
+ env['parameters']['external_nw'] = os_utils.get_external_net(conn)
+ env['template'] = templ
+ env['parameters']['image_n'] = TESTCASE_CONFIG.image_name
+ env['parameters']['av_zone_1'] = az_1
+
+ os_utils.update_stack(conn, stack_id, **env)
+
+ test_utils.wait_stack_for_status(conn, stack_id, 'UPDATE_COMPLETE')
+
+ fip_1_output = os_utils.get_output(conn, stack_id, 'fip_1_o')
+ fip = fip_1_output['output_value']
+
+ results.add_to_summary(0, "=")
+ results.record_action("Ping %s via Floating IP" % vms[0].name)
+ results.add_to_summary(0, "-")
+ results.ping_ip_test(fip)
+
+ except Exception as e:
+ logger.error("exception occurred while executing testcase_8bis: %s", e)
+ raise
+ finally:
+ test_utils.cleanup_glance(conn, image_ids)
+ test_utils.cleanup_neutron(conn, neutron_client, [], bgpvpn_ids,
+ [], [], [], [])
+
+ try:
+ test_utils.delete_stack_and_wait(conn, stack_id)
+ except Exception as e:
+ logger.error(
+ "exception occurred while executing testcase_8bis: %s", e)
+
+ return results.compile_summary()
+
+
+if __name__ == '__main__':
+ sys.exit(main())