aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--ansible/group_vars/all.yml1
-rw-r--r--ansible/install-inventory.ini3
-rw-r--r--ansible/install.yaml59
-rw-r--r--ansible/roles/configure_uwsgi/tasks/main.yml8
-rw-r--r--ansible/roles/configure_uwsgi/templates/yardstick.ini.j22
-rw-r--r--ansible/roles/download_samplevnfs/defaults/main.yml14
-rw-r--r--docker/Dockerfile2
-rw-r--r--docker/Dockerfile.aarch64.patch4
-rw-r--r--docs/conf.py1
-rw-r--r--docs/conf.yaml3
-rw-r--r--docs/index.rst17
-rw-r--r--docs/requirements.txt5
-rw-r--r--docs/testing/user/userguide/opnfv_yardstick_tc074.rst11
-rw-r--r--etc/yardstick/nodes/standalone/pod_landslide.yaml130
-rw-r--r--etc/yardstick/nodes/standalone/pod_landslide_network_dedicated.yaml164
-rw-r--r--etc/yardstick/nodes/standalone/pod_vepc_sut.yaml37
-rw-r--r--etc/yardstick/yardstick.conf.sample2
-rwxr-xr-xnsb_setup.sh77
-rw-r--r--samples/fio.yaml30
-rw-r--r--samples/lmbench.yaml33
-rw-r--r--samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml49
-rw-r--r--samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_4ports.yaml71
-rw-r--r--samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml49
-rw-r--r--samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml45
-rw-r--r--samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml45
-rw-r--r--samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg6
-rw-r--r--samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg10
-rw-r--r--samples/vnf_samples/nsut/vepc/landslide_tg_topology.yaml50
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide.yaml57
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide_multi_dmf.yaml57
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_network_dedicated_bearer_create_landslide.yaml164
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_network_service_request_landslide.yaml67
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_saegw_tput_relocation_landslide.yaml62
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_ue_dedicated_bearer_create_landslide.yaml74
-rw-r--r--samples/vnf_samples/nsut/vepc/tc_epc_ue_service_request_landslide.yaml228
-rw-r--r--samples/vnf_samples/nsut/vepc/vepc_vnf_topology_landslide.yaml50
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp.yaml79
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp_tcp.yaml136
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp.yaml79
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp_tcp.yaml136
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer.yaml147
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer_multi_dmf.yaml150
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_dedicated_bearer.yaml681
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_service_request.yaml341
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_saegw_relocation.yaml177
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_dedicated_bearer.yaml353
-rw-r--r--samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_service_request.yaml378
-rw-r--r--samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml44
-rw-r--r--samples/vnf_samples/vnf_descriptors/tg_landslide_tpl.yaml38
-rw-r--r--samples/vnf_samples/vnf_descriptors/vepc_vnf.yaml38
-rw-r--r--tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml10
-rw-r--r--tests/opnfv/test_suites/opnfv_k8-calico-nofeature-noha_daily.yaml18
-rw-r--r--tests/opnfv/test_suites/opnfv_k8-canal-nofeature-noha_daily.yaml18
-rw-r--r--tests/opnfv/test_suites/opnfv_k8-contiv-nofeature-noha_daily.yaml18
-rw-r--r--tests/opnfv/test_suites/opnfv_k8-flannel-nofeature-noha_daily.yaml18
-rw-r--r--tests/opnfv/test_suites/opnfv_k8-nosdn-istio-noha_daily.yaml18
-rw-r--r--tox.ini11
-rw-r--r--yardstick/benchmark/contexts/standalone/model.py2
-rw-r--r--yardstick/benchmark/contexts/standalone/ovs_dpdk.py15
-rw-r--r--yardstick/benchmark/runners/duration.py3
-rw-r--r--yardstick/benchmark/runners/proxduration.py3
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash4
-rw-r--r--yardstick/benchmark/scenarios/base.py3
-rw-r--r--yardstick/benchmark/scenarios/networking/vnf_generic.py3
-rw-r--r--yardstick/benchmark/scenarios/storage/storperf.py4
-rw-r--r--yardstick/common/exceptions.py12
-rw-r--r--yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py376
-rw-r--r--yardstick/network_services/traffic_profile/__init__.py1
-rw-r--r--yardstick/network_services/traffic_profile/base.py3
-rw-r--r--yardstick/network_services/traffic_profile/ixia_rfc2544.py133
-rw-r--r--yardstick/network_services/traffic_profile/landslide_profile.py47
-rw-r--r--yardstick/network_services/traffic_profile/prox_binsearch.py9
-rw-r--r--yardstick/network_services/traffic_profile/prox_profile.py5
-rw-r--r--yardstick/network_services/utils.py3
-rw-r--r--yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py46
-rw-r--r--yardstick/network_services/vnf_generic/vnf/epc_vnf.py53
-rw-r--r--yardstick/network_services/vnf_generic/vnf/prox_helpers.py2
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_landslide.py1203
-rw-r--r--yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py5
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_arithmetic.py228
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_duration.py18
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_proxduration.py2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py56
-rw-r--r--yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py229
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py136
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py4
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py70
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py94
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py6
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py1911
91 files changed, 9031 insertions, 235 deletions
diff --git a/.gitignore b/.gitignore
index 8be48ac62..79e351fce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,3 +33,5 @@ cover/
.idea/
# tox virtualenvs
.tox/
+# docs build artifacts
+docs/_build/*
diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index 9f5293272..596560508 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -7,6 +7,7 @@ release: xenial
normal_image_file: "{{ workspace }}/yardstick-image.img"
nsb_image_file: "{{ workspace }}/yardstick-nsb-image.img"
ubuntu_image_file: /tmp/workspace/yardstick/yardstick-trusty-server.raw
+installation_mode: "{{ INSTALLATION_MODE | default('baremetal') }}"
proxy_env:
PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/bin
http_proxy: "{{ lookup('env', 'http_proxy') }}"
diff --git a/ansible/install-inventory.ini b/ansible/install-inventory.ini
index e15a2e96a..4e8629428 100644
--- a/ansible/install-inventory.ini
+++ b/ansible/install-inventory.ini
@@ -17,8 +17,9 @@ jumphost
[all:vars]
arch_amd64=amd64
arch_arm64=arm64
-inst_mode_container=container
inst_mode_baremetal=baremetal
+inst_mode_container=container
+inst_mode_container_pull=container_pull
ubuntu_archive={"amd64": "http://archive.ubuntu.com/ubuntu/", "arm64": "http://ports.ubuntu.com/ubuntu-ports/"}
# Uncomment credentials below if needed
# ansible_user=root
diff --git a/ansible/install.yaml b/ansible/install.yaml
index fa8419b53..0800ee534 100644
--- a/ansible/install.yaml
+++ b/ansible/install.yaml
@@ -15,7 +15,6 @@
- hosts: jumphost
become: yes
vars:
- installation_mode: "{{ INSTALLATION_MODE | default('baremetal') }}"
yardstick_dir: "{{ YARDSTICK_DIR | default('/home/opnfv/repos/yardstick') }}"
virtual_environment: "{{ VIRTUAL_ENVIRONMENT | default(False) }}"
nsb_dir: "{{ NSB_DIR | default('/opt/nsb_bin/') }}"
@@ -28,27 +27,30 @@
state: directory
owner: root
mode: 0777
+ when:
+ - installation_mode != inst_mode_container_pull
roles:
- - add_repos_jumphost
- - install_dependencies_jumphost
- - install_yardstick
- - configure_uwsgi
- - configure_nginx
- - configure_gui
- - download_trex
- - install_trex
- - configure_rabbitmq
+ - { role: add_repos_jumphost, when: installation_mode != inst_mode_container_pull }
+ - { role: install_dependencies_jumphost, when: installation_mode != inst_mode_container_pull }
+ - { role: install_yardstick, when: installation_mode != inst_mode_container_pull }
+ - { role: configure_uwsgi, when: installation_mode != inst_mode_container_pull }
+ - { role: configure_nginx, when: installation_mode != inst_mode_container_pull }
+ - { role: configure_gui, when: installation_mode != inst_mode_container_pull }
+ - { role: download_trex, when: installation_mode != inst_mode_container_pull }
+ - { role: install_trex, when: installation_mode != inst_mode_container_pull }
+ - { role: configure_rabbitmq, when: installation_mode != inst_mode_container_pull }
+
post_tasks:
- service:
name: nginx
state: restarted
- when: installation_mode != inst_mode_container
+ when: installation_mode == inst_mode_baremetal
- shell: uwsgi -i /etc/yardstick/yardstick.ini
- when: installation_mode != inst_mode_container
+ when: installation_mode == inst_mode_baremetal
- name: Prepare baremetal and standalone servers
@@ -106,6 +108,7 @@
include_role:
name: build_yardstick_image
tasks_from: pre_build.yml
+ when: installation_mode != inst_mode_container
- hosts: chroot_image
@@ -120,6 +123,7 @@
include_role:
name: build_yardstick_image
tasks_from: "cloudimg_modify_{{ img_property }}.yml"
+ when: installation_mode != inst_mode_container
- hosts: jumphost
@@ -130,3 +134,34 @@
include_role:
name: build_yardstick_image
tasks_from: post_build.yml
+ when: installation_mode != inst_mode_container
+
+
+- name: start yardstick container on jumphost
+ hosts: jumphost
+
+ tasks:
+ - include_role:
+ name: install_dependencies_jumphost
+ when: installation_mode == inst_mode_container_pull
+
+ - include_role:
+ name: docker
+ when: installation_mode == inst_mode_container_pull
+
+ - name: Start yardstick container
+ docker_container:
+ name: yardstick
+ pull: yes
+ recreate: yes
+ image: "{{ yardstick_docker_image|default('opnfv/yardstick:latest') }}"
+ state: started
+ restart_policy: always
+ privileged: yes
+ interactive: yes
+ volumes:
+ - "{{ openrc_file|default('/dev/null') }}:/etc/yardstick/openstack.creds:ro"
+ - /var/run/docker.sock:/var/run/docker.sock
+ - /opt:/opt
+ - /etc/localtime:/etc/localtime:ro
+ when: installation_mode == inst_mode_container_pull
diff --git a/ansible/roles/configure_uwsgi/tasks/main.yml b/ansible/roles/configure_uwsgi/tasks/main.yml
index 6a2244657..8822bda53 100644
--- a/ansible/roles/configure_uwsgi/tasks/main.yml
+++ b/ansible/roles/configure_uwsgi/tasks/main.yml
@@ -39,6 +39,14 @@
owner: root
mode: 0644
+- set_fact:
+ uwsgi_log: "logto"
+ when: installation_mode == inst_mode_container
+
+- set_fact:
+ uwsgi_log: "daemonize"
+ when: installation_mode != inst_mode_container
+
- name: Create the UWSGI config file
template:
src: yardstick.ini.j2
diff --git a/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2 b/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2
index 495febb19..1890f16f9 100644
--- a/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2
+++ b/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2
@@ -12,7 +12,7 @@ chmod-socket = 666
callable = app_wrapper
enable-threads = true
close-on-exec = 1
-logto = {{ log_dir }}/uwsgi.log
+{{ uwsgi_log }} = {{ log_dir }}/uwsgi.log
socket = {{ socket_file }}
{# If virtual environment, we need to add:
virtualenv = <virtual_env> #}
diff --git a/ansible/roles/download_samplevnfs/defaults/main.yml b/ansible/roles/download_samplevnfs/defaults/main.yml
index c5e880e57..104f594f5 100644
--- a/ansible/roles/download_samplevnfs/defaults/main.yml
+++ b/ansible/roles/download_samplevnfs/defaults/main.yml
@@ -1,4 +1,16 @@
---
+# samplevnf_version must be a valid version accepted by "git checkout"
+# It can be either:
+# - a branch name: fetch branch latest commits, as of installation time
+# - a tag name: frozen and reproducible, from stable branches, or
+# - a commit id: frozen and reproducible, from any branch
+# Some examples:
+# - branch name: "master", "stable/gambia", "stable/fraser"
+# - tag name: "opnfv-6.2.0"
+# - commit id: "3afd384b7e68a3cd29f4d2cdf39785f8441d0b6f"
+# Please refer to https://git.opnfv.org/samplevnf for possible values
+# beyond the one specified below
+
samplevnf_url: "https://git.opnfv.org/samplevnf"
samplevnf_dest: "{{ clone_dest }}/samplevnf"
-samplevnf_version: "stable/fraser"
+samplevnf_version: "3afd384b7e68a3cd29f4d2cdf39785f8441d0b6f"
diff --git a/docker/Dockerfile b/docker/Dockerfile
index eeeeabca9..d594b46b9 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -26,7 +26,7 @@ ENV YARDSTICK_REPO_DIR="${REPOS_DIR}/yardstick/" \
RUN apt-get update && apt-get install -y git python python-setuptools python-pip iputils-ping && apt-get -y autoremove && apt-get clean
RUN easy_install -U setuptools==30.0.0
-RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 openstacksdk==0.9.17 python-openstackclient==3.12.1 python-heatclient==1.11.1 ansible==2.4.2
+RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 openstacksdk==0.9.17 python-openstackclient==3.12.1 python-heatclient==1.11.1 ansible==2.5.5
RUN mkdir -p ${REPOS_DIR}
diff --git a/docker/Dockerfile.aarch64.patch b/docker/Dockerfile.aarch64.patch
index a6909ee4b..6c32404ca 100644
--- a/docker/Dockerfile.aarch64.patch
+++ b/docker/Dockerfile.aarch64.patch
@@ -31,14 +31,14 @@ index 71ce6b58..fce7c116 100644
+RUN apt-get update && apt-get install -y git python python-setuptools python-pip iputils-ping && apt-get -y autoremove && \
+ apt-get install -y libssl-dev && apt-get -y install libffi-dev && apt-get clean
RUN easy_install -U setuptools==30.0.0
- RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 openstacksdk==0.9.17 python-openstackclient==3.12.1 python-heatclient==1.11.1 ansible==2.4.2
+ RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 openstacksdk==0.9.17 python-openstackclient==3.12.1 python-heatclient==1.11.1 ansible==2.5.5
@@ -40,7 +41,8 @@ RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${Y
RUN git clone --depth 1 https://gerrit.opnfv.org/gerrit/releng ${RELENG_REPO_DIR}
RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/storperf ${STORPERF_REPO_DIR}
-RUN ansible-playbook -i ${YARDSTICK_REPO_DIR}/ansible/install-inventory.ini -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml
-+RUN sed -i -e '/- configure_gui/d' ${YARDSTICK_REPO_DIR}/ansible/install.yaml && \
++RUN sed -i -e '/configure_gui/d' ${YARDSTICK_REPO_DIR}/ansible/install.yaml && \
+ ansible-playbook -i ${YARDSTICK_REPO_DIR}/ansible/install-inventory.ini -c local -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml
RUN ${YARDSTICK_REPO_DIR}/docker/supervisor.sh
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 000000000..86fddf13e
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1 @@
+from docs_conf.conf import * # pylint: disable=wildcard-import
diff --git a/docs/conf.yaml b/docs/conf.yaml
new file mode 100644
index 000000000..01e08ec7f
--- /dev/null
+++ b/docs/conf.yaml
@@ -0,0 +1,3 @@
+---
+project_cfg: opnfv
+project: Yardstick
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 000000000..e1339b0dd
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,17 @@
+.. This work is licensed under a Creative Commons Attribution 4.0 International License.
+.. SPDX-License-Identifier: CC-BY-4.0
+.. (c) Open Platform for NFV Project, Inc. and its contributors
+
+.. _yardstick:
+
+=========
+Yardstick
+=========
+
+.. toctree::
+ :numbered:
+ :maxdepth: 2
+
+ release/release-notes/index
+ testing/user/userguide/index
+ testing/developer/devguide/index
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 000000000..440843584
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,5 @@
+lfdocs-conf
+sphinx_opnfv_theme
+# Uncomment the following line if your project uses Sphinx to document
+# HTTP APIs
+# sphinxcontrib-httpdomain
diff --git a/docs/testing/user/userguide/opnfv_yardstick_tc074.rst b/docs/testing/user/userguide/opnfv_yardstick_tc074.rst
index 261a8bd95..d6beeaff9 100644
--- a/docs/testing/user/userguide/opnfv_yardstick_tc074.rst
+++ b/docs/testing/user/userguide/opnfv_yardstick_tc074.rst
@@ -111,6 +111,17 @@ Yardstick Test Case Description TC074
| | Query the status of the supplied job_id and report on |
| | metrics. If a workload is supplied, will report on only |
| | that subset. |
+| | * availability_zone: Specify the availability zone which |
+| | the stack will use to create instances. |
+| | * volume_type: |
+| | Cinder volumes can have different types, for example |
+| | encrypted vs. not encrypted. |
+| | To be able to profile the difference between the two. |
+| | * subnet_CIDR: Specify subnet CIDR of private network |
+| | * stack_name: Specify the name of the stack that will be |
+| | created, the default: "StorperfAgentGroup" |
+| | * volume_count: Specify the number of volumes per |
+| | virtual machines |
| | |
| | There are default values for each above-mentioned option. |
| | |
diff --git a/etc/yardstick/nodes/standalone/pod_landslide.yaml b/etc/yardstick/nodes/standalone/pod_landslide.yaml
new file mode 100644
index 000000000..c84aed142
--- /dev/null
+++ b/etc/yardstick/nodes/standalone/pod_landslide.yaml
@@ -0,0 +1,130 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+nodes:
+-
+ name: "tg__0"
+ role: tg__0
+ tas_manager:
+ ip: 192.168.122.100
+ super_user: SUPER_USER
+ super_user_password: SUPER_USER_PASSWORD
+ cfguser_password: CFGUSER_PASSWORD
+ test_user: TEST_USER
+ test_user_password: TEST_USER_PASSWORD
+ proto: http
+ license: LICENSE_NUMBER
+ interfaces: # dummy values
+ xe0:
+ vpci: "0000:05:00.0"
+ local_mac: "68:05:ca:30:3d:50"
+ driver: "i40e"
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ xe1:
+ vpci: "0000:05:00.1"
+ local_mac: "68:05:ca:30:3d:51"
+ driver: "i40e"
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ config:
+ - test_server:
+ name: TestServer_1
+ role: SGW_Node
+ ip: 192.168.122.101
+ thread_model: Fireball
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ phySubnets:
+ - base: 10.42.32.100
+ mask: "/24"
+ name: &ts1_port1 eth5
+ numIps: 20
+ - base: 10.42.33.100
+ mask: "/24"
+ name: &ts1_port2 eth6
+ numIps: 20
+ preResolvedArpAddress: # required for testcases with enabled Fireball mode
+ - StartingAddress: 10.42.33.10
+ NumNodes: 1
+ suts:
+ - name: SGW-C TestNode
+ role: SgwControlAddr
+ managementIp: 12.0.1.1
+ phy: *ts1_port1
+ ip: 10.42.32.100
+ # nextHop: ''
+ - name: SGW-U TestNode
+ role: SgwUserAddr
+ managementIp: 12.0.1.2
+ phy: *ts1_port1
+ ip: 10.42.32.101
+ # nextHop: ''
+
+ - test_server:
+ name: TestServer_2
+ role: SGW_Nodal
+ ip: 192.168.122.102
+ thread_model: Fireball
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ phySubnets:
+ - base: 10.42.32.1
+ mask: "/24"
+ name: &ts2_port1 eth5
+ numIps: 100
+ - base: 10.42.33.1
+ mask: "/24"
+ name: &ts2_port2 eth6
+ numIps: 100
+ suts:
+ - name: eNodeB TestNode
+ role: EnbUserAddr
+ managementIp: 12.0.2.1
+ phy: *ts2_port1
+ ip: 10.42.32.2
+ # nextHop: ''
+ - name: Target eNodeB
+ role: MobEnbUserAddr
+ managementIp: 12.0.2.2
+ phy: *ts2_port1
+ ip: 10.42.32.3
+ # nextHop: ''
+ - name: MME TestNode
+ role: MmeControlAddr
+ managementIp: 12.0.3.1
+ phy: *ts2_port1
+ ip: 10.42.32.1
+ # nextHop: ''
+ - name: NetHost TestNode
+ role: NetworkHostAddrLocal
+ managementIp: 12.0.4.1
+ phy: *ts2_port2
+ ip: 10.42.33.10
+ # nextHop: ''
+ - name: PGW SUT
+ role: PgwV4Sut
+ managementIp: 12.0.5.1
+ phy: *ts1_port1
+ ip: 10.42.32.105
+ # nextHop: ''
+ - name: SGW-C SUT
+ role: SgwSut
+ managementIp: 12.0.6.1
+ ip: 10.42.32.100
+ - name: SGW-U SUT
+ role: SgwUserSut
+ managementIp: 12.0.6.2
+ ip: 10.42.32.101
diff --git a/etc/yardstick/nodes/standalone/pod_landslide_network_dedicated.yaml b/etc/yardstick/nodes/standalone/pod_landslide_network_dedicated.yaml
new file mode 100644
index 000000000..6b8db54c2
--- /dev/null
+++ b/etc/yardstick/nodes/standalone/pod_landslide_network_dedicated.yaml
@@ -0,0 +1,164 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+nodes:
+-
+ name: "tg__0"
+ role: tg__0
+ tas_manager:
+ ip: 192.168.122.100
+ super_user: sms
+ super_user_password: a1b2c3d4
+ cfguser_password: cfguser
+ test_user: demoaff
+ test_user_password: demo123
+ proto: http
+ license: 49
+ interfaces: # dummy config
+ xe0:
+ vpci: "0000:05:00.0"
+ local_mac: "68:05:ca:30:3d:50"
+ driver: "i40e"
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ xe1:
+ vpci: "0000:05:00.1"
+ local_mac: "68:05:ca:30:3d:51"
+ driver: "i40e"
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ config:
+ - test_server:
+ name: TestServer_1
+ role: SGW_Node
+ ip: 192.168.122.101
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ thread_model: Fireball
+ phySubnets:
+ - base: 10.42.32.100
+ mask: "/24"
+ name: &ts1_port1 eth5
+ numIps: 20
+ - base: 10.42.33.100
+ mask: "/24"
+ name: &ts1_port2 eth6
+ numIps: 20
+ suts:
+ - name: SGW-C TestNode
+ role: SgwControlAddr
+ managementIp: 12.0.1.1
+ phy: *ts1_port1
+ ip: 10.42.32.100
+ # nextHop: ''
+ - name: SGW-U TestNode
+ role: SgwUserAddr
+ managementIp: 12.0.1.2
+ phy: *ts1_port1
+ ip: 10.42.32.101
+ # nextHop: ''
+ - name: PGW-C SUT
+ role: PgwSut
+ managementIp: 12.0.5.2
+ phy: *ts1_port1
+ ip: 10.42.32.108
+ # nextHop: ''
+
+ - test_server:
+ name: TestServer_1
+ role: PGW_Node
+ ip: 192.168.122.101
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ suts:
+ - name: PDN GW TestNode
+ role: PdnGwAddr
+ managementIp: 12.0.5.1
+ phy: *ts1_port1
+ ip: 10.42.32.103
+ nextHop: ''
+ - name: AGW TestNode
+ role: AgwNodeAddr
+ managementIp: 12.0.7.2
+ phy: *ts1_port1
+ ip: 10.42.32.107
+ nextHop: ''
+ - name: PCRF SUT
+ role: TyCcClnSutPrimarySrv
+ managementIp: 12.0.7.1
+ ip: 10.42.32.95
+
+ - test_server:
+ name: TestServer_2
+ role: SGW_Nodal
+ ip: 192.168.122.102
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ thread_model: Fireball
+ phySubnets:
+ - base: 10.42.32.1
+ mask: "/24"
+ name: &ts2_port1 eth5
+ numIps: 100
+ - base: 10.42.33.1
+ mask: "/24"
+ name: &ts2_port2 eth6
+ numIps: 50
+ suts:
+ - name: eNodeB TestNode
+ role: EnbUserAddr
+ managementIp: 12.0.2.1
+ phy: *ts2_port1
+ ip: 10.42.32.2
+ nextHop: ''
+ - name: MME TestNode
+ role: MmeControlAddr
+ managementIp: 12.0.3.1
+ phy: *ts2_port1
+ ip: 10.42.32.1
+ nextHop: ''
+ - name: NetHost TestNode
+ role: NetworkHostAddrLocal
+ managementIp: 12.0.4.1
+ phy: *ts2_port2
+ ip: 10.42.33.1
+ nextHop: ''
+ - name: PGW-C SUT
+ role: PgwV4Sut
+ managementIp: 12.0.5.1
+ ip: 10.42.32.103
+ - name: SGW-C SUT
+ role: SgwSut
+ managementIp: 12.0.1.1
+ ip: 10.42.32.100
+ - name: SGW-U SUT
+ role: SgwUserSut
+ managementIp: 12.0.1.2
+ ip: 10.42.32.101
+
+ - test_server:
+ name: TestServer_2
+ role: PCRF_Node
+ ip: 192.168.122.102
+ # override port-subnet and static route reservation information for this
+ # test server within the test session.
+ suts:
+ - name: AgwSrvNode TestNode
+ role: AgwSrvNode
+ managementIp: 12.0.7.1
+ phy: *ts2_port1
+ ip: 10.42.32.95
+ nextHop: ''
+
diff --git a/etc/yardstick/nodes/standalone/pod_vepc_sut.yaml b/etc/yardstick/nodes/standalone/pod_vepc_sut.yaml
new file mode 100644
index 000000000..8467303e9
--- /dev/null
+++ b/etc/yardstick/nodes/standalone/pod_vepc_sut.yaml
@@ -0,0 +1,37 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+---
+# Sample config file for fully emulated EPC environment
+
+
+nodes:
+-
+ name: "vnf__0"
+ role: vnf__0
+ ip: 192.168.122.200
+ user: user
+ password: password
+ interfaces: # dummy config
+ xe0:
+ vpci: "0000:05:00.0"
+ local_mac: "68:05:ca:30:3d:50"
+ driver: "i40e"
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ xe1:
+ vpci: "0000:05:00.1"
+ local_mac: "68:05:ca:30:3d:51"
+ driver: "i40e"
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
diff --git a/etc/yardstick/yardstick.conf.sample b/etc/yardstick/yardstick.conf.sample
index 5675cc3bd..ccfa86d5c 100644
--- a/etc/yardstick/yardstick.conf.sample
+++ b/etc/yardstick/yardstick.conf.sample
@@ -32,3 +32,5 @@ password = root
trex_path=/opt/nsb_bin/trex/scripts
bin_path=/opt/nsb_bin
trex_client_lib=/opt/nsb_bin/trex_client/stl
+# Path to 32-bit Java installation, for Spirent Landslide TG API
+jre_path_i386=/usr/lib/jvm/java-8-openjdk-i386/jre
diff --git a/nsb_setup.sh b/nsb_setup.sh
index 1f5344980..335db8dd2 100755
--- a/nsb_setup.sh
+++ b/nsb_setup.sh
@@ -13,14 +13,78 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+usage()
+{
+ cat <<EOF
+
+Yardstick NSB setup script.
+
+Usage: $0 [-h] [[-o] admin-openrc-for-openstack] [-i yardstick-docker-image]
+
+Options:
+ -h Show this message and exit
+ -o openrc Specify admin-openrc file with OpenStack credentials
+ Defaults to none
+ -i image Specify Yardstick Docker image, e.g. opnfv/yardstick:stable
+ Default value provided by ansible/nsb_setup.yml
+ See https://hub.docker.com/r/opnfv/yardstick/tags/
+
+EOF
+}
+
+OPTSTR=':ho:i:'
+openrc=
+image=
+
+# For backward compatibility reasons, accept openrc both as an argument
+# and as the -o option. Hence these two loops.
+while [ $# -ge 1 ]; do
+ OPTIND=1
+ while getopts ${OPTSTR} OPT; do
+ case $OPT in
+ h)
+ usage
+ exit 0
+ ;;
+ o)
+ openrc=${OPTARG}
+ ;;
+ i)
+ image=${OPTARG}
+ ;;
+ :)
+ usage
+ echo "ERROR: Missing value for -${OPTARG} option"
+ exit 1
+ ;;
+ *)
+ usage
+ echo "ERROR: Invalid -${OPTARG} option"
+ exit 1
+ ;;
+ esac
+ done
+
+ if [ ${OPTIND} -eq 1 ]; then
+ openrc=$1
+ shift
+ else
+ shift $((OPTIND - 1))
+ fi
+done
+
# OPENRC handling has to be first due no_proxy
-if [ $# -eq 1 ]; then
- OPENRC=$(readlink -f -- "$1")
+if [ -n "${openrc}" ]; then
+ OPENRC=$(readlink -f -- "${openrc}")
extra_args="${extra_args} -e openrc_file=${OPENRC}"
source "${OPENRC}"
CONTROLLER_IP=$(echo ${OS_AUTH_URL} | sed -ne "s#http://\([0-9a-zA-Z.\-]*\):*[0-9]*/.*#\1#p")
fi
+if [ -n "${image}" ]; then
+ extra_args="${extra_args} -e yardstick_docker_image=${image}"
+fi
+
env_http_proxy=$(sed -ne "s/^http_proxy=[\"\']\(.*\)[\"\']/\1/p" /etc/environment)
if [[ -z ${http_proxy} ]] && [[ ! -z ${env_http_proxy} ]]; then
export http_proxy=${env_http_proxy}
@@ -67,16 +131,9 @@ pip install ansible==2.5.5 shade==1.22.2 docker-py==1.10.6
ANSIBLE_SCRIPTS="ansible"
-if [[ -n ${1} ]]; then
- yardstick_docker_image="-e yardstick_docker_image=${1}"
-else
- yardstick_docker_image=""
-fi
-
-# no quotes for yardstick_docker_image so when empty it is removed as whitespace
cd ${ANSIBLE_SCRIPTS} &&\
ansible-playbook \
-e img_property="nsb" \
- ${yardstick_docker_image} \
-e YARD_IMG_ARCH='amd64' ${extra_args}\
-i install-inventory.ini nsb_setup.yml
+
diff --git a/samples/fio.yaml b/samples/fio.yaml
index b6e5a282f..0890766cf 100644
--- a/samples/fio.yaml
+++ b/samples/fio.yaml
@@ -9,6 +9,7 @@
---
# Sample benchmark task config file
# measure storage performance using fio
+# can be used both on Openstack and Kubernetes with "context_type"
#
# For this sample just like running the command below on the test vm and
# getting benchmark info back to the yardstick.
@@ -18,18 +19,24 @@
# -direct=1 -group_reporting -numjobs=1 -time_based \
# --output-format=json
+{% set context_type = context_type or "Heat" %}
+{% set separator = separator or "." %}
+{% if context_type == "Kubernetes" %}
+{% set separator = "-" %}
+{% endif %}
+
schema: "yardstick:task:0.1"
scenarios:
-
type: Fio
options:
- filename: /home/ubuntu/data.raw
+ filename: /tmp/data.raw
bs: 4k
iodepth: 1
rw: rw
ramp_time: 10
- host: fio.demo
+ host: fio{{ separator }}demo
runner:
type: Duration
duration: 60
@@ -44,7 +51,25 @@ scenarios:
action: monitor
context:
+ type: {{ context_type }}
name: demo
+ {% if context_type == "Kubernetes" %}
+
+ servers:
+ fio:
+ image: opnfv/yardstick-image-k8s
+ resources:
+ limits:
+ cpu: 1
+ memory: 1Gi
+ requests:
+ cpu: 1
+ memory: 1Gi
+ command: /bin/bash
+ args: ['-c', 'mkdir /root/.ssh; cp /tmp/.ssh/authorized_keys ~/.ssh/.;
+ chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; service ssh restart;
+ while true ; do sleep 10000; done']
+ {% else %}
image: yardstick-image
flavor: yardstick-flavor
user: ubuntu
@@ -54,3 +79,4 @@ context:
networks:
test:
cidr: "10.0.1.0/24"
+ {% endif %}
diff --git a/samples/lmbench.yaml b/samples/lmbench.yaml
index ea2966b24..7050243f9 100644
--- a/samples/lmbench.yaml
+++ b/samples/lmbench.yaml
@@ -9,6 +9,13 @@
---
# Sample benchmark task config file
# measure memory read latency and memory bandwidth using lmbench
+# can be used both on Openstack and Kubernetes with "context_type"
+
+{% set context_type = context_type or "Heat" %}
+{% set separator = separator or "." %}
+{% if context_type == "Kubernetes" %}
+{% set separator = "-" %}
+{% endif %}
schema: "yardstick:task:0.1"
@@ -19,7 +26,7 @@ scenarios:
test_type: "latency"
stop_size: 32.0
- host: demeter.demo
+ host: demeter{{ separator }}demo
runner:
type: Arithmetic
@@ -39,7 +46,7 @@ scenarios:
test_type: "bandwidth"
benchmark: "wr"
- host: demeter.demo
+ host: demeter{{ separator }}demo
runner:
type: Arithmetic
@@ -55,7 +62,24 @@ scenarios:
action: monitor
context:
+ type: {{ context_type }}
name: demo
+ {% if context_type == "Kubernetes" %}
+ servers:
+ demeter:
+ image: opnfv/yardstick-image-k8s
+ resources:
+ limits:
+ cpu: 1
+ memory: 1Gi
+ requests:
+ cpu: 1
+ memory: 1Gi
+ command: /bin/bash
+ args: ['-c', 'mkdir /root/.ssh; cp /tmp/.ssh/authorized_keys ~/.ssh/.;
+ chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; service ssh restart;
+ while true ; do sleep 10000; done']
+ {% else %}
image: yardstick-image
flavor: yardstick-flavor
user: ubuntu
@@ -71,6 +95,5 @@ context:
networks:
test:
- cidr: '10.0.1.0/24'
-
-
+ cidr: "10.0.1.0/24"
+ {% endif %}
diff --git a/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml
new file mode 100644
index 000000000..007d16f82
--- /dev/null
+++ b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_2ports.yaml
@@ -0,0 +1,49 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+nsd:nsd-catalog:
+ nsd:
+ - id: agnostic-topology
+ name: agnostic-topology
+ short-name: agnostic-topology
+ description: agnostic-topology
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/ixia_rfc2544_tpl.yaml #TG type
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/agnostic_vnf.yaml #VNF type
+
+ vld:
+ - id: uplink_0
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_0
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_4ports.yaml b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_4ports.yaml
new file mode 100644
index 000000000..1447faff3
--- /dev/null
+++ b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_ixia_4ports.yaml
@@ -0,0 +1,71 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+nsd:nsd-catalog:
+ nsd:
+ - id: agnostic-topology
+ name: agnostic-topology
+ short-name: agnostic-topology
+ description: agnostic-topology
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/ixia_rfc2544_tpl.yaml #TG type
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/agnostic_vnf.yaml #VNF type
+
+ vld:
+ - id: uplink_0
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_0
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0
+
+ - id: uplink_1
+ name: tg__0 to vnf__0 link 3
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe2
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe2
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_1
+ name: vnf__0 to tg__0 link 4
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe3
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe3
+ vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml
new file mode 100644
index 000000000..173880f08
--- /dev/null
+++ b/samples/vnf_samples/nsut/agnostic/agnostic_vnf_topology_trex_2ports.yaml
@@ -0,0 +1,49 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+nsd:nsd-catalog:
+ nsd:
+ - id: agnostic-topology
+ name: agnostic-topology
+ short-name: agnostic-topology
+ description: agnostic-topology
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/tg_rfc2544_tpl.yaml #TG type
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/agnostic_vnf.yaml #VNF type
+
+ vld:
+ - id: uplink_0
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_0
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0 \ No newline at end of file
diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml
new file mode 100644
index 000000000..53935dec2
--- /dev/null
+++ b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_ipv4_64B_trex.yaml
@@ -0,0 +1,45 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+ traffic_profile: ../../traffic_profiles/ipv4_throughput.yaml
+ topology: agnostic_vnf_topology_trex_2ports.yaml
+ nodes:
+ tg__0: tg_0.yardstick
+ vnf__0: vnf_0.yardstick
+ options:
+ framesize:
+ uplink: {64B: 100}
+ downlink: {64B: 100}
+ flow:
+ src_ip: [{'tg__0': 'xe0'}]
+ dst_ip: [{'tg__0': 'xe1'}]
+ count: 1
+ traffic_type: 4
+ rfc2544:
+ allowed_drop_rate: 0.0001 - 0.0001
+ vnf__0:
+ []
+ runner:
+ type: Iteration
+ iterations: 10
+ interval: 35
+context:
+ type: Node
+ name: yardstick
+ nfvi_type: baremetal
+ file: /etc/yardstick/nodes/pod.yaml
diff --git a/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml
new file mode 100644
index 000000000..c054a985b
--- /dev/null
+++ b/samples/vnf_samples/nsut/agnostic/tc_baremetal_rfc2544_latency_ipv4_64B_ixia.yaml
@@ -0,0 +1,45 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+ traffic_profile: ../../traffic_profiles/ixia_ipv4_latency.yaml
+ topology: agnostic_vnf_topology_ixia_2ports.yaml
+ nodes:
+ tg__0: tg_0.yardstick
+ vnf__0: vnf_0.yardstick
+ options:
+ framesize:
+ uplink: {64B: 100}
+ downlink: {64B: 100}
+ flow:
+ src_ip: [{'tg__0': 'xe0'}]
+ dst_ip: [{'tg__0': 'xe1'}]
+ count: 1
+ traffic_type: 4
+ rfc2544:
+ allowed_drop_rate: 0.0001 - 0.0001
+ vnf__0:
+ []
+ runner:
+ type: Iteration
+ iterations: 10
+ interval: 35
+context:
+ type: Node
+ name: yardstick
+ nfvi_type: baremetal
+ file: /etc/yardstick/nodes/pod_ixia.yaml
diff --git a/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg b/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg
index 80b29f349..35f3646e7 100644
--- a/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg
+++ b/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-2.cfg
@@ -22,12 +22,16 @@ no-output=no ; disable DPDK debug output
[port 0]
name=if0
mac=hardware
+rx desc=2048
+tx desc=2048
[port 1]
name=if1
mac=hardware
+rx desc=2048
+tx desc=2048
[defaults]
-mempool size=4K
+mempool size=8K
[lua]
lpm4 = dofile("ipv4-2port.lua")
diff --git a/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg b/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg
index 09adbbe55..bd696c4b0 100644
--- a/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg
+++ b/samples/vnf_samples/nsut/prox/configs/handle_l3fwd-4.cfg
@@ -22,18 +22,26 @@ no-output=no ; disable DPDK debug output
[port 0]
name=if0
mac=hardware
+rx desc=2048
+tx desc=2048
[port 1]
name=if1
mac=hardware
+rx desc=2048
+tx desc=2048
[port 2]
name=if2
mac=hardware
+rx desc=2048
+tx desc=2048
[port 3]
name=if3
mac=hardware
+rx desc=2048
+tx desc=2048
[defaults]
-mempool size=4K
+mempool size=8K
[lua]
lpm4 = dofile("ipv4.lua")
diff --git a/samples/vnf_samples/nsut/vepc/landslide_tg_topology.yaml b/samples/vnf_samples/nsut/vepc/landslide_tg_topology.yaml
new file mode 100644
index 000000000..ccf496bf9
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/landslide_tg_topology.yaml
@@ -0,0 +1,50 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nsd:nsd-catalog:
+ nsd:
+ - id: landslide-tg-topology
+ name: landslide-tg-topology
+ short-name: landslide-tg-topology
+ description: landslide-tg-topology
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/tg_landslide_tpl.yaml #TG type
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/tg_landslide_tpl.yaml #VNF type: Emulated vEPC
+
+ vld:
+ - id: uplink_0
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_0
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide.yaml
new file mode 100644
index 000000000..0b94d313f
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide.yaml
@@ -0,0 +1,57 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ UE default bearer creation test case. Measure successful default bearer
+ creation rate, total number of active bearer per server.
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_default_bearer.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 5
+ packetSize: 512
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6' # interface(s) in Node test type to loop traffic back from NetHost
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ FireballEn: 'false'
+ Sessions: '20000'
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ FireballEn: 'false'
+ Sessions: '20000'
+
+ runner:
+ type: Duration
+ duration: 200
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide_multi_dmf.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide_multi_dmf.yaml
new file mode 100644
index 000000000..76567062a
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_default_bearer_create_landslide_multi_dmf.yaml
@@ -0,0 +1,57 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ UE default bearer creation test case. Measure successful default bearer
+ creation rate, total number of active bearer per server.
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp_tcp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_default_bearer_multi_dmf.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ - transactionRate: 5
+ packetSize: 512
+ - transactionRate: 5
+ packetSize: 1518
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6' # interface(s) in Node test type to loop traffic back from NetHost
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: '20000'
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: '20000'
+
+ runner:
+ type: Duration
+ duration: 300
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_network_dedicated_bearer_create_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_network_dedicated_bearer_create_landslide.yaml
new file mode 100644
index 000000000..65f58bd0d
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_network_dedicated_bearer_create_landslide.yaml
@@ -0,0 +1,164 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ NW triggered dedicated bearer creation test case. Measure successful dedicated bearers
+ creation rate, total number of active bearer per server.
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_network_dedicated_bearer.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 5
+ packetSize: 512
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==udp
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6' # interface(s) in Node test type to loop traffic back from NetHost
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: 50000
+ UeInitBearerEn: 'false'
+ DedicatedsPerDefaultBearer: 1 # number of dedicated bearers per default
+ DefaultBearers: 1 # number of default bearers
+ FireballEn: 'false' # Fireball settings
+
+ # APN settings (number of APNs and APN's names)
+ Gtp2ApnNumSpecifiedApns_0: '1'
+ Gtp2ApnSpecified_0:
+ array: [dummy.an]
+ class: Array
+
+ - type: PGW_Node # test type from test session profile
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: 50000
+ DedicatedsPerDefaultBearer: 1 # number of dedicated bearers per default
+ DefaultBearers: 1 # number of default bearers
+ FireballEn: 'false' # Fireball settings
+
+ # APN settings (number of APNs and APN's names)
+ Gtp2ApnNumSpecifiedApns_0: '1'
+ Gtp2ApnSpecified_0:
+ class: Array
+ array: [dummy.an]
+
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: 50000
+ UeInitBearerEn: 'false'
+ DedicatedsPerDefaultBearer: 1 # number of dedicated bearers per default
+ DefaultBearers: 1 # number of default bearers
+ PgwNodeEn: 'false' # Emulate PGW Node
+ FireballEn: 'false' # Fireball settings
+
+ # APN settings (number of APNs and APN's names)
+ Gtp2ApnNumSpecifiedApns_0: '1'
+ Gtp2ApnSpecified_0:
+ class: Array
+ array: [dummy.an]
+
+ # Creation delay individually for each dedicated bearer
+ # Array items specifies timeout between default and dedicated bearers creation
+ # Array items corresponds to specific dedicated bearer
+ ConnectBearerDelay:
+ class: Array
+ array: ['1']
+
+ - type: PCRF_Node # test type from test session profile
+ Sessions: 50000
+ DisconnectRate: '1000'
+
+ # Starting IP address
+ StartingMsIpAddr: 1.0.0.1
+
+ # APN settings (APN's Names)
+ TyCcSrvApns:
+ class: Array
+ array: [dummy.an]
+
+ # Timer column (in seconds)
+ # Value specifies timeout after which dedicated bearer will be created
+ # None-zero timeout corresponds to dedicated bearer, zero timeout - to default bearer
+ TyCcV4SrvRuleInterval_1: '10' # APN1 dedicated bearer
+ TyCcV4SrvRuleInterval_2: '0' # APN1 default bearer
+
+ # QoS Class ID
+ # Name Pattern: TyCcV4SrvCrQci_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>
+ TyCcV4SrvCrQci_1_1_1: '1' # QCI of dedicated bearer
+
+ # Dedicated bearer Uplink/Downlink Bandwidth settings
+ # Name Pattern: TyCcV4SrvPrMaxUL_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>
+ # Name Pattern: TyCcV4SrvPrGuaranteedUplink_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>
+ TyCcV4SrvPrMaxUL_1_1_1: '300' # Uplink Max Bandwidth
+ TyCcV4SrvPrMaxDL_1_1_1: '300' # Downlink Max Bandwidth
+ TyCcV4SrvPrGuaranteedUplink_1_1_1: '300' # Uplink Guaranteed Bandwidth
+ TyCcV4SrvPrGuaranteedDownlink_1_1_1: '300' # Downlink Guaranteed Bandwidth
+
+ # Dedicated bearer ARP Rules
+ # Name Pattern: TyCcV4SrvPrArpEn_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>
+ # Name Pattern: TyCcV4SrvPrArpValue_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>
+ TyCcV4SrvPrArpEn_1_1_1: 'true' # Enable ARP Rules
+ TyCcV4SrvPrArpValue_1_1_1: '1' # ARP Value
+ TyCcV4SrvPrArpPreemptCapEn_1_1_1: 'true' # Enable Pre-emption Capability
+ TyCcV4SrvPrArpPreemptVulnEn_1_1_1: 'true' # Enable Pre-emption Vulnerability
+
+ # Packet Filter Description
+ # Name Pattern:
+ # TyCcV4SrvCrFilter_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>_<FILTER_NUM>
+ # To explicitly specify protocol number with decimal number, use following naming pattern:
+ # permit in <PROTOCOL_NUMBER> from
+ TyCcV4SrvCrFilter_1_1_1_1: permit in 17 from
+
+ # Packet Filter Destination IP
+ # Name Pattern:
+ # TyCcV4SrvCrFilterDestIp_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>_<FILTER_NUM>
+ # Parameter's value specifies filter's destination IP address and remote port range
+ TyCcV4SrvCrFilterDestIp_1_1_1_1: 0.0.0.0 0-65535
+
+ # Packet Filter IP Ext
+ # Name Pattern:
+ # TyCcV4SrvCrUserIpExt_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>_<FILTER_NUM>
+ # Parameter's value specifies filter's local port range
+ TyCcV4SrvCrUserIpExt_1_1_1_1: 0-65535
+
+ # Packet Filter Flow Direction
+ # Name Pattern:
+ # TyCcV4SrvCrFilterDirection_<RULE_SET_NUM>_<CHAR_RULE_NUM>_<RULE_DEF_NUM>_<FILTER_NUM>
+ TyCcV4SrvCrFilterDirection_1_1_1_1: '3' # Bi-Directional
+
+ # Diameter Transmission Protocol
+ TyCcSrvTcpProtocol: '1' # 0 - TCP, 1 - SCTP
+
+ runner:
+ type: Duration
+ duration: 600
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide_network_dedicated.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_network_service_request_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_network_service_request_landslide.yaml
new file mode 100644
index 000000000..55a96f4e4
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_network_service_request_landslide.yaml
@@ -0,0 +1,67 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ Downlink Data Notification from Network to UE that are in Idle state.
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_network_service_request.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 0.1
+ packetSize: 512
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==udp
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6'
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: '20000'
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: '20000'
+
+ # Configurations:
+ # 1. Specify continuous periodical events: UE goes to Idle state -> DL Data Notification
+ # E.g. Set Gtp2IdleEntryTime = 5 - UE goes to idle state after 5 seconds
+ # Set transactionRate = 0.1 - Send traffic periodically every 10 seconds
+ # 2. Set traffic run start delay
+ # E.g. Set Gtp2IdleEntryTime = 5 - UE goes to idle state after 5 seconds
+ # Set TrafficStartDelay with value greater that Gtp2IdleEntryTime
+ Gtp2IdleEntryTime: '5' # Idle Entry Time (s)
+
+ # Downlink Data Notification settings
+ TrafficStartDelay: 1000 # Data Start Delay (ms)
+
+ runner:
+ type: Duration
+ duration: 300
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_saegw_tput_relocation_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_saegw_tput_relocation_landslide.yaml
new file mode 100644
index 000000000..cece2a747
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_saegw_tput_relocation_landslide.yaml
@@ -0,0 +1,62 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ SAEGW throughput with relocation test case
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_saegw_relocation.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 5
+ packetSize: 512
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6' # interface(s) in Node test type to loop traffic back from NetHost
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: '20000'
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: '20000'
+ # Relocation settings
+ HandoffType: '0' # 0 - X2, 1 - S1, 2 - TAU/RAU
+ MobilityTimeMs: '10000' # Mobility Delay Time (ms)
+ StartType: When All Sessions Started # When All Sessions Started or When Session Started
+ SessionRetries: 'true' # Enable/disable Session Start Retries
+ MobilityRate: '120.0' # Mobility Rate
+ MobilityMode: Single Handoff # Handoff Mode: Single Handoff or Continuous Handoff
+ MobilityIntervalShape: Fixed # Mobility Rate Interval Distribution
+
+ runner:
+ type: Duration
+ duration: 300
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_ue_dedicated_bearer_create_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_ue_dedicated_bearer_create_landslide.yaml
new file mode 100644
index 000000000..81a4149f8
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_ue_dedicated_bearer_create_landslide.yaml
@@ -0,0 +1,74 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ UE triggered dedicated bearer creation test case. Measure successful dedicated bearers
+ creation rate, total number of active bearer per server.
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_ue_dedicated_bearer.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 5
+ packetSize: 512
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==udp
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6' # interface(s) in Node test type to loop traffic back from NetHost
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: '20000'
+ UeInitBearerEn: 'true'
+ DedicatedsPerDefaultBearer: 1 # number of dedicated bearers per default
+ DefaultBearers: 1 # number of default bearers
+
+ # Fireball settings
+ FireballEn: 'false'
+
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: '20000'
+ UeInitBearerEn: 'true'
+ DedicatedsPerDefaultBearer: '1' # number of dedicated bearers per default
+ DefaultBearers: '1' # number of default bearers
+
+ # Connection delay individually for each dedicated bearer
+ ConnectBearerDelay:
+ class: Array
+ array: ['5']
+
+ # Fireball settings
+ FireballEn: 'false'
+
+ runner:
+ type: Duration
+ duration: 300
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/tc_epc_ue_service_request_landslide.yaml b/samples/vnf_samples/nsut/vepc/tc_epc_ue_service_request_landslide.yaml
new file mode 100644
index 000000000..eaf4ae99f
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/tc_epc_ue_service_request_landslide.yaml
@@ -0,0 +1,228 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+schema: yardstick:task:0.1
+description: >
+ UE triggered bearer modification request with new QoS and TFT settings
+
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/landslide/landslide_dmf_udp.yaml"
+ session_profile: "../../traffic_profiles/landslide/landslide_session_ue_service_request.yaml"
+ topology: "vepc_vnf_topology_landslide.yaml"
+ nodes:
+ tg__0: tg__0.traffic_gen
+ vnf__0: vnf__0.vnf_epc
+ options:
+ dmf:
+ transactionRate: 5
+ packetSize: 512
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==udp
+ test_cases: # test case parameters to apply on session profile
+ - type: SGW_Node # test type from test session profile
+ AssociatedPhys: 'eth6'
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ Sessions: '20000'
+ UeInitBearerEn: 'true'
+ DedicatedsPerDefaultBearer: 1 # number of dedicated bearers per default
+ DefaultBearers: 1 # number of default bearers
+ FireballEn: 'false' # Fireball settings
+
+ # Number of TFTs
+ # Parameter name pattern: TrafficNumTftsForContext<DEDICATED_BEARER_INDEX>
+ TrafficNumTftsForContext0: '1'
+
+ # TFT Settings
+ # Parameter name(s) depends on number of dedicated bearers and number of TFTs per bearer.
+ # Parameter naming pattern: "TrafficTftForContext<DEDICATED_BEARER_INDEX>_<TFT_INDEX>"
+ # E.g.:
+ # "TrafficTftForContext0_0" - dedicated bearer 1, 1st TFT
+ # "TrafficTftForContext0_1" - dedicated bearer 1, 2nd TFT
+ # "TrafficTftForContext1_0" - dedicated bearer 2, 1st TFT
+ TrafficTftForContext0_0:
+ array:
+ - '255' # Packet Evaluation Precedence
+ - '6' # Protocol Number
+ - ''
+ - '' # Starting Remote Port
+ - '' # Ending Remote Port
+ - '' # Remote Address
+ - '' # Starting Local Port
+ - '' # Ending Local Port
+ - '' # Type of Service
+ - '' # Mask
+ - '' # Security Parameter Index
+ - '' # Flow Label
+ - ''
+ - '' # Include In Bearer Modification Request
+ - '3' # Direction: 0 - Pre Rel 7, 1 - Downlink, 2 - Uplink, 3 - Bi-Directional
+ - ''
+ - ''
+ - ''
+ - ''
+ class: Array
+
+ - type: SGW_Nodal # test type from test session profile
+ StartRate: '1000.0'
+ DisconnectRate: '1000.0'
+ Sessions: '20000'
+ UeInitBearerEn: 'true'
+ DedicatedsPerDefaultBearer: '1' # number of dedicated bearers per default
+ DefaultBearers: '1' # number of default bearers
+ FireballEn: 'false' # Fireball settings
+
+ # Creation delay individually for each dedicated bearer
+ # Array items specifies timeout between default and dedicated bearers creation
+ # Array items corresponds to specific dedicated bearer:
+ # E.g. 1st item - 1st dedicated bearer, 2nd item - 2nd dedicated bearer, etc.
+ ConnectBearerDelay:
+ class: Array
+ array: ['1']
+
+ # Data start delay (ms)
+ TrafficStartDelay: 1000
+
+ # Number of TFTs
+ # Parameter name pattern: TrafficNumTftsForContext<DEDICATED_BEARER_INDEX>
+ TrafficNumTftsForContext0: '1'
+
+ # TFT settings
+ # Parameter name(s) depends on number of dedicated bearers and number of TFTs per bearer.
+ # Parameter naming pattern: "TrafficTftForContext<DEDICATED_BEARER_INDEX>_<TFT_INDEX>"
+ # E.g.:
+ # "TrafficTftForContext0_0" - dedicated bearer 1, 1st TFT
+ # "TrafficTftForContext0_1" - dedicated bearer 1, 2nd TFT
+ # "TrafficTftForContext1_0" - dedicated bearer 2, 1st TFT
+ TrafficTftForContext0_0:
+ array:
+ - '255' # Packet Evaluation Precedence
+ - '6' # Protocol Number
+ - ''
+ - '' # Starting Remote Port
+ - '' # Ending Remote Port
+ - '' # Remote Address
+ - '' # Starting Local Port
+ - '' # Ending Local Port
+ - '' # Type of Service
+ - '' # Mask
+ - '' # Security Parameter Index
+ - '' # Flow Label
+ - ''
+ - '' # Include In Bearer Modification Request
+ - '3' # Direction: 0 - Pre Rel 7, 1 - Downlink, 2 - Uplink, 3 - Bi-Directional
+ - ''
+ - ''
+ - ''
+ - ''
+ class: Array
+
+ # Bearers modification settings
+ # Dedicated bearers modification settings and TFT filters
+ Gtp2BearerModEn: 'true' # Enable/Disable bearer modification
+ Gtp2BearerModInit: 'UE' # Bearer modification initiator
+ Gtp2BearerDelayTime: '5' # Delay time (s)
+ Gtp2IncModQos_2: 'true' # Include QoS IE
+ Gtp2BearerContinuousMod: 'false' # Continuous modifications
+ # Operation code in TFT settings:
+ # Parameter name(s) depends on number of dedicated bearers
+ # Parameter naming pattern: "TrafficOpCodeForContext<DEDICATED_BEARER_INDEX>_2"
+ # E.g.:
+ # TrafficOpCodeForContext0_2 - operation code for 1st dedicated bearer's TFT
+ # TrafficOpCodeForContext1_2 - operation code for 2st dedicated bearer's TFT
+ # 1 - create new TFT
+ # 2 - delete existing TFT
+ # 3 - add packet filters to existing TFT
+ # 4 - replace packet filters in existing TFT
+ # 5 - delete packet filters from existing TFT
+ TrafficOpCodeForContext0_2: '1'
+
+ # Number of TFTs
+ # Parameter name pattern: TrafficNumTftsForContext<DEDICATED_BEARER_INDEX>_2
+ TrafficNumTftsForContext0_2: '1'
+
+ # TFT settings
+ # Parameter name(s) depends on number of dedicated bearers and number of TFTs per bearer.
+ # Parameter naming pattern: "TrafficTftForContext<DEDICATED_BEARER_INDEX>_<TFT_INDEX>_2"
+ # E.g.:
+ # "TrafficTftForContext0_0" - dedicated bearer 1, 1st TFT
+ # "TrafficTftForContext0_1" - dedicated bearer 1, 2nd TFT
+ # "TrafficTftForContext1_0" - dedicated bearer 2, 1st TFT
+ TrafficTftForContext0_0_2:
+ class: Array
+ array:
+ - '255' # Packet Evaluation Precedence
+ - '17' # Protocol Number
+ - ''
+ - '2003' # Starting Remote Port
+ - '2003' # Ending Remote Port
+ - '' # Remote Address
+ - '2002' # Starting Local Port
+ - '2002' # Ending Local Port
+ - '' # Type of Service
+ - '' # Mask
+ - '' # Security Parameter Index
+ - '' # Flow Label
+ - ''
+ - 'true' # Include In Bearer Modification Request
+ - '3' # Direction: 0 - Pre Rel 7, 1 - Downlink, 2 - Uplink, 3 - Bi-Directional
+ - ''
+ - ''
+ - ''
+ - ''
+
+ # Modified bearers QoS settings
+ Gtp2QosDetail_2: Individual # bearers QoS details (Summary, Individual, Per Bearer)
+
+ # Parameter name(s) depends on number of dedicated bearers
+ # Parameter(s) naming pattern: "Gtp2QosClassId_2_<BEARER_INDEX>"
+ # E.g.:
+ # Gtp2QosClassId_2_1 - default bearer class identifier
+ # Gtp2QosClassId_2_2 - 1st dedicated bearer class identifier
+ # Gtp2QosClassId_2_3 - 2st dedicated bearer class identifier
+ # Modified default bearer settings
+ Gtp2QosClassId_2_1: '1' # Bearer class identifier
+ Gtp2QosArpValue_2_1: '1' # Bearer ARP priority level
+ Gtp2QosArpPreemptCapEn_2_1: 'false' # Pre-emption capability
+ Gtp2QosArpPreemptVulnEn_2_1: 'false' # Pre-emption vulnerability
+ Gtp2QosMaxUplink_2_1: '1000' # Uplink maximum bit rates (kb/s)
+ Gtp2QosMaxDownlink_2_1: '1000' # Downlink maximum bit rates (kb/s)
+ Gtp2QosGuarUplink_2_1: '1000' # Uplink guaranteed bit rates (kb/s)
+ Gtp2QosGuarDownlink_2_1: '1000' # Downlink guaranteed bit rates (kb/s)
+
+ # Modified dedicated bearer settings
+ Gtp2QosClassId_2_2: '5' # Bearer class identifier
+ Gtp2QosArpValue_2_2: '1' # Bearer ARP priority level
+ Gtp2QosArpPreemptCapEn_2_2: 'false' # Pre-emption capability
+ Gtp2QosArpPreemptVulnEn_2_2: 'false' # Pre-emption vulnerability
+
+ # Uncomment this settings in case Gtp2QosClassId_2_2 is equal to 1
+ # Gtp2QosMaxUplink_2_2: '1000' # Uplink maximum bit rates (kb/s)
+ # Gtp2QosMaxDownlink_2_2: '1000' # Downlink maximum bit rates (kb/s)
+ # Gtp2QosGuarUplink_2_2: '1000' # Uplink guaranteed bit rates (kb/s)
+ # Gtp2QosGuarDownlink_2_2: '1000' # Downlink guaranteed bit rates (kb/s)
+
+ runner:
+ type: Duration
+ duration: 300
+ interval: 5
+
+contexts:
+- name: traffic_gen
+ type: Node
+ file: /etc/yardstick/nodes/pod_landslide.yaml
+- name: vnf_epc
+ type: Node
+ file: /etc/yardstick/nodes/pod_vepc_sut.yaml
diff --git a/samples/vnf_samples/nsut/vepc/vepc_vnf_topology_landslide.yaml b/samples/vnf_samples/nsut/vepc/vepc_vnf_topology_landslide.yaml
new file mode 100644
index 000000000..f54cdaf81
--- /dev/null
+++ b/samples/vnf_samples/nsut/vepc/vepc_vnf_topology_landslide.yaml
@@ -0,0 +1,50 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nsd:nsd-catalog:
+ nsd:
+ - id: vEPC
+ name: vEPC
+ short-name: vEPC
+ description: vEPC VNF with Spirent landslide TG
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/tg_landslide_tpl.yaml #TG type
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/vepc_vnf.yaml #VNF type
+
+ vld:
+ - id: uplink_0
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink_0
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp.yaml
new file mode 100644
index 000000000..f25239f57
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp.yaml
@@ -0,0 +1,79 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+schema: "nsb:traffic_profile:0.1"
+
+name: LandslideProfile
+description: Spirent Landslide traffic profile (Data Message Flow)
+
+traffic_profile:
+ traffic_type: LandslideProfile
+
+dmf_config:
+ dmf:
+ library: test
+ name: Fireball UDP
+ description: "Basic data flow using UDP/IP (Fireball DMF)"
+ keywords: 'UDP '
+ dataProtocol: fb_udp
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol == (udp or fb_udp)
+ clientPort:
+ clientPort: 2002
+ isClientPortRange: 'false'
+ serverPort: 2003
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: true
+ billingIncludeSubflow: true
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp_tcp.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp_tcp.yaml
new file mode 100644
index 000000000..e613f1769
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_fb_udp_tcp.yaml
@@ -0,0 +1,136 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+schema: "nsb:traffic_profile:0.1"
+
+name: LandslideProfile
+description: Spirent Landslide traffic profile (Data Message Flow)
+
+traffic_profile:
+ traffic_type: LandslideProfile
+
+dmf_config:
+ -
+ dmf:
+ library: test
+ name: Fireball UDP
+ description: "Basic data flow using UDP/IP"
+ keywords: 'UDP '
+ dataProtocol: fb_udp
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==(udp or fb_udp)
+ clientPort:
+ clientPort: 2012
+ isClientPortRange: 'false'
+ serverPort: 2013
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: true
+ billingIncludeSubflow: true
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
+ -
+ dmf:
+ library: test
+ name: Fireball TCP
+ description: "Basic data flow using TCP/IP"
+ keywords: 'TCP '
+ dataProtocol: fb_tcp
+ clientPort:
+ clientPort: 2002
+ isClientPortRange: 'false'
+ serverPort: 2003
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: true
+ billingIncludeSubflow: true
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp.yaml
new file mode 100644
index 000000000..c7fabd182
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp.yaml
@@ -0,0 +1,79 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+schema: "nsb:traffic_profile:0.1"
+
+name: LandslideProfile
+description: Spirent Landslide traffic profile (Data Message Flow)
+
+traffic_profile:
+ traffic_type: LandslideProfile
+
+dmf_config:
+ dmf:
+ library: test
+ name: Basic UDP
+ description: "Basic data flow using UDP/IP"
+ keywords: 'UDP '
+ dataProtocol: udp
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==udp.
+ clientPort:
+ clientPort: 2002
+ isClientPortRange: 'false'
+ serverPort: 2003
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: true
+ billingIncludeSubflow: true
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp_tcp.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp_tcp.yaml
new file mode 100644
index 000000000..80c0db0d0
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_dmf_udp_tcp.yaml
@@ -0,0 +1,136 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+schema: "nsb:traffic_profile:0.1"
+
+name: LandslideProfile
+description: Spirent Landslide traffic profile (Data Message Flow)
+
+traffic_profile:
+ traffic_type: LandslideProfile
+
+dmf_config:
+ -
+ dmf:
+ library: test
+ name: Basic UDP
+ description: "Basic data flow using UDP/IP"
+ keywords: 'UDP '
+ dataProtocol: udp
+ burstCount: 1 # Applies only to Basic UDP DMF, DataProtocol==(udp or fb_udp)
+ clientPort:
+ clientPort: 2012
+ isClientPortRange: 'false'
+ serverPort: 2013
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: 'true'
+ billingIncludeSubflow: 'true'
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
+ -
+ dmf:
+ library: test
+ name: Basic TCP
+ description: "Basic data flow using TCP/IP"
+ keywords: 'TCP '
+ dataProtocol: tcp
+ clientPort:
+ clientPort: 2002
+ isClientPortRange: 'false'
+ serverPort: 2003
+ connection:
+ initiatingSide: Client
+ disconnectSide: Client
+ underlyingProtocol: none
+ persistentConnection: 'false'
+ protocolId: 0
+ persistentConnection: 'false'
+ transactionRate: 8.0
+ transactions:
+ totalTransactions: 0
+ retries: 0
+ dataResponseTime: 60000
+ packetSize: 64
+ segment:
+ segmentSize: 64000
+ maxSegmentSize: 0
+ size:
+ sizeDistribution: Fixed
+ sizeDeviation: 10
+ interval:
+ intervalDistribution: Fixed
+ intervalDeviation: 10
+ ipHeader:
+ typeOfService: 0
+ timeToLive: 64
+ tcpConnection:
+ force3Way: 'false'
+ fixedRetryTime: 0
+ maxPacketsToForceAck: 0
+ tcp:
+ windowSize: 32768
+ windowScaling: -1
+ disableFinAckWait: 'false'
+ disconnectType: FIN
+ slowStart: 'false'
+ connectOnly: 'false'
+ vtag:
+ VTagMask: '0x0'
+ VTagValue: '0x0'
+ sctpPayloadProtocolId: 0
+ billingIncludeSyn: 'true'
+ billingIncludeSubflow: 'true'
+ billingRecordPerTransaction: 'false'
+ tcpPush: 'false'
+ hostDataExpansionRatio: 1
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer.yaml
new file mode 100644
index 000000000..a90d8a189
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer.yaml
@@ -0,0 +1,147 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: 'UE default bearer creation test case'
+name: default_bearer_capacity
+keywords: ''
+duration: 60
+tsGroups:
+- tsId: SGW_NODE_TS_NAME # SGW-Node test server name placeholder
+ testCases:
+ - name: ''
+ type: SGW_Node
+ AssociatedPhys: ''
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 13.6.0
+ PgwNodeEn: 'true'
+ S5Protocol: GTPv2
+ Sessions: '100000'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: SGW_CONTROL_IP # SGW-C TestNode IP address placeholder
+ mtu: 1500
+ numLinksOrNodes: 1
+ phy: SGW_CONTROL_PHY
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: SGW_USER_IP # SGW-U TestNode IP address placeholder
+ mtu: 1500
+ numLinksOrNodes: 1
+ phy: SGW_USER_PHY
+ TestType: SGW-NODE
+ TrafficMtu: '1500'
+- tsId: SGW_NODAL_TS_NAME # SGW-Nodal test server name placeholder
+ testCases:
+ - name: ''
+ type: SGW_Nodal
+ parameters:
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ mainflows:
+ - library: TEST_USER
+ name: Basic UDP
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0
+ startPaused: 'false'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: ENB_USER_IP # eNodeB TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: ENB_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ FireballEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 13.6.0
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: MME_CONTROL_IP # MME TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: MME_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: NET_HOST_IP # NetHost TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: NET_HOST_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME # PGW TestNode name placeholder
+ S5Protocol: GTPv2
+ Sessions: '100000'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME # SGW-C SUT name placeholder
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME # SGW-U SUT name placeholder
+ StartRate: '1000.0'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficMtu: '1500'
+ TrafficStartType: When All Sessions Established
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer_multi_dmf.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer_multi_dmf.yaml
new file mode 100644
index 000000000..7b1f50160
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_default_bearer_multi_dmf.yaml
@@ -0,0 +1,150 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: 'UE default bearer creation test case'
+name: default_bearer_capacity
+keywords: ''
+duration: 60
+tsGroups:
+- tsId: SGW_NODE_TS_NAME # SGW-Node test server name placeholder
+ testCases:
+ - name: ''
+ type: SGW_Node
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 13.6.0
+ PgwNodeEn: 'true'
+ S5Protocol: GTPv2
+ Sessions: '100000'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: SGW_CONTROL_IP # SGW-C TestNode IP address placeholder
+ mtu: 1500
+ numLinksOrNodes: 1
+ phy: SGW_CONTROL_PHY
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: SGW_USER_IP # SGW-U TestNode IP address placeholder
+ mtu: 1500
+ numLinksOrNodes: 1
+ phy: SGW_USER_PHY
+ TestType: SGW-NODE
+ TrafficMtu: '1500'
+- tsId: SGW_NODAL_TS_NAME # SGW-Nodal test server name placeholder
+ testCases:
+ - name: ''
+ type: SGW_Nodal
+ parameters:
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ mainflows:
+ - library: test
+ name: Basic UDP
+ - library: test
+ name: Basic TCP
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0
+ startPaused: 'false'
+ - mainflowIdx: 1
+ mixType: ''
+ rate: 0
+ startPaused: 'false'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: ENB_USER_IP # eNodeB TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: ENB_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 13.6.0
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: MME_CONTROL_IP # MME TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: MME_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: NET_HOST_IP # NetHost TestNode IP address placeholder
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: NET_HOST_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanUserPriority: 0
+ vlanTagType: 0
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME # PGW TestNode name placeholder
+ S5Protocol: GTPv2
+ Sessions: '100000'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME # SGW-C SUT name placeholder
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME # SGW-U SUT name placeholder
+ StartRate: '1000.0'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficMtu: '1500'
+ TrafficStartType: When All Sessions Established
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_dedicated_bearer.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_dedicated_bearer.yaml
new file mode 100644
index 000000000..2e79d8d51
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_dedicated_bearer.yaml
@@ -0,0 +1,681 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: Network initiated dedicated bearer creation test case
+duration: 60
+keywords: ''
+library: test
+name: network_dedicated_bearer_creation
+tsGroups:
+- testCases:
+ - name: ''
+ AssociatedPhys: ''
+ parameters:
+ BillingEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2CfgFileEn: 'false'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2ExtEn: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2MobGtpuForwardingEndptId: '5000000'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PersistentImsiEn: 'false'
+ Gtp2PiggybackEn_sgw: '0'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2RestartCnt: '1'
+ Gtp2S5GtpcTunnelEndptId: '3000000'
+ Gtp2S5GtpuTunnelEndptId: '4000000'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2Version: 15.2.0
+ PgwNodeEn: 'false'
+ PgwNumSutsEn: 'false'
+ PgwSut:
+ class: Sut
+ name: PGW_SUT_NAME
+ PgwUserSutEn: 'false'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SeparateS5InterfacesEn: 'false'
+ Sessions: '1'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwControlAddrErrInj: '0'
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwUserAddrErrInj: '0'
+ SgwUserDualStackEn: 'false'
+ SxaControlNodeAddrXPort: '8805'
+ SxaUserNodeAddrXPort: '8805'
+ TestType: SGW-NODE
+ TrafficMtu: '1400'
+ type: SGW_Node
+ - name: ''
+ parameters:
+ AgwNodeAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: AGW_NODE_NAME
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: AGW_NODE_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ AgwNodeAddrErrInj: '0'
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ BillingEn: 'false'
+ ConnectBearerDelay:
+ array: []
+ class: Array
+ DataTraffic: Disabled
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ DisconnectDedicatedBearerEn: 'false'
+ FireballEn: 'false'
+ ForwardSessionVLanTag: '0'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2ExtEn: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2MultDedsPerMsgEn: 'false'
+ Gtp2PcoAddEn: 'false'
+ Gtp2PcoIpcpEn: 'false'
+ Gtp2PersistentImsiEn: 'false'
+ Gtp2PiggybackEn_pgw: '0'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2ResponseDelayEn: 'false'
+ Gtp2RestartCnt: '1'
+ Gtp2RouterAdDelay: '1'
+ Gtp2Tac: '0'
+ Gtp2Version: 15.2.0
+ MobilityType: None
+ OverloadCtlEn: 'false'
+ PcrfClnAgwIf: Gx
+ PdnGwAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: PGW_CONTROL_NAME
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: PGW_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ PdnGwAddrErrInj: '0'
+ PdnGwUsrAddrEn: 'false'
+ PgwDualStackEn: 'false'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ S6bIfEn: 'false'
+ Sessions: '1'
+ SgiNasIfEn: 'false'
+ SgiNodeEn: 'false'
+ SgiPtpTunnelEn: 'false'
+ TestType: PGW-NODE
+ TrafficMtu: '1400'
+ TrafficNumTftsForContext0: '1'
+ TyCcClnAddFailedAvpEn: 'false'
+ TyCcClnApplicationId: '16777238'
+ TyCcClnAvpCfgFileEn: 'false'
+ TyCcClnConfiguration: Primary Server Only
+ TyCcClnDistributionMode: Dedicated
+ TyCcClnDoNotInitiateDprEn: 'false'
+ TyCcClnDprCause: '2'
+ TyCcClnHostAvpEn: 'true'
+ TyCcClnOriginHost: AGW.Spirent.com
+ TyCcClnOriginRealm: Spirent.com
+ TyCcClnProductName: 'Landslide PCRF'
+ TyCcClnRetryTime: '5000'
+ TyCcClnSctp3SackRuleEn: 'false'
+ TyCcClnSctpAckDelay: '100'
+ TyCcClnSctpSackThreshold: '2'
+ TyCcClnSutPort: '3868'
+ TyCcClnSutPrimaryHost: AGWServer.Spirent.com
+ TyCcClnSutPrimaryRealm: Spirent.com
+ TyCcClnSutPrimarySrv:
+ class: Sut
+ name: PCRF_TESTNODE_NAME
+ TyCcClnTcpProtocol: '1'
+ TyCcClnTcpWinSize: '32768'
+ TyCcClnVendorId: '10415'
+ TyCcClnVsa:
+ attrInfos: []
+ class: Vsa
+ isCriteria: 'false'
+ isGeneric: 'false'
+ protocol: '301'
+ TyCcClnWatchDogTime: '30'
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'false'
+ type: PGW_Node
+ tsId: SGW_PGW_NODE_TC_NAME
+- testCases:
+ - name: ''
+ parameters:
+ ApnDnsEn: 'false'
+ ApnToPgwMappingEn: 'false'
+ AutoStopControlLayer: 'false'
+ ConnectBearerDelay:
+ array: []
+ class: Array
+ ContinuousWithVerification: 'false'
+ CpCiotEpsOptimizationEn: 'false'
+ CtlBearerToDscpEn: 'false'
+ DataHostCfgFileEn: 'false'
+ DataResumeRate: '3000'
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedicatedBearerConnectRateEn: 'false'
+ DedicatedBearerDisconnectRateEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ DisconnectDedicatedBearerEn: 'false'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0.0
+ rows:
+ - clientPort: 0
+ context: 0
+ node: 0
+ overridePort: 'false'
+ ratingGroup: 0
+ role: 0
+ serviceId: 0
+ transport: Any
+ mainflows:
+ - library: test
+ name: Basic UDP
+ DualStackEn: 'false'
+ EDrxValueEn: 'false'
+ EirIfEn: 'false'
+ EmergencyAttachWithImeiEn: 'false'
+ EmergencyAttachWoAuthEn: 'false'
+ EmergencyPdnIndexEn: 'false'
+ EnableExternalData: '0'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: ENB_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: ENB_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ EnbUserAddrErrInj: '0'
+ FireballEn: 'false'
+ Gtp2ActivationDelay: '0'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnNumSpecifiedApns_1: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnRetries_1: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnSpecified_1:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2ApnTotalApns_1: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2Apn_1: ssenoauth146
+ Gtp2BearerModEn: 'false'
+ Gtp2CfgFileEn: 'false'
+ Gtp2ChargingChars: '0x0'
+ Gtp2DelayDlPacketNotifReq: '1'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2EnbUliEn: 'false'
+ Gtp2ExtEn: 'false'
+ Gtp2FwdUplinkDataEcmIdle: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IdleEntryTime: '0'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncPcoOpt: none
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2MaxWaitTimeEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2ModBearerDlDataDelay: '0'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PcoAddEn: 'false'
+ Gtp2PcoIpcpEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2RejectDedEn: 'false'
+ Gtp2RemoteUeReportTime: '0'
+ Gtp2RestartCnt: '1'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2SwVersionEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2UeDaySaveTime: '0'
+ Gtp2UeMultPdnConnReqSameApnEn_0: 'false'
+ Gtp2UeTimeZone: '0'
+ Gtp2UliDbCmdCbRspEn: 'true'
+ Gtp2Version: 15.2.0
+ HomeAddrType: '1'
+ HomeAddrTypePerBearerEn: 'false'
+ HssIfEn: 'false'
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: MME_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: MME_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ MmeControlAddrErrInj: '0'
+ MultipathTcpEn: 'false'
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: NET_HOST_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: NET_HOST_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ NetworkHostAddrLocalErrInj: '0'
+ NetworkHostNatedTrafficEn: 'false'
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_TESTNODE_NAME
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SecPgwV4SutEn: 'false'
+ SessionIntervalShape: Fixed
+ SessionRetries: 'true'
+ Sessions: '1'
+ SgwNumSutsEn: 'false'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME
+ StartRate: '1000.0'
+ T3324PwrSavingValueEn: 'false'
+ T3412ExValueEn: 'false'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficDontFragIp: '0'
+ TrafficErrorInject: '0'
+ TrafficHostIdleTimeEnabler: 'false'
+ TrafficMtu: '1400'
+ TrafficStartDelay: '1000'
+ TrafficStartType: When All Sessions Established
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'false'
+ UseStaticBearerIp: 'false'
+ type: SGW_Nodal
+ - name: ''
+ parameters:
+ AffinityModeEn: 'false'
+ AgwSrvNode:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: PRIMARY_AGW_NAME
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: PRIMARY_AGW_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ AgwSrvNodeErrInj: '0'
+ CommandMode: 'Off'
+ DiaAvpDataSize: '200'
+ DisconnectRate: '1000.0'
+ HomeAddrType: '1'
+ LteVersion: 9.6.0
+ PcrfProtocol: pcrf_gx_srv
+ RoamingEn: 'false'
+ Sessions: '1'
+ StartingMsIpAddr: 1.0.0.1
+ TestType: PCRF-NODE
+ TyCcDsSrvNumRuleSet: '0'
+ TyCcSrvAddFailedAvpEn: 'false'
+ TyCcSrvApnCaseInsensitiveEn: 'true'
+ TyCcSrvApnMapEn: 'true'
+ TyCcSrvApnProfilesEn: 'false'
+ TyCcSrvApns:
+ array: []
+ class: Array
+ TyCcSrvApplicationId: '16777238'
+ TyCcSrvAuthKey: '505024101215074'
+ TyCcSrvAuthKeyType: IMSI
+ TyCcSrvAvpCfgFileEn: 'false'
+ TyCcSrvCcaIDelayEn: 'false'
+ TyCcSrvCcaTDelayEn: 'false'
+ TyCcSrvCcaUDelayEn: 'false'
+ TyCcSrvChargingAvpEn: 'false'
+ TyCcSrvCopyFilterFromRxEn: 'false'
+ TyCcSrvDoNotInitiateDprEn: 'false'
+ TyCcSrvDprCause: '2'
+ TyCcSrvExcludeFlowDirEn: 'false'
+ TyCcSrvImeiSvKeyEn: 'false'
+ TyCcSrvMobSupportEn: 'false'
+ TyCcSrvNumPeers: '1'
+ TyCcSrvOfflineAvpEn: 'false'
+ TyCcSrvOnlineAvpEn: 'false'
+ TyCcSrvOriginHost: AGWServer.Spirent.com
+ TyCcSrvOriginRealm: Spirent.com
+ TyCcSrvPktFltIdAlwaysEn: 'false'
+ TyCcSrvProductName: 'Landslide PCRF'
+ TyCcSrvRetryTime: '5000'
+ TyCcSrvSctp3SackRuleEn: 'false'
+ TyCcSrvSctpAckDelay: '100'
+ TyCcSrvSctpAckEn: 'true'
+ TyCcSrvSctpHeartbeatInterval: '30'
+ TyCcSrvSctpMaxRetransAssoc: '5'
+ TyCcSrvSctpMultiHomedMultiSrcEn: 'false'
+ TyCcSrvSctpSackThreshold: '2'
+ TyCcSrvSecondaryPcrfEn: 'false'
+ TyCcSrvTcpProtocol: '1'
+ TyCcSrvTcpWinSize: '32768'
+ TyCcSrvVendorId: '10415'
+ TyCcSrvVsaDbList: '30'
+ TyCcSrvWatchDogTime: '30'
+ TyCcV41Vsa:
+ attrInfos: []
+ class: Vsa
+ isCriteria: 'false'
+ isGeneric: 'false'
+ protocol: '603'
+ TyCcV42Vsa:
+ attrInfos: []
+ class: Vsa
+ isCriteria: 'false'
+ isGeneric: 'false'
+ protocol: '603'
+ TyCcV4AvpDataSize1: '200'
+ TyCcV4AvpDataSize2: '0'
+ TyCcV4SrvApn_1: '0'
+ TyCcV4SrvApn_2: '0'
+ TyCcV4SrvCrAction_1_1: Install
+ TyCcV4SrvCrAction_2_1: Install
+ TyCcV4SrvCrActivationTimeEn_1_1: 'false'
+ TyCcV4SrvCrActivationTimeEn_2_1: 'false'
+ TyCcV4SrvCrBearerIdEn_1_1: 'false'
+ TyCcV4SrvCrBearerIdEn_2_1: 'false'
+ TyCcV4SrvCrDeactivationTimeEn_1_1: 'false'
+ TyCcV4SrvCrDeactivationTimeEn_2_1: 'false'
+ TyCcV4SrvCrFilterDestIp_1_1_1_1: any
+ TyCcV4SrvCrFilterDirection_1_1_1_1: '3'
+ TyCcV4SrvCrFilterFlowLabel_1_1_1_1: ''
+ TyCcV4SrvCrFilterId_1_1_1_1: Fltr_V4_1_1_1_1
+ TyCcV4SrvCrFilterSpi_1_1_1_1: ''
+ TyCcV4SrvCrFilterTos_1_1_1_1: ''
+ TyCcV4SrvCrFilter_1_1_1_1: permit in ip from
+ TyCcV4SrvCrIpType_1_1_1_1: '0'
+ TyCcV4SrvCrNumBaseName_1_1: '0'
+ TyCcV4SrvCrNumBaseName_2_1: '0'
+ TyCcV4SrvCrNumFilters_1_1_1: '1'
+ TyCcV4SrvCrNumFilters_2_1_1: '0'
+ TyCcV4SrvCrNumRuleDef_1_1: '1'
+ TyCcV4SrvCrNumRuleDef_2_1: '1'
+ TyCcV4SrvCrNumRuleName_1_1: '1'
+ TyCcV4SrvCrNumRuleName_2_1: '1'
+ TyCcV4SrvCrOverwriteSrcIpEn_1_1_1_1: 'false'
+ TyCcV4SrvCrPolRuleEn_1_1_1: 'true'
+ TyCcV4SrvCrPolRuleEn_2_1_1: 'true'
+ TyCcV4SrvCrQciEn_1_1_1: 'true'
+ TyCcV4SrvCrQciEn_2_1_1: 'true'
+ TyCcV4SrvCrQci_1_1_1: '1'
+ TyCcV4SrvCrQci_2_1_1: '1'
+ TyCcV4SrvCrResourceAllocEn_1_1: 'false'
+ TyCcV4SrvCrResourceAllocEn_2_1: 'false'
+ TyCcV4SrvCrRuleDefAfChargIdEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefAfChargIdEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefAppSvcProvIdEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefAppSvcProvIdEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefFlowStatusEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefFlowStatusEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefMcdNumEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefMcdNumEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefMetMethodEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefMetMethodEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefName_1_1_1: dedicated_rule_definition
+ TyCcV4SrvCrRuleDefName_2_1_1: default_rule_definition
+ TyCcV4SrvCrRuleDefOfflineAvpEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefOfflineAvpEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefOnlineAvpEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefOnlineAvpEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefPrecEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefPrecEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefRatGrpEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefRatGrpEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefSponsorIdEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefSponsorIdEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleDefSrvIDEn_1_1_1: 'false'
+ TyCcV4SrvCrRuleDefSrvIDEn_2_1_1: 'false'
+ TyCcV4SrvCrRuleName_1_1_1: dedicated_charging_rule
+ TyCcV4SrvCrRuleName_2_1_1: default_charging_rule
+ TyCcV4SrvCrUserIpExt_1_1_1_1: ''
+ TyCcV4SrvNumCr_1: '1'
+ TyCcV4SrvNumCr_2: '1'
+ TyCcV4SrvNumRuleSet: '2'
+ TyCcV4SrvPrArpEn_1_1_1: 'false'
+ TyCcV4SrvPrArpEn_2_1_1: 'false'
+ TyCcV4SrvPrBearerIdEn_1_1_1: 'false'
+ TyCcV4SrvPrBearerIdEn_2_1_1: 'false'
+ TyCcV4SrvPrGuaranteedBwEn_1_1_1: 'true'
+ TyCcV4SrvPrGuaranteedBwEn_2_1_1: 'false'
+ TyCcV4SrvPrGuaranteedDownlink_1_1_1: '100'
+ TyCcV4SrvPrGuaranteedUplink_1_1_1: '100'
+ TyCcV4SrvPrIncPacketFilterUsage_1_1_1: 'false'
+ TyCcV4SrvPrIncPacketFilterUsage_2_1_1: 'false'
+ TyCcV4SrvPrMaxBwEn_1_1_1: 'true'
+ TyCcV4SrvPrMaxBwEn_2_1_1: 'false'
+ TyCcV4SrvPrMaxDL_1_1_1: '100'
+ TyCcV4SrvPrMaxUL_1_1_1: '100'
+ TyCcV4SrvPrUseAssignedEn_1_1_1: 'false'
+ TyCcV4SrvPrUseAssignedEn_2_1_1: 'false'
+ TyCcV4SrvRevalidateEn_1: 'false'
+ TyCcV4SrvRevalidateEn_2: 'false'
+ TyCcV4SrvRuleInterval_1: '10'
+ TyCcV4SrvRuleInterval_2: '0'
+ TyCcV6SrvNumRuleSet: '0'
+ TyCcVsa:
+ attrInfos: []
+ class: Vsa
+ isCriteria: 'false'
+ isGeneric: 'false'
+ protocol: '303'
+ type: PCRF_Node
+ tsId: SGW_NODAL_PCRF_NODE_TS_NAME
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_service_request.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_service_request.yaml
new file mode 100644
index 000000000..2589a6b47
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_network_service_request.yaml
@@ -0,0 +1,341 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: Network triggered service request
+keywords: ''
+duration: 60
+library: test
+name: network_initiated_service_request
+tsGroups:
+- testCases:
+ - name: ''
+ AssociatedPhys: ''
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ BillingEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2CfgFileEn: 'false'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2ExtEn: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2MobGtpuForwardingEndptId: '5000000'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PersistentImsiEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2ResponseDelayEn: 'false'
+ Gtp2RestartCnt: '1'
+ Gtp2RouterAdDelay: '1'
+ Gtp2S5GtpcTunnelEndptId: '3000000'
+ Gtp2S5GtpuTunnelEndptId: '4000000'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2Version: 15.2.0
+ PgwNodeEn: 'true'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ Sessions: '1000'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwControlAddrErrInj: '0'
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwUserAddrErrInj: '0'
+ SgwUserDualStackEn: 'false'
+ TestType: SGW-NODE
+ TrafficMtu: '1400'
+ UeDhcpV4En: 'false'
+ type: SGW_Node
+ tsId: SGW_NODE_TS_NAME
+- testCases:
+ - name: ''
+ parameters:
+ ApnDnsEn: 'false'
+ ApnToPgwMappingEn: 'false'
+ AutoStopControlLayer: 'false'
+ ContinuousWithVerification: 'false'
+ CpCiotEpsOptimizationEn: 'false'
+ CtlBearerToDscpEn: 'false'
+ DataHostCfgFileEn: 'false'
+ DataResumeRate: '3000'
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0.0
+ rows:
+ - clientPort: 0
+ context: 0
+ node: 0
+ overridePort: 'false'
+ ratingGroup: 0
+ role: Server
+ serviceId: 0
+ transport: Any
+ mainflows:
+ - library: test
+ name: Basic UDP
+ DualStackEn: 'false'
+ EDrxValueEn: 'false'
+ EirIfEn: 'false'
+ EmergencyAttachWithImeiEn: 'false'
+ EmergencyAttachWoAuthEn: 'false'
+ EmergencyPdnIndexEn: 'false'
+ EnableExternalData: '0'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: ENB_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: ENB_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ EnbUserAddrErrInj: '0'
+ FireballEn: 'false'
+ Gtp2ActivationDelay: '0'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnNumSpecifiedApns_1: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnRetries_1: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnSpecified_1:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2ApnTotalApns_1: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2Apn_1: ssenoauth146
+ Gtp2BearerModEn: 'false'
+ Gtp2CfgFileEn: 'false'
+ Gtp2ChargingChars: '0x0'
+ Gtp2DelayDlPacketNotifReq: '1'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2EnbUliEn: 'false'
+ Gtp2ExtEn: 'false'
+ Gtp2FwdUplinkDataEcmIdle: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IdleEntryTime: '0'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncPcoOpt: none
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2MaxWaitTimeEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2ModBearerDlDataDelay: '0'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PcoAddEn: 'false'
+ Gtp2PcoIpcpEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2RejectDedEn: 'false'
+ Gtp2RemoteUeReportTime: '0'
+ Gtp2RestartCnt: '1'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2SwVersionEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2UeDaySaveTime: '0'
+ Gtp2UeMultPdnConnReqSameApnEn_0: 'false'
+ Gtp2UeTimeZone: '0'
+ Gtp2UliDbCmdCbRspEn: 'true'
+ Gtp2Version: 15.2.0
+ HomeAddrType: '1'
+ HomeAddrTypePerBearerEn: 'false'
+ HssIfEn: 'false'
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: MME_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: MME_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ MmeControlAddrErrInj: '0'
+ MultipathTcpEn: 'false'
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: NET_HOST_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: NET_HOST_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ NetworkHostAddrLocalErrInj: '0'
+ NetworkHostNatedTrafficEn: 'false'
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SecPgwV4SutEn: 'false'
+ SessionIntervalShape: Fixed
+ SessionRetries: 'true'
+ Sessions: '1000'
+ SgwNumSutsEn: 'false'
+ SgwSut:
+ class: Sut
+ name: PGW_SUT_NAME
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME
+ StartRate: '1000.0'
+ T3324PwrSavingValueEn: 'false'
+ T3412ExValueEn: 'false'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficDontFragIp: '0'
+ TrafficErrorInject: '0'
+ TrafficHostIdleTimeEnabler: 'false'
+ TrafficMtu: '1400'
+ TrafficStartDelay: '10000'
+ TrafficStartType: When All Sessions Established
+ UeDhcpV4En: 'false'
+ UseStaticBearerIp: 'false'
+ type: SGW_Nodal
+ tsId: SGW_NODAL_TS_NAME
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_saegw_relocation.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_saegw_relocation.yaml
new file mode 100644
index 000000000..f6daeee40
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_saegw_relocation.yaml
@@ -0,0 +1,177 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: SAEGW throughput with relocation test case
+keywords: ''
+duration: 60
+library: test
+name: saegw_relocation
+tsGroups:
+- testCases:
+ - name: ''
+ type: SGW_Node
+ AssociatedPhys: ''
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ BillingEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 15.2.0
+ PgwNodeEn: 'true'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ Sessions: '20000'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_CONTROL_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: SGW_CONTROL_PHY
+ SgwControlAddrErrInj: '0'
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ ip: SGW_USER_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: SGW_USER_PHY
+ SgwUserAddrErrInj: '0'
+ SgwUserDualStackEn: 'false'
+ TestType: SGW-NODE
+ TrafficMtu: '1400'
+ UeDhcpV4En: 'false'
+ tsId: SGW_NODE_TS_NAME
+- testCases:
+ - name: ''
+ type: SGW_Nodal
+ parameters:
+ ApnDnsEn: 'false'
+ ApnToPgwMappingEn: 'false'
+ AutoStopControlLayer: 'false'
+ ContinuousWithVerification: 'false'
+ CtlBearerToDscpEn: 'false'
+ DataHostCfgFileEn: 'false'
+ DataResumeRate: '3000'
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedicatedsPerDefaultBearer: '0'
+ DefaultBearers: '1'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0.0
+ mainflows:
+ - library: test
+ name: Basic UDP
+ DualStackEn: 'false'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: ENB_USER_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: ENB_USER_PHY
+ FireballEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2Version: 15.2.0
+ HandoffType: '0'
+ HomeAddrType: '1'
+ HomeAddrTypePerBearerEn: 'false'
+ HssIfEn: 'false'
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: MME_CONTROL_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: MME_CONTROL_PHY
+ MmeControlAddrErrInj: '0'
+ MobEnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: TARGET_ENB_USER_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: TARGET_ENB_USER_PHY
+ MobEnbUserAddrErrInj: '0'
+ MobilityIntervalShape: Fixed
+ MobilityMode: Single Handoff
+ MobilityRate: '1.0'
+ MobilityTimeMs: '10000'
+ MultipathTcpEn: 'false'
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: NET_HOST_IP
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ phy: NET_HOST_PHY
+ NetworkHostAddrLocalErrInj: '0'
+ NetworkHostNatedTrafficEn: 'false'
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SecPgwV4SutEn: 'false'
+ SessionIntervalShape: Fixed
+ SessionRetries: 'true'
+ Sessions: '20000'
+ SgwNumSutsEn: 'false'
+ SgwRelocationEn: 'false'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME
+ StartRate: '1000.0'
+ StartType: When All Sessions Started
+ TestActivity: Intra-MME Mobility
+ TestType: SGW-NODAL
+ TrafficMtu: '1400'
+ TrafficStartDelay: '1000'
+ TrafficStartType: When Session Established
+ tsId: SGW_NODAL_TS_NAME
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_dedicated_bearer.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_dedicated_bearer.yaml
new file mode 100644
index 000000000..ace6e0258
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_dedicated_bearer.yaml
@@ -0,0 +1,353 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: 'UE initiated dedicated bearer creation test case'
+duration: 60
+keywords: ''
+library: test
+name: capacity_dedicated_bearer_creation
+tsGroups:
+- testCases:
+ - name: ''
+ AssociatedPhys: ''
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ BillingEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2CfgFileEn: 'false'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2ExtEn: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2MobGtpuForwardingEndptId: '5000000'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PersistentImsiEn: 'false'
+ Gtp2PiggybackEn_sgw: '0'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2ResponseDelayEn: 'false'
+ Gtp2RestartCnt: '1'
+ Gtp2RouterAdDelay: '1'
+ Gtp2S5GtpcTunnelEndptId: '3000000'
+ Gtp2S5GtpuTunnelEndptId: '4000000'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2Version: 15.2.0
+ PgwNodeEn: 'true'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ Sessions: '1000'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: eth5
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwControlAddrErrInj: '0'
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: eth5
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwUserAddrErrInj: '0'
+ SgwUserDualStackEn: 'false'
+ SxaControlNodeAddrXPort: '8805'
+ SxaUserNodeAddrXPort: '8805'
+ TestType: SGW-NODE
+ TrafficMtu: '1400'
+ TrafficNumTftsForContext0: '1'
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'false'
+ type: SGW_Node
+ tsId: SGW_NODE_TS_NAME
+- testCases:
+ - name: ''
+ parameters:
+ ApnDnsEn: 'false'
+ ApnToPgwMappingEn: 'false'
+ AutoStopControlLayer: 'false'
+ ContinuousWithVerification: 'false'
+ CpCiotEpsOptimizationEn: 'false'
+ CtlBearerToDscpEn: 'false'
+ DataHostCfgFileEn: 'false'
+ DataResumeRate: '3000'
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedBearerConnectDelay: '0'
+ DedBearerDisconnectDelay: '0'
+ DedicatedBearerConnectRateEn: 'false'
+ DedicatedBearerDisconnectRateEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ DisconnectDedicatedBearerEn: 'false'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0.0
+ rows:
+ - clientPort: 0
+ context: 0
+ node: 0
+ overridePort: 'false'
+ ratingGroup: 0
+ role: 0
+ serviceId: 0
+ transport: Any
+ mainflows:
+ - library: test
+ name: Basic UDP
+ DualStackEn: 'false'
+ EDrxValueEn: 'false'
+ EirIfEn: 'false'
+ EmergencyAttachWithImeiEn: 'false'
+ EmergencyAttachWoAuthEn: 'false'
+ EmergencyPdnIndexEn: 'false'
+ EnableExternalData: '0'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: ENB_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: eth5
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ EnbUserAddrErrInj: '0'
+ FireballEn: 'false'
+ Gtp2ActivationDelay: '0'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnNumSpecifiedApns_1: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnRetries_1: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnSpecified_1:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2ApnTotalApns_1: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2Apn_1: ssenoauth146
+ Gtp2BearerModEn: 'false'
+ Gtp2CfgFileEn: 'false'
+ Gtp2ChargingChars: '0x0'
+ Gtp2DelayDlPacketNotifReq: '1'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2EnbUliEn: 'false'
+ Gtp2ExtEn: 'false'
+ Gtp2FwdUplinkDataEcmIdle: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IdleEntryTime: '0'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncPcoOpt: none
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2MaxWaitTimeEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2ModBearerDlDataDelay: '0'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PcoAddEn: 'false'
+ Gtp2PcoIpcpEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '1'
+ Gtp2QosGuarUplink_1: '1'
+ Gtp2QosMaxDownlink_1: '1'
+ Gtp2QosMaxUplink_1: '1'
+ Gtp2RadioAccessType: '6'
+ Gtp2RejectDedEn: 'false'
+ Gtp2RemoteUeReportTime: '0'
+ Gtp2RestartCnt: '1'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2SwVersionEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2UeDaySaveTime: '0'
+ Gtp2UeMultPdnConnReqSameApnEn_0: 'false'
+ Gtp2UeTimeZone: '0'
+ Gtp2UliDbCmdCbRspEn: 'true'
+ Gtp2Version: 15.2.0
+ HomeAddrType: '1'
+ HomeAddrTypePerBearerEn: 'false'
+ HssIfEn: 'false'
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: MME_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: eth5
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ MmeControlAddrErrInj: '0'
+ MultipathTcpEn: 'false'
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: NET_HOST_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: eth5
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ NetworkHostAddrLocalErrInj: '0'
+ NetworkHostNatedTrafficEn: 'false'
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SecPgwV4SutEn: 'false'
+ SessionIntervalShape: Fixed
+ SessionRetries: 'true'
+ Sessions: '1000'
+ SgwNumSutsEn: 'false'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME
+ StartRate: '1000.0'
+ T3324PwrSavingValueEn: 'false'
+ T3412ExValueEn: 'false'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficDontFragIp: '0'
+ TrafficErrorInject: '0'
+ TrafficHostIdleTimeEnabler: 'false'
+ TrafficMtu: '1400'
+ TrafficNumTftsForContext0: '1'
+ TrafficStartDelay: '1000'
+ TrafficStartType: When All Sessions Established
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'true'
+ UseStaticBearerIp: 'false'
+ type: SGW_Nodal
+ tsId: SGW_NODAL_TS_NAME
diff --git a/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_service_request.yaml b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_service_request.yaml
new file mode 100644
index 000000000..c4b178558
--- /dev/null
+++ b/samples/vnf_samples/traffic_profiles/landslide/landslide_session_ue_service_request.yaml
@@ -0,0 +1,378 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+description: ue initiates service request test case
+keywords: ''
+duration: 60
+library: test
+name: ue_initiates_service_request
+tsGroups:
+- testCases:
+ - name: ''
+ AssociatedPhys: ''
+ parameters:
+ BearerAddrPool: 2001::1
+ BearerV4AddrPool: 1.0.0.1
+ BillingEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ FireballEn: 'false'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2CfgFileEn: 'false'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2ExtEn: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2MobGtpuForwardingEndptId: '5000000'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PersistentImsiEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosDetail: Summary
+ Gtp2QosGuarDownlink_1: '150'
+ Gtp2QosGuarUplink_1: '150'
+ Gtp2QosMaxDownlink_1: '200'
+ Gtp2QosMaxUplink_1: '200'
+ Gtp2RadioAccessType: '6'
+ Gtp2ResponseDelayEn: 'false'
+ Gtp2RestartCnt: '1'
+ Gtp2RouterAdDelay: '1'
+ Gtp2S5GtpcTunnelEndptId: '3000000'
+ Gtp2S5GtpuTunnelEndptId: '4000000'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2Version: 15.2.0
+ PgwNodeEn: 'true'
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ Sessions: '1'
+ SgiPtpTunnelEn: 'false'
+ SgwControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwControlAddrErrInj: '0'
+ SgwUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: SGW_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: SGW_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ SgwUserAddrErrInj: '0'
+ SgwUserDualStackEn: 'false'
+ TestType: SGW-NODE
+ TrafficMtu: '1400'
+ TrafficNumTftsForContext0: '0'
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'true'
+ type: SGW_Node
+ tsId: SGW_NODE_TS_NAME
+- testCases:
+ - name: ''
+ parameters:
+ ApnDnsEn: 'false'
+ ApnToPgwMappingEn: 'false'
+ AutoStopControlLayer: 'false'
+ ContinuousWithVerification: 'false'
+ CpCiotEpsOptimizationEn: 'false'
+ CtlBearerToDscpEn: 'false'
+ DataHostCfgFileEn: 'false'
+ DataResumeRate: '3000'
+ DataTraffic: Continuous
+ DataUserCfgFileEn: 'false'
+ DedBearerConnectDelay: '0'
+ DedBearerDisconnectDelay: '0'
+ DedicatedBearerConnectRateEn: 'false'
+ DedicatedBearerDisconnectRateEn: 'false'
+ DedicatedsPerDefaultBearer: '1'
+ DefaultBearers: '1'
+ DisconnectRate: '1000.0'
+ Dmf:
+ class: Dmf
+ instanceGroups:
+ - mainflowIdx: 0
+ mixType: ''
+ rate: 0.0
+ rows:
+ - clientPort: 0
+ context: 0
+ node: 0
+ overridePort: 'false'
+ ratingGroup: 0
+ role: 0
+ serviceId: 0
+ transport: Any
+ mainflows:
+ - library: test
+ name: Basic UDP
+ DualStackEn: 'false'
+ EDrxValueEn: 'false'
+ EirIfEn: 'false'
+ EmergencyAttachWithImeiEn: 'false'
+ EmergencyAttachWoAuthEn: 'false'
+ EmergencyPdnIndexEn: 'false'
+ EnableExternalData: '0'
+ EnbUserAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: ENB_USER_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: ENB_USER_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ EnbUserAddrErrInj: '0'
+ FireballEn: 'false'
+ Gtp2ActivationDelay: '0'
+ Gtp2AmbrDownlink: '1'
+ Gtp2AmbrUplink: '1'
+ Gtp2ApnNumSpecifiedApns_0: '0'
+ Gtp2ApnNumSpecifiedApns_1: '0'
+ Gtp2ApnRestriction: '0'
+ Gtp2ApnRetries_0: '0'
+ Gtp2ApnRetries_1: '0'
+ Gtp2ApnSelectMode: '0'
+ Gtp2ApnSpecified_0:
+ array: []
+ class: Array
+ Gtp2ApnSpecified_1:
+ array: []
+ class: Array
+ Gtp2ApnTotalApns_0: '1'
+ Gtp2ApnTotalApns_1: '1'
+ Gtp2Apn_0: ssenoauth146
+ Gtp2Apn_1: ssenoauth146
+ Gtp2BearerContinuousMod: 'false'
+ Gtp2BearerDelayTime: '10'
+ Gtp2BearerModEn: 'true'
+ Gtp2BearerModInit: UE
+ Gtp2CfgFileEn: 'false'
+ Gtp2ChargingChars: '0x0'
+ Gtp2DelayDlPacketNotifReq: '1'
+ Gtp2Ecgi: '0'
+ Gtp2EcgiSize: '28'
+ Gtp2EchoTimeSec: '0'
+ Gtp2EnbUliEn: 'false'
+ Gtp2ExtEn: 'false'
+ Gtp2FwdUplinkDataEcmIdle: 'false'
+ Gtp2GtpcTunnelEndptId: '1000000'
+ Gtp2GtpuIncludeSeqEn: 'true'
+ Gtp2GtpuTunnelEndptId: '2000000'
+ Gtp2IdleEntryTime: '0'
+ Gtp2IgnoreRestartCtrEn: 'false'
+ Gtp2Imei: '50502410121507'
+ Gtp2Imsi: '505024101215074'
+ Gtp2IncCgiEn: 'false'
+ Gtp2IncEcgiEn: 'true'
+ Gtp2IncModQos_2: 'true'
+ Gtp2IncPcoOpt: none
+ Gtp2IncRaiEn: 'false'
+ Gtp2IncSaiEn: 'false'
+ Gtp2IncTaiEn: 'true'
+ Gtp2MacroEnbEn: 'false'
+ Gtp2MaxWaitTimeEn: 'false'
+ Gtp2Mcc: '000'
+ Gtp2Mnc: '000'
+ Gtp2ModBearerDlDataDelay: '0'
+ Gtp2MsIsdnEn: 'false'
+ Gtp2N3Attempts: '5'
+ Gtp2PagingTimeMs: '0'
+ Gtp2PcoAddEn: 'false'
+ Gtp2PcoIpcpEn: 'false'
+ Gtp2QosArpPreemptCapEn_1: 'false'
+ Gtp2QosArpPreemptCapEn_2: 'false'
+ Gtp2QosArpPreemptCapEn_2_1: 'false'
+ Gtp2QosArpPreemptCapEn_2_2: 'false'
+ Gtp2QosArpPreemptVulnEn_1: 'false'
+ Gtp2QosArpPreemptVulnEn_2: 'false'
+ Gtp2QosArpPreemptVulnEn_2_1: 'false'
+ Gtp2QosArpPreemptVulnEn_2_2: 'false'
+ Gtp2QosArpValue_1: '1'
+ Gtp2QosArpValue_2: '1'
+ Gtp2QosArpValue_2_1: '1'
+ Gtp2QosArpValue_2_2: '1'
+ Gtp2QosClassId_1: '1'
+ Gtp2QosClassId_2: '1'
+ Gtp2QosClassId_2_1: '1'
+ Gtp2QosClassId_2_2: '5'
+ Gtp2QosDetail: Individual
+ Gtp2QosDetail_2: Individual
+ Gtp2QosGuarDownlink_1: '150'
+ Gtp2QosGuarDownlink_2: '1000'
+ Gtp2QosGuarDownlink_2_1: '150'
+ Gtp2QosGuarUplink_1: '150'
+ Gtp2QosGuarUplink_2: '1000'
+ Gtp2QosGuarUplink_2_1: '150'
+ Gtp2QosMaxDownlink_1: '200'
+ Gtp2QosMaxDownlink_2: '2000'
+ Gtp2QosMaxDownlink_2_1: '250'
+ Gtp2QosMaxUplink_1: '200'
+ Gtp2QosMaxUplink_2: '2000'
+ Gtp2QosMaxUplink_2_1: '250'
+ Gtp2RadioAccessType: '6'
+ Gtp2RejectDedEn: 'false'
+ Gtp2RemoteUeReportTime: '0'
+ Gtp2RestartCnt: '1'
+ Gtp2SupportMabrEn: 'false'
+ Gtp2SwVersionEn: 'false'
+ Gtp2T3Time: '20'
+ Gtp2Tac: '0'
+ Gtp2UeDaySaveTime: '0'
+ Gtp2UeMultPdnConnReqSameApnEn_0: 'false'
+ Gtp2UeTimeZone: '0'
+ Gtp2UliDbCmdCbRspEn: 'true'
+ Gtp2Version: 15.2.0
+ HomeAddrType: '1'
+ HomeAddrTypePerBearerEn: 'false'
+ HssIfEn: 'false'
+ MmeControlAddr:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: MME_CONTROL_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: MME_CONTROL_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ MmeControlAddrErrInj: '0'
+ MultipathTcpEn: 'false'
+ NetworkHost: Local
+ NetworkHostAddrLocal:
+ class: TestNode
+ ethStatsEnabled: 'false'
+ forcedEthInterface: ''
+ innerVlanId: 0
+ ip: NET_HOST_IP
+ mac: ''
+ mtu: 1500
+ nextHop: ''
+ numLinksOrNodes: 1
+ numVlan: 1
+ phy: NET_HOST_PHY
+ uniqueVlanAddr: 'false'
+ vlanDynamic: 0
+ vlanId: 0
+ vlanTagType: 0
+ vlanUserPriority: 0
+ NetworkHostAddrLocalErrInj: '0'
+ NetworkHostNatedTrafficEn: 'false'
+ PgwNodeEn: 'false'
+ PgwUserSutEn: 'false'
+ PgwV4Sut:
+ class: Sut
+ name: PGW_SUT_NAME
+ QciToDscpMarkingsEn: 'false'
+ S5Protocol: GTPv2
+ SecPgwV4SutEn: 'false'
+ SessionIntervalShape: Fixed
+ SessionRetries: 'true'
+ Sessions: '1'
+ SgwNumSutsEn: 'false'
+ SgwSut:
+ class: Sut
+ name: SGW_CONTROL_NAME
+ SgwUserSut:
+ class: Sut
+ name: SGW_USER_NAME
+ StartRate: '1000.0'
+ T3324PwrSavingValueEn: 'false'
+ T3412ExValueEn: 'false'
+ TestActivity: Capacity Test
+ TestType: SGW-NODAL
+ TrafficAutoStartingDestPort: 'false'
+ TrafficAutoStartingDestPort_2: 'false'
+ TrafficDontFragIp: '0'
+ TrafficErrorInject: '0'
+ TrafficHostIdleTimeEnabler: 'false'
+ TrafficMtu: '1400'
+ TrafficNumTftsForContext0: '0'
+ TrafficNumTftsForContext0_2: '0'
+ TrafficOpCodeForContext0_2: '0'
+ TrafficStartDelay: '1000'
+ TrafficStartType: When All Sessions Established
+ UeDhcpV4En: 'false'
+ UeInitBearerEn: 'true'
+ UseStaticBearerIp: 'false'
+ type: SGW_Nodal
+ tsId: SGW_NODAL_TS_NAME
diff --git a/samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml b/samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml
new file mode 100644
index 000000000..14a3910e3
--- /dev/null
+++ b/samples/vnf_samples/vnf_descriptors/agnostic_vnf.yaml
@@ -0,0 +1,44 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: AgnosticVnf
+ name: AgnosticVnf
+ short-name: AgnosticVnf
+ description: 'VNFD for AgnosticVNF which wraps around any unsupported VNF
+ and allows for blackbox testing of the VNF.'
+ mgmt-interface:
+ vdu-id: AgnosticVnf-baremetal
+ {% if user is defined %}
+ user: '{{user}}' # Value filled by vnfdgen
+ {% endif %}
+ {% if password is defined %}
+ password: '{{password}}' # Value filled by vnfdgen
+ {% endif %}
+ {% if ip is defined %}
+ ip: '{{ip}}' # Value filled by vnfdgen
+ {% endif %}
+ {% if key_filename is defined %}
+ key_filename: '{{key_filename}}' # Value filled by vnfdgen
+ {% endif %}
+ vdu:
+ - id: AgnosticVnf-baremetal
+ name: AgnosticVnf-baremetal
+ description: Agnostic vnf
+ routing_table: {{ routing_table }}
+ nd_route_tbl: {{ nd_route_tbl }}
+ benchmark:
+ kpi:
+ [] \ No newline at end of file
diff --git a/samples/vnf_samples/vnf_descriptors/tg_landslide_tpl.yaml b/samples/vnf_samples/vnf_descriptors/tg_landslide_tpl.yaml
new file mode 100644
index 000000000..48963f0a9
--- /dev/null
+++ b/samples/vnf_samples/vnf_descriptors/tg_landslide_tpl.yaml
@@ -0,0 +1,38 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: LandslideTrafficGen # NSB python class mapping
+ name: LandslideTrafficGen
+ short-name: landslide
+ description: Spirent Landslide traffic generator
+ mgmt-interface:
+ vdu-id: landslide-tas
+ super-user: '{{tas_manager.super_user}}'
+ super-user-password: '{{tas_manager.super_user_password}}'
+ user: '{{tas_manager.test_user}}'
+ password: '{{tas_manager.test_user_password}}'
+ cfguser_password: '{{tas_manager.cfguser_password}}'
+ ip: '{{tas_manager.ip}}'
+ proto: '{{tas_manager.proto}}' # protocol used for REST API- http
+ license: '{{tas_manager.license}}' # Landslide license
+ config: {{config}}
+ vdu:
+ - id: abclient-baremetal
+ name: abclient-baremetal
+ description: AB client interface details
+ benchmark:
+ kpi: []
+
diff --git a/samples/vnf_samples/vnf_descriptors/vepc_vnf.yaml b/samples/vnf_samples/vnf_descriptors/vepc_vnf.yaml
new file mode 100644
index 000000000..73d3468bf
--- /dev/null
+++ b/samples/vnf_samples/vnf_descriptors/vepc_vnf.yaml
@@ -0,0 +1,38 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: EPCVnf # NSB python class mapping
+ name: EPCVnf
+ short-name: EPCVnf
+ description: EPCVnf
+ mgmt-interface:
+ vdu-id: vepcvnf-baremetal
+ {% if user is defined %}
+ user: '{{user}}' # Value filled by vnfdgen
+ {% endif %}
+ {% if password is defined %}
+ password: '{{password}}' # Value filled by vnfdgen
+ {% endif %}
+ {% if ip is defined %}
+ ip: '{{ip}}' # Value filled by vnfdgen
+ {% endif %}
+ vdu:
+ - id: vepcvnf-baremetal
+ name: vepc-vnf-baremetal
+ description: vEPCVnf workload
+ external-interface: []
+ benchmark:
+ kpi: []
diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
index d08dbaa6e..e4f715c84 100644
--- a/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
+++ b/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
@@ -22,6 +22,11 @@ description: >
{% set queue_depths = queue_depths or "4" %}
{% set steady_state_samples = steady_state_samples or 10 %}
{% set volume_size = volume_size or 4 %}
+{% set volume_count = volume_count or 1 %}
+{% set volume_type = volume_type or "" %}
+{% set availability_zone = availability_zone or "nova" %}
+{% set subnet_CIDR = subnet_CIDR or "172.16.0.0/16" %}
+{% set stack_name = stack_name or "StorperfAgentGroup" %}
scenarios:
-
type: StorPerf
@@ -39,6 +44,11 @@ scenarios:
workload: {{workload}}
workloads: {{workloads}}
steady_state_samples: {{steady_state_samples}}
+ volume_count: {{volume_count}}
+ volume_type: {{volume_type}}
+ availability_zone: {{availability_zone}}
+ subnet_CIDR: {{subnet_CIDR}}
+ stack_name: {{stack_name}}
runner:
type: Iteration
diff --git a/tests/opnfv/test_suites/opnfv_k8-calico-nofeature-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_k8-calico-nofeature-noha_daily.yaml
new file mode 100644
index 000000000..8e465af43
--- /dev/null
+++ b/tests/opnfv/test_suites/opnfv_k8-calico-nofeature-noha_daily.yaml
@@ -0,0 +1,18 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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
+##############################################################################
+---
+# k8 calico nofeature noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "k8-calico-nofeature-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc080.yaml
diff --git a/tests/opnfv/test_suites/opnfv_k8-canal-nofeature-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_k8-canal-nofeature-noha_daily.yaml
new file mode 100644
index 000000000..5df46f5a9
--- /dev/null
+++ b/tests/opnfv/test_suites/opnfv_k8-canal-nofeature-noha_daily.yaml
@@ -0,0 +1,18 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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
+##############################################################################
+---
+# k8 canal nofeature noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "k8-canal-nofeature-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc080.yaml
diff --git a/tests/opnfv/test_suites/opnfv_k8-contiv-nofeature-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_k8-contiv-nofeature-noha_daily.yaml
new file mode 100644
index 000000000..c38d8b0fa
--- /dev/null
+++ b/tests/opnfv/test_suites/opnfv_k8-contiv-nofeature-noha_daily.yaml
@@ -0,0 +1,18 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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
+##############################################################################
+---
+# k8 contiv nofeature noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "k8-contiv-nofeature-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc080.yaml
diff --git a/tests/opnfv/test_suites/opnfv_k8-flannel-nofeature-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_k8-flannel-nofeature-noha_daily.yaml
new file mode 100644
index 000000000..3de14e2a6
--- /dev/null
+++ b/tests/opnfv/test_suites/opnfv_k8-flannel-nofeature-noha_daily.yaml
@@ -0,0 +1,18 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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
+##############################################################################
+---
+# k8 flannel nofeature noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "k8-flannel-nofeature-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc080.yaml
diff --git a/tests/opnfv/test_suites/opnfv_k8-nosdn-istio-noha_daily.yaml b/tests/opnfv/test_suites/opnfv_k8-nosdn-istio-noha_daily.yaml
new file mode 100644
index 000000000..0e5844cd3
--- /dev/null
+++ b/tests/opnfv/test_suites/opnfv_k8-nosdn-istio-noha_daily.yaml
@@ -0,0 +1,18 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# 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
+##############################################################################
+---
+# k8 nosdn istio noha daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "k8-nosdn-istio-noha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc080.yaml
diff --git a/tox.ini b/tox.ini
index 313f1eca2..016228458 100644
--- a/tox.ini
+++ b/tox.ini
@@ -44,6 +44,17 @@ commands =
basepython = python3
commands = {[testenv:functional]commands}
+[testenv:docs]
+deps = -rdocs/requirements.txt
+commands =
+ sphinx-build -b html -n -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/html
+ echo "Generated docs available in {toxinidir}/docs/_build/html"
+whitelist_externals = echo
+
+[testenv:docs-linkcheck]
+deps = -rdocs/requirements.txt
+commands = sphinx-build -b linkcheck -d {envtmpdir}/doctrees ./docs/ {toxinidir}/docs/_build/linkcheck
+
[testenv:os-requirements]
commands =
python {toxinidir}/tools/os-requirements-check.py {envdir}
diff --git a/yardstick/benchmark/contexts/standalone/model.py b/yardstick/benchmark/contexts/standalone/model.py
index fa78fc1eb..1004c62d1 100644
--- a/yardstick/benchmark/contexts/standalone/model.py
+++ b/yardstick/benchmark/contexts/standalone/model.py
@@ -564,7 +564,7 @@ class StandaloneContextHelper(object):
key_filename = ''.join(
[constants.YARDSTICK_ROOT_PATH,
'yardstick/resources/files/yardstick_key-',
- id_name])
+ id_name, '-', vm_name])
ssh.SSH.gen_keys(key_filename)
node['key_filename'] = key_filename
# Update image with public key
diff --git a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
index 73311f0c2..3ad1097b0 100644
--- a/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
+++ b/yardstick/benchmark/contexts/standalone/ovs_dpdk.py
@@ -46,7 +46,8 @@ class OvsDpdkContext(base.Context):
'2.7.0': '16.11.1',
'2.7.1': '16.11.2',
'2.7.2': '16.11.3',
- '2.8.0': '17.05.2'
+ '2.8.0': '17.05.2',
+ '2.8.1': '17.05.2'
}
DEFAULT_OVS = '2.6.0'
@@ -166,8 +167,7 @@ class OvsDpdkContext(base.Context):
version = self.ovs_properties.get('version', {})
ovs_ver = [int(x) for x in version.get('ovs', self.DEFAULT_OVS).split('.')]
ovs_add_port = ('ovs-vsctl add-port {br} {port} -- '
- 'set Interface {port} type={type_}{dpdk_args}')
- ovs_add_queue = 'ovs-vsctl set Interface {port} options:n_rxq={queue}'
+ 'set Interface {port} type={type_}{dpdk_args}{dpdk_rxq}')
chmod_vpath = 'chmod 0777 {0}/var/run/openvswitch/dpdkvhostuser*'
cmd_list = [
@@ -176,6 +176,8 @@ class OvsDpdkContext(base.Context):
'ovs-vsctl add-br {0} -- set bridge {0} datapath_type=netdev'.
format(MAIN_BRIDGE)
]
+ dpdk_rxq = " options:n_rxq={queue}".format(
+ queue=self.ovs_properties.get("queues", 1))
ordered_network = collections.OrderedDict(self.networks)
for index, vnf in enumerate(ordered_network.values()):
@@ -183,10 +185,7 @@ class OvsDpdkContext(base.Context):
dpdk_args = " options:dpdk-devargs=%s" % vnf.get("phy_port")
dpdk_list.append(ovs_add_port.format(
br=MAIN_BRIDGE, port='dpdk%s' % vnf.get("port_num", 0),
- type_='dpdk', dpdk_args=dpdk_args))
- dpdk_list.append(ovs_add_queue.format(
- port='dpdk%s' % vnf.get("port_num", 0),
- queue=self.ovs_properties.get("queues", 1)))
+ type_='dpdk', dpdk_args=dpdk_args, dpdk_rxq=dpdk_rxq))
# Sorting the array to make sure we execute dpdk0... in the order
list.sort(dpdk_list)
@@ -196,7 +195,7 @@ class OvsDpdkContext(base.Context):
for index, _ in enumerate(ordered_network):
cmd_list.append(ovs_add_port.format(
br=MAIN_BRIDGE, port='dpdkvhostuser%s' % index,
- type_='dpdkvhostuser', dpdk_args=""))
+ type_='dpdkvhostuser', dpdk_args="", dpdk_rxq=""))
ovs_flow = ("ovs-ofctl add-flow {0} in_port=%s,action=output:%s".
format(MAIN_BRIDGE))
diff --git a/yardstick/benchmark/runners/duration.py b/yardstick/benchmark/runners/duration.py
index 14fd8bb47..55c3690fd 100644
--- a/yardstick/benchmark/runners/duration.py
+++ b/yardstick/benchmark/runners/duration.py
@@ -106,7 +106,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
sequence += 1
- if (errors and sla_action is None) or time.time() > timeout or aborted.is_set():
+ if ((errors and sla_action is None) or time.time() > timeout
+ or aborted.is_set() or benchmark.is_ended()):
LOG.info("Worker END")
break
diff --git a/yardstick/benchmark/runners/proxduration.py b/yardstick/benchmark/runners/proxduration.py
index 61a468fd3..e217904b9 100644
--- a/yardstick/benchmark/runners/proxduration.py
+++ b/yardstick/benchmark/runners/proxduration.py
@@ -112,7 +112,8 @@ def _worker_process(queue, cls, method_name, scenario_cfg,
sequence += 1
- if (errors and sla_action is None) or time.time() > timeout or aborted.is_set():
+ if ((errors and sla_action is None) or time.time() > timeout
+ or aborted.is_set() or benchmark.is_ended()):
LOG.info("Worker END")
break
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash
index d34ce9338..cda469cf9 100755
--- a/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/fault_process_kill.bash
@@ -16,7 +16,7 @@ set -e
process_name=$1
if [ "$process_name" = "keystone" ]; then
- for pid in $(ps aux | grep "keystone" | grep -iv heartbeat | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}'); \
+ for pid in $(ps aux | grep "keystone" | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}'); \
do
kill -9 "${pid}"
done
@@ -26,7 +26,7 @@ elif [ "$process_name" = "haproxy" ]; then
kill -9 "${pid}"
done
else
- for pid in $(pgrep -fa [^-_a-zA-Z0-9]${process_name} | grep -iv heartbeat | awk '{print $1}');
+ for pid in $(pgrep -fa [^-_a-zA-Z0-9]${process_name} | awk '{print $1}');
do
kill -9 "${pid}"
done
diff --git a/yardstick/benchmark/scenarios/base.py b/yardstick/benchmark/scenarios/base.py
index 90a87ac29..1737bb942 100644
--- a/yardstick/benchmark/scenarios/base.py
+++ b/yardstick/benchmark/scenarios/base.py
@@ -50,6 +50,9 @@ class Scenario(object):
def run(self, *args):
"""Entry point for scenario classes, called from runner worker"""
+ def is_ended(self):
+ return False
+
def teardown(self):
"""Default teardown implementation for Scenario classes"""
pass
diff --git a/yardstick/benchmark/scenarios/networking/vnf_generic.py b/yardstick/benchmark/scenarios/networking/vnf_generic.py
index 6d68c5e64..20fff61ed 100644
--- a/yardstick/benchmark/scenarios/networking/vnf_generic.py
+++ b/yardstick/benchmark/scenarios/networking/vnf_generic.py
@@ -63,6 +63,9 @@ class NetworkServiceTestCase(scenario_base.Scenario):
self.bin_path = get_nsb_option('bin_path', '')
self._mq_ids = []
+ def is_ended(self):
+ return self.traffic_profile is not None and self.traffic_profile.is_ended()
+
def _get_ip_flow_range(self, ip_start_range):
"""Retrieve a CIDR first and last viable IPs
diff --git a/yardstick/benchmark/scenarios/storage/storperf.py b/yardstick/benchmark/scenarios/storage/storperf.py
index 8093cd2d2..f2fcce651 100644
--- a/yardstick/benchmark/scenarios/storage/storperf.py
+++ b/yardstick/benchmark/scenarios/storage/storperf.py
@@ -87,7 +87,9 @@ class StorPerf(base.Scenario):
env_args = {}
env_args_payload_list = ["agent_count", "agent_flavor",
"public_network", "agent_image",
- "volume_size"]
+ "volume_size", "volume_type",
+ "volume_count", "availability_zone",
+ "stack_name", "subnet_CIDR"]
for env_argument in env_args_payload_list:
try:
diff --git a/yardstick/common/exceptions.py b/yardstick/common/exceptions.py
index c9d61e45c..5e0df973a 100644
--- a/yardstick/common/exceptions.py
+++ b/yardstick/common/exceptions.py
@@ -424,3 +424,15 @@ class InvalidMacAddress(YardstickException):
class ValueCheckError(YardstickException):
message = 'Constraint "%(value1)s %(operator)s %(value2)s" does not hold'
+
+
+class RestApiError(RuntimeError):
+ def __init__(self, message):
+ self._message = message
+ super(RestApiError, self).__init__(message)
+
+
+class LandslideTclException(RuntimeError):
+ def __init__(self, message):
+ self._message = message
+ super(LandslideTclException, self).__init__(message)
diff --git a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
index 29533808c..d4f75babb 100644
--- a/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
+++ b/yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2018 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -50,6 +50,20 @@ TRAFFIC_STATUS_STOPPED = 'stopped'
SUPPORTED_PROTO = [PROTO_UDP]
+class Vlan(object):
+ def __init__(self,
+ vlan_id, vlan_id_step=None, vlan_id_direction='increment',
+ prio=None, prio_step=None, prio_direction='increment',
+ tp_id=None):
+ self.vlan_id = vlan_id
+ self.vlan_id_step = vlan_id_step
+ self.vlan_id_direction = vlan_id_direction
+ self.prio = prio
+ self.prio_step = prio_step
+ self.prio_direction = prio_direction
+ self.tp_id = tp_id
+
+
# NOTE(ralonsoh): this pragma will be removed in the last patch of this series
class IxNextgen(object): # pragma: no cover
@@ -107,6 +121,11 @@ class IxNextgen(object): # pragma: no cover
return self._ixnet
raise exceptions.IxNetworkClientNotConnected()
+ def get_vports(self):
+ """Return the list of assigned ports (vport objects)"""
+ vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
+ return vports
+
def _get_config_element_by_flow_group_name(self, flow_group_name):
"""Get a config element using the flow group name
@@ -225,15 +244,20 @@ class IxNextgen(object): # pragma: no cover
zip(self._cfg['cards'], self._cfg['ports'])]
log.info('Create and assign vports: %s', ports)
- for port in ports:
- vport = self.ixnet.add(self.ixnet.getRoot(), 'vport')
- self.ixnet.commit()
- self.ixnet.execute('assignPorts', [port], [], [vport], True)
+
+ vports = []
+ for _ in ports:
+ vports.append(self.ixnet.add(self.ixnet.getRoot(), 'vport'))
self.ixnet.commit()
+
+ self.ixnet.execute('assignPorts', ports, [], vports, True)
+ self.ixnet.commit()
+
+ for vport in vports:
if self.ixnet.getAttribute(vport, '-state') != 'up':
log.warning('Port %s is down', vport)
- def _create_traffic_item(self):
+ def _create_traffic_item(self, traffic_type='raw'):
"""Create the traffic item to hold the flow groups
The traffic item tracking by "Traffic Item" is enabled to retrieve the
@@ -243,7 +267,7 @@ class IxNextgen(object): # pragma: no cover
traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic',
'trafficItem')
self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544',
- '-trafficType', 'raw')
+ '-trafficType', traffic_type)
self.ixnet.commit()
traffic_item_id = self.ixnet.remapIds(traffic_item)[0]
@@ -251,27 +275,25 @@ class IxNextgen(object): # pragma: no cover
'-trackBy', 'trafficGroupId0')
self.ixnet.commit()
- def _create_flow_groups(self):
- """Create the flow groups between the assigned ports"""
+ def _create_flow_groups(self, uplink, downlink):
+ """Create the flow groups between the endpoints"""
traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic',
'trafficItem')[0]
log.info('Create the flow groups')
- vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
- uplink_ports = vports[::2]
- downlink_ports = vports[1::2]
+
index = 0
- for up, down in zip(uplink_ports, downlink_ports):
+ for up, down in zip(uplink, downlink):
log.info('FGs: %s <--> %s', up, down)
endpoint_set_1 = self.ixnet.add(traffic_item_id, 'endpointSet')
endpoint_set_2 = self.ixnet.add(traffic_item_id, 'endpointSet')
self.ixnet.setMultiAttribute(
endpoint_set_1, '-name', str(index + 1),
- '-sources', [up + '/protocols'],
- '-destinations', [down + '/protocols'])
+ '-sources', [up],
+ '-destinations', [down])
self.ixnet.setMultiAttribute(
endpoint_set_2, '-name', str(index + 2),
- '-sources', [down + '/protocols'],
- '-destinations', [up + '/protocols'])
+ '-sources', [down],
+ '-destinations', [up])
self.ixnet.commit()
index += 2
@@ -281,7 +303,7 @@ class IxNextgen(object): # pragma: no cover
'/traffic/protocolTemplate:"{}"'.format(protocol_name))
self.ixnet.execute('append', previous_element, protocol)
- def _setup_config_elements(self):
+ def _setup_config_elements(self, add_default_proto=True):
"""Setup the config elements
The traffic item is configured to allow individual configurations per
@@ -303,12 +325,13 @@ class IxNextgen(object): # pragma: no cover
self.ixnet.setAttribute(config_element + '/frameRateDistribution',
'-streamDistribution', 'splitRateEvenly')
self.ixnet.commit()
- self._append_procotol_to_stack(
- PROTO_UDP, config_element + '/stack:"ethernet-1"')
- self._append_procotol_to_stack(
- PROTO_IPV4, config_element + '/stack:"ethernet-1"')
+ if add_default_proto:
+ self._append_procotol_to_stack(
+ PROTO_UDP, config_element + '/stack:"ethernet-1"')
+ self._append_procotol_to_stack(
+ PROTO_IPV4, config_element + '/stack:"ethernet-1"')
- def create_traffic_model(self):
+ def create_traffic_model(self, uplink_ports, downlink_ports):
"""Create a traffic item and the needed flow groups
Each flow group inside the traffic item (only one is present)
@@ -319,10 +342,27 @@ class IxNextgen(object): # pragma: no cover
FlowGroup3: port3 -> port4
FlowGroup4: port3 <- port4
"""
- self._create_traffic_item()
- self._create_flow_groups()
+ self._create_traffic_item('raw')
+ uplink_endpoints = [port + '/protocols' for port in uplink_ports]
+ downlink_endpoints = [port + '/protocols' for port in downlink_ports]
+ self._create_flow_groups(uplink_endpoints, downlink_endpoints)
self._setup_config_elements()
+ def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies):
+ """Create a traffic item and the needed flow groups
+
+ Each flow group inside the traffic item (only one is present)
+ represents the traffic between two topologies:
+ (uplink) (downlink)
+ FlowGroup1: uplink1 -> downlink1
+ FlowGroup2: uplink1 <- downlink1
+ FlowGroup3: uplink2 -> downlink2
+ FlowGroup4: uplink2 <- downlink2
+ """
+ self._create_traffic_item('ipv4')
+ self._create_flow_groups(uplink_topologies, downlink_topologies)
+ self._setup_config_elements(False)
+
def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
"""Set the MAC address in a config element stack Ethernet field
@@ -366,16 +406,15 @@ class IxNextgen(object): # pragma: no cover
raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
type = traffic_param.get('traffic_type', 'fixedDuration')
- rate = traffic_param['rate']
rate_unit = (
'framesPerSecond' if traffic_param['rate_unit'] ==
tp_base.TrafficProfileConfig.RATE_FPS else 'percentLineRate')
weighted_range_pairs = self._parse_framesize(
- traffic_param['outer_l2']['framesize'])
- srcmac = str(traffic_param.get('srcmac', '00:00:00:00:00:01'))
- dstmac = str(traffic_param.get('dstmac', '00:00:00:00:00:02'))
+ traffic_param['outer_l2'].get('framesize', {}))
+ srcmac = str(traffic_param['outer_l2'].get('srcmac', '00:00:00:00:00:01'))
+ dstmac = str(traffic_param['outer_l2'].get('dstmac', '00:00:00:00:00:02'))
- if traffic_param['outer_l2']['QinQ']:
+ if traffic_param['outer_l2'].get('QinQ'):
s_vlan = traffic_param['outer_l2']['QinQ']['S-VLAN']
c_vlan = traffic_param['outer_l2']['QinQ']['C-VLAN']
@@ -400,21 +439,27 @@ class IxNextgen(object): # pragma: no cover
self.ixnet.setMultiAttribute(
config_element + '/transmissionControl',
'-type', type, '-duration', duration)
+
self.ixnet.setMultiAttribute(
config_element + '/frameRate',
- '-rate', rate, '-type', rate_unit)
- self.ixnet.setMultiAttribute(
- config_element + '/frameSize',
- '-type', 'weightedPairs',
- '-weightedRangePairs', weighted_range_pairs)
+ '-rate', traffic_param['rate'], '-type', rate_unit)
+
+ if len(weighted_range_pairs):
+ self.ixnet.setMultiAttribute(
+ config_element + '/frameSize',
+ '-type', 'weightedPairs',
+ '-weightedRangePairs', weighted_range_pairs)
+
self.ixnet.commit()
- self._update_frame_mac(
- self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
- 'destinationAddress', dstmac)
- self._update_frame_mac(
- self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
- 'sourceAddress', srcmac)
+ if dstmac:
+ self._update_frame_mac(
+ self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
+ 'destinationAddress', dstmac)
+ if srcmac:
+ self._update_frame_mac(
+ self._get_stack_item(fg_id, PROTO_ETHERNET)[0],
+ 'sourceAddress', srcmac)
def _update_vlan_tag(self, fg_id, params, vlan=0):
field_to_param_map = {
@@ -474,20 +519,24 @@ class IxNextgen(object): # pragma: no cover
if not self._get_config_element_by_flow_group_name(fg_id):
raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
- count = traffic_param['outer_l3']['count']
- srcip = str(traffic_param['outer_l3']['srcip'])
- dstip = str(traffic_param['outer_l3']['dstip'])
- srcseed = traffic_param['outer_l3']['srcseed']
- dstseed = traffic_param['outer_l3']['dstseed']
- srcmask = traffic_param['outer_l3']['srcmask'] or IP_VERSION_4_MASK
- dstmask = traffic_param['outer_l3']['dstmask'] or IP_VERSION_4_MASK
-
- self._update_ipv4_address(
- self._get_stack_item(fg_id, PROTO_IPV4)[0],
- 'srcIp', srcip, srcseed, srcmask, count)
- self._update_ipv4_address(
- self._get_stack_item(fg_id, PROTO_IPV4)[0],
- 'dstIp', dstip, dstseed, dstmask, count)
+ if traffic_param['outer_l3']:
+ count = traffic_param['outer_l3']['count']
+ srcip = traffic_param['outer_l3']['srcip']
+ dstip = traffic_param['outer_l3']['dstip']
+ srcseed = traffic_param['outer_l3']['srcseed']
+ dstseed = traffic_param['outer_l3']['dstseed']
+ srcmask = traffic_param['outer_l3']['srcmask'] \
+ or IP_VERSION_4_MASK
+ dstmask = traffic_param['outer_l3']['dstmask'] \
+ or IP_VERSION_4_MASK
+ if srcip:
+ self._update_ipv4_address(
+ self._get_stack_item(fg_id, PROTO_IPV4)[0],
+ 'srcIp', str(srcip), srcseed, srcmask, count)
+ if dstip:
+ self._update_ipv4_address(
+ self._get_stack_item(fg_id, PROTO_IPV4)[0],
+ 'dstIp', str(dstip), dstseed, dstmask, count)
def update_l4(self, traffic):
"""Update the L4 headers
@@ -501,7 +550,10 @@ class IxNextgen(object): # pragma: no cover
if not self._get_config_element_by_flow_group_name(fg_id):
raise exceptions.IxNetworkFlowNotPresent(flow_group=fg_id)
- proto = traffic_param['outer_l3']['proto']
+ proto = traffic_param['outer_l3'].get('proto')
+ if not (proto and traffic_param['outer_l4']):
+ continue
+
if proto not in SUPPORTED_PROTO:
raise exceptions.IXIAUnsupportedProtocol(protocol=proto)
@@ -514,12 +566,15 @@ class IxNextgen(object): # pragma: no cover
dstport = traffic_param['outer_l4']['dstport']
dstmask = traffic_param['outer_l4']['dstportmask']
- if proto in SUPPORTED_PROTO:
- self._update_udp_port(self._get_stack_item(fg_id, proto)[0],
- 'srcPort', srcport, seed, srcmask, count)
-
- self._update_udp_port(self._get_stack_item(fg_id, proto)[0],
- 'dstPort', dstport, seed, dstmask, count)
+ if proto == PROTO_UDP:
+ if srcport:
+ self._update_udp_port(
+ self._get_stack_item(fg_id, proto)[0],
+ 'srcPort', srcport, seed, srcmask, count)
+ if dstport:
+ self._update_udp_port(
+ self._get_stack_item(fg_id, proto)[0],
+ 'dstPort', dstport, seed, dstmask, count)
def _update_udp_port(self, descriptor, field, value,
seed=1, mask=0, count=1):
@@ -570,6 +625,12 @@ class IxNextgen(object): # pragma: no cover
self.LATENCY_NAME_MAP))
return stats
+ def start_protocols(self):
+ self.ixnet.execute('startAllProtocols')
+
+ def stop_protocols(self):
+ self.ixnet.execute('stopAllProtocols')
+
def start_traffic(self):
"""Start the traffic injection in the traffic item
@@ -587,3 +648,194 @@ class IxNextgen(object): # pragma: no cover
self.ixnet.execute('start', '/traffic')
# pylint: disable=unnecessary-lambda
utils.wait_until_true(lambda: self.is_traffic_running())
+
+ def add_topology(self, name, vports):
+ log.debug("add_topology: name='%s' ports='%s'", name, vports)
+ obj = self.ixnet.add(self.ixnet.getRoot(), 'topology')
+ self.ixnet.setMultiAttribute(obj, '-name', name, '-vports', vports)
+ self.ixnet.commit()
+ return obj
+
+ def add_device_group(self, topology, name, multiplier):
+ log.debug("add_device_group: tpl='%s', name='%s', multiplier='%s'",
+ topology, name, multiplier)
+
+ obj = self.ixnet.add(topology, 'deviceGroup')
+ self.ixnet.setMultiAttribute(obj, '-name', name, '-multiplier',
+ multiplier)
+ self.ixnet.commit()
+ return obj
+
+ def add_ethernet(self, dev_group, name):
+ log.debug(
+ "add_ethernet: device_group='%s' name='%s'", dev_group, name)
+ obj = self.ixnet.add(dev_group, 'ethernet')
+ self.ixnet.setMultiAttribute(obj, '-name', name)
+ self.ixnet.commit()
+ return obj
+
+ def _create_vlans(self, ethernet, count):
+ self.ixnet.setMultiAttribute(ethernet, '-useVlans', 'true')
+ self.ixnet.setMultiAttribute(ethernet, '-vlanCount', count)
+ self.ixnet.commit()
+
+ def _configure_vlans(self, ethernet, vlans):
+ vlans_obj = self.ixnet.getList(ethernet, 'vlan')
+ for i, vlan_obj in enumerate(vlans_obj):
+ if vlans[i].vlan_id_step is not None:
+ vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId')
+ self.ixnet.setMultiAttribute(vlan_id_obj, '-clearOverlays',
+ 'true', '-pattern', 'counter')
+ vlan_id_counter = self.ixnet.add(vlan_id_obj, 'counter')
+ self.ixnet.setMultiAttribute(vlan_id_counter, '-start',
+ vlans[i].vlan_id, '-step',
+ vlans[i].vlan_id_step,
+ '-direction',
+ vlans[i].vlan_id_direction)
+ else:
+ vlan_id_obj = self.ixnet.getAttribute(vlan_obj, '-vlanId')
+ self.ixnet.setMultiAttribute(vlan_id_obj + '/singleValue',
+ '-value', vlans[i].vlan_id)
+
+ if vlans[i].prio_step is not None:
+ prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority')
+ self.ixnet.setMultiAttribute(prio_obj, '-clearOverlays', 'true',
+ '-pattern', 'counter')
+ prio_counter = self.ixnet.add(prio_obj, 'counter')
+ self.ixnet.setMultiAttribute(prio_counter,
+ '-start', vlans[i].prio,
+ '-step', vlans[i].prio_step,
+ '-direction', vlans[i].prio_direction)
+ elif vlans[i].prio is not None:
+ prio_obj = self.ixnet.getAttribute(vlan_obj, '-priority')
+ self.ixnet.setMultiAttribute(prio_obj + '/singleValue',
+ '-value', vlans[i].prio)
+
+ if vlans[i].tp_id is not None:
+ tp_id_obj = self.ixnet.getAttribute(vlan_obj, '-tpid')
+ self.ixnet.setMultiAttribute(tp_id_obj + '/singleValue',
+ '-value', vlans[i].tp_id)
+
+ self.ixnet.commit()
+
+ def add_vlans(self, ethernet, vlans):
+ log.debug("add_vlans: ethernet='%s'", ethernet)
+
+ if vlans is None or len(vlans) == 0:
+ raise RuntimeError(
+ "Invalid 'vlans' argument. Expected list of Vlan instances.")
+
+ self._create_vlans(ethernet, len(vlans))
+ self._configure_vlans(ethernet, vlans)
+
+ def add_ipv4(self, ethernet, name='',
+ addr=None, addr_step=None, addr_direction='increment',
+ prefix=None, prefix_step=None, prefix_direction='increment',
+ gateway=None, gw_step=None, gw_direction='increment'):
+ log.debug("add_ipv4: ethernet='%s' name='%s'", ethernet, name)
+ obj = self.ixnet.add(ethernet, 'ipv4')
+ if name != '':
+ self.ixnet.setAttribute(obj, '-name', name)
+ self.ixnet.commit()
+
+ if addr_step is not None:
+ # handle counter pattern
+ _address = self.ixnet.getAttribute(obj, '-address')
+ self.ixnet.setMultiAttribute(_address, '-clearOverlays', 'true',
+ '-pattern', 'counter')
+
+ address_counter = self.ixnet.add(_address, 'counter')
+ self.ixnet.setMultiAttribute(address_counter,
+ '-start', addr,
+ '-step', addr_step,
+ '-direction', addr_direction)
+ elif addr is not None:
+ # handle single value
+ _address = self.ixnet.getAttribute(obj, '-address')
+ self.ixnet.setMultiAttribute(_address + '/singleValue', '-value',
+ addr)
+
+ if prefix_step is not None:
+ # handle counter pattern
+ _prefix = self.ixnet.getAttribute(obj, '-prefix')
+ self.ixnet.setMultiAttribute(_prefix, '-clearOverlays', 'true',
+ '-pattern', 'counter')
+ prefix_counter = self.ixnet.add(_prefix, 'counter')
+ self.ixnet.setMultiAttribute(prefix_counter,
+ '-start', prefix,
+ '-step', prefix_step,
+ '-direction', prefix_direction)
+ elif prefix is not None:
+ # handle single value
+ _prefix = self.ixnet.getAttribute(obj, '-prefix')
+ self.ixnet.setMultiAttribute(_prefix + '/singleValue', '-value',
+ prefix)
+
+ if gw_step is not None:
+ # handle counter pattern
+ _gateway = self.ixnet.getAttribute(obj, '-gatewayIp')
+ self.ixnet.setMultiAttribute(_gateway, '-clearOverlays', 'true',
+ '-pattern', 'counter')
+
+ gateway_counter = self.ixnet.add(_gateway, 'counter')
+ self.ixnet.setMultiAttribute(gateway_counter,
+ '-start', gateway,
+ '-step', gw_step,
+ '-direction', gw_direction)
+ elif gateway is not None:
+ # handle single value
+ _gateway = self.ixnet.getAttribute(obj, '-gatewayIp')
+ self.ixnet.setMultiAttribute(_gateway + '/singleValue', '-value',
+ gateway)
+
+ self.ixnet.commit()
+ return obj
+
+ def add_pppox_client(self, xproto, auth, user, pwd):
+ log.debug(
+ "add_pppox_client: xproto='%s', auth='%s', user='%s', pwd='%s'",
+ xproto, auth, user, pwd)
+ obj = self.ixnet.add(xproto, 'pppoxclient')
+ self.ixnet.commit()
+
+ if auth == 'pap':
+ auth_type = self.ixnet.getAttribute(obj, '-authType')
+ self.ixnet.setMultiAttribute(auth_type + '/singleValue', '-value',
+ auth)
+ pap_user = self.ixnet.getAttribute(obj, '-papUser')
+ self.ixnet.setMultiAttribute(pap_user + '/singleValue', '-value',
+ user)
+ pap_pwd = self.ixnet.getAttribute(obj, '-papPassword')
+ self.ixnet.setMultiAttribute(pap_pwd + '/singleValue', '-value',
+ pwd)
+ else:
+ raise NotImplementedError()
+
+ self.ixnet.commit()
+ return obj
+
+ def add_bgp(self, ipv4, dut_ip, local_as, bgp_type=None):
+ """Add BGP protocol"""
+ log.debug("add_bgp: ipv4='%s', dut_ip='%s', local_as='%s'", ipv4,
+ dut_ip, local_as)
+ obj = self.ixnet.add(ipv4, 'bgpIpv4Peer')
+ self.ixnet.commit()
+
+ # Set DUT IP address
+ dut_ip_addr = self.ixnet.getAttribute(obj, '-dutIp')
+ self.ixnet.setAttribute(dut_ip_addr + '/singleValue',
+ '-value', dut_ip)
+
+ # Set local AS number
+ local_as_number = self.ixnet.getAttribute(obj, '-localAs2Bytes')
+ self.ixnet.setAttribute(local_as_number + '/singleValue',
+ '-value', local_as)
+
+ if bgp_type:
+ # Set BGP type. If not specified, default value is using.
+ # Default type is "internal"
+ bgp_type_field = self.ixnet.getAttribute(obj, '-type')
+ self.ixnet.setAttribute(bgp_type_field + '/singleValue',
+ '-value', bgp_type)
+ self.ixnet.commit()
+ return obj
diff --git a/yardstick/network_services/traffic_profile/__init__.py b/yardstick/network_services/traffic_profile/__init__.py
index a1b26a24d..91d8a665f 100644
--- a/yardstick/network_services/traffic_profile/__init__.py
+++ b/yardstick/network_services/traffic_profile/__init__.py
@@ -28,6 +28,7 @@ def register_modules():
'yardstick.network_services.traffic_profile.prox_ramp',
'yardstick.network_services.traffic_profile.rfc2544',
'yardstick.network_services.traffic_profile.pktgen',
+ 'yardstick.network_services.traffic_profile.landslide_profile',
]
for module in modules:
diff --git a/yardstick/network_services/traffic_profile/base.py b/yardstick/network_services/traffic_profile/base.py
index 4fbceea9b..ea3f17874 100644
--- a/yardstick/network_services/traffic_profile/base.py
+++ b/yardstick/network_services/traffic_profile/base.py
@@ -97,6 +97,9 @@ class TrafficProfile(object):
self.params = tp_config
self.config = TrafficProfileConfig(tp_config)
+ def is_ended(self):
+ return False
+
def execute_traffic(self, traffic_generator, **kawrgs):
""" This methods defines the behavior of the traffic generator.
It will be called in a loop until the traffic generator exits.
diff --git a/yardstick/network_services/traffic_profile/ixia_rfc2544.py b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
index 44bf2eafc..b8aa78d80 100644
--- a/yardstick/network_services/traffic_profile/ixia_rfc2544.py
+++ b/yardstick/network_services/traffic_profile/ixia_rfc2544.py
@@ -56,68 +56,83 @@ class IXIARFC2544Profile(trex_traffic_profile.TrexProfile):
if not traffickey.startswith((self.UPLINK, self.DOWNLINK)):
continue
+ # values should be single-item dict, so just grab the first item
try:
- # values should be single-item dict, so just grab the first item
- try:
- key, value = next(iter(values.items()))
- except StopIteration:
- result[traffickey] = {}
- continue
-
- port_id = value.get('id', 1)
- port_index = port_id - 1
-
- if value.get('outer_l3v4'):
- ip = value['outer_l3v4']
- src_key, dst_key = 'srcip4', 'dstip4'
- else:
- ip = value['outer_l3v6']
- src_key, dst_key = 'srcip6', 'dstip6'
-
- srcip, srcmask = self._get_ip_and_mask(ip[src_key])
- dstip, dstmask = self._get_ip_and_mask(ip[dst_key])
-
- outer_l4 = value.get('outer_l4')
- src_port, src_port_mask = self._get_fixed_and_mask(outer_l4['srcport'])
- dst_port, dst_port_mask = self._get_fixed_and_mask(outer_l4['dstport'])
- result[traffickey] = {
- 'bidir': False,
- 'id': port_id,
- 'rate': self.rate,
- 'rate_unit': self.rate_unit,
- 'outer_l2': {
- 'framesize': value['outer_l2']['framesize'],
- 'framesPerSecond': True,
- 'QinQ': value['outer_l2'].get('QinQ'),
- 'srcmac': mac['src_mac_{}'.format(port_index)],
- 'dstmac': mac['dst_mac_{}'.format(port_index)],
- },
- 'outer_l3': {
- 'count': ip['count'],
- 'dscp': ip['dscp'],
- 'ttl': ip['ttl'],
- 'srcseed': ip.get('srcseed', 1),
- 'dstseed': ip.get('dstseed', 1),
- 'srcip': srcip,
- 'dstip': dstip,
- 'srcmask': srcmask,
- 'dstmask': dstmask,
- 'type': key,
- 'proto': ip['proto'],
- },
- 'outer_l4': {
- 'srcport': src_port,
- 'dstport': dst_port,
- 'srcportmask': src_port_mask,
- 'dstportmask': dst_port_mask,
- 'count': outer_l4['count'],
- 'seed': outer_l4.get('seed', 1)
- }
-
- }
- except KeyError:
+ key, value = next(iter(values.items()))
+ except StopIteration:
+ result[traffickey] = {}
continue
+ port_id = value.get('id', 1)
+ port_index = port_id - 1
+
+ result[traffickey] = {
+ 'bidir': False,
+ 'id': port_id,
+ 'rate': self.rate,
+ 'rate_unit': self.rate_unit,
+ 'outer_l2': {},
+ 'outer_l3': {},
+ 'outer_l4': {},
+ }
+
+ outer_l2 = value.get('outer_l2')
+ if outer_l2:
+ result[traffickey]['outer_l2'].update({
+ 'framesize': outer_l2.get('framesize'),
+ 'framesPerSecond': True,
+ 'QinQ': outer_l2.get('QinQ'),
+ 'srcmac': mac.get('src_mac_{}'.format(port_index)),
+ 'dstmac': mac.get('dst_mac_{}'.format(port_index)),
+ })
+
+ if value.get('outer_l3v4'):
+ outer_l3 = value['outer_l3v4']
+ src_key, dst_key = 'srcip4', 'dstip4'
+ else:
+ outer_l3 = value.get('outer_l3v6')
+ src_key, dst_key = 'srcip6', 'dstip6'
+ if outer_l3:
+ srcip = srcmask = dstip = dstmask = None
+ if outer_l3.get(src_key):
+ srcip, srcmask = self._get_ip_and_mask(outer_l3[src_key])
+ if outer_l3.get(dst_key):
+ dstip, dstmask = self._get_ip_and_mask(outer_l3[dst_key])
+
+ result[traffickey]['outer_l3'].update({
+ 'count': outer_l3.get('count', 1),
+ 'dscp': outer_l3.get('dscp'),
+ 'ttl': outer_l3.get('ttl'),
+ 'srcseed': outer_l3.get('srcseed', 1),
+ 'dstseed': outer_l3.get('dstseed', 1),
+ 'srcip': srcip,
+ 'dstip': dstip,
+ 'srcmask': srcmask,
+ 'dstmask': dstmask,
+ 'type': key,
+ 'proto': outer_l3.get('proto'),
+ })
+
+ outer_l4 = value.get('outer_l4')
+ if outer_l4:
+ src_port = src_port_mask = dst_port = dst_port_mask = None
+ if outer_l4.get('srcport'):
+ src_port, src_port_mask = (
+ self._get_fixed_and_mask(outer_l4['srcport']))
+
+ if outer_l4.get('dstport'):
+ dst_port, dst_port_mask = (
+ self._get_fixed_and_mask(outer_l4['dstport']))
+
+ result[traffickey]['outer_l4'].update({
+ 'srcport': src_port,
+ 'dstport': dst_port,
+ 'srcportmask': src_port_mask,
+ 'dstportmask': dst_port_mask,
+ 'count': outer_l4.get('count', 1),
+ 'seed': outer_l4.get('seed', 1),
+ })
+
return result
def _ixia_traffic_generate(self, traffic, ixia_obj):
diff --git a/yardstick/network_services/traffic_profile/landslide_profile.py b/yardstick/network_services/traffic_profile/landslide_profile.py
new file mode 100644
index 000000000..f79226fb4
--- /dev/null
+++ b/yardstick/network_services/traffic_profile/landslide_profile.py
@@ -0,0 +1,47 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+""" Spirent Landslide traffic profile definitions """
+
+from yardstick.network_services.traffic_profile import base
+
+
+class LandslideProfile(base.TrafficProfile):
+ """
+ This traffic profile handles attributes of Landslide data stream
+ """
+
+ def __init__(self, tp_config):
+ super(LandslideProfile, self).__init__(tp_config)
+
+ # for backward compatibility support dict and list of dicts
+ if isinstance(tp_config["dmf_config"], dict):
+ self.dmf_config = [tp_config["dmf_config"]]
+ else:
+ self.dmf_config = tp_config["dmf_config"]
+
+ def execute(self, traffic_generator):
+ pass
+
+ def update_dmf(self, options):
+ if 'dmf' in options:
+ if isinstance(options['dmf'], dict):
+ _dmfs = [options['dmf']]
+ else:
+ _dmfs = options['dmf']
+
+ for index, _dmf in enumerate(_dmfs):
+ try:
+ self.dmf_config[index].update(_dmf)
+ except IndexError:
+ pass
diff --git a/yardstick/network_services/traffic_profile/prox_binsearch.py b/yardstick/network_services/traffic_profile/prox_binsearch.py
index 16a0411ec..f924cf419 100644
--- a/yardstick/network_services/traffic_profile/prox_binsearch.py
+++ b/yardstick/network_services/traffic_profile/prox_binsearch.py
@@ -66,6 +66,9 @@ class ProxBinSearchProfile(ProxProfile):
yield test_value
test_value = self.mid_point
+ def is_ended(self):
+ return self.done.is_set()
+
def run_test_with_pkt_size(self, traffic_gen, pkt_size, duration):
"""Run the test for a single packet size.
@@ -93,7 +96,7 @@ class ProxBinSearchProfile(ProxProfile):
# success, the binary search will complete on an integer multiple
# of the precision, rather than on a fraction of it.
- theor_max_thruput = 0
+ theor_max_thruput = 0.0
result_samples = {}
@@ -195,9 +198,9 @@ class ProxBinSearchProfile(ProxProfile):
LOG.info(
">>>##>> Result Reached PktSize %s Theor_Max_Thruput %s Actual_throughput %s",
- pkt_size, theor_max_thruput, result_samples.get("RxThroughput", 0))
+ pkt_size, theor_max_thruput, result_samples.get("RxThroughput", 0.0))
result_samples["Status"] = STATUS_RESULT
result_samples["Next_Step"] = ""
- result_samples["Actual_throughput"] = result_samples.get("RxThroughput", 0)
+ result_samples["Actual_throughput"] = result_samples.get("RxThroughput", 0.0)
result_samples["theor_max_throughput"] = theor_max_thruput
self.queue.put(result_samples)
diff --git a/yardstick/network_services/traffic_profile/prox_profile.py b/yardstick/network_services/traffic_profile/prox_profile.py
index 343ef1da2..de4b3f9a0 100644
--- a/yardstick/network_services/traffic_profile/prox_profile.py
+++ b/yardstick/network_services/traffic_profile/prox_profile.py
@@ -16,6 +16,7 @@
from __future__ import absolute_import
import logging
+import multiprocessing
from yardstick.network_services.traffic_profile.base import TrafficProfile
from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxProfileHelper
@@ -56,7 +57,7 @@ class ProxProfile(TrafficProfile):
def __init__(self, tp_config):
super(ProxProfile, self).__init__(tp_config)
self.queue = None
- self.done = False
+ self.done = multiprocessing.Event()
self.results = []
# TODO: get init values from tp_config
@@ -116,7 +117,7 @@ class ProxProfile(TrafficProfile):
try:
pkt_size = next(self.pkt_size_iterator)
except StopIteration:
- self.done = True
+ self.done.set()
return
# Adjust packet size upwards if it's less than the minimum
diff --git a/yardstick/network_services/utils.py b/yardstick/network_services/utils.py
index 4b987fafe..9c64fecde 100644
--- a/yardstick/network_services/utils.py
+++ b/yardstick/network_services/utils.py
@@ -36,6 +36,9 @@ OPTS = [
cfg.StrOpt('trex_client_lib',
default=os.path.join(NSB_ROOT, 'trex_client/stl'),
help='trex python library path.'),
+ cfg.StrOpt('jre_path_i386',
+ default='',
+ help='path to installation of 32-bit Java 1.7+.'),
]
CONF.register_opts(OPTS, group="nsb")
diff --git a/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py b/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
new file mode 100644
index 000000000..115fddcf0
--- /dev/null
+++ b/yardstick/network_services/vnf_generic/vnf/agnostic_vnf.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+from yardstick.network_services.vnf_generic.vnf import base
+
+LOG = logging.getLogger(__name__)
+
+
+class AgnosticVnf(base.GenericVNF):
+ """ AgnosticVnf implementation. """
+ def __init__(self, name, vnfd, task_id):
+ super(AgnosticVnf, self).__init__(name, vnfd, task_id)
+
+ def instantiate(self, scenario_cfg, context_cfg):
+ pass
+
+ def wait_for_instantiate(self):
+ pass
+
+ def terminate(self):
+ pass
+
+ def scale(self, flavor=""):
+ pass
+
+ def collect_kpi(self):
+ pass
+
+ def start_collect(self):
+ pass
+
+ def stop_collect(self):
+ pass
diff --git a/yardstick/network_services/vnf_generic/vnf/epc_vnf.py b/yardstick/network_services/vnf_generic/vnf/epc_vnf.py
new file mode 100644
index 000000000..66d16d07f
--- /dev/null
+++ b/yardstick/network_services/vnf_generic/vnf/epc_vnf.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+
+from yardstick.network_services.vnf_generic.vnf import base
+
+LOG = logging.getLogger(__name__)
+
+
+class EPCVnf(base.GenericVNF):
+
+ def __init__(self, name, vnfd, task_id):
+ super(EPCVnf, self).__init__(name, vnfd, task_id)
+
+ def instantiate(self, scenario_cfg, context_cfg):
+ """Prepare VNF for operation and start the VNF process/VM
+
+ :param scenario_cfg: Scenario config
+ :param context_cfg: Context config
+ """
+ pass
+
+ def wait_for_instantiate(self):
+ """Wait for VNF to start"""
+ pass
+
+ def terminate(self):
+ """Kill all VNF processes"""
+ pass
+
+ def scale(self, flavor=""):
+ pass
+
+ def collect_kpi(self):
+ pass
+
+ def start_collect(self):
+ pass
+
+ def stop_collect(self):
+ pass
diff --git a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
index 3241719e8..321c05779 100644
--- a/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
+++ b/yardstick/network_services/vnf_generic/vnf/prox_helpers.py
@@ -984,7 +984,7 @@ class ProxResourceHelper(ClientResourceHelper):
def _run_traffic_once(self, traffic_profile):
traffic_profile.execute_traffic(self)
- if traffic_profile.done:
+ if traffic_profile.done.is_set():
self._queue.put({'done': True})
LOG.debug("tg_prox done")
self._terminated.value = 1
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_landslide.py b/yardstick/network_services/vnf_generic/vnf/tg_landslide.py
new file mode 100644
index 000000000..a146b72ca
--- /dev/null
+++ b/yardstick/network_services/vnf_generic/vnf/tg_landslide.py
@@ -0,0 +1,1203 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import collections
+import logging
+import requests
+import six
+import time
+
+from yardstick.common import exceptions
+from yardstick.common import utils as common_utils
+from yardstick.common import yaml_loader
+from yardstick.network_services import utils as net_serv_utils
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+
+try:
+ from lsapi import LsApi
+except ImportError:
+ LsApi = common_utils.ErrorClass
+
+LOG = logging.getLogger(__name__)
+
+
+class LandslideTrafficGen(sample_vnf.SampleVNFTrafficGen):
+ APP_NAME = 'LandslideTG'
+
+ def __init__(self, name, vnfd, task_id, setup_env_helper_type=None,
+ resource_helper_type=None):
+ if resource_helper_type is None:
+ resource_helper_type = LandslideResourceHelper
+ super(LandslideTrafficGen, self).__init__(name, vnfd, task_id,
+ setup_env_helper_type,
+ resource_helper_type)
+
+ self.bin_path = net_serv_utils.get_nsb_option('bin_path')
+ self.name = name
+ self.runs_traffic = True
+ self.traffic_finished = False
+ self.session_profile = None
+
+ def listen_traffic(self, traffic_profile):
+ pass
+
+ def terminate(self):
+ self.resource_helper.disconnect()
+
+ def instantiate(self, scenario_cfg, context_cfg):
+ super(LandslideTrafficGen, self).instantiate(scenario_cfg, context_cfg)
+ self.resource_helper.connect()
+
+ # Create test servers
+ test_servers = [x['test_server'] for x in self.vnfd_helper['config']]
+ self.resource_helper.create_test_servers(test_servers)
+
+ # Create SUTs
+ [self.resource_helper.create_suts(x['suts']) for x in
+ self.vnfd_helper['config']]
+
+ # Fill in test session based on session profile and test case options
+ self._load_session_profile()
+
+ def run_traffic(self, traffic_profile):
+ self.resource_helper.abort_running_tests()
+ # Update DMF profile with related test case options
+ traffic_profile.update_dmf(self.scenario_helper.all_options)
+ # Create DMF in test user library
+ self.resource_helper.create_dmf(traffic_profile.dmf_config)
+ # Create/update test session in test user library
+ self.resource_helper.create_test_session(self.session_profile)
+ # Start test session
+ self.resource_helper.create_running_tests(self.session_profile['name'])
+
+ def collect_kpi(self):
+ return self.resource_helper.collect_kpi()
+
+ def wait_for_instantiate(self):
+ pass
+
+ @staticmethod
+ def _update_session_suts(suts, testcase):
+ """ Create SUT entry. Update related EPC block in session profile. """
+ for sut in suts:
+ # Update session profile EPC element with SUT info from pod file
+ tc_role = testcase['parameters'].get(sut['role'])
+ if tc_role:
+ _param = {}
+ if tc_role['class'] == 'Sut':
+ _param['name'] = sut['name']
+ elif tc_role['class'] == 'TestNode':
+ _param.update({x: sut[x] for x in {'ip', 'phy', 'nextHop'}
+ if x in sut and sut[x]})
+ testcase['parameters'][sut['role']].update(_param)
+ else:
+ LOG.info('Unexpected SUT role in pod file: "%s".', sut['role'])
+ return testcase
+
+ def _update_session_test_servers(self, test_server, _tsgroup_index):
+ """ Update tsId, reservations, pre-resolved ARP in session profile """
+ # Update test server name
+ test_groups = self.session_profile['tsGroups']
+ test_groups[_tsgroup_index]['tsId'] = test_server['name']
+
+ # Update preResolvedArpAddress
+ arp_key = 'preResolvedArpAddress'
+ _preresolved_arp = test_server.get(arp_key) # list of dicts
+ if _preresolved_arp:
+ test_groups[_tsgroup_index][arp_key] = _preresolved_arp
+
+ # Update reservations
+ if 'phySubnets' in test_server:
+ reservation = {'tsId': test_server['name'],
+ 'tsIndex': _tsgroup_index,
+ 'tsName': test_server['name'],
+ 'phySubnets': test_server['phySubnets']}
+ if 'reservations' in self.session_profile:
+ self.session_profile['reservations'].append(reservation)
+ else:
+ self.session_profile['reservePorts'] = 'true'
+ self.session_profile['reservations'] = [reservation]
+
+ @staticmethod
+ def _update_session_tc_params(tc_options, testcase):
+ for _param_key in tc_options:
+ if _param_key == 'AssociatedPhys':
+ testcase[_param_key] = tc_options[_param_key]
+ continue
+ testcase['parameters'][_param_key] = tc_options[_param_key]
+ return testcase
+
+ def _load_session_profile(self):
+
+ with common_utils.open_relative_file(
+ self.scenario_helper.scenario_cfg['session_profile'],
+ self.scenario_helper.task_path) as stream:
+ self.session_profile = yaml_loader.yaml_load(stream)
+
+ # Raise exception if number of entries differs in following files,
+ _config_files = ['pod file', 'session_profile file', 'test_case file']
+ # Count testcases number in all tsGroups of session profile
+ session_tests_num = [xx for x in self.session_profile['tsGroups']
+ for xx in x['testCases']]
+ # Create a set containing number of list elements in each structure
+ _config_files_blocks_num = [
+ len(x) for x in
+ (self.vnfd_helper['config'], # test_servers and suts info
+ session_tests_num,
+ self.scenario_helper.all_options['test_cases'])] # test case file
+
+ if len(set(_config_files_blocks_num)) != 1:
+ raise RuntimeError('Unequal number of elements. {}'.format(
+ dict(six.moves.zip_longest(_config_files,
+ _config_files_blocks_num))))
+
+ ts_names = set()
+ _tsgroup_idx = -1
+ _testcase_idx = 0
+
+ # Iterate over data structures to overwrite session profile defaults
+ # _config: single list element holding test servers and SUTs info
+ # _tc_options: single test case parameters
+ for _config, tc_options in zip(
+ self.vnfd_helper['config'], # test servers and SUTS
+ self.scenario_helper.all_options['test_cases']): # testcase
+
+ _ts_config = _config['test_server']
+
+ # Calculate test group/test case indexes based on test server name
+ if _ts_config['name'] in ts_names:
+ _testcase_idx += 1
+ else:
+ _tsgroup_idx += 1
+ _testcase_idx = 0
+
+ _testcase = \
+ self.session_profile['tsGroups'][_tsgroup_idx]['testCases'][
+ _testcase_idx]
+
+ if _testcase['type'] != _ts_config['role']:
+ raise RuntimeError(
+ 'Test type mismatch in TC#{} of test server {}'.format(
+ _testcase_idx, _ts_config['name']))
+
+ # Fill session profile with test servers parameters
+ if _ts_config['name'] not in ts_names:
+ self._update_session_test_servers(_ts_config, _tsgroup_idx)
+ ts_names.add(_ts_config['name'])
+
+ # Fill session profile with suts parameters
+ self.session_profile['tsGroups'][_tsgroup_idx]['testCases'][
+ _testcase_idx].update(
+ self._update_session_suts(_config['suts'], _testcase))
+
+ # Update test case parameters
+ self.session_profile['tsGroups'][_tsgroup_idx]['testCases'][
+ _testcase_idx].update(
+ self._update_session_tc_params(tc_options, _testcase))
+
+
+class LandslideResourceHelper(sample_vnf.ClientResourceHelper):
+ """Landslide TG helper class"""
+
+ REST_STATUS_CODES = {'OK': 200, 'CREATED': 201, 'NO CHANGE': 409}
+ REST_API_CODES = {'NOT MODIFIED': 500810}
+
+ def __init__(self, setup_helper):
+ super(LandslideResourceHelper, self).__init__(setup_helper)
+ self._result = {}
+ self.vnfd_helper = setup_helper.vnfd_helper
+ self.scenario_helper = setup_helper.scenario_helper
+
+ # TAS Manager config initialization
+ self._url = None
+ self._user_id = None
+ self.session = None
+ self.license_data = {}
+
+ # TCL session initialization
+ self._tcl = LandslideTclClient(LsTclHandler(), self)
+
+ self.session = requests.Session()
+ self.running_tests_uri = 'runningTests'
+ self.test_session_uri = 'testSessions'
+ self.test_serv_uri = 'testServers'
+ self.suts_uri = 'suts'
+ self.users_uri = 'users'
+ self.user_lib_uri = None
+ self.run_id = None
+
+ def abort_running_tests(self, timeout=60, delay=5):
+ """ Abort running test sessions, if any """
+ _start_time = time.time()
+ while time.time() < _start_time + timeout:
+ run_tests_states = {x['id']: x['testStateOrStep']
+ for x in self.get_running_tests()}
+ if not set(run_tests_states.values()).difference(
+ {'COMPLETE', 'COMPLETE_ERROR'}):
+ break
+ else:
+ [self.stop_running_tests(running_test_id=_id, force=True)
+ for _id, _state in run_tests_states.items()
+ if 'COMPLETE' not in _state]
+ time.sleep(delay)
+ else:
+ raise RuntimeError(
+ 'Some test runs not stopped during {} seconds'.format(timeout))
+
+ def _build_url(self, resource, action=None):
+ """ Build URL string
+
+ :param resource: REST API resource name
+ :type resource: str
+ :param action: actions name and value
+ :type action: dict('name': <str>, 'value': <str>)
+ :returns str: REST API resource name with optional action info
+ """
+ # Action is optional and accepted only in presence of resource param
+ if action and not resource:
+ raise ValueError("Resource name not provided")
+ # Concatenate actions
+ _action = ''.join(['?{}={}'.format(k, v) for k, v in
+ action.items()]) if action else ''
+
+ return ''.join([self._url, resource, _action])
+
+ def get_response_params(self, method, resource, params=None):
+ """ Retrieve params from JSON response of specific resource URL
+
+ :param method: one of supported REST API methods
+ :type method: str
+ :param resource: URI, requested resource name
+ :type resource: str
+ :param params: attributes to be found in JSON response
+ :type params: list(str)
+ """
+ _res = []
+ params = params if params else []
+ response = self.exec_rest_request(method, resource)
+ # Get substring between last slash sign and question mark (if any)
+ url_last_part = resource.rsplit('/', 1)[-1].rsplit('?', 1)[0]
+ _response_json = response.json()
+ # Expect dict(), if URL last part and top dict key don't match
+ # Else, if they match, expect list()
+ k, v = list(_response_json.items())[0]
+ if k != url_last_part:
+ v = [v] # v: list(dict(str: str))
+ # Extract params, or whole list of dicts (without top level key)
+ for x in v:
+ _res.append({param: x[param] for param in params} if params else x)
+ return _res
+
+ def _create_user(self, auth, level=1):
+ """ Create new user
+
+ :param auth: data to create user account on REST server
+ :type auth: dict
+ :param level: Landslide user permissions level
+ :type level: int
+ :returns int: user id
+ """
+ # Set expiration date in two years since account creation date
+ _exp_date = time.strftime(
+ '{}/%m/%d %H:%M %Z'.format(time.gmtime().tm_year + 2))
+ _username = auth['user']
+ _fields = {"contactInformation": "", "expiresOn": _exp_date,
+ "fullName": "Test User",
+ "isActive": "true", "level": level,
+ "password": auth['password'],
+ "username": _username}
+ _response = self.exec_rest_request('post', self.users_uri,
+ json_data=_fields, raise_exc=False)
+ _resp_json = _response.json()
+ if _response.status_code == self.REST_STATUS_CODES['CREATED']:
+ # New user created
+ _id = _resp_json['id']
+ LOG.info("New user created: username='%s', id='%s'", _username,
+ _id)
+ elif _resp_json.get('apiCode') == self.REST_API_CODES['NOT MODIFIED']:
+ # User already exists
+ LOG.info("Account '%s' already exists.", _username)
+ # Get user id
+ _id = self._modify_user(_username, {"isActive": "true"})['id']
+ else:
+ raise exceptions.RestApiError(
+ 'Error during new user "{}" creation'.format(_username))
+ return _id
+
+ def _modify_user(self, username, fields):
+ """ Modify information about existing user
+
+ :param username: user name of account to be modified
+ :type username: str
+ :param fields: data to modify user account on REST server
+ :type fields: dict
+ :returns dict: user info
+ """
+ _response = self.exec_rest_request('post', self.users_uri,
+ action={'username': username},
+ json_data=fields, raise_exc=False)
+ if _response.status_code == self.REST_STATUS_CODES['OK']:
+ _response = _response.json()
+ else:
+ raise exceptions.RestApiError(
+ 'Error during user "{}" data update: {}'.format(
+ username,
+ _response.status_code))
+ LOG.info("User account '%s' modified: '%s'", username, _response)
+ return _response
+
+ def _delete_user(self, username):
+ """ Delete user account
+
+ :param username: username field
+ :type username: str
+ :returns bool: True if succeeded
+ """
+ self.exec_rest_request('delete', self.users_uri,
+ action={'username': username})
+
+ def _get_users(self, username=None):
+ """ Get user records from REST server
+
+ :param username: username field
+ :type username: None|str
+ :returns list(dict): empty list, or user record, or list of all users
+ """
+ _response = self.get_response_params('get', self.users_uri)
+ _res = [u for u in _response if
+ u['username'] == username] if username else _response
+ return _res
+
+ def exec_rest_request(self, method, resource, action=None, json_data=None,
+ logs=True, raise_exc=True):
+ """ Execute REST API request, return response object
+
+ :param method: one of supported requests ('post', 'get', 'delete')
+ :type method: str
+ :param resource: URL of resource
+ :type resource: str
+ :param action: data used to provide URI located after question mark
+ :type action: dict
+ :param json_data: mandatory only for 'post' method
+ :type json_data: dict
+ :param logs: debug logs display flag
+ :type raise_exc: bool
+ :param raise_exc: if True, raise exception on REST API call error
+ :returns requests.Response(): REST API call response object
+ """
+ json_data = json_data if json_data else {}
+ action = action if action else {}
+ _method = method.upper()
+ method = method.lower()
+ if method not in ('post', 'get', 'delete'):
+ raise ValueError("Method '{}' not supported".format(_method))
+
+ if method == 'post' and not action:
+ if not (json_data and isinstance(json_data, collections.Mapping)):
+ raise ValueError(
+ 'JSON data missing in {} request'.format(_method))
+
+ r = getattr(self.session, method)(self._build_url(resource, action),
+ json=json_data)
+ if raise_exc and not r.ok:
+ msg = 'Failed to "{}" resource "{}". Reason: "{}"'.format(
+ method, self._build_url(resource, action), r.reason)
+ raise exceptions.RestApiError(msg)
+
+ if logs:
+ LOG.debug("RC: %s | Request: %s | URL: %s", r.status_code, method,
+ r.request.url)
+ LOG.debug("Response: %s", r.json())
+ return r
+
+ def connect(self):
+ """Connect to RESTful server using test user account"""
+ tas_info = self.vnfd_helper['mgmt-interface']
+ # Supported REST Server ports: HTTP - 8080, HTTPS - 8181
+ _port = '8080' if tas_info['proto'] == 'http' else '8181'
+ tas_info.update({'port': _port})
+ self._url = '{proto}://{ip}:{port}/api/'.format(**tas_info)
+ self.session.headers.update({'Accept': 'application/json',
+ 'Content-type': 'application/json'})
+ # Login with super user to create test user
+ self.session.auth = (
+ tas_info['super-user'], tas_info['super-user-password'])
+ LOG.info("Connect using superuser: server='%s'", self._url)
+ auth = {x: tas_info[x] for x in ('user', 'password')}
+ self._user_id = self._create_user(auth)
+ # Login with test user
+ self.session.auth = auth['user'], auth['password']
+ # Test user validity
+ self.exec_rest_request('get', '')
+
+ self.user_lib_uri = 'libraries/{{}}/{}'.format(self.test_session_uri)
+ LOG.info("Login with test user: server='%s'", self._url)
+ # Read existing license
+ self.license_data['lic_id'] = tas_info['license']
+
+ # Tcl client init
+ self._tcl.connect(tas_info['ip'], *self.session.auth)
+
+ return self.session
+
+ def disconnect(self):
+ self.session = None
+ self._tcl.disconnect()
+
+ def terminate(self):
+ self._terminated.value = 1
+
+ def create_dmf(self, dmf):
+ if isinstance(dmf, list):
+ for _dmf in dmf:
+ self._tcl.create_dmf(_dmf)
+ else:
+ self._tcl.create_dmf(dmf)
+
+ def delete_dmf(self, dmf):
+ if isinstance(dmf, list):
+ for _dmf in dmf:
+ self._tcl.delete_dmf(_dmf)
+ else:
+ self._tcl.delete_dmf(dmf)
+
+ def create_suts(self, suts):
+ # Keep only supported keys in suts object
+ for _sut in suts:
+ sut_entry = {k: v for k, v in _sut.items()
+ if k not in {'phy', 'nextHop', 'role'}}
+ _response = self.exec_rest_request(
+ 'post', self.suts_uri, json_data=sut_entry,
+ logs=False, raise_exc=False)
+ if _response.status_code != self.REST_STATUS_CODES['CREATED']:
+ LOG.info(_response.reason) # Failed to create
+ _name = sut_entry.pop('name')
+ # Modify existing SUT
+ self.configure_sut(sut_name=_name, json_data=sut_entry)
+ else:
+ LOG.info("SUT created: %s", sut_entry)
+
+ def get_suts(self, suts_id=None):
+ if suts_id:
+ _suts = self.exec_rest_request(
+ 'get', '{}/{}'.format(self.suts_uri, suts_id)).json()
+ else:
+ _suts = self.get_response_params('get', self.suts_uri)
+
+ return _suts
+
+ def configure_sut(self, sut_name, json_data):
+ """ Modify information of specific SUTs
+
+ :param sut_name: name of existing SUT
+ :type sut_name: str
+ :param json_data: SUT settings
+ :type json_data: dict()
+ """
+ LOG.info("Modifying SUT information...")
+ _response = self.exec_rest_request('post',
+ self.suts_uri,
+ action={'name': sut_name},
+ json_data=json_data,
+ raise_exc=False)
+ if _response.status_code not in {self.REST_STATUS_CODES[x] for x in
+ {'OK', 'NO CHANGE'}}:
+ raise exceptions.RestApiError(_response.reason)
+
+ LOG.info("Modified SUT: %s", sut_name)
+
+ def delete_suts(self, suts_ids=None):
+ if not suts_ids:
+ _curr_suts = self.get_response_params('get', self.suts_uri)
+ suts_ids = [x['id'] for x in _curr_suts]
+ LOG.info("Deleting SUTs with following IDs: %s", suts_ids)
+ for _id in suts_ids:
+ self.exec_rest_request('delete',
+ '{}/{}'.format(self.suts_uri, _id))
+ LOG.info("\tDone for SUT id: %s", _id)
+
+ def _check_test_servers_state(self, test_servers_ids=None, delay=10,
+ timeout=300):
+ LOG.info("Waiting for related test servers state change to READY...")
+ # Wait on state change
+ _start_time = time.time()
+ while time.time() - _start_time < timeout:
+ ts_ids_not_ready = {x['id'] for x in
+ self.get_test_servers(test_servers_ids)
+ if x['state'] != 'READY'}
+ if ts_ids_not_ready == set():
+ break
+ time.sleep(delay)
+ else:
+ raise RuntimeError(
+ 'Test servers not in READY state after {} seconds.'.format(
+ timeout))
+
+ def create_test_servers(self, test_servers):
+ """ Create test servers
+
+ :param test_servers: input data for test servers creation
+ mandatory fields: managementIp
+ optional fields: name
+ :type test_servers: list(dict)
+ """
+ _ts_ids = []
+ for _ts in test_servers:
+ _msg = 'Created test server "%(name)s"'
+ _ts_ids.append(self._tcl.create_test_server(_ts))
+ if _ts.get('thread_model'):
+ _msg += ' in mode: "%(thread_model)s"'
+ LOG.info(_msg, _ts)
+
+ self._check_test_servers_state(_ts_ids)
+
+ def get_test_servers(self, test_server_ids=None):
+ if not test_server_ids: # Get all test servers info
+ _test_servers = self.exec_rest_request(
+ 'get', self.test_serv_uri).json()[self.test_serv_uri]
+ LOG.info("Current test servers configuration: %s", _test_servers)
+ return _test_servers
+
+ _test_servers = []
+ for _id in test_server_ids:
+ _test_servers.append(self.exec_rest_request(
+ 'get', '{}/{}'.format(self.test_serv_uri, _id)).json())
+ LOG.info("Current test servers configuration: %s", _test_servers)
+ return _test_servers
+
+ def configure_test_servers(self, action, json_data=None,
+ test_server_ids=None):
+ if not test_server_ids:
+ test_server_ids = [x['id'] for x in self.get_test_servers()]
+ elif isinstance(test_server_ids, int):
+ test_server_ids = [test_server_ids]
+ for _id in test_server_ids:
+ self.exec_rest_request('post',
+ '{}/{}'.format(self.test_serv_uri, _id),
+ action=action, json_data=json_data)
+ LOG.info("Test server (id: %s) configuration done: %s", _id,
+ action)
+ return test_server_ids
+
+ def delete_test_servers(self, test_servers_ids=None):
+ # Delete test servers
+ for _ts in self.get_test_servers(test_servers_ids):
+ self.exec_rest_request('delete', '{}/{}'.format(self.test_serv_uri,
+ _ts['id']))
+ LOG.info("Deleted test server: %s", _ts['name'])
+
+ def create_test_session(self, test_session):
+ # Use tcl client to create session
+ test_session['library'] = self._user_id
+ LOG.debug("Creating session='%s'", test_session['name'])
+ self._tcl.create_test_session(test_session)
+
+ def get_test_session(self, test_session_name=None):
+ if test_session_name:
+ uri = 'libraries/{}/{}/{}'.format(self._user_id,
+ self.test_session_uri,
+ test_session_name)
+ else:
+ uri = self.user_lib_uri.format(self._user_id)
+ _test_sessions = self.exec_rest_request('get', uri).json()
+ return _test_sessions
+
+ def configure_test_session(self, template_name, test_session):
+ # Override specified test session parameters
+ LOG.info('Update test session parameters: %s', test_session['name'])
+ test_session.update({'library': self._user_id})
+ return self.exec_rest_request(
+ method='post',
+ action={'action': 'overrideAndSaveAs'},
+ json_data=test_session,
+ resource='{}/{}'.format(self.user_lib_uri.format(self._user_id),
+ template_name))
+
+ def delete_test_session(self, test_session):
+ return self.exec_rest_request('delete', '{}/{}'.format(
+ self.user_lib_uri.format(self._user_id), test_session))
+
+ def create_running_tests(self, test_session_name):
+ r = self.exec_rest_request('post',
+ self.running_tests_uri,
+ json_data={'library': self._user_id,
+ 'name': test_session_name})
+ if r.status_code != self.REST_STATUS_CODES['CREATED']:
+ raise exceptions.RestApiError('Failed to start test session.')
+ self.run_id = r.json()['id']
+
+ def get_running_tests(self, running_test_id=None):
+ """Get JSON structure of specified running test entity
+
+ :param running_test_id: ID of created running test entity
+ :type running_test_id: int
+ :returns list: running tests entity
+ """
+ if not running_test_id:
+ running_test_id = ''
+ _res_name = '{}/{}'.format(self.running_tests_uri, running_test_id)
+ _res = self.exec_rest_request('get', _res_name, logs=False).json()
+ # If no run_id specified, skip top level key in response dict.
+ # Else return JSON as list
+ return _res.get('runningTests', [_res])
+
+ def delete_running_tests(self, running_test_id=None):
+ if not running_test_id:
+ running_test_id = ''
+ _res_name = '{}/{}'.format(self.running_tests_uri, running_test_id)
+ self.get_response_params('delete', _res_name)
+ LOG.info("Deleted running test with id: %s", running_test_id)
+
+ def _running_tests_action(self, running_test_id, action, json_data=None):
+ if not json_data:
+ json_data = {}
+ # Supported actions:
+ # 'stop', 'abort', 'continue', 'update', 'sendTcCommand', 'sendOdc'
+ _res_name = '{}/{}'.format(self.running_tests_uri, running_test_id)
+ self.exec_rest_request('post', _res_name, {'action': action},
+ json_data)
+ LOG.debug("Executed action: '%s' on running test id: %s", action,
+ running_test_id)
+
+ def stop_running_tests(self, running_test_id, json_data=None, force=False):
+ _action = 'abort' if force else 'stop'
+ self._running_tests_action(running_test_id, _action,
+ json_data=json_data)
+ LOG.info('Performed action: "%s" to test run with id: %s', _action,
+ running_test_id)
+
+ def check_running_test_state(self, run_id):
+ r = self.exec_rest_request('get',
+ '{}/{}'.format(self.running_tests_uri,
+ run_id))
+ return r.json().get("testStateOrStep")
+
+ def get_running_tests_results(self, run_id):
+ _res = self.exec_rest_request(
+ 'get',
+ '{}/{}/{}'.format(self.running_tests_uri,
+ run_id,
+ 'measurements')).json()
+ return _res
+
+ def _write_results(self, results):
+ # Avoid None value at test session start
+ _elapsed_time = results['elapsedTime'] if results['elapsedTime'] else 0
+
+ _res_tabs = results.get('tabs')
+ # Avoid parsing 'tab' dict key initially (missing or empty)
+ if not _res_tabs:
+ return
+
+ # Flatten nested dict holding Landslide KPIs of current test run
+ flat_kpis_dict = {}
+ for _tab, _kpis in six.iteritems(_res_tabs):
+ for _kpi, _value in six.iteritems(_kpis):
+ # Combine table name and KPI name using delimiter "::"
+ _key = '::'.join([_tab, _kpi])
+ try:
+ # Cast value from str to float
+ # Remove comma and/or measure units, e.g. "us"
+ flat_kpis_dict[_key] = float(
+ _value.split(' ')[0].replace(',', ''))
+ except ValueError: # E.g. if KPI represents datetime
+ pass
+ LOG.info("Polling test results of test run id: %s. Elapsed time: %s "
+ "seconds", self.run_id, _elapsed_time)
+ return flat_kpis_dict
+
+ def collect_kpi(self):
+ if 'COMPLETE' in self.check_running_test_state(self.run_id):
+ self._result.update({'done': True})
+ return self._result
+ _res = self.get_running_tests_results(self.run_id)
+ _kpis = self._write_results(_res)
+ if _kpis:
+ _kpis.update({'run_id': int(self.run_id)})
+ _kpis.update({'iteration': _res['iteration']})
+ self._result.update(_kpis)
+ return self._result
+
+
+class LandslideTclClient(object):
+ """Landslide TG TCL client class"""
+
+ DEFAULT_TEST_NODE = {
+ 'ethStatsEnabled': True,
+ 'forcedEthInterface': '',
+ 'innerVlanId': 0,
+ 'ip': '',
+ 'mac': '',
+ 'mtu': 1500,
+ 'nextHop': '',
+ 'numLinksOrNodes': 1,
+ 'numVlan': 1,
+ 'phy': '',
+ 'uniqueVlanAddr': False,
+ 'vlanDynamic': 0,
+ 'vlanId': 0,
+ 'vlanUserPriority': 0,
+ 'vlanTagType': 0
+ }
+
+ TEST_NODE_CMD = \
+ 'ls::create -TestNode-{} -under $p_ -Type "eth"' \
+ ' -Phy "{phy}" -Ip "{ip}" -NumLinksOrNodes {numLinksOrNodes}' \
+ ' -NextHop "{nextHop}" -Mac "{mac}" -MTU {mtu}' \
+ ' -ForcedEthInterface "{forcedEthInterface}"' \
+ ' -EthStatsEnabled {ethStatsEnabled}' \
+ ' -VlanId {vlanId} -VlanUserPriority {vlanUserPriority}' \
+ ' -NumVlan {numVlan} -UniqueVlanAddr {uniqueVlanAddr}' \
+ ';'
+
+ def __init__(self, tcl_handler, ts_context):
+ self.tcl_server_ip = None
+ self._user = None
+ self._library_id = None
+ self._basic_library_id = None
+ self._tcl = tcl_handler
+ self._ts_context = ts_context
+ self.ts_ids = set()
+
+ # Test types names expected in session profile, test case and pod files
+ self._tc_types = {"SGW_Nodal", "SGW_Node", "MME_Nodal", "PGW_Node",
+ "PCRF_Node"}
+
+ self._class_param_config_handler = {
+ "Array": self._configure_array_param,
+ "TestNode": self._configure_test_node_param,
+ "Sut": self._configure_sut_param,
+ "Dmf": self._configure_dmf_param
+ }
+
+ def connect(self, tcl_server_ip, username, password):
+ """ Connect to TCL server with username and password
+
+ :param tcl_server_ip: TCL server IP address
+ :type tcl_server_ip: str
+ :param username: existing username on TCL server
+ :type username: str
+ :param password: password related to username on TCL server
+ :type password: str
+ """
+ LOG.info("connect: server='%s' user='%s'", tcl_server_ip, username)
+ res = self._tcl.execute(
+ "ls::login {} {} {}".format(tcl_server_ip, username, password))
+ if 'java0x' not in res: # handle assignment reflects login success
+ raise exceptions.LandslideTclException(
+ "connect: login failed ='{}'.".format(res))
+ self._library_id = self._tcl.execute(
+ "ls::get [ls::query LibraryInfo -userLibraryName {}] -Id".format(
+ username))
+ self._basic_library_id = self._get_library_id('Basic')
+ self.tcl_server_ip = tcl_server_ip
+ self._user = username
+ LOG.debug("connect: user='%s' me='%s' basic='%s'", self._user,
+ self._library_id,
+ self._basic_library_id)
+
+ def disconnect(self):
+ """ Disconnect from TCL server. Drop TCL connection configuration """
+ LOG.info("disconnect: server='%s' user='%s'",
+ self.tcl_server_ip, self._user)
+ self._tcl.execute("ls::logout")
+ self.tcl_server_ip = None
+ self._user = None
+ self._library_id = None
+ self._basic_library_id = None
+
+ def _add_test_server(self, name, ip):
+ try:
+ # Check if test server exists with name equal to _ts_name
+ ts_id = int(self.resolve_test_server_name(name))
+ except ValueError:
+ # Such test server does not exist. Attempt to create it
+ ts_id = self._tcl.execute(
+ 'ls::perform AddTs -Name "{}" -Ip "{}"'.format(name, ip))
+ try:
+ int(ts_id)
+ except ValueError:
+ # Failed to create test server, e.g. limit reached
+ raise RuntimeError(
+ 'Failed to create test server: "{}". {}'.format(name,
+ ts_id))
+ return ts_id
+
+ def _update_license(self, name):
+ """ Setup/update test server license
+
+ :param name: test server name
+ :type name: str
+ """
+ # Retrieve current TsInfo configuration, result stored in handle "ts"
+ self._tcl.execute(
+ 'set ts [ls::retrieve TsInfo -Name "{}"]'.format(name))
+
+ # Set license ID, if it differs from current one, update test server
+ _curr_lic_id = self._tcl.execute('ls::get $ts -RequestedLicense')
+ if _curr_lic_id != self._ts_context.license_data['lic_id']:
+ self._tcl.execute('ls::config $ts -RequestedLicense {}'.format(
+ self._ts_context.license_data['lic_id']))
+ self._tcl.execute('ls::perform ModifyTs $ts')
+
+ def _set_thread_model(self, name, thread_model):
+ # Retrieve test server configuration, store it in handle "tsc"
+ _cfguser_password = self._ts_context.vnfd_helper['mgmt-interface'][
+ 'cfguser_password']
+ self._tcl.execute(
+ 'set tsc [ls::perform RetrieveTsConfiguration '
+ '-name "{}" {}]'.format(name, _cfguser_password))
+ # Configure ThreadModel, if it differs from current one
+ thread_model_map = {'Legacy': 'V0',
+ 'Max': 'V1',
+ 'Fireball': 'V1_FB3'}
+ _model = thread_model_map[thread_model]
+ _curr_model = self._tcl.execute('ls::get $tsc -ThreadModel')
+ if _curr_model != _model:
+ self._tcl.execute(
+ 'ls::config $tsc -ThreadModel "{}"'.format(_model))
+ self._tcl.execute(
+ 'ls::perform ApplyTsConfiguration $tsc {}'.format(
+ _cfguser_password))
+
+ def create_test_server(self, test_server):
+ _ts_thread_model = test_server.get('thread_model')
+ _ts_name = test_server['name']
+
+ ts_id = self._add_test_server(_ts_name, test_server['ip'])
+
+ self._update_license(_ts_name)
+
+ # Skip below code modifying thread_model if it is not defined
+ if _ts_thread_model:
+ self._set_thread_model(_ts_name, _ts_thread_model)
+
+ return ts_id
+
+ def create_test_session(self, test_session):
+ """ Create, configure and save Landslide test session object.
+
+ :param test_session: Landslide TestSession object
+ :type test_session: dict
+ """
+ LOG.info("create_test_session: name='%s'", test_session['name'])
+ self._tcl.execute('set test_ [ls::create TestSession]')
+ self._tcl.execute('ls::config $test_ -Library {} -Name "{}"'.format(
+ self._library_id, test_session['name']))
+ self._tcl.execute('ls::config $test_ -Description "{}"'.format(
+ test_session['description']))
+ if 'keywords' in test_session:
+ self._tcl.execute('ls::config $test_ -Keywords "{}"'.format(
+ test_session['keywords']))
+ if 'duration' in test_session:
+ self._tcl.execute('ls::config $test_ -Duration "{}"'.format(
+ test_session['duration']))
+ if 'iterations' in test_session:
+ self._tcl.execute('ls::config $test_ -Iterations "{}"'.format(
+ test_session['iterations']))
+ if 'reservePorts' in test_session:
+ if test_session['reservePorts'] == 'true':
+ self._tcl.execute('ls::config $test_ -Reserve Ports')
+
+ if 'reservations' in test_session:
+ for _reservation in test_session['reservations']:
+ self._configure_reservation(_reservation)
+
+ if 'reportOptions' in test_session:
+ self._configure_report_options(test_session['reportOptions'])
+
+ for _index, _group in enumerate(test_session['tsGroups']):
+ self._configure_ts_group(_group, _index)
+
+ self._save_test_session()
+
+ def create_dmf(self, dmf):
+ """ Create, configure and save Landslide Data Message Flow object.
+
+ :param dmf: Landslide Data Message Flow object
+ :type: dmf: dict
+ """
+ self._tcl.execute('set dmf_ [ls::create Dmf]')
+ _lib_id = self._get_library_id(dmf['dmf']['library'])
+ self._tcl.execute('ls::config $dmf_ -Library {} -Name "{}"'.format(
+ _lib_id,
+ dmf['dmf']['name']))
+ for _param_key in dmf:
+ if _param_key == 'dmf':
+ continue
+ _param_value = dmf[_param_key]
+ if isinstance(_param_value, dict):
+ # Configure complex parameter
+ _tcl_cmd = 'ls::config $dmf_'
+ for _sub_param_key in _param_value:
+ _sub_param_value = _param_value[_sub_param_key]
+ if isinstance(_sub_param_value, str):
+ _tcl_cmd += ' -{} "{}"'.format(_sub_param_key,
+ _sub_param_value)
+ else:
+ _tcl_cmd += ' -{} {}'.format(_sub_param_key,
+ _sub_param_value)
+
+ self._tcl.execute(_tcl_cmd)
+ else:
+ # Configure simple parameter
+ if isinstance(_param_value, str):
+ self._tcl.execute(
+ 'ls::config $dmf_ -{} "{}"'.format(_param_key,
+ _param_value))
+ else:
+ self._tcl.execute(
+ 'ls::config $dmf_ -{} {}'.format(_param_key,
+ _param_value))
+ self._save_dmf()
+
+ def configure_dmf(self, dmf):
+ # Use create to reconfigure and overwrite existing dmf
+ self.create_dmf(dmf)
+
+ def delete_dmf(self, dmf):
+ raise NotImplementedError
+
+ def _save_dmf(self):
+ # Call 'Validate' to set default values for missing parameters
+ res = self._tcl.execute('ls::perform Validate -Dmf $dmf_')
+ if res == 'Invalid':
+ res = self._tcl.execute('ls::get $dmf_ -ErrorsAndWarnings')
+ LOG.error("_save_dmf: %s", res)
+ raise exceptions.LandslideTclException("_save_dmf: {}".format(res))
+ else:
+ res = self._tcl.execute('ls::save $dmf_ -overwrite')
+ LOG.debug("_save_dmf: result (%s)", res)
+
+ def _configure_report_options(self, options):
+ for _option_key in options:
+ _option_value = options[_option_key]
+ if _option_key == 'format':
+ _format = 0
+ if _option_value == 'CSV':
+ _format = 1
+ self._tcl.execute(
+ 'ls::config $test_.ReportOptions -Format {} '
+ '-Ts -3 -Tc -3'.format(_format))
+ else:
+ self._tcl.execute(
+ 'ls::config $test_.ReportOptions -{} {}'.format(
+ _option_key,
+ _option_value))
+
+ def _configure_ts_group(self, ts_group, ts_group_index):
+ try:
+ _ts_id = int(self.resolve_test_server_name(ts_group['tsId']))
+ except ValueError:
+ raise RuntimeError('Test server name "{}" does not exist.'.format(
+ ts_group['tsId']))
+ if _ts_id not in self.ts_ids:
+ self._tcl.execute(
+ 'set tss_ [ls::create TsGroup -under $test_ -tsId {} ]'.format(
+ _ts_id))
+ self.ts_ids.add(_ts_id)
+ for _case in ts_group.get('testCases', []):
+ self._configure_tc_type(_case, ts_group_index)
+
+ self._configure_preresolved_arp(ts_group.get('preResolvedArpAddress'))
+
+ def _configure_tc_type(self, tc, ts_group_index):
+ if tc['type'] not in self._tc_types:
+ raise RuntimeError('Test type {} not supported.'.format(
+ tc['type']))
+ tc['type'] = tc['type'].replace('_', ' ')
+ res = self._tcl.execute(
+ 'set tc_ [ls::retrieve testcase -libraryId {0} "{1}"]'.format(
+ self._basic_library_id, tc['type']))
+ if 'Invalid' in res:
+ raise RuntimeError('Test type {} not found in "Basic" '
+ 'library.'.format(tc['type']))
+ self._tcl.execute(
+ 'ls::config $test_.TsGroup({}) -children-Tc $tc_'.format(
+ ts_group_index))
+ self._tcl.execute('ls::config $tc_ -Library {0} -Name "{1}"'.format(
+ self._basic_library_id, tc['name']))
+ self._tcl.execute(
+ 'ls::config $tc_ -Description "{}"'.format(tc['type']))
+ self._tcl.execute(
+ 'ls::config $tc_ -Keywords "GTP LTE {}"'.format(tc['type']))
+ if 'linked' in tc:
+ self._tcl.execute(
+ 'ls::config $tc_ -Linked {}'.format(tc['linked']))
+ if 'AssociatedPhys' in tc:
+ self._tcl.execute('ls::config $tc_ -AssociatedPhys "{}"'.format(
+ tc['AssociatedPhys']))
+ if 'parameters' in tc:
+ self._configure_parameters(tc['parameters'])
+
+ def _configure_parameters(self, params):
+ self._tcl.execute('set p_ [ls::get $tc_ -children-Parameters(0)]')
+ for _param_key in sorted(params):
+ _param_value = params[_param_key]
+ if isinstance(_param_value, dict):
+ # Configure complex parameter
+ if _param_value['class'] in self._class_param_config_handler:
+ self._class_param_config_handler[_param_value['class']](
+ _param_key,
+ _param_value)
+ else:
+ # Configure simple parameter
+ self._tcl.execute(
+ 'ls::create {} -under $p_ -Value "{}"'.format(
+ _param_key,
+ _param_value))
+
+ def _configure_array_param(self, name, params):
+ self._tcl.execute('ls::create -Array-{} -under $p_ ;'.format(name))
+ for param in params['array']:
+ self._tcl.execute(
+ 'ls::create ArrayItem -under $p_.{} -Value "{}"'.format(name,
+ param))
+
+ def _configure_test_node_param(self, name, params):
+ _params = self.DEFAULT_TEST_NODE
+ _params.update(params)
+
+ # TCL command expects lower case 'true' or 'false'
+ _params['ethStatsEnabled'] = str(_params['ethStatsEnabled']).lower()
+ _params['uniqueVlanAddr'] = str(_params['uniqueVlanAddr']).lower()
+
+ cmd = self.TEST_NODE_CMD.format(name, **_params)
+ self._tcl.execute(cmd)
+
+ def _configure_sut_param(self, name, params):
+ self._tcl.execute(
+ 'ls::create -Sut-{} -under $p_ -Name "{}";'.format(name,
+ params['name']))
+
+ def _configure_dmf_param(self, name, params):
+ self._tcl.execute('ls::create -Dmf-{} -under $p_ ;'.format(name))
+
+ for _flow_index, _flow in enumerate(params['mainflows']):
+ _lib_id = self._get_library_id(_flow['library'])
+ self._tcl.execute(
+ 'ls::perform AddDmfMainflow $p_.Dmf {} "{}"'.format(
+ _lib_id,
+ _flow['name']))
+
+ if not params.get('instanceGroups'):
+ return
+
+ _instance_group = params['instanceGroups'][_flow_index]
+
+ # Traffic Mixer parameters handling
+ for _key in ['mixType', 'rate']:
+ if _key in _instance_group:
+ self._tcl.execute(
+ 'ls::config $p_.Dmf.InstanceGroup({}) -{} {}'.format(
+ _flow_index, _key, _instance_group[_key]))
+
+ # Assignments parameters handling
+ for _row_id, _row in enumerate(_instance_group.get('rows', [])):
+ self._tcl.execute(
+ 'ls::config $p_.Dmf.InstanceGroup({}).Row({}) -Node {} '
+ '-OverridePort {} -ClientPort {} -Context {} -Role {} '
+ '-PreferredTransport {} -RatingGroup {} '
+ '-ServiceID {}'.format(
+ _flow_index, _row_id, _row['node'],
+ _row['overridePort'], _row['clientPort'],
+ _row['context'], _row['role'], _row['transport'],
+ _row['ratingGroup'], _row['serviceId']))
+
+ def _configure_reservation(self, reservation):
+ _ts_id = self.resolve_test_server_name(reservation['tsId'])
+ self._tcl.execute(
+ 'set reservation_ [ls::create Reservation -under $test_]')
+ self._tcl.execute(
+ 'ls::config $reservation_ -TsIndex {} -TsId {} '
+ '-TsName "{}"'.format(reservation['tsIndex'],
+ _ts_id,
+ reservation['tsName']))
+ for _subnet in reservation['phySubnets']:
+ self._tcl.execute(
+ 'set physubnet_ [ls::create PhySubnet -under $reservation_]')
+ self._tcl.execute(
+ 'ls::config $physubnet_ -Name "{}" -Base "{}" -Mask "{}" '
+ '-NumIps {}'.format(_subnet['name'], _subnet['base'],
+ _subnet['mask'], _subnet['numIps']))
+
+ def _configure_preresolved_arp(self, pre_resolved_arp):
+ if not pre_resolved_arp: # Pre-resolved ARP configuration not found
+ return
+ for _entry in pre_resolved_arp:
+ # TsGroup handle name should correspond in _configure_ts_group()
+ self._tcl.execute(
+ 'ls::create PreResolvedArpAddress -under $tss_ '
+ '-StartingAddress "{StartingAddress}" '
+ '-NumNodes {NumNodes}'.format(**_entry))
+
+ def delete_test_session(self, test_session):
+ raise NotImplementedError
+
+ def _save_test_session(self):
+ # Call 'Validate' to set default values for missing parameters
+ res = self._tcl.execute('ls::perform Validate -TestSession $test_')
+ if res == 'Invalid':
+ res = self._tcl.execute('ls::get $test_ -ErrorsAndWarnings')
+ raise exceptions.LandslideTclException(
+ "Test session validation failed. Server response: {}".format(
+ res))
+ else:
+ self._tcl.execute('ls::save $test_ -overwrite')
+ LOG.debug("Test session saved successfully.")
+
+ def _get_library_id(self, library):
+ _library_id = self._tcl.execute(
+ "ls::get [ls::query LibraryInfo -systemLibraryName {}] -Id".format(
+ library))
+ try:
+ int(_library_id)
+ return _library_id
+ except ValueError:
+ pass
+
+ _library_id = self._tcl.execute(
+ "ls::get [ls::query LibraryInfo -userLibraryName {}] -Id".format(
+ library))
+ try:
+ int(_library_id)
+ except ValueError:
+ LOG.error("_get_library_id: library='%s' not found.", library)
+ raise exceptions.LandslideTclException(
+ "_get_library_id: library='{}' not found.".format(
+ library))
+
+ return _library_id
+
+ def resolve_test_server_name(self, ts_name):
+ return self._tcl.execute("ls::query TsId {}".format(ts_name))
+
+
+class LsTclHandler(object):
+ """Landslide TCL Handler class"""
+
+ LS_OK = "ls_ok"
+ JRE_PATH = net_serv_utils.get_nsb_option('jre_path_i386')
+
+ def __init__(self):
+ self.tcl_cmds = {}
+ self._ls = LsApi(jre_path=self.JRE_PATH)
+ self._ls.tcl(
+ "ls::config ApiOptions -NoReturnSuccessResponseString '{}'".format(
+ self.LS_OK))
+
+ def execute(self, command):
+ res = self._ls.tcl(command)
+ self.tcl_cmds[command] = res
+ return res
diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
index 94ab06980..558a62935 100644
--- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
+++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py
@@ -96,7 +96,10 @@ class IxiaResourceHelper(ClientResourceHelper):
"""Initialize the IXIA IxNetwork client and configure the server"""
self.client.clear_config()
self.client.assign_ports()
- self.client.create_traffic_model()
+ vports = self.client.get_vports()
+ uplink_vports = vports[::2]
+ downlink_vports = vports[1::2]
+ self.client.create_traffic_model(uplink_vports, downlink_vports)
def run_traffic(self, traffic_profile, *args):
if self._terminated.value:
diff --git a/yardstick/tests/unit/benchmark/runner/test_arithmetic.py b/yardstick/tests/unit/benchmark/runner/test_arithmetic.py
index 7b1e1e976..35d935cd5 100644
--- a/yardstick/tests/unit/benchmark/runner/test_arithmetic.py
+++ b/yardstick/tests/unit/benchmark/runner/test_arithmetic.py
@@ -14,16 +14,26 @@ import os
import time
from yardstick.benchmark.runners import arithmetic
+from yardstick.common import exceptions as y_exc
class ArithmeticRunnerTest(unittest.TestCase):
class MyMethod(object):
- def __init__(self):
+ SLA_VALIDATION_ERROR_SIDE_EFFECT = 1
+ BROAD_EXCEPTION_SIDE_EFFECT = 2
+
+ def __init__(self, side_effect=0):
self.count = 101
+ self.side_effect = side_effect
def __call__(self, data):
self.count += 1
data['my_key'] = self.count
+ if self.side_effect == self.SLA_VALIDATION_ERROR_SIDE_EFFECT:
+ raise y_exc.SLAValidationError(case_name='My Case',
+ error_msg='my error message')
+ elif self.side_effect == self.BROAD_EXCEPTION_SIDE_EFFECT:
+ raise y_exc.YardstickException
return self.count
def setUp(self):
@@ -218,3 +228,219 @@ class ArithmeticRunnerTest(unittest.TestCase):
self.assertEqual(result['sequence'], count)
self.assertGreater(result['timestamp'], timestamp)
timestamp = result['timestamp']
+
+ def test__worker_process_except_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_on_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+ self.assertEqual(count, 8)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_except_sla_validation_error_sla_cfg_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_sla_validation_error_sla_cfg_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'],
+ ('My Case SLA validation failed. '
+ 'Error: my error message',))
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+ self.assertEqual(count, 8)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.my_method.assert_called_once()
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_not_called()
+
+ def test__worker_process_output_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ with self.assertRaisesRegexp(
+ y_exc.SLAValidationError,
+ 'My Case SLA validation failed. Error: my error message'):
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.assertEqual(self.benchmark.my_method.count, 102)
+ self.benchmark.teardown.assert_not_called()
+ self.assertTrue(queue.empty())
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_broad_exception_no_sla_cfg_early_exit(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.benchmark.my_method.assert_called_once()
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 64, 'size': 500})
+
+ def test__worker_process_output_on_broad_exception_no_sla_cfg(self):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 102)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 64, 'size': 500})
+ self.assertEqual(queue.qsize(), 1)
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['data'], {'my_key': 102})
+ self.assertRegexpMatches(
+ result['errors'],
+ 'YardstickException: An unknown exception occurred.')
+ self.assertEqual(result['sequence'], 1)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_broad_exception_sla_cfg_not_none(self):
+ self.scenario_cfg['sla'] = {'action': 'some action'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_on_broad_exception_sla_cfg_not_none(self):
+ self.scenario_cfg['sla'] = {'action': 'some action'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ self.assertTrue(output_queue.empty())
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertRegexpMatches(
+ result['errors'],
+ 'YardstickException: An unknown exception occurred.')
+ self.assertEqual(result['sequence'], count)
+
+ def test__worker_process_benchmark_teardown_on_broad_exception(self):
+ self.benchmark.teardown = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ with self.assertRaises(SystemExit) as raised:
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ self.assertEqual(raised.exception.code, 1)
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
diff --git a/yardstick/tests/unit/benchmark/runner/test_duration.py b/yardstick/tests/unit/benchmark/runner/test_duration.py
index d4801ef2c..fa47e96bf 100644
--- a/yardstick/tests/unit/benchmark/runner/test_duration.py
+++ b/yardstick/tests/unit/benchmark/runner/test_duration.py
@@ -97,9 +97,9 @@ class DurationRunnerTest(unittest.TestCase):
multiprocessing.Event(), mock.Mock())
self._assert_defaults__worker_run_setup_and_teardown()
- self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
- self.assertGreater(self.benchmark.my_method.call_count, 2)
- self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.call_count, 0)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
def test__worker_process_called_without_cfg(self):
scenario_cfg = {'runner': {}}
@@ -140,9 +140,9 @@ class DurationRunnerTest(unittest.TestCase):
time.sleep(0.1)
self._assert_defaults__worker_run_setup_and_teardown()
- self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
- self.assertGreater(self.benchmark.my_method.count, 103)
- self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.count, 1)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
count = 101
while not output_queue.empty():
@@ -181,9 +181,9 @@ class DurationRunnerTest(unittest.TestCase):
time.sleep(0.1)
self._assert_defaults__worker_run_setup_and_teardown()
- self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 2)
- self.assertGreater(self.benchmark.my_method.count, 103)
- self.assertGreater(self.benchmark.post_run_wait_time.call_count, 2)
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.count, 1)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
count = 0
while not queue.empty():
diff --git a/yardstick/tests/unit/benchmark/runner/test_proxduration.py b/yardstick/tests/unit/benchmark/runner/test_proxduration.py
index 3299c5b05..056195fd3 100644
--- a/yardstick/tests/unit/benchmark/runner/test_proxduration.py
+++ b/yardstick/tests/unit/benchmark/runner/test_proxduration.py
@@ -97,7 +97,7 @@ class ProxDurationRunnerTest(unittest.TestCase):
{}, multiprocessing.Event(), mock.Mock())
self._assert_defaults__worker_run_setup_and_teardown()
- self.assertGreater(self.benchmark.my_method.call_count, 2)
+ self.assertGreater(self.benchmark.my_method.call_count, 0)
def test__worker_process_called_without_cfg(self):
scenario_cfg = {'runner': {}}
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
index c4ac347f4..ba63e5f9e 100644
--- a/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
@@ -6,11 +6,6 @@
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
-
-# Unittest for yardstick.benchmark.scenarios.compute.lmbench.Lmbench
-
-from __future__ import absolute_import
-
import unittest
import mock
@@ -18,13 +13,9 @@ from oslo_serialization import jsonutils
from yardstick.benchmark.scenarios.compute import lmbench
from yardstick.common import exceptions as y_exc
+from yardstick import ssh
-# pylint: disable=unused-argument
-# disable this for now because I keep forgetting mock patch arg ordering
-
-
-@mock.patch('yardstick.benchmark.scenarios.compute.lmbench.ssh')
class LmbenchTestCase(unittest.TestCase):
def setUp(self):
@@ -38,16 +29,23 @@ class LmbenchTestCase(unittest.TestCase):
self.result = {}
- def test_successful_setup(self, mock_ssh):
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh.stop()
+
+ def test_successful_setup(self):
l = lmbench.Lmbench({}, self.ctx)
- mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.mock_ssh.from_node().execute.return_value = (0, '', '')
l.setup()
self.assertIsNotNone(l.client)
self.assertTrue(l.setup_done)
- def test_unsuccessful_unknown_type_run(self, mock_ssh):
+ def test_unsuccessful_unknown_type_run(self):
options = {
"test_type": "foo"
@@ -58,7 +56,7 @@ class LmbenchTestCase(unittest.TestCase):
self.assertRaises(RuntimeError, l.run, self.result)
- def test_successful_latency_run_no_sla(self, mock_ssh):
+ def test_successful_latency_run_no_sla(self):
options = {
"test_type": "latency",
@@ -69,12 +67,12 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '[{"latency": 4.944, "size": 0.00049}]'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
l.run(self.result)
expected_result = {"latencies0.latency": 4.944, "latencies0.size": 0.00049}
self.assertEqual(self.result, expected_result)
- def test_successful_bandwidth_run_no_sla(self, mock_ssh):
+ def test_successful_bandwidth_run_no_sla(self):
options = {
"test_type": "bandwidth",
@@ -86,12 +84,12 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 11025.5}'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
l.run(self.result)
expected_result = jsonutils.loads(sample_output)
self.assertEqual(self.result, expected_result)
- def test_successful_latency_run_sla(self, mock_ssh):
+ def test_successful_latency_run_sla(self):
options = {
"test_type": "latency",
@@ -105,12 +103,12 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '[{"latency": 4.944, "size": 0.00049}]'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
l.run(self.result)
expected_result = {"latencies0.latency": 4.944, "latencies0.size": 0.00049}
self.assertEqual(self.result, expected_result)
- def test_successful_bandwidth_run_sla(self, mock_ssh):
+ def test_successful_bandwidth_run_sla(self):
options = {
"test_type": "bandwidth",
@@ -125,12 +123,12 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 11025.5}'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
l.run(self.result)
expected_result = jsonutils.loads(sample_output)
self.assertEqual(self.result, expected_result)
- def test_unsuccessful_latency_run_sla(self, mock_ssh):
+ def test_unsuccessful_latency_run_sla(self):
options = {
"test_type": "latency",
@@ -144,10 +142,10 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '[{"latency": 37.5, "size": 0.00049}]'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
- def test_unsuccessful_bandwidth_run_sla(self, mock_ssh):
+ def test_unsuccessful_bandwidth_run_sla(self):
options = {
"test_type": "bandwidth",
@@ -162,10 +160,10 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 9925.5}'
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
- def test_successful_latency_for_cache_run_sla(self, mock_ssh):
+ def test_successful_latency_for_cache_run_sla(self):
options = {
"test_type": "latency_for_cache",
@@ -179,16 +177,16 @@ class LmbenchTestCase(unittest.TestCase):
l = lmbench.Lmbench(args, self.ctx)
sample_output = "{\"L1cache\": 1.6}"
- mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
l.run(self.result)
expected_result = jsonutils.loads(sample_output)
self.assertEqual(self.result, expected_result)
- def test_unsuccessful_script_error(self, mock_ssh):
+ def test_unsuccessful_script_error(self):
options = {"test_type": "bandwidth"}
args = {"options": options}
l = lmbench.Lmbench(args, self.ctx)
- mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.mock_ssh.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, l.run, self.result)
diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
index 92ceeae83..66fed81f1 100644
--- a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
+++ b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
@@ -186,6 +186,169 @@ class TestIxNextgen(unittest.TestCase):
self.assertIn([64, 64, 75], output)
self.assertIn([512, 512, 25], output)
+ def test_add_topology(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_topology('topology 1', 'vports')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('my_root', 'topology')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'topology 1', '-vports', 'vports')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_device_group(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_device_group('topology', 'device group 1', '1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('topology',
+ 'deviceGroup')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'device group 1', '-multiplier', '1')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_ethernet(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_ethernet('device_group', 'ethernet 1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('device_group',
+ 'ethernet')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'ethernet 1')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_vlans_single(self):
+ obj = 'ethernet'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.ixnet.getList.return_value = ['vlan1', 'vlan2']
+ vlan1 = ixnet_api.Vlan(vlan_id=100, tp_id='ethertype88a8', prio=2)
+ vlan2 = ixnet_api.Vlan(vlan_id=101, tp_id='ethertype88a8', prio=3)
+ self.ixnet_gen.add_vlans(obj, [vlan1, vlan2])
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('ethernet',
+ '-vlanCount', 2)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 100)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 101)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 2)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 3)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'ethertype88a8')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_vlans_increment(self):
+ obj = 'ethernet'
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.ixnet.getList.return_value = ['vlan1']
+ vlan = ixnet_api.Vlan(vlan_id=100, vlan_id_step=1, prio=3, prio_step=2)
+ self.ixnet_gen.add_vlans(obj, [vlan])
+ self.ixnet.setMultiAttribute.assert_any_call('obj', '-start', 100,
+ '-step', 1,
+ '-direction', 'increment')
+ self.ixnet.setMultiAttribute.assert_any_call('obj', '-start', 3,
+ '-step', 2,
+ '-direction', 'increment')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_vlans_invalid(self):
+ vlans = []
+ self.assertRaises(RuntimeError, self.ixnet_gen.add_vlans, 'obj', vlans)
+
+ def test_add_ipv4(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_ipv4_single(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1', addr='100.1.1.100',
+ prefix='24', gateway='100.1.1.200')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '100.1.1.100')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '24')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '100.1.1.200')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_ipv4_counter(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1',
+ addr='100.1.1.100',
+ addr_step='1',
+ addr_direction='increment',
+ prefix='24',
+ gateway='100.1.1.200',
+ gw_step='1',
+ gw_direction='increment')
+ self.ixnet_gen.ixnet.add.assert_any_call('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.ixnet_gen.ixnet.add.assert_any_call('attr', 'counter')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('obj', '-start',
+ '100.1.1.100',
+ '-step', '1',
+ '-direction',
+ 'increment')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '24')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('obj', '-start',
+ '100.1.1.200',
+ '-step', '1',
+ '-direction',
+ 'increment')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_pppox_client(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_pppox_client('ethernet 1', 'pap', 'user', 'pwd')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1',
+ 'pppoxclient')
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'pap')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'user')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'pwd')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_pppox_client_invalid_auth(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.assertRaises(NotImplementedError, self.ixnet_gen.add_pppox_client,
+ 'ethernet 1', 'invalid_auth', 'user', 'pwd')
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_not_called()
+
+ def test_add_bgp(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_bgp(ipv4='ipv4 1',
+ dut_ip='10.0.0.1',
+ local_as=65000,
+ bgp_type='external')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ipv4 1', 'bgpIpv4Peer')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '10.0.0.1')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 65000)
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'external')
+
@mock.patch.object(IxNetwork, 'IxNet')
def test_connect(self, mock_ixnet):
mock_ixnet.return_value = self.ixnet
@@ -239,8 +402,8 @@ class TestIxNextgen(unittest.TestCase):
self.ixnet_gen._cfg = config
self.assertIsNone(self.ixnet_gen.assign_ports())
- self.assertEqual(self.ixnet.execute.call_count, 2)
- self.assertEqual(self.ixnet.commit.call_count, 4)
+ self.assertEqual(self.ixnet.execute.call_count, 1)
+ self.assertEqual(self.ixnet.commit.call_count, 3)
self.assertEqual(self.ixnet.getAttribute.call_count, 2)
@mock.patch.object(ixnet_api, 'log')
@@ -273,17 +436,24 @@ class TestIxNextgen(unittest.TestCase):
'-trackBy', 'trafficGroupId0')
def test__create_flow_groups(self):
+ uplink_endpoints = ['up_endp1', 'up_endp2']
+ downlink_endpoints = ['down_endp1', 'down_endp2']
self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
- self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
- self.ixnet_gen._create_flow_groups()
+ self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2', 'endp3',
+ 'endp4']
+ self.ixnet_gen._create_flow_groups(uplink_endpoints, downlink_endpoints)
self.ixnet_gen.ixnet.add.assert_has_calls([
mock.call('traffic_item', 'endpointSet'),
mock.call('traffic_item', 'endpointSet')])
self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
- mock.call('endp1', '-name', '1', '-sources', ['1/protocols'],
- '-destinations', ['2/protocols']),
- mock.call('endp2', '-name', '2', '-sources', ['2/protocols'],
- '-destinations', ['1/protocols'])])
+ mock.call('endp1', '-name', '1', '-sources', ['up_endp1'],
+ '-destinations', ['down_endp1']),
+ mock.call('endp2', '-name', '2', '-sources', ['down_endp1'],
+ '-destinations', ['up_endp1']),
+ mock.call('endp3', '-name', '3', '-sources', ['up_endp2'],
+ '-destinations', ['down_endp2']),
+ mock.call('endp4', '-name', '4', '-sources', ['down_endp2'],
+ '-destinations', ['up_endp2'])])
def test__append_protocol_to_stack(self):
@@ -313,12 +483,31 @@ class TestIxNextgen(unittest.TestCase):
def test_create_traffic_model(self, mock__setup_config_elements,
mock__create_flow_groups,
mock__create_traffic_item):
-
- self.ixnet_gen.create_traffic_model()
- mock__create_traffic_item.assert_called_once()
- mock__create_flow_groups.assert_called_once()
+ uplink_ports = ['port1', 'port3']
+ downlink_ports = ['port2', 'port4']
+ uplink_endpoints = ['port1/protocols', 'port3/protocols']
+ downlink_endpoints = ['port2/protocols', 'port4/protocols']
+ self.ixnet_gen.create_traffic_model(uplink_ports, downlink_ports)
+ mock__create_traffic_item.assert_called_once_with('raw')
+ mock__create_flow_groups.assert_called_once_with(uplink_endpoints,
+ downlink_endpoints)
mock__setup_config_elements.assert_called_once()
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
+ @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
+ def test_create_ipv4_traffic_model(self, mock__setup_config_elements,
+ mock__create_flow_groups,
+ mock__create_traffic_item):
+ uplink_topologies = ['up1', 'up3']
+ downlink_topologies = ['down2', 'down4']
+ self.ixnet_gen.create_ipv4_traffic_model(uplink_topologies,
+ downlink_topologies)
+ mock__create_traffic_item.assert_called_once_with('ipv4')
+ mock__create_flow_groups.assert_called_once_with(uplink_topologies,
+ downlink_topologies)
+ mock__setup_config_elements.assert_called_once_with(False)
+
def test__update_frame_mac(self):
with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item') as \
mock_get_field:
@@ -469,6 +658,9 @@ class TestIxNextgen(unittest.TestCase):
'outer_l3': {
'proto': 'unsupported',
},
+ 'outer_l4': {
+ 'seed': 1
+ }
},
}
with mock.patch.object(self.ixnet_gen,
@@ -524,3 +716,16 @@ class TestIxNextgen(unittest.TestCase):
self.assertIsNone(result)
self.ixnet.getList.assert_called_once()
self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
+
+ def test_start_protocols(self):
+ self.ixnet_gen.start_protocols()
+ self.ixnet.execute.assert_called_once_with('startAllProtocols')
+
+ def test_stop_protocols(self):
+ self.ixnet_gen.stop_protocols()
+ self.ixnet.execute.assert_called_once_with('stopAllProtocols')
+
+ def test_get_vports(self):
+ self.ixnet_gen._ixnet.getRoot.return_value = 'root'
+ self.ixnet_gen.get_vports()
+ self.ixnet.getList.assert_called_once_with('root', 'vport')
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py
new file mode 100644
index 000000000..afd550029
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py
@@ -0,0 +1,136 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+import unittest
+
+from yardstick.network_services.traffic_profile import landslide_profile
+
+TP_CONFIG = {
+ 'schema': "nsb:traffic_profile:0.1",
+ 'name': 'LandslideProfile',
+ 'description': 'Spirent Landslide traffic profile (Data Message Flow)',
+ 'traffic_profile': {
+ 'traffic_type': 'LandslideProfile'
+ },
+ 'dmf_config': {
+ 'dmf': {
+ 'library': 'test',
+ 'name': 'Fireball UDP',
+ 'description': "Basic data flow using UDP/IP (Fireball DMF)",
+ 'keywords': 'UDP ',
+ 'dataProtocol': 'fb_udp',
+ 'burstCount': 1,
+ 'clientPort': {
+ 'clientPort': 2002,
+ 'isClientPortRange': 'false'
+ },
+ 'serverPort': 2003,
+ 'connection': {
+ 'initiatingSide': 'Client',
+ 'disconnectSide': 'Client',
+ 'underlyingProtocol': 'none',
+ 'persistentConnection': 'false'
+ },
+ 'protocolId': 0,
+ 'persistentConnection': 'false',
+ 'transactionRate': 8.0,
+ 'transactions': {
+ 'totalTransactions': 0,
+ 'retries': 0,
+ 'dataResponseTime': 60000,
+ 'packetSize': 64
+ },
+ 'segment': {
+ 'segmentSize': 64000,
+ 'maxSegmentSize': 0
+ },
+ 'size': {
+ 'sizeDistribution': 'Fixed',
+ 'sizeDeviation': 10
+ },
+ 'interval': {
+ 'intervalDistribution': 'Fixed',
+ 'intervalDeviation': 10
+ },
+ 'ipHeader': {
+ 'typeOfService': 0,
+ 'timeToLive': 64
+ },
+ 'tcpConnection': {
+ 'force3Way': 'false',
+ 'fixedRetryTime': 0,
+ 'maxPacketsToForceAck': 0
+ },
+ 'tcp': {
+ 'windowSize': 32768,
+ 'windowScaling': -1,
+ 'disableFinAckWait': 'false'
+ },
+ 'disconnectType': 'FIN',
+ 'slowStart': 'false',
+ 'connectOnly': 'false',
+ 'vtag': {
+ 'VTagMask': '0x0',
+ 'VTagValue': '0x0'
+ },
+ 'sctpPayloadProtocolId': 0,
+ 'billingIncludeSyn': 'true',
+ 'billingIncludeSubflow': 'true',
+ 'billingRecordPerTransaction': 'false',
+ 'tcpPush': 'false',
+ 'hostDataExpansionRatio': 1
+ }
+ }
+}
+DMF_OPTIONS = {
+ 'dmf': {
+ 'transactionRate': 5,
+ 'packetSize': 512,
+ 'burstCount': 1
+ }
+}
+
+
+class TestLandslideProfile(unittest.TestCase):
+
+ def test___init__(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ self.assertListEqual([TP_CONFIG["dmf_config"]],
+ ls_traffic_profile.dmf_config)
+
+ def test___init__config_not_a_dict(self):
+ _tp_config = copy.deepcopy(TP_CONFIG)
+ _tp_config['dmf_config'] = [_tp_config['dmf_config']]
+ ls_traffic_profile = landslide_profile.LandslideProfile(_tp_config)
+ self.assertListEqual(_tp_config['dmf_config'],
+ ls_traffic_profile.dmf_config)
+
+ def test_execute(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ self.assertIsNone(ls_traffic_profile.execute(None))
+
+ def test_update_dmf_options_dict(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ ls_traffic_profile.update_dmf(DMF_OPTIONS)
+ self.assertDictContainsSubset(DMF_OPTIONS['dmf'],
+ ls_traffic_profile.dmf_config[0])
+
+ def test_update_dmf_options_list(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ _dmf_options = copy.deepcopy(DMF_OPTIONS)
+ _dmf_options['dmf'] = [_dmf_options['dmf']]
+ ls_traffic_profile.update_dmf(_dmf_options)
+ self.assertTrue(all([x in ls_traffic_profile.dmf_config[0]
+ for x in DMF_OPTIONS['dmf']]))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
index cf31cc27c..11bee03a4 100644
--- a/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
@@ -100,13 +100,13 @@ class TestProxProfile(unittest.TestCase):
profile = ProxProfile(tp_config)
- self.assertFalse(profile.done)
+ self.assertFalse(profile.done.is_set())
for _ in packet_sizes:
with self.assertRaises(NotImplementedError):
profile.execute_traffic(traffic_generator)
self.assertIsNone(profile.execute_traffic(traffic_generator))
- self.assertTrue(profile.done)
+ self.assertTrue(profile.done.is_set())
def test_bounds_iterator(self):
tp_config = {
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py
new file mode 100644
index 000000000..3374cbe76
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py
@@ -0,0 +1,70 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import uuid
+
+from yardstick.network_services.vnf_generic.vnf import agnostic_vnf
+
+NAME = 'vnf__0'
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'id': 'AgnosticVnf', # NSB python class mapping
+ 'name': 'AgnosticVnf',
+ 'short-name': 'AgnosticVnf',
+ 'description': 'AgnosticVnf',
+ 'mgmt-interface': {
+ 'vdu-id': 'vepcvnf-baremetal',
+ 'user': 'user',
+ 'password': 'password',
+ 'ip': 'ip'
+ },
+ 'vdu': [{
+ 'id': 'vepcvnf-baremetal',
+ 'name': 'vepc-vnf-baremetal',
+ 'description': 'vAgnosticVnf workload',
+ 'external-interface': []}],
+ 'benchmark': {
+ 'kpi': []}}]}}
+
+
+class TestAgnosticVnf(unittest.TestCase):
+
+ def setUp(self):
+ self._id = uuid.uuid1().int
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.agnostic_vnf = agnostic_vnf.AgnosticVnf(NAME, self.vnfd, self._id)
+
+ def test_instantiate(self):
+ self.assertIsNone(self.agnostic_vnf.instantiate({}, {}))
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.agnostic_vnf.wait_for_instantiate())
+
+ def test_terminate(self):
+ self.assertIsNone(self.agnostic_vnf.terminate())
+
+ def test_scale(self):
+ self.assertIsNone(self.agnostic_vnf.scale())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.agnostic_vnf.collect_kpi())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.agnostic_vnf.start_collect())
+
+ def test_stop_collect(self):
+ self.assertIsNone(self.agnostic_vnf.stop_collect())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py
new file mode 100644
index 000000000..6d14ddb54
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py
@@ -0,0 +1,94 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+import unittest
+import uuid
+
+from yardstick.network_services.vnf_generic.vnf import epc_vnf
+
+NAME = 'vnf__0'
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'id': 'EPCVnf', # NSB python class mapping
+ 'name': 'EPCVnf',
+ 'short-name': 'EPCVnf',
+ 'description': 'EPCVnf',
+ 'mgmt-interface': {
+ 'vdu-id': 'vepcvnf-baremetal',
+ 'user': 'user', # Value filled by vnfdgen
+ 'password': 'password', # Value filled by vnfdgen
+ 'ip': 'ip' # Value filled by vnfdgen
+ },
+ 'vdu': [{
+ 'id': 'vepcvnf-baremetal',
+ 'name': 'vepc-vnf-baremetal',
+ 'description': 'vEPCVnf workload',
+ 'external-interface': []}],
+ 'benchmark': {
+ 'kpi': []}}]}}
+
+
+class TestEPCVnf(unittest.TestCase):
+
+ def setUp(self):
+ self._id = uuid.uuid1().int
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.epc_vnf = epc_vnf.EPCVnf(NAME, self.vnfd, self._id)
+
+ def test___init__(self, *args):
+ _epc_vnf = epc_vnf.EPCVnf(NAME, self.vnfd, self._id)
+ for x in {'user', 'password', 'ip'}:
+ self.assertEqual(self.vnfd['mgmt-interface'][x],
+ _epc_vnf.vnfd_helper.mgmt_interface[x])
+ self.assertEqual(NAME, _epc_vnf.name)
+ self.assertEqual([], _epc_vnf.kpi)
+ self.assertEqual({}, _epc_vnf.config)
+ self.assertFalse(_epc_vnf.runs_traffic)
+
+ def test___init__missing_ip(self, *args):
+ _vnfd = copy.deepcopy(self.vnfd)
+ _vnfd['mgmt-interface'].pop('ip')
+ _epc_vnf = epc_vnf.EPCVnf(NAME, _vnfd, self._id)
+ for x in {'user', 'password'}:
+ self.assertEqual(_vnfd['mgmt-interface'][x],
+ _epc_vnf.vnfd_helper.mgmt_interface[x])
+ self.assertNotIn('ip', _epc_vnf.vnfd_helper.mgmt_interface)
+ self.assertEqual(NAME, _epc_vnf.name)
+ self.assertEqual([], _epc_vnf.kpi)
+ self.assertEqual({}, _epc_vnf.config)
+ self.assertFalse(_epc_vnf.runs_traffic)
+
+ def test_instantiate(self):
+ self.assertIsNone(self.epc_vnf.instantiate({}, {}))
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.epc_vnf.wait_for_instantiate())
+
+ def test_terminate(self):
+ self.assertIsNone(self.epc_vnf.terminate())
+
+ def test_scale(self):
+ self.assertIsNone(self.epc_vnf.scale())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.epc_vnf.collect_kpi())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.epc_vnf.start_collect())
+
+ def test_stop_collect(self):
+ self.assertIsNone(self.epc_vnf.stop_collect())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
index 3b095647c..3d6ebb25b 100644
--- a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
@@ -1527,14 +1527,16 @@ class TestProxResourceHelper(unittest.TestCase):
def test_run_traffic(self):
setup_helper = mock.MagicMock()
helper = prox_helpers.ProxResourceHelper(setup_helper)
- traffic_profile = mock.MagicMock(**{"done": True})
+ traffic_profile = mock.MagicMock()
+ traffic_profile.done.is_set.return_value = True
helper.run_traffic(traffic_profile)
self.assertEqual(helper._terminated.value, 1)
def test__run_traffic_once(self):
setup_helper = mock.MagicMock()
helper = prox_helpers.ProxResourceHelper(setup_helper)
- traffic_profile = mock.MagicMock(**{"done": True})
+ traffic_profile = mock.MagicMock()
+ traffic_profile.done.is_set.return_value = True
helper._run_traffic_once(traffic_profile)
self.assertEqual(helper._terminated.value, 1)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py
new file mode 100644
index 000000000..53439972a
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py
@@ -0,0 +1,1911 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+import mock
+import requests
+import time
+import unittest
+import uuid
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.common import exceptions
+from yardstick.common import utils as common_utils
+from yardstick.common import yaml_loader
+from yardstick.network_services import utils as net_serv_utils
+from yardstick.network_services.traffic_profile import landslide_profile
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_landslide
+
+
+NAME = "tg__0"
+
+EXAMPLE_URL = 'http://example.com/'
+TCL_SUCCESS_RESPONSE = 'ls_ok'
+
+TEST_SERVERS = [
+ {'ip': '192.168.122.101',
+ 'phySubnets': [
+ {'mask': '/24',
+ 'base': '10.42.32.100',
+ 'numIps': 20,
+ 'name': 'eth1'}
+ ],
+ 'role': 'SGW_Node',
+ 'name': 'TestServer_1'},
+ {'ip': '192.168.122.102',
+ 'phySubnets': [
+ {'mask': '/24',
+ 'base': '10.42.32.1',
+ 'numIps': 100,
+ 'name': 'eth1'
+ },
+ {'mask': '/24',
+ 'base': '10.42.33.1',
+ 'numIps': 100,
+ 'name': 'eth2'}
+ ],
+ 'preResolvedArpAddress': [
+ {'NumNodes': 1,
+ 'StartingAddress': '10.42.33.5'}
+ ],
+ 'role': 'SGW_Nodal',
+ 'name': 'TestServer_2',
+ 'thread_model': 'Fireball'
+ }
+]
+
+TS1_SUTS = [
+ {'name': 'SGW - C TestNode',
+ 'role': 'SgwControlAddr',
+ 'managementIp': '12.0.1.1',
+ 'ip': '10.42.32.100',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'SGW - U TestNode',
+ 'role': 'SgwUserAddr',
+ 'managementIp': '12.0.1.2',
+ 'ip': '10.42.32.101',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ }
+]
+
+TS2_SUTS = [
+ {'name': 'eNodeB TestNode',
+ 'role': 'EnbUserAddr',
+ 'managementIp': '12.0.2.1',
+ 'ip': '10.42.32.2',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'MME TestNode',
+ 'role': 'MmeControlAddr',
+ 'managementIp': '12.0.3.1',
+ 'ip': '10.42.32.1',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'NetHost TestNode',
+ 'role': 'NetworkHostAddrLocal',
+ 'managementIp': '12.0.4.1',
+ 'ip': '10.42.33.1',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'PGW TestNode',
+ 'role': 'PgwV4Sut',
+ 'managementIp': '12.0.5.1',
+ 'ip': '10.42.32.105',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'SGW - C SUT',
+ 'role': 'SgwSut',
+ 'managementIp': '12.0.6.1',
+ 'ip': '10.42.32.100'
+ },
+ {'name': 'SGW - U SUT',
+ 'role': 'SgwUserSut',
+ 'managementIp': '12.0.6.2',
+ 'ip': '10.42.32.101'}
+]
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'short-name': 'landslide',
+ 'vdu': [{
+ 'description': 'AB client interface details',
+ 'name': 'abclient-baremetal',
+ 'id': 'abclient-baremetal',
+ 'external-interface': []}],
+ 'description': 'Spirent Landslide traffic generator',
+ 'config': [{'test_server': TEST_SERVERS[0], 'suts': TS1_SUTS},
+ {'test_server': TEST_SERVERS[1], 'suts': TS2_SUTS}],
+ 'mgmt-interface': {
+ 'vdu-id': 'landslide-tas',
+ 'user': 'user',
+ 'password': 'user',
+ 'super-user': 'super-user',
+ 'super-user-password': 'super-user-password',
+ 'cfguser_password': 'cfguser_password',
+ 'license': 48,
+ 'proto': 'http',
+ 'ip': '1.1.1.1'},
+ 'benchmark': {
+ 'kpi': [
+ 'tx_throughput_mbps',
+ 'rx_throughput_mbps',
+ 'in_packets',
+ 'out_packets',
+ 'activation_rate_sessps',
+ 'deactivation_rate_sessps']},
+ 'id': 'LandslideTrafficGen',
+ 'name': 'LandslideTrafficGen'}]}}
+
+TAS_INFO = VNFD['vnfd:vnfd-catalog']['vnfd'][0]['mgmt-interface']
+
+DMF_CFG = {
+ "dmf": {
+ "library": "test",
+ "name": "Basic UDP"
+ },
+ "clientPort": {
+ "clientPort": 2002,
+ "isClientPortRange": "false"
+ },
+ "dataProtocol": "udp",
+ "serverPort": 2003
+}
+
+RESERVATIONS = [
+ {'tsName': TEST_SERVERS[0]['name'],
+ 'phySubnets': TEST_SERVERS[0]['phySubnets'],
+ 'tsId': TEST_SERVERS[0]['name'],
+ 'tsIndex': 0},
+ {'tsName': TEST_SERVERS[1]['name'],
+ 'phySubnets': TEST_SERVERS[1]['phySubnets'],
+ 'tsId': TEST_SERVERS[1]['name'],
+ 'tsIndex': 1}]
+
+SESSION_PROFILE = {
+ 'keywords': '',
+ 'duration': 60,
+ 'iterations': 1,
+ 'description': 'UE default bearer creation test case',
+ 'name': 'default_bearer_capacity',
+ 'reportOptions': {'format': 'CSV'},
+ 'reservePorts': 'false',
+ 'tsGroups': [
+ {
+ 'testCases': [{
+ 'type': 'SGW_Node',
+ 'name': '',
+ 'linked': "false",
+ 'AssociatedPhys': '',
+ 'parameters': {
+ 'SgiPtpTunnelEn': 'false',
+ 'Gtp2Imsi': '505024101215074',
+ 'Sessions': '100000',
+ 'S5Protocol': 'GTPv2',
+ 'TrafficMtu': '1500',
+ 'Gtp2Version': '13.6.0',
+ 'BearerV4AddrPool': '1.0.0.1',
+ 'Gtp2Imei': '50502410121507',
+ 'PgwNodeEn': 'true',
+ 'DedicatedsPerDefaultBearer': '0',
+ 'DefaultBearers': '1',
+ 'SgwUserAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'SGW_USER_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'SgwControlAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'SGW_CONTROL_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500,
+ 'nextHop': 'SGW_CONTROL_NEXT_HOP'
+ },
+ 'BearerAddrPool': '2001::1',
+ 'TestType': 'SGW-NODE'
+ }
+ }],
+ 'tsId': TEST_SERVERS[0]['name']},
+ {
+ 'testCases': [{
+ 'type': 'SGW_Nodal',
+ 'name': '',
+ 'parameters': {
+ 'DataTraffic': 'Continuous',
+ 'TrafficStartType': 'When All Sessions Established',
+ 'NetworkHost': 'Local',
+ 'Gtp2Imsi': '505024101215074',
+ 'Dmf': {
+ 'mainflows': [
+ {
+ 'name': 'Basic UDP',
+ 'library': 'test'
+ }
+ ],
+ 'class': 'Dmf',
+ 'instanceGroups': [
+ {
+ 'startPaused': "false",
+ 'rate': 0,
+ 'mainflowIdx': 0,
+ 'mixType': ''
+ }
+ ]
+ },
+ 'S5Protocol': 'GTPv2',
+ 'DataUserCfgFileEn': 'false',
+ 'PgwUserSutEn': 'false',
+ 'MmeControlAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'MME_CONTROL_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'SgwUserSut': {
+ 'class': 'Sut',
+ 'name': 'SGW_USER_NAME'
+ },
+ 'TestActivity': 'Capacity Test',
+ 'NetworkHostAddrLocal': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth2',
+ 'forcedEthInterface': '',
+ 'ip': 'NET_HOST_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'DedicatedsPerDefaultBearer': '0',
+ 'DisconnectRate': '1000.0',
+ 'Sessions': '100000',
+ 'SgwSut': {
+ 'class': 'Sut',
+ 'name': 'SGW_CONTROL_NAME'
+ },
+ 'TrafficMtu': '1500',
+ 'Gtp2Version': '13.6.0',
+ 'Gtp2Imei': '50502410121507',
+ 'PgwNodeEn': 'false',
+ 'StartRate': '1000.0',
+ 'PgwV4Sut': {
+ 'class': 'Sut',
+ 'name': 'PGW_SUT_NAME'
+ },
+ 'DefaultBearers': '1',
+ 'EnbUserAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'ENB_USER_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'TestType': 'SGW-NODAL'
+ }
+ }],
+ 'tsId': TEST_SERVERS[1]['name']
+ }
+ ]
+}
+
+
+class TestLandslideTrafficGen(unittest.TestCase):
+ SCENARIO_CFG = {
+ 'session_profile': '/traffic_profiles/landslide/'
+ 'landslide_session_default_bearer.yaml',
+ 'task_path': '',
+ 'runner': {
+ 'type': 'Iteration',
+ 'iterations': 1
+ },
+ 'nodes': {
+ 'tg__0': 'tg__0.traffic_gen',
+ 'vnf__0': 'vnf__0.vnf_epc'
+ },
+ 'topology': 'landslide_tg_topology.yaml',
+ 'type': 'NSPerf',
+ 'traffic_profile': '../../traffic_profiles/landslide/'
+ 'landslide_dmf_udp.yaml',
+ 'options': {
+ 'test_cases': [
+ {
+ 'BearerAddrPool': '2002::2',
+ 'type': 'SGW_Node',
+ 'BearerV4AddrPool': '2.0.0.2',
+ 'Sessions': '90000'
+ },
+ {
+ 'StartRate': '900.0',
+ 'type': 'SGW_Nodal',
+ 'DisconnectRate': '900.0',
+ 'Sessions': '90000'
+ }
+ ],
+ 'dmf':
+ {
+ 'transactionRate': 1000,
+ 'packetSize': 512
+ }
+ }
+ }
+
+ CONTEXT_CFG = {
+ 'contexts': [
+ {
+ 'type': 'Node',
+ 'name': 'traffic_gen',
+ 'file': '/etc/yardstick/nodes/pod_landslide.yaml'
+ },
+ {
+ 'type': 'Node',
+ 'name': 'vnf_epc',
+ 'file': '/etc/yardstick/nodes/pod_vepc_sut.yaml'
+ }
+ ]
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "nsb:traffic_profile:0.1",
+ "name": "LandslideProfile",
+ "description": "Spirent Landslide traffic profile",
+ "traffic_profile": {
+ "traffic_type": "LandslideProfile"
+ },
+ "dmf_config": {
+ "dmf": {
+ "library": "test",
+ "name": "Basic UDP"
+ },
+ "description": "Basic data flow using UDP/IP",
+ "keywords": "UDP",
+ "dataProtocol": "udp"
+ }
+ }
+
+ SUCCESS_CREATED_CODE = 201
+ SUCCESS_OK_CODE = 200
+ SUCCESS_RECORD_ID = 5
+ TEST_USER_ID = 11
+
+ def setUp(self):
+ self._id = uuid.uuid1().int
+
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ self.mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper.start()
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.ls_tg = tg_landslide.LandslideTrafficGen(
+ NAME, self.vnfd, self._id)
+ self.session_profile = copy.deepcopy(SESSION_PROFILE)
+ self.ls_tg.session_profile = self.session_profile
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+ self.mock_ssh_helper.stop()
+
+ @mock.patch.object(net_serv_utils, 'get_nsb_option')
+ def test___init__(self, mock_get_nsb_option, *args):
+ _path_to_nsb = 'path/to/nsb'
+ mock_get_nsb_option.return_value = _path_to_nsb
+ ls_tg = tg_landslide.LandslideTrafficGen(NAME, self.vnfd, self._id)
+ self.assertIsInstance(ls_tg.resource_helper,
+ tg_landslide.LandslideResourceHelper)
+ mock_get_nsb_option.assert_called_once_with('bin_path')
+ self.assertEqual(_path_to_nsb, ls_tg.bin_path)
+ self.assertEqual(NAME, ls_tg.name)
+ self.assertTrue(ls_tg.runs_traffic)
+ self.assertFalse(ls_tg.traffic_finished)
+ self.assertIsNone(ls_tg.session_profile)
+
+ def test_listen_traffic(self):
+ _traffic_profile = {}
+ self.assertIsNone(self.ls_tg.listen_traffic(_traffic_profile))
+
+ def test_terminate(self, *args):
+ self.ls_tg.resource_helper._tcl = mock.Mock()
+ self.assertIsNone(self.ls_tg.terminate())
+ self.ls_tg.resource_helper._tcl.disconnect.assert_called_once()
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate(self, *args):
+ self.ls_tg._tg_process = mock.Mock()
+ self.ls_tg._tg_process.start = mock.Mock()
+ self.ls_tg.resource_helper.connect = mock.Mock()
+ self.ls_tg.resource_helper.create_test_servers = mock.Mock()
+ self.ls_tg.resource_helper.create_suts = mock.Mock()
+ self.ls_tg._load_session_profile = mock.Mock()
+ self.assertIsNone(self.ls_tg.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
+ self.ls_tg.resource_helper.connect.assert_called_once()
+ self.ls_tg.resource_helper.create_test_servers.assert_called_once()
+ _suts_blocks_num = len([item['suts'] for item in self.vnfd['config']])
+ self.assertEqual(_suts_blocks_num,
+ self.ls_tg.resource_helper.create_suts.call_count)
+ self.ls_tg._load_session_profile.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_run_traffic(self, mock_get_tests, *args):
+ self.ls_tg.resource_helper._url = EXAMPLE_URL
+ self.ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_traffic_profile = mock.Mock(
+ spec=landslide_profile.LandslideProfile)
+ mock_traffic_profile.dmf_config = {'keywords': 'UDP',
+ 'dataProtocol': 'udp'}
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ self.ls_tg.resource_helper._user_id = self.TEST_USER_ID
+ mock_get_tests.return_value = [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'COMPLETE'}]
+ mock_post = mock.Mock()
+ mock_post.status_code = self.SUCCESS_CREATED_CODE
+ mock_post.json.return_value = {'id': self.SUCCESS_RECORD_ID}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value = mock_post
+ self.ls_tg.resource_helper.session = mock_session
+ self.ls_tg.resource_helper._tcl = mock.Mock()
+ _tcl = self.ls_tg.resource_helper._tcl
+ self.assertIsNone(self.ls_tg.run_traffic(mock_traffic_profile))
+ self.assertEqual(self.SUCCESS_RECORD_ID,
+ self.ls_tg.resource_helper.run_id)
+ mock_traffic_profile.update_dmf.assert_called_with(
+ self.ls_tg.scenario_helper.all_options)
+ _tcl.create_dmf.assert_called_with(mock_traffic_profile.dmf_config)
+ _tcl.create_test_session.assert_called_with(self.session_profile)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ def test_collect_kpi(self, mock_check_running_test_state, *args):
+ self.ls_tg.resource_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_check_running_test_state.return_value = 'COMPLETE'
+ self.assertEqual({'done': True}, self.ls_tg.collect_kpi())
+ mock_check_running_test_state.assert_called_once()
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.ls_tg.wait_for_instantiate())
+ self.ls_tg.wait_for_instantiate()
+
+ def test__update_session_suts_no_tc_role(self, *args):
+ _suts = [{'role': 'epc_role'}]
+ _testcase = {'parameters': {'diff_epc_role': {'class': 'Sut'}}}
+ res = self.ls_tg._update_session_suts(_suts, _testcase)
+ self.assertEqual(_testcase, res)
+
+ def test__update_session_suts(self, *args):
+
+ def get_testnode_param(role, key, session_prof):
+ """ Get value by key from the deep nested dict to avoid calls like:
+ e.g. session_prof['tsGroups'][0]['testCases'][1]['parameters'][key]
+ """
+ for group in session_prof['tsGroups']:
+ for tc in group['testCases']:
+ tc_params = tc['parameters']
+ if tc_params.get(role):
+ return tc_params[role][key]
+
+ def get_sut_param(role, key, suts):
+ """ Search list of dicts for one with specific role.
+ Return the value of related dict by key. Expect key presence.
+ """
+ for sut in suts:
+ if sut.get('role') == role:
+ return sut[key]
+
+ # TestNode to verify
+ testnode_role = 'SgwControlAddr'
+ # SUT to verify
+ sut_role = 'SgwUserSut'
+
+ config_suts = [config['suts'] for config in self.vnfd['config']]
+ session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
+ for _tc in _ts_group['testCases']]
+ for suts, tc in zip(config_suts, session_tcs):
+ self.assertEqual(tc, self.ls_tg._update_session_suts(suts, tc))
+
+ # Verify TestNode class objects keys were updated
+ for _key in {'ip', 'phy', 'nextHop'}:
+ self.assertEqual(
+ get_testnode_param(testnode_role, _key, self.ls_tg.session_profile),
+ get_sut_param(testnode_role, _key, TS1_SUTS))
+ # Verify Sut class objects name was updated
+ self.assertEqual(
+ get_testnode_param(sut_role, 'name', self.ls_tg.session_profile),
+ get_sut_param(sut_role, 'name', TS2_SUTS))
+
+ def test__update_session_test_servers(self, *args):
+ for ts_index, ts in enumerate(TEST_SERVERS):
+ self.assertIsNone(
+ self.ls_tg._update_session_test_servers(ts, ts_index))
+ # Verify preResolvedArpAddress key was added
+ self.assertTrue(any(
+ _item.get('preResolvedArpAddress')
+ for _item in self.ls_tg.session_profile['tsGroups']))
+ # Verify reservations key was added to session profile
+ self.assertEqual(RESERVATIONS,
+ self.ls_tg.session_profile.get('reservations'))
+ self.assertEqual('true',
+ self.ls_tg.session_profile.get('reservePorts'))
+
+ def test__update_session_tc_params_assoc_phys(self):
+ _tc_options = {'AssociatedPhys': 'eth1'}
+ _testcase = {}
+ _testcase_orig = copy.deepcopy(_testcase)
+ res = self.ls_tg._update_session_tc_params(_tc_options, _testcase)
+ self.assertNotEqual(_testcase_orig, res)
+ self.assertEqual(_tc_options, _testcase)
+
+ def test__update_session_tc_params(self, *args):
+
+ def get_session_tc_param_value(param, tc_type, session_prof):
+ """ Get param value from the deep nested dict to avoid calls like:
+ session_prof['tsGroups'][0]['testCases'][0]['parameters'][key]
+ """
+ for test_group in session_prof['tsGroups']:
+ session_tc = test_group['testCases'][0]
+ if session_tc['type'] == tc_type:
+ return session_tc['parameters'].get(param)
+
+ session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
+ for _tc in _ts_group['testCases']]
+ scenario_tcs = [_tc for _tc in
+ self.SCENARIO_CFG['options']['test_cases']]
+ for tc_options, tc in zip(scenario_tcs, session_tcs):
+ self.assertEqual(
+ tc,
+ self.ls_tg._update_session_tc_params(tc_options, tc))
+
+ # Verify that each test case parameter was updated
+ # Params been compared are deeply nested. Using loops to ease access.
+ for _tc in self.SCENARIO_CFG['options']['test_cases']:
+ for _key, _val in _tc.items():
+ if _key != 'type':
+ self.assertEqual(
+ _val,
+ get_session_tc_param_value(_key, _tc.get('type'),
+ self.ls_tg.session_profile))
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_test_servers')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_suts')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_tc_params')
+ def test__load_session_profile(self, mock_upd_ses_tc_params,
+ mock_upd_ses_suts, mock_upd_ses_ts,
+ mock_yaml_load, *args):
+ self.ls_tg.scenario_helper.scenario_cfg = \
+ copy.deepcopy(self.SCENARIO_CFG)
+ mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
+ self.assertIsNone(self.ls_tg._load_session_profile())
+ self.assertIsNotNone(self.ls_tg.session_profile)
+ # Number of blocks in configuration files
+ # Number of test servers, suts and tc params blocks should be equal
+ _config_files_blocks_num = len([item['test_server']
+ for item in self.vnfd['config']])
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_ts.call_count)
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_suts.call_count)
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_tc_params.call_count)
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ def test__load_session_profile_unequal_num_of_cfg_blocks(
+ self, mock_yaml_load, *args):
+ vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ls_traffic_gen = tg_landslide.LandslideTrafficGen(NAME, vnfd, self._id)
+ ls_traffic_gen.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
+ # Delete test_servers item from pod file to make it not valid
+ ls_traffic_gen.vnfd_helper['config'].pop()
+ with self.assertRaises(RuntimeError):
+ ls_traffic_gen._load_session_profile()
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ def test__load_session_profile_test_type_mismatch(self, mock_yaml_load,
+ *args):
+ vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ # Swap test servers data in pod file
+ vnfd['config'] = list(reversed(vnfd['config']))
+ ls_tg = tg_landslide.LandslideTrafficGen(NAME, vnfd, self._id)
+ ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_yaml_load.return_value = SESSION_PROFILE
+ with self.assertRaises(RuntimeError):
+ ls_tg._load_session_profile()
+
+
+class TestLandslideResourceHelper(unittest.TestCase):
+
+ PROTO_PORT = 8080
+ EXAMPLE_URL = ''.join([TAS_INFO['proto'], '://', TAS_INFO['ip'], ':',
+ str(PROTO_PORT), '/api/'])
+ SUCCESS_CREATED_CODE = 201
+ SUCCESS_OK_CODE = 200
+ INVALID_REST_CODE = '400'
+ NOT_MODIFIED_CODE = 500810
+ ERROR_CODE = 500800
+ SUCCESS_RECORD_ID = 11
+ EXPIRE_DATE = '2020/01/01 12:00 FLE Standard Time'
+ TEST_USER = 'test'
+ TEST_TERMINATED = 1
+ AUTH_DATA = {'user': TAS_INFO['user'], 'password': TAS_INFO['password']}
+ TEST_SESSION_NAME = 'default_bearer_capacity'
+
+ USERS_DATA = {
+ "users": [{
+ "url": ''.join([EXAMPLE_URL, 'users/', str(SUCCESS_RECORD_ID)]),
+ "id": SUCCESS_RECORD_ID,
+ "level": 1,
+ "username": TEST_USER
+ }]
+ }
+
+ CREATE_USER_DATA = {'username': TAS_INFO['user'],
+ 'expiresOn': EXPIRE_DATE,
+ 'level': 1,
+ 'contactInformation': '',
+ 'fullName': 'Test User',
+ 'password': TAS_INFO['password'],
+ 'isActive': 'true'}
+
+ SUTS_DATA = {
+ "suts": [
+ {
+ "url": ''.join([EXAMPLE_URL, 'suts/', str(SUCCESS_RECORD_ID)]),
+ "id": SUCCESS_RECORD_ID,
+ "name": "10.41.32.1"
+ }]}
+
+ TEST_SERVERS_DATA = {
+ "testServers": [
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/1"]),
+ "id": 1,
+ "name": TEST_SERVERS[0]['name'],
+ "state": "READY",
+ "version": "16.4.0.10"
+ },
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/2"]),
+ "id": 2,
+ "name": TEST_SERVERS[1]['name'],
+ "state": "READY",
+ "version": "16.4.0.10"
+ }
+
+ ]
+ }
+
+ RUN_ID = 3
+
+ RUNNING_TESTS_DATA = {
+ "runningTests": [{
+ "url": ''.join([EXAMPLE_URL, "runningTests/{}".format(RUN_ID)]),
+ "measurementsUrl": ''.join(
+ [EXAMPLE_URL,
+ "runningTests/{}/measurements".format(RUN_ID)]),
+ "criteriaUrl": ''.join(
+ [EXAMPLE_URL,
+ "runningTests/{}/criteria".format(RUN_ID)]),
+ "noteToUser": "",
+ "id": RUN_ID,
+ "library": SUCCESS_RECORD_ID,
+ "name": "default_bearer_capacity",
+ "user": TEST_USER,
+ "criteriaStatus": "NA",
+ "testStateOrStep": "COMPLETE"
+ }]}
+
+ TEST_RESULTS_DATA = {
+ "interval": 0,
+ "elapsedTime": 138,
+ "actualTime": 1521548057296,
+ "iteration": 1,
+ "tabs": {
+ "Test Summary": {
+ "Start Time": "Tue Mar 20 07:11:55 CDT 2018",
+ "Actual Dedicated Bearer Session Connects": "100",
+ "Actual Dedicated Bearer Session Disconnects": "100",
+ "Actual Disconnect Rate(Sessions / Second)(P - I)": "164.804",
+ "Average Session Disconnect Time(P - I)": "5.024 s",
+ "Total Data Sent + Received Packets / Sec(P - I)": "1,452.294"
+ }}}
+
+ def setUp(self):
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ mock_env_helper = mock.Mock()
+ self.res_helper = tg_landslide.LandslideResourceHelper(mock_env_helper)
+ self.res_helper._url = EXAMPLE_URL
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+ self.res_helper._url = None
+
+ def test___init__(self, *args):
+ self.assertIsInstance(self.res_helper,
+ tg_landslide.LandslideResourceHelper)
+ self.assertEqual({}, self.res_helper._result)
+ self.assertIsNone(self.res_helper.run_id)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests_no_running_tests(self, mock_get_tests,
+ mock_stop_tests, *args):
+ tests_data = [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'COMPLETE'}]
+ mock_get_tests.return_value = tests_data
+ self.assertIsNone(self.res_helper.abort_running_tests())
+ mock_stop_tests.assert_not_called()
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests(self, mock_get_tests, mock_stop_tests, *args):
+ test_states_seq = iter(['RUNNING', 'COMPLETE'])
+
+ def configure_mock(*args):
+ return [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': next(test_states_seq)}]
+
+ mock_get_tests.side_effect = configure_mock
+ self.assertIsNone(self.res_helper.abort_running_tests())
+ mock_stop_tests.assert_called_once_with(
+ running_test_id=self.SUCCESS_RECORD_ID,
+ force=True)
+ self.assertEqual(2, mock_get_tests.call_count)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests_error(self, mock_get_tests, mock_stop_tests,
+ *args):
+ tests_data = {'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'RUNNING'}
+ mock_get_tests.return_value = [tests_data]
+ with self.assertRaises(RuntimeError):
+ self.res_helper.abort_running_tests(timeout=1, delay=1)
+ mock_stop_tests.assert_called_with(
+ running_test_id=self.SUCCESS_RECORD_ID,
+ force=True)
+
+ def test__build_url(self, *args):
+ resource = 'users'
+ action = {'action': 'userCreate'}
+ expected_url = ''.join([EXAMPLE_URL, 'users?action=userCreate'])
+ self.assertEqual(expected_url,
+ self.res_helper._build_url(resource, action))
+
+ def test__build_url_error(self, *args):
+ resource = ''
+ action = {'action': 'userCreate'}
+
+ with self.assertRaises(ValueError):
+ self.res_helper._build_url(resource, action)
+
+ def test_get_response_params(self, *args):
+ method = 'get'
+ resource = 'users'
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.USERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ resp = self.res_helper.get_response_params(method, resource)
+ self.assertTrue(resp)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, '_get_users')
+ @mock.patch.object(time, 'time')
+ def test__create_user(self, mock_time, mock_get_users, *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertEqual(self.SUCCESS_RECORD_ID,
+ self.res_helper._create_user(self.AUTH_DATA))
+ mock_get_users.assert_not_called()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, '_modify_user')
+ @mock.patch.object(time, 'time')
+ def test__create_user_username_exists(self, mock_time, mock_modify_user,
+ *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ mock_modify_user.return_value = {'id': self.SUCCESS_RECORD_ID,
+ 'result': 'No changes requested'}
+ post_resp_data = {
+ 'status_code': self.ERROR_CODE,
+ 'json.return_value': {'id': self.SUCCESS_OK_CODE,
+ 'apiCode': self.NOT_MODIFIED_CODE}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper._create_user(self.AUTH_DATA)
+ mock_modify_user.assert_called_once_with(TAS_INFO['user'],
+ {'isActive': 'true'})
+ self.assertEqual(self.SUCCESS_RECORD_ID, res)
+
+ @mock.patch.object(time, 'time')
+ def test__create_user_error(self, mock_time, *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'apiCode': self.ERROR_CODE}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper._create_user(self.AUTH_DATA)
+
+ def test__modify_user(self, *args):
+ post_data = {'username': 'test_user'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper._modify_user(username=self.TEST_USER,
+ fields=post_data)
+ self.assertEqual(self.SUCCESS_RECORD_ID, res['id'])
+
+ def test__modify_user_rest_resp_fail(self, *args):
+ post_data = {'non-existing-key': ''}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.ok = False
+ self.res_helper.session = mock_session
+ self.assertRaises(exceptions.RestApiError,
+ self.res_helper._modify_user,
+ username=self.TEST_USER, fields=post_data)
+ mock_session.post.assert_called_once()
+
+ def test__delete_user(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper._delete_user(
+ username=self.TEST_USER))
+
+ def test__get_users(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.USERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertEqual(self.USERS_DATA['users'],
+ self.res_helper._get_users())
+
+ def test_exec_rest_request(self, *args):
+ resource = 'testServers'
+ action = {'action': 'modify'}
+ expected_url = ''.join([EXAMPLE_URL, 'testServers?action=modify'])
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.res_helper.exec_rest_request('post', resource, action)
+ self.res_helper.session.post.assert_called_once_with(expected_url,
+ json={})
+
+ def test_exec_rest_request_unsupported_method_error(self, *args):
+ resource = 'testServers'
+ action = {'action': 'modify'}
+ with self.assertRaises(ValueError):
+ self.res_helper.exec_rest_request('patch', resource, action)
+
+ def test_exec_rest_request_missed_action_arg(self, *args):
+ resource = 'testServers'
+ with self.assertRaises(ValueError):
+ self.res_helper.exec_rest_request('post', resource)
+
+ def test_exec_rest_request_raise_exc(self):
+ resource = 'users'
+ action = {'action': 'modify'}
+ post_resp_data = {'status_code': self.ERROR_CODE,
+ 'json.return_value': {
+ 'status_code': self.ERROR_CODE}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.assertRaises(exceptions.RestApiError,
+ self.res_helper.exec_rest_request,
+ 'post', resource, action, raise_exc=True)
+
+ @mock.patch.object(time, 'time')
+ def test_connect(self, mock_time, *args):
+ vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ self.res_helper.vnfd_helper = vnfd
+
+ self.res_helper._tcl = mock.Mock()
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session, headers={})
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.connect(), requests.Session)
+ self.res_helper._tcl.connect.assert_called_once_with(
+ TAS_INFO['ip'],
+ TAS_INFO['user'],
+ TAS_INFO['password'])
+
+ def test_disconnect(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.disconnect())
+ self.assertIsNone(self.res_helper.session)
+ self.res_helper._tcl.disconnect.assert_called_once()
+
+ def test_terminate(self, *args):
+ self.assertIsNone(self.res_helper.terminate())
+ self.assertEqual(self.TEST_TERMINATED,
+ self.res_helper._terminated.value)
+
+ def test_create_dmf(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.create_dmf(DMF_CFG))
+ self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_create_dmf_as_list(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.create_dmf([DMF_CFG]))
+ self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_delete_dmf(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.delete_dmf(DMF_CFG))
+ self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_delete_dmf_as_list(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.delete_dmf([DMF_CFG]))
+ self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
+ def test_create_suts(self, mock_configure_sut, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.create_suts(TS1_SUTS))
+ mock_configure_sut.assert_not_called()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
+ def test_create_suts_sut_exists(self, mock_configure_sut, *args):
+ sut_name = 'test_sut'
+ suts = [
+ {'name': sut_name,
+ 'role': 'SgwControlAddr',
+ 'managementIp': '12.0.1.1',
+ 'ip': '10.42.32.100'
+ }
+ ]
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.create_suts(suts))
+ mock_configure_sut.assert_called_once_with(
+ sut_name=sut_name,
+ json_data={k: v for k, v in suts[0].items()
+ if k not in {'phy', 'nextHop', 'role', 'name'}})
+
+ def test_get_suts(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.get_suts(), list)
+
+ def test_get_suts_single_id(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA['suts'][0]}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.get_suts(suts_id=2), dict)
+
+ def test_configure_sut(self, *args):
+ post_data = {'managementIp': '2.2.2.2'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.configure_sut('test_name',
+ post_data))
+ mock_session.post.assert_called_once()
+
+ def test_configure_sut_error(self, *args):
+ post_data = {'managementIp': '2.2.2.2'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper.configure_sut('test_name', post_data)
+
+ def test_delete_suts(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA}
+ delete_resp_data = {'status_code': self.SUCCESS_OK_CODE}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ mock_session.delete.return_value.configure_mock(**delete_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_suts())
+ mock_session.delete.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_test_servers')
+ def test__check_test_servers_state(self, mock_get_test_servers, *args):
+ mock_get_test_servers.return_value = \
+ self.TEST_SERVERS_DATA['testServers']
+ self.res_helper._check_test_servers_state()
+ mock_get_test_servers.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_test_servers')
+ def test__check_test_servers_state_server_not_ready(
+ self, mock_get_test_servers, *args):
+ test_servers_not_ready = [
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/1"]),
+ "id": 1,
+ "name": "TestServer_1",
+ "state": "NOT_READY",
+ "version": "16.4.0.10"
+ }
+ ]
+
+ mock_get_test_servers.return_value = test_servers_not_ready
+ with self.assertRaises(RuntimeError):
+ self.res_helper._check_test_servers_state(timeout=1, delay=0)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ '_check_test_servers_state')
+ def test_create_test_servers(self, mock_check_ts_state, *args):
+ test_servers_ids = [
+ ts['id'] for ts in self.TEST_SERVERS_DATA['testServers']]
+
+ self.res_helper.license_data['lic_id'] = TAS_INFO['license']
+ self.res_helper._tcl.create_test_server = mock.Mock()
+ self.res_helper._tcl.create_test_server.side_effect = test_servers_ids
+ self.assertIsNone(self.res_helper.create_test_servers(TEST_SERVERS))
+ mock_check_ts_state.assert_called_once_with(test_servers_ids)
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name')
+ @mock.patch.object(tg_landslide.LsTclHandler, 'execute')
+ def test_create_test_servers_error(self, mock_execute,
+ mock_resolve_ts_name, *args):
+ self.res_helper.license_data['lic_id'] = TAS_INFO['license']
+ # Return message for case test server wasn't created
+ mock_execute.return_value = 'TS not found'
+ # Return message for case test server name wasn't resolved
+ mock_resolve_ts_name.return_value = 'TS not found'
+ with self.assertRaises(RuntimeError):
+ self.res_helper.create_test_servers(TEST_SERVERS)
+
+ def test_get_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_servers()
+ self.assertEqual(self.TEST_SERVERS_DATA['testServers'], res)
+
+ def test_get_test_servers_by_id(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+
+ _ts = self.TEST_SERVERS_DATA['testServers'][0]
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': _ts}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_servers(test_server_ids=[_ts['id']])
+ self.assertEqual([_ts], res)
+
+ def test_configure_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.configure_test_servers(
+ action={'action': 'recycle'})
+ self.assertEqual(
+ [x['id'] for x in self.TEST_SERVERS_DATA['testServers']],
+ res)
+ self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
+ mock_session.post.call_count)
+
+ def test_delete_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_test_servers())
+ self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
+ mock_session.delete.call_count)
+
+ def test_create_test_session_res_helper(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper._tcl = mock.Mock()
+ test_session = {'name': 'test'}
+ self.assertIsNone(self.res_helper.create_test_session(test_session))
+ self.res_helper._tcl.create_test_session.assert_called_once_with(
+ {'name': 'test', 'library': self.SUCCESS_RECORD_ID})
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name',
+ return_value='Not Found')
+ def test_create_test_session_ts_name_not_found(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ test_session = {
+ 'duration': 60,
+ 'description': 'UE default bearer creation test case',
+ 'name': 'default_bearer_capacity',
+ 'tsGroups': [{'testCases': [{'type': 'SGW_Node',
+ 'name': ''}],
+ 'tsId': 'TestServer_3'}]
+ }
+ with self.assertRaises(RuntimeError):
+ self.res_helper.create_test_session(test_session)
+
+ def test_get_test_session(self, *args):
+ test_session = {"name": self.TEST_SESSION_NAME}
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': test_session}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_session(self.TEST_SESSION_NAME)
+ self.assertEqual(test_session, res)
+
+ def test_configure_test_session(self, *args):
+ test_session = {'name': self.TEST_SESSION_NAME}
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
+ self.res_helper.test_session_uri)
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper.configure_test_session(self.TEST_SESSION_NAME,
+ test_session)
+ self.assertIsNotNone(res)
+ mock_session.post.assert_called_once()
+
+ def test_delete_test_session(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
+ self.res_helper.test_session_uri)
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper.delete_test_session(self.TEST_SESSION_NAME)
+ self.assertIsNotNone(res)
+ mock_session.delete.assert_called_once()
+
+ def test_create_running_tests(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ test_session = {'id': self.SUCCESS_RECORD_ID}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': test_session}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
+ self.assertEqual(self.SUCCESS_RECORD_ID, self.res_helper.run_id)
+
+ def test_create_running_tests_error(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
+
+ def test_get_running_tests(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_running_tests()
+ self.assertEqual(self.RUNNING_TESTS_DATA['runningTests'], res)
+
+ def test_delete_running_tests(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ delete_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA}
+ mock_session.delete.return_value.configure_mock(**delete_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_running_tests())
+
+ def test__running_tests_action(self, *args):
+ action = 'abort'
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper._running_tests_action(self.SUCCESS_RECORD_ID,
+ action)
+ self.assertIsNone(res)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ '_running_tests_action')
+ def test_stop_running_tests(self, mock_tests_action, *args):
+ res = self.res_helper.stop_running_tests(self.SUCCESS_RECORD_ID)
+ self.assertIsNone(res)
+ mock_tests_action.assert_called_once()
+
+ def test_check_running_test_state(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {
+ 'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA["runningTests"][0]}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.check_running_test_state(self.SUCCESS_RECORD_ID)
+ self.assertEqual(
+ self.RUNNING_TESTS_DATA["runningTests"][0]['testStateOrStep'],
+ res)
+
+ def test_get_running_tests_results(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_RESULTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_running_tests_results(
+ self.SUCCESS_RECORD_ID)
+ self.assertEqual(self.TEST_RESULTS_DATA, res)
+
+ def test__write_results(self, *args):
+ res = self.res_helper._write_results(self.TEST_RESULTS_DATA)
+ exp_res = {
+ "Test Summary::Actual Dedicated Bearer Session Connects": 100.0,
+ "Test Summary::Actual Dedicated Bearer Session Disconnects": 100.0,
+ "Test Summary::Actual Disconnect Rate(Sessions / Second)(P - I)": 164.804,
+ "Test Summary::Average Session Disconnect Time(P - I)": 5.024,
+ "Test Summary::Total Data Sent + Received Packets / Sec(P - I)": 1452.294
+ }
+ self.assertEqual(exp_res, res)
+
+ def test__write_results_no_tabs(self, *args):
+ _res_data = copy.deepcopy(self.TEST_RESULTS_DATA)
+ del _res_data['tabs']
+ # Return None if tabs not found in test results dict
+ self.assertIsNone(self.res_helper._write_results(_res_data))
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests_results')
+ def test_collect_kpi_test_running(self, mock_tests_results,
+ mock_tests_state, *args):
+ self.res_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_tests_state.return_value = 'RUNNING'
+ mock_tests_results.return_value = self.TEST_RESULTS_DATA
+ res = self.res_helper.collect_kpi()
+ self.assertNotIn('done', res)
+ mock_tests_state.assert_called_once_with(self.res_helper.run_id)
+ mock_tests_results.assert_called_once_with(self.res_helper.run_id)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests_results')
+ def test_collect_kpi_test_completed(self, mock_tests_results,
+ mock_tests_state, *args):
+ self.res_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_tests_state.return_value = 'COMPLETE'
+ res = self.res_helper.collect_kpi()
+ self.assertIsNotNone(res)
+ mock_tests_state.assert_called_once_with(self.res_helper.run_id)
+ mock_tests_results.assert_not_called()
+ self.assertDictContainsSubset({'done': True}, res)
+
+
+class TestLandslideTclClient(unittest.TestCase):
+ def setUp(self):
+ self.mock_tcl_handler = mock.Mock(spec=tg_landslide.LsTclHandler)
+ self.ls_res_helper = mock.Mock(
+ spec=tg_landslide.LandslideResourceHelper)
+ self.ls_tcl_client = tg_landslide.LandslideTclClient(
+ self.mock_tcl_handler,
+ self.ls_res_helper)
+
+ def test___init__(self, *args):
+ self.ls_tcl_client = tg_landslide.LandslideTclClient(
+ self.mock_tcl_handler,
+ self.ls_res_helper)
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+ self.assertEqual(set(), self.ls_tcl_client.ts_ids)
+ self.assertIsInstance(self.ls_tcl_client._tc_types, set)
+ self.assertIsNotNone(self.ls_tcl_client._tc_types)
+
+ def test_connect_login_success(self, *args):
+ lib_id = '123'
+ exec_responses = ['java0x2', lib_id, lib_id]
+ auth = ('user', 'password')
+ self.mock_tcl_handler.execute.side_effect = exec_responses
+ self.ls_tcl_client.connect(TAS_INFO['ip'], *auth)
+ self.assertEqual(lib_id, self.ls_tcl_client._library_id)
+ self.assertEqual(lib_id, self.ls_tcl_client._basic_library_id)
+ self.assertEqual(TAS_INFO['ip'], self.ls_tcl_client.tcl_server_ip)
+ self.assertEqual(auth[0], self.ls_tcl_client._user)
+ self.assertEqual(len(exec_responses),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call("ls::login 1.1.1.1 user password"),
+ mock.call("ls::get [ls::query LibraryInfo -userLibraryName user] -Id"),
+ ])
+
+ def test_connect_login_failed(self, *args):
+ exec_responses = ['Login failed']
+ auth = ('user', 'password')
+ self.mock_tcl_handler.execute.side_effect = exec_responses
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client.connect,
+ TAS_INFO['ip'],
+ *auth)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertEqual(len(exec_responses),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_called_with(
+ "ls::login 1.1.1.1 user password")
+
+ def test_disconnect(self, *args):
+ self.ls_tcl_client.disconnect()
+ self.mock_tcl_handler.execute.assert_called_once_with("ls::logout")
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+
+ def test_create_test_server(self, *args):
+ return_value = '2'
+ self.ls_tcl_client._ts_context.vnfd_helper = \
+ VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': return_value}
+ self.mock_tcl_handler.execute.return_value = return_value
+ self.ls_tcl_client._set_thread_model = mock.Mock()
+ res = self.ls_tcl_client.create_test_server(TEST_SERVERS[1])
+ self.assertEqual(3, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId TestServer_2'),
+ mock.call('set ts [ls::retrieve TsInfo -Name "TestServer_2"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ ])
+ self.ls_tcl_client._set_thread_model.assert_called_once_with(
+ TEST_SERVERS[1]['name'],
+ TEST_SERVERS[1]['thread_model'])
+ self.assertEqual(int(return_value), res)
+
+ def test_create_test_server_fail_limit_reach(self, *args):
+ self.mock_tcl_handler.execute.side_effect = ['TS not found',
+ 'Add failed']
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client.create_test_server,
+ TEST_SERVERS[0])
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId TestServer_1'),
+ mock.call('ls::perform AddTs -Name "TestServer_1" '
+ '-Ip "192.168.122.101"'),
+ ])
+
+ def test__add_test_server(self):
+ ts_id = '2'
+ self.mock_tcl_handler.execute.side_effect = ['TS not found', ts_id]
+ self.assertEqual(ts_id,
+ self.ls_tcl_client._add_test_server('name', 'ip'))
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId name'),
+ mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
+ ])
+
+ def test__add_test_server_failed(self):
+ self.mock_tcl_handler.execute.side_effect = ['TS not found',
+ 'Add failed']
+ self.assertRaises(RuntimeError, self.ls_tcl_client._add_test_server,
+ 'name', 'ip')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId name'),
+ mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
+ ])
+
+ def test__update_license(self):
+ curr_lic_id = '111'
+ new_lic_id = '222'
+ exec_resp = ['java0x4',
+ curr_lic_id,
+ TCL_SUCCESS_RESPONSE,
+ TCL_SUCCESS_RESPONSE]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._update_license('name')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ mock.call('ls::config $ts -RequestedLicense 222'),
+ mock.call('ls::perform ModifyTs $ts'),
+ ])
+
+ def test__update_license_same_as_current(self):
+ curr_lic_id = '111'
+ new_lic_id = '111'
+ exec_resp = ['java0x4', curr_lic_id]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._update_license('name')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ ])
+
+ def test__set_thread_model_update_needed(self):
+ self.ls_tcl_client._ts_context.vnfd_helper = {
+ 'mgmt-interface': {
+ 'cfguser_password': 'cfguser_password'
+ }
+ }
+ exec_resp = ['java0x4', 'V0', '', '']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._set_thread_model('name', 'Fireball')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set tsc [ls::perform RetrieveTsConfiguration '
+ '-name "name" cfguser_password]'),
+ mock.call('ls::get $tsc -ThreadModel'),
+ mock.call('ls::config $tsc -ThreadModel "V1_FB3"'),
+ mock.call('ls::perform ApplyTsConfiguration $tsc cfguser_password'),
+ ])
+
+ def test__set_thread_model_no_update_needed(self):
+ self.ls_tcl_client._ts_context.vnfd_helper = {
+ 'mgmt-interface': {
+ 'cfguser_password': 'cfguser_password'
+ }
+ }
+ exec_resp = ['java0x4', 'V0']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._set_thread_model('name', 'Legacy')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set tsc [ls::perform RetrieveTsConfiguration '
+ '-name "name" cfguser_password]'),
+ mock.call('ls::get $tsc -ThreadModel'),
+ ])
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name', side_effect=['4', '2'])
+ def test_create_test_session(self, *args):
+ _session_profile = copy.deepcopy(SESSION_PROFILE)
+ _session_profile['reservations'] = RESERVATIONS
+ self.ls_tcl_client._save_test_session = mock.Mock()
+ self.ls_tcl_client._configure_ts_group = mock.Mock()
+ self.ls_tcl_client._library_id = 42
+ self.ls_tcl_client.create_test_session(_session_profile)
+ self.assertEqual(17, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set test_ [ls::create TestSession]'),
+ mock.call('ls::config $test_ -Library 42 '
+ '-Name "default_bearer_capacity"'),
+ mock.call('ls::config $test_ -Description ' \
+ '"UE default bearer creation test case"'),
+ mock.call('ls::config $test_ -Keywords ""'),
+ mock.call('ls::config $test_ -Duration "60"'),
+ mock.call('ls::config $test_ -Iterations "1"'),
+ # _configure_reservation
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 0 '
+ '-TsId 4 -TsName "TestServer_1"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.100" '
+ '-Mask "/24" -NumIps 20'),
+ # _configure_reservation
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 1 '
+ '-TsId 2 -TsName "TestServer_2"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.1" '
+ '-Mask "/24" -NumIps 100'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth2" -Base "10.42.33.1" '
+ '-Mask "/24" -NumIps 100'),
+ # _configure_report_options
+ mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
+ ])
+
+ def test_create_dmf(self):
+ self.mock_tcl_handler.execute.return_value = '2'
+ self.ls_tcl_client._save_dmf = mock.Mock()
+ self.ls_tcl_client.create_dmf(copy.deepcopy(DMF_CFG))
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+ # This is needed because the dictionary is unordered and the arguments
+ # can come in either order
+ call1 = mock.call(
+ 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
+ call2 = mock.call(
+ 'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
+ self.assertTrue(
+ call1 in self.mock_tcl_handler.execute.mock_calls or
+ call2 in self.mock_tcl_handler.execute.mock_calls)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set dmf_ [ls::create Dmf]'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName test] -Id'),
+ mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
+ mock.call('ls::config $dmf_ -dataProtocol "udp"'),
+ # mock.call(
+ # 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
+ mock.call('ls::config $dmf_ -serverPort 2003'),
+ ], any_order=True)
+
+ def test_configure_dmf(self):
+ self.mock_tcl_handler.execute.return_value = '2'
+ self.ls_tcl_client._save_dmf = mock.Mock()
+ self.ls_tcl_client.configure_dmf(DMF_CFG)
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+ # This is need because the dictionary is unordered and the arguments
+ # can come in either order
+ call1 = mock.call(
+ 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
+ call2 = mock.call(
+ 'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
+ self.assertTrue(
+ call1 in self.mock_tcl_handler.execute.mock_calls or
+ call2 in self.mock_tcl_handler.execute.mock_calls)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set dmf_ [ls::create Dmf]'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName test] -Id'),
+ mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
+ mock.call('ls::config $dmf_ -dataProtocol "udp"'),
+ # mock.call(
+ # 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
+ mock.call('ls::config $dmf_ -serverPort 2003'),
+ ], any_order=True)
+
+ def test_delete_dmf(self):
+ self.assertRaises(NotImplementedError,
+ self.ls_tcl_client.delete_dmf,
+ DMF_CFG)
+
+ def test__save_dmf_valid(self):
+ exec_resp = [TCL_SUCCESS_RESPONSE, TCL_SUCCESS_RESPONSE]
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._save_dmf()
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -Dmf $dmf_'),
+ mock.call('ls::save $dmf_ -overwrite'),
+ ])
+
+ def test__save_dmf_invalid(self):
+ exec_resp = ['Invalid', 'List of errors and warnings']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._save_dmf)
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -Dmf $dmf_'),
+ mock.call('ls::get $dmf_ -ErrorsAndWarnings'),
+ ])
+
+ def test__configure_report_options(self):
+ _options = {'format': 'CSV', 'PerInterval': 'false'}
+ self.ls_tcl_client._configure_report_options(_options)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
+ mock.call('ls::config $test_.ReportOptions -PerInterval false'),
+ ],
+ any_order=True)
+
+ def test___configure_ts_group(self, *args):
+ _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
+ self.ls_tcl_client._configure_tc_type = mock.Mock()
+ self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='2')
+ self.ls_tcl_client._configure_ts_group(_ts_group, 0)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'set tss_ [ls::create TsGroup -under $test_ -tsId 2 ]')
+
+ def test___configure_ts_group_resolve_ts_fail(self, *args):
+ _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
+ self.ls_tcl_client._configure_tc_type = mock.Mock()
+ self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='TS Not Found')
+ self.assertRaises(RuntimeError, self.ls_tcl_client._configure_ts_group,
+ _ts_group, 0)
+ self.mock_tcl_handler.execute.assert_not_called()
+
+ def test__configure_tc_type(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.ls_tcl_client._configure_tc_type(_tc, 0)
+ self.assertEqual(7, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_tc_type_optional_param_omitted(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ del _tc['linked']
+ self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.ls_tcl_client._configure_tc_type(_tc, 0)
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_tc_type_wrong_type(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ _tc['type'] = 'not_supported'
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client._configure_tc_type,
+ _tc, 0)
+ self.mock_tcl_handler.assert_not_called()
+
+ def test__configure_tc_type_not_found_basic_lib(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.mock_tcl_handler.execute.return_value = 'Invalid'
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client._configure_tc_type,
+ _tc, 0)
+
+ def test__configure_parameters(self):
+ _params = copy.deepcopy(
+ SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
+ self.ls_tcl_client._configure_parameters(_params)
+ self.assertEqual(16, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_array_param(self):
+ _array = {"class": "Array",
+ "array": ["0"]}
+ self.ls_tcl_client._configure_array_param('name', _array)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Array-name -under $p_ ;'),
+ mock.call('ls::create ArrayItem -under $p_.name -Value "0"'),
+ ])
+
+ def test__configure_test_node_param(self):
+ _params = copy.deepcopy(
+ SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
+ self.ls_tcl_client._configure_test_node_param('SgwUserAddr',
+ _params['SgwUserAddr'])
+ cmd = ('ls::create -TestNode-SgwUserAddr -under $p_ -Type "eth" '
+ '-Phy "eth1" -Ip "SGW_USER_IP" -NumLinksOrNodes 1 '
+ '-NextHop "SGW_CONTROL_NEXT_HOP" -Mac "" -MTU 1500 '
+ '-ForcedEthInterface "" -EthStatsEnabled false -VlanId 0 '
+ '-VlanUserPriority 0 -NumVlan 1 -UniqueVlanAddr false;')
+ self.mock_tcl_handler.execute.assert_called_once_with(cmd)
+
+ def test__configure_sut_param(self):
+ _params = {'name': 'name'}
+ self.ls_tcl_client._configure_sut_param('name', _params)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'ls::create -Sut-name -under $p_ -Name "name";')
+
+ def test__configure_dmf_param(self):
+ _params = {"mainflows": [{"library": '111',
+ "name": "Basic UDP"}],
+ "instanceGroups": [{
+ "mainflowIdx": 0,
+ "mixType": "",
+ "rate": 0.0,
+ "rows": [{
+ "clientPort": 0,
+ "context": 0,
+ "node": 0,
+ "overridePort": "false",
+ "ratingGroup": 0,
+ "role": 0,
+ "serviceId": 0,
+ "transport": "Any"}]
+ }]}
+ self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
+ res = self.ls_tcl_client._configure_dmf_param('name', _params)
+ self.assertEqual(5, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Dmf-name -under $p_ ;'),
+ mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0) -mixType '),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0) -rate 0.0'),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0).Row(0) -Node 0 '
+ '-OverridePort false -ClientPort 0 -Context 0 -Role 0 '
+ '-PreferredTransport Any -RatingGroup 0 '
+ '-ServiceID 0'),
+ ])
+
+ def test__configure_dmf_param_no_instance_groups(self):
+ _params = {"mainflows": [{"library": '111',
+ "name": "Basic UDP"}]}
+ self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
+ res = self.ls_tcl_client._configure_dmf_param('name', _params)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Dmf-name -under $p_ ;'),
+ mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
+ ])
+
+ def test__configure_reservation(self):
+ _reservation = copy.deepcopy(RESERVATIONS[0])
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='4')
+ res = self.ls_tcl_client._configure_reservation(_reservation)
+ self.assertIsNone(res)
+ self.assertEqual(4, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 0 -TsId 4 ' + \
+ '-TsName "TestServer_1"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" ' + \
+ '-Base "10.42.32.100" -Mask "/24" -NumIps 20'),
+ ])
+
+ def test__configure_preresolved_arp(self):
+ _arp = [{'StartingAddress': '10.81.1.10',
+ 'NumNodes': 1}]
+ res = self.ls_tcl_client._configure_preresolved_arp(_arp)
+ self.mock_tcl_handler.execute.assert_called_once()
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'ls::create PreResolvedArpAddress -under $tss_ ' + \
+ '-StartingAddress "10.81.1.10" -NumNodes 1')
+
+ def test__configure_preresolved_arp_none(self):
+ res = self.ls_tcl_client._configure_preresolved_arp(None)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_not_called()
+
+ def test_delete_test_session(self):
+ self.assertRaises(NotImplementedError,
+ self.ls_tcl_client.delete_test_session, {})
+
+ def test__save_test_session(self):
+ self.mock_tcl_handler.execute.side_effect = [TCL_SUCCESS_RESPONSE,
+ TCL_SUCCESS_RESPONSE]
+ res = self.ls_tcl_client._save_test_session()
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -TestSession $test_'),
+ mock.call('ls::save $test_ -overwrite'),
+ ])
+
+ def test__save_test_session_invalid(self):
+ self.mock_tcl_handler.execute.side_effect = ['Invalid', 'Errors']
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._save_test_session)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -TestSession $test_'),
+ mock.call('ls::get $test_ -ErrorsAndWarnings'),
+ ])
+
+ def test__get_library_id_system_lib(self):
+ self.mock_tcl_handler.execute.return_value = '111'
+ res = self.ls_tcl_client._get_library_id('name')
+ self.mock_tcl_handler.execute.assert_called_once()
+ self.assertEqual('111', res)
+ self.mock_tcl_handler.execute.assert_called_with(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id')
+
+ def test__get_library_id_user_lib(self):
+ self.mock_tcl_handler.execute.side_effect = ['Not found', '222']
+ res = self.ls_tcl_client._get_library_id('name')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertEqual('222', res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
+ ])
+
+ def test__get_library_id_exception(self):
+ self.mock_tcl_handler.execute.side_effect = ['Not found', 'Not found']
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._get_library_id,
+ 'name')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
+ ])
+
+
+class TestLsTclHandler(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+
+ def test___init__(self, *args):
+ self.ls_tcl_handler = tg_landslide.LsTclHandler()
+ self.assertEqual({}, self.ls_tcl_handler.tcl_cmds)
+ self.ls_tcl_handler._ls.tcl.assert_called_once()
+
+ def test_execute(self, *args):
+ self.ls_tcl_handler = tg_landslide.LsTclHandler()
+ self.ls_tcl_handler.execute('command')
+ self.assertIn('command', self.ls_tcl_handler.tcl_cmds)