Merge "Change IxNextgen library load" into stable/fraser
authorRodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Wed, 27 Jun 2018 16:48:33 +0000 (16:48 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Wed, 27 Jun 2018 16:48:33 +0000 (16:48 +0000)
44 files changed:
ansible/install-inventory.ini [new file with mode: 0644]
ansible/install.yaml [new file with mode: 0644]
ansible/nsb_setup.yml
ansible/roles/add_repos_jumphost/tasks/Debian.yml [new file with mode: 0644]
ansible/roles/add_repos_jumphost/tasks/main.yml [moved from ansible/install_dependencies.yml with 81% similarity]
ansible/roles/add_repos_jumphost/vars/main.yml [new file with mode: 0644]
ansible/roles/configure_gui/tasks/main.yml [new file with mode: 0644]
ansible/roles/configure_nginx/tasks/main.yml [new file with mode: 0644]
ansible/roles/configure_nginx/templates/yardstick.conf.j2 [new file with mode: 0644]
ansible/roles/configure_rabbitmq/tasks/main.yml [new file with mode: 0644]
ansible/roles/configure_uwsgi/tasks/main.yml [new file with mode: 0644]
ansible/roles/configure_uwsgi/templates/yardstick.ini.j2 [new file with mode: 0644]
ansible/roles/download_trex/tasks/main.yml
ansible/roles/install_dependencies_jumphost/tasks/Debian.yml [new file with mode: 0755]
ansible/roles/install_dependencies_jumphost/tasks/RedHat.yml [moved from ansible/roles/install_dependencies/tasks/RedHat.yml with 90% similarity]
ansible/roles/install_dependencies_jumphost/tasks/Suse.yml [moved from ansible/roles/install_dependencies/tasks/Debian.yml with 70% similarity, mode: 0644]
ansible/roles/install_dependencies_jumphost/tasks/main.yml [moved from ansible/roles/install_dependencies/tasks/main.yml with 100% similarity]
ansible/roles/install_yardstick/tasks/main.yml [new file with mode: 0644]
ansible/roles/install_yardstick/tasks/regular_install.yml [new file with mode: 0644]
ansible/roles/install_yardstick/tasks/virtual_install.yml [new file with mode: 0644]
ansible/yardstick-install-inventory.ini [deleted file]
docker/Dockerfile
install.sh
nsb_setup.sh
yardstick/benchmark/contexts/heat.py
yardstick/benchmark/scenarios/networking/vnf_generic.py
yardstick/common/utils.py
yardstick/network_services/traffic_profile/base.py
yardstick/network_services/traffic_profile/ixia_rfc2544.py
yardstick/network_services/traffic_profile/rfc2544.py
yardstick/network_services/traffic_profile/trex_traffic_profile.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/tg_rfc2544_trex.py
yardstick/network_services/vnf_generic/vnf/tg_trex.py
yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
yardstick/tests/unit/benchmark/contexts/test_heat.py
yardstick/tests/unit/common/test_utils.py
yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
yardstick/tests/unit/network_services/traffic_profile/test_base.py
yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py

diff --git a/ansible/install-inventory.ini b/ansible/install-inventory.ini
new file mode 100644 (file)
index 0000000..6aa9905
--- /dev/null
@@ -0,0 +1,30 @@
+# the group of systems on which to install yardstick
+# by default just localhost
+[jumphost]
+#yardstickvm1 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=local
+localhost ansible_connection=local
+
+# section below is only due backward compatibility.
+# it will be removed later
+[yardstick:children]
+jumphost
+
+[yardstick-standalone]
+#yardstickvm2 ansible_host=192.168.2.51 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=ssh
+# uncomment hosts below if you would to test yardstick-standalone/sriov scenarios
+#yardstick-standalone-node ansible_host=192.168.1.2
+#yardstick-standalone-node-2 ansible_host=192.168.1.3
+
+[yardstick-baremetal]
+#yardstickvm3 ansible_host=192.168.2.52 ansible_user=ubuntu ansible_ssh_pass=password ansible_connection=ssh
+# hostname ansible_host=192.168.1.2
+
+[all:vars]
+arch_amd64=amd64
+arch_arm64=arm64
+inst_mode_container=container
+inst_mode_baremetal=baremetal
+ubuntu_archive={"amd64": "http://archive.ubuntu.com/ubuntu/", "arm64": "http://ports.ubuntu.com/ubuntu-ports/"}
+# uncomment credentials below for yardstick-standalone
+#ansible_user=root
+#ansible_pass=root
diff --git a/ansible/install.yaml b/ansible/install.yaml
new file mode 100644 (file)
index 0000000..d174579
--- /dev/null
@@ -0,0 +1,99 @@
+# 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.
+---
+- 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/') }}"
+
+  pre_tasks:
+
+    - name: Create NSB binaries directory, accesible to any user
+      file:
+        path: "{{ nsb_dir }}"
+        state: directory
+        owner: root
+        mode: 0777
+
+  roles:
+    - add_repos_jumphost
+    - install_dependencies_jumphost
+    - install_yardstick
+    - configure_uwsgi
+    - configure_nginx
+    - download_trex
+    - install_trex
+    - configure_rabbitmq
+
+  post_tasks:
+
+    - service:
+        name: nginx
+        state: restarted
+      when: installation_mode != inst_mode_container
+
+    - shell: uwsgi -i /etc/yardstick/yardstick.ini
+      when: installation_mode != inst_mode_container
+
+- name: Prepare baremetal and standalone server(s)
+  hosts: yardstick-baremetal,yardstick-standalone
+  become: yes
+  vars:
+    YARD_IMG_ARCH: "{{ arch_amd64 }}"
+  environment:
+    proxy_env:
+      http_proxy: "{{ lookup('env', 'http_proxy') }}"
+      https_proxy: "{{ lookup('env', 'https_proxy') }}"
+      ftp_proxy: "{{ lookup('env', 'ftp_proxy') }}"
+      no_proxy: "{{ lookup('env', 'no_proxy') }}"
+
+  roles:
+    - add_custom_repos
+    - role: set_package_installer_proxy
+      when: proxy_env is defined and proxy_env
+    # can't update grub in chroot/docker
+    - enable_hugepages_on_boot
+    # needed for collectd plugins
+    - increase_open_file_limits
+    - install_image_dependencies
+    - role: download_dpdk
+    # dpdk_version: "17.02"
+    - install_dpdk
+    - download_trex
+    - install_trex
+    - download_civetweb
+    - install_civetweb
+    - download_samplevnfs
+    - role: install_samplevnf
+      vnf_name: PROX
+    - role: install_samplevnf
+      vnf_name: UDP_Replay
+    - role: install_samplevnf
+      vnf_name: ACL
+    - role: install_samplevnf
+      vnf_name: FW
+    - role: install_samplevnf
+      vnf_name: CGNATP
+    # build shared DPDK for collectd only, required DPDK downloaded already
+    - install_dpdk_shared
+    - install_rabbitmq
+    - download_intel_cmt_cat
+    - install_intel_cmt_cat
+    - download_pmu_tools
+    - install_pmu_tools
+    - download_collectd
+    - install_collectd
index 56e591a..a00d991 100644 (file)
@@ -22,7 +22,7 @@
   environment:
     "{{ proxy_env }}"
   roles:
-    - install_dependencies
+    - install_dependencies_jumphost
     - docker
 
 - name: "handle all openstack stuff when: openrc_file is defined"
diff --git a/ansible/roles/add_repos_jumphost/tasks/Debian.yml b/ansible/roles/add_repos_jumphost/tasks/Debian.yml
new file mode 100644 (file)
index 0000000..0b67c66
--- /dev/null
@@ -0,0 +1,82 @@
+# 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.
+---
+# Arguments needed: arch_arm64, arch_amd64, ubuntu_archive
+
+- name: Set the repositories architecture name
+  set_fact:
+    arch: "{{ arch_arm64 if ansible_architecture == 'aarch64' else arch_amd64 }}"
+    extra_arch: "{{ arch_amd64 if ansible_architecture == 'aarch64' else arch_arm64 }}"
+
+- name: Define the repositories names
+  set_fact:
+    repo: "{{ ubuntu_archive[arch] }}"
+    extra_repo: "{{ ubuntu_archive[extra_arch] }}"
+
+- name: Add architecture to the default repository list
+  replace:
+    path: "{{ sources_list_file }}"
+    regexp: '(^deb\s+)([^\[].*)$'
+    replace: 'deb [arch={{ arch }}] \2'
+
+- name: Remove support for source repositories
+  replace:
+    path: "{{ sources_list_file }}"
+    regexp: "^deb-src "
+    replace: "# deb-src "
+
+- name: Add extra architecture
+  apt:
+    dpkg_options: "add-architecture {{ extra_arch }}"
+
+- name: Define the default release version
+  copy:
+    dest: "{{ default_distro_file }}"
+    content: 'APT::Default-Release "{{ ansible_distribution_release }}";'
+
+- name: Remove extra repository file
+  file:
+    path: "{{ repo_file }}"
+    state: absent
+  ignore_errors: yes
+
+- name: Add extra repository file
+  file:
+    path: "{{ repo_file }}"
+    state: touch
+
+- name: Add the repository for qemu_static_user/xenial
+  blockinfile:
+    path: "{{ repo_file }}"
+    marker: "MARKER"
+    content: |
+      deb [arch={{ arch }}] {{ repo }} xenial-updates universe
+  when: ansible_distribution_release != "xenial"
+
+- name: Add extra architecture repositories if installing in container
+  blockinfile:
+    path: "{{ repo_file }}"
+    marker: "MARKER"
+    content: |
+      deb [arch={{ extra_arch }}] {{ extra_repo }} {{ ansible_distribution_release }} main universe multiverse restricted
+      deb [arch={{ extra_arch }}] {{ extra_repo }} {{ ansible_distribution_release }}-updates main universe multiverse restricted
+      deb [arch={{ extra_arch }}] {{ extra_repo }} {{ ansible_distribution_release }}-security main universe multiverse restricted
+      deb [arch={{ extra_arch }}] {{ extra_repo }} {{ ansible_distribution_release }}-proposed main universe multiverse restricted
+  when: installation_mode == "container"
+
+- name: Remove the marker
+  lineinfile:
+    dest: "{{ repo_file }}"
+    state: absent
+    regexp: "MARKER"
similarity index 81%
rename from ansible/install_dependencies.yml
rename to ansible/roles/add_repos_jumphost/tasks/main.yml
index 1c7d201..f50fd9f 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Intel Corporation.
+# 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.
@@ -12,8 +12,5 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
-- name: install yardstick dependencies
-  hosts: all
-
-  roles:
-    - install_dependencies
+- include: "{{ ansible_os_family }}.yml"
+  when: ansible_os_family == "Debian"
diff --git a/ansible/roles/add_repos_jumphost/vars/main.yml b/ansible/roles/add_repos_jumphost/vars/main.yml
new file mode 100644 (file)
index 0000000..30e4447
--- /dev/null
@@ -0,0 +1,17 @@
+# 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.
+---
+repo_file: "/etc/apt/sources.list.d/yardstick.list"
+sources_list_file: "/etc/apt/sources.list"
+default_distro_file: "/etc/apt/apt.conf.d/default-distro"
diff --git a/ansible/roles/configure_gui/tasks/main.yml b/ansible/roles/configure_gui/tasks/main.yml
new file mode 100644 (file)
index 0000000..846a9cb
--- /dev/null
@@ -0,0 +1,33 @@
+# 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.
+---
+- name: Define variables
+  set_fact:
+    gui_dir: "{{ yardstick_dir }}/gui/"
+
+- name: Run gui.sh
+  shell:
+    cmd: /bin/bash gui.sh
+    chdir: "{{ gui_dir }}"
+
+- name: Create nginx/yardstick directory
+  file:
+    path: /etc/nginx/yardstick
+    state: directory
+    recurse: yes
+
+- name: Move dist to /etc/nginx/yardstick/gui
+  shell:
+    cmd: mv dist /etc/nginx/yardstick/gui
+    chdir: "{{ gui_dir }}"
diff --git a/ansible/roles/configure_nginx/tasks/main.yml b/ansible/roles/configure_nginx/tasks/main.yml
new file mode 100644 (file)
index 0000000..e0f7f75
--- /dev/null
@@ -0,0 +1,33 @@
+# 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.
+---
+- name: Define variables
+  set_fact:
+    socket_file: "{{ socket_file|default('/var/run/yardstick.sock') }}"
+
+- name: Make sure conf.d directory exists
+  file:
+    path: /etc/nginx/conf.d
+    state: directory
+
+- name: Create the nginx config file
+  template:
+    src: yardstick.conf.j2
+    dest: "/etc/nginx/conf.d/yardstick.conf"
+
+- name: Configure ports if RedHat OS
+  shell: |
+    semanage port -m -t http_port_t  -p tcp 5000
+    semanage port -m -t http_port_t  -p udp 5000
+  when: ansible_os_family == "RedHat"
diff --git a/ansible/roles/configure_nginx/templates/yardstick.conf.j2 b/ansible/roles/configure_nginx/templates/yardstick.conf.j2
new file mode 100644 (file)
index 0000000..484096c
--- /dev/null
@@ -0,0 +1,18 @@
+server {
+    listen 5000;
+    server_name localhost;
+    index index.htm index.html;
+    location / {
+        include uwsgi_params;
+        client_max_body_size    2000m;
+        uwsgi_pass unix://{{ socket_file }};
+    }
+
+    location /gui/ {
+        alias /etc/nginx/yardstick/gui/;
+    }
+
+    location /report/ {
+        alias /tmp/;
+    }
+}
diff --git a/ansible/roles/configure_rabbitmq/tasks/main.yml b/ansible/roles/configure_rabbitmq/tasks/main.yml
new file mode 100644 (file)
index 0000000..3ad60c1
--- /dev/null
@@ -0,0 +1,30 @@
+# 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.
+---
+- name: Restart rabbitmq
+  service:
+    name: rabbitmq-server
+    state: restarted
+
+- name: rabbitmqctl start_app
+  shell: rabbitmqctl start_app
+
+- name: Configure rabbitmq
+  rabbitmq_user:
+    user: yardstick
+    password: yardstick
+    configure_priv: .*
+    read_priv: .*
+    write_priv: .*
+    state: present
diff --git a/ansible/roles/configure_uwsgi/tasks/main.yml b/ansible/roles/configure_uwsgi/tasks/main.yml
new file mode 100644 (file)
index 0000000..6a22446
--- /dev/null
@@ -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.
+---
+- name: Define variables
+  set_fact:
+    config_dir: "/etc/yardstick/"
+    log_dir: "/var/log/yardstick/"
+    socket_file: "/var/run/yardstick.sock"
+
+- name: Create UWSGI config directory
+  file:
+    path: "/etc/yardstick"
+    state: directory
+    owner: root
+    mode: 0755
+
+- name: Create API log directory
+  file:
+    path: "{{ log_dir }}"
+    state: directory
+    owner: root
+    mode: 0777
+
+- name: Create the socket for communicating
+  file:
+    path: "{{ socket_file }}"
+    state: touch
+    owner: root
+    mode: 0644
+
+- name: Create the UWSGI config file
+  template:
+    src: yardstick.ini.j2
+    dest: "{{ config_dir }}yardstick.ini"
diff --git a/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2 b/ansible/roles/configure_uwsgi/templates/yardstick.ini.j2
new file mode 100644 (file)
index 0000000..c049daf
--- /dev/null
@@ -0,0 +1,18 @@
+[uwsgi]
+master = true
+debug = true
+chdir = {{ yardstick_dir }}api
+module = server
+plugins = python
+processes = 10
+threads = 5
+async = true
+max-requests = 5000
+chmod-socket = 666
+callable = app_wrapper
+enable-threads = true
+close-on-exec = 1
+daemonize = {{ log_dir }}uwsgi.log
+socket = {{ socket_file }}
+{# If virtual environment, we need to add:
+   virtualenv = <virtual_env> #}
\ No newline at end of file
index baa964f..9df67d9 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
+- name: make sure trex_dest exists
+  file:
+    path: "{{ trex_dest }}"
+    state: directory
+
 - name: fetch Trex
   get_url:
     url: "{{ trex_url }}"
diff --git a/ansible/roles/install_dependencies_jumphost/tasks/Debian.yml b/ansible/roles/install_dependencies_jumphost/tasks/Debian.yml
new file mode 100755 (executable)
index 0000000..9baf7e5
--- /dev/null
@@ -0,0 +1,76 @@
+# Copyright (c) 2017 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.
+---
+- name: Update repositories
+  apt:
+    update_cache: yes
+
+- name: Install core packages
+  action: "{{ ansible_pkg_mgr }} name={{ item }} state=present"
+  with_items:
+    - wget
+    - curl
+    - screen
+    - procps
+    - socat
+    - sshpass
+    - sudo
+    - vim
+    - libffi-dev
+    - libfuse-dev
+    - libssl-dev
+    - libxft-dev
+    - libxml2-dev
+    - libxss-dev
+    - libxslt-dev
+    - libxslt1-dev
+    - libzmq-dev
+    - qemu-user-static
+    - qemu-utils
+    - kpartx
+    - python
+    - python-setuptools
+    - python-dev
+    - python-pip
+    - python-libvirt
+    - python-virtualenv
+    - bridge-utils
+    - ebtables
+    - openssl
+    - ccze
+    - nginx-full
+    - uwsgi
+    - uwsgi-plugin-python
+    - supervisor
+    - lsof
+    - nodejs
+    - npm
+    - rabbitmq-server
+
+- name: Install libc6:arm64 package
+  action: "{{ ansible_pkg_mgr }} name={{ item }} state=present"
+  with_items:
+    - libc6:arm64
+  when:
+    - arch is defined
+    - arch != arch_arm64
+    - installation_mode == inst_mode_container
+
+- name: Remove dependencies that are no longer required
+  apt:
+    update_cache: yes
+
+- name: Remove useless packages from the cache
+  apt:
+    autoclean: yes
     - python-setuptools
     - libffi-devel
     - python-devel
-    - kpartx
-
+    - nodejs
+    - npm
+    - gcc
+    - lsof
+    - procps
+    - bridge-utils
+    - ebtables
+    - openssl
+    - python-virtualenv
+    - ccze
old mode 100755 (executable)
new mode 100644 (file)
similarity index 70%
rename from ansible/roles/install_dependencies/tasks/Debian.yml
rename to ansible/roles/install_dependencies_jumphost/tasks/Suse.yml
index bba6fb1..af53c9c
@@ -1,4 +1,4 @@
-# Copyright (c) 2017 Intel Corporation.
+# 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.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 ---
+- name: Install EPEL if needed
+  action: "{{ ansible_pkg_mgr }} name=epel-release state=present"
+  when: ansible_distribution in ['RedHat', 'CentOS', 'ScientificLinux']
+
 - name: Install core packages
   action: "{{ ansible_pkg_mgr }} name={{ item }} state=present"
   with_items:
-    - python-minimal
+    - deltarpm
     - wget
+    - expect
     - curl
     - screen
-    - procps
     - git
     - socat
     - sshpass
-    - libxslt1-dev
-    - libffi-dev
-    - libfuse-dev
     - qemu-kvm
-    - qemu-user-static
-    - qemu-utils
     - kpartx
-    - libvirt0
-    - python-libvirt
+    - libxslt-devel
+    - libffi-devel
+    - openssl-devel
+    - nginx
+    - uwsgi
+    - python-setuptools
+    - libffi-devel
+    - python-devel
+    - nodejs
+    - npm
+    - gcc
+    - lsof
+    - procps
     - bridge-utils
     - ebtables
     - openssl
-    - libssl-dev
-    - python-dev
     - python-virtualenv
     - ccze
-    - libxml2-dev
-    - libxslt-dev
-    - libzmq-dev
-    - nginx-full
-    - uwsgi
-    - uwsgi-plugin-python
-    - supervisor
-    - python-setuptools
-    - lsof
diff --git a/ansible/roles/install_yardstick/tasks/main.yml b/ansible/roles/install_yardstick/tasks/main.yml
new file mode 100644 (file)
index 0000000..ee1b837
--- /dev/null
@@ -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.
+---
+# Arguments needed: map_min_addr_file, yardstick_dir
+
+- name: Define variables
+  set_fact:
+    map_min_addr_file: "/etc/sysctl.d/mmap_min_addr.conf"
+
+- name: Remove the kernel minimum virtual address restriction that a process is allowed to mmap
+  copy:
+    dest: "{{ map_min_addr_file }}"
+    content: "vm.mmap_min_addr = 0\n"
+
+- name: Config git SSL
+  git_config:
+    name: http.sslVerify
+    scope: global
+    value: False
+
+# There is a bug with the easy install ansible module in suse linux.
+# Until this is fixed the shell command must be used
+- name: Install pip
+  shell: easy_install -U pip
+#    easy_install:
+#    name: pip
+#    state: latest
+
+- name: install yardstick without virtual environment
+  include_tasks: regular_install.yml
+  when: virtual_environment == False
+
+- name: install yardstick with virtual environment
+  include_tasks: virtual_install.yml
+  when: virtual_environment == True
diff --git a/ansible/roles/install_yardstick/tasks/regular_install.yml b/ansible/roles/install_yardstick/tasks/regular_install.yml
new file mode 100644 (file)
index 0000000..cd0e86f
--- /dev/null
@@ -0,0 +1,23 @@
+# 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.
+---
+- name: Install Yardstick requirements
+  pip:
+    requirements: "{{ yardstick_dir }}/requirements.txt"
+
+- name: Install Yardstick code
+  pip:
+    name: "."
+    extra_args: -e
+    chdir: "{{ yardstick_dir }}/"
diff --git a/ansible/roles/install_yardstick/tasks/virtual_install.yml b/ansible/roles/install_yardstick/tasks/virtual_install.yml
new file mode 100644 (file)
index 0000000..8545acb
--- /dev/null
@@ -0,0 +1,25 @@
+# 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.
+---
+- name: Install Yardstick requirements
+  pip:
+    requirements: "{{ yardstick_dir }}/requirements.txt"
+    virtualenv: "{{ yardstick_dir }}/virtualenv"
+
+- name: Install Yardstick code
+  pip:
+    name: "{{ yardstick_dir }}/."
+    extra_args: -e
+    virtualenv: "{{ yardstick_dir }}/virtualenv"
+
diff --git a/ansible/yardstick-install-inventory.ini b/ansible/yardstick-install-inventory.ini
deleted file mode 100644 (file)
index e276076..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# the group of systems on which to install yardstick
-# by default just localhost
-[jumphost]
-localhost  ansible_connection=local
-
-# section below is only due backward compatibility.
-# it will be removed later
-[yardstick:children]
-jumphost
-
-[yardstick-standalone]
-# uncomment hosts below if you would to test yardstick-standalone/sriov scenarios
-#yardstick-standalone-node ansible_host=192.168.1.2
-#yardstick-standalone-node-2 ansible_host=192.168.1.2
-
-[all:vars]
-# incomment credentials below for yardstick-standalone
-#ansible_user=root
-#ansible_pass=root
-
index 95ec185..2467329 100644 (file)
@@ -20,32 +20,35 @@ ENV REPOS_DIR="/home/opnfv/repos" \
 # Set work directory
 
 # Yardstick repo
-ENV YARDSTICK_REPO_DIR="${REPOS_DIR}/yardstick" \
+ENV YARDSTICK_REPO_DIR="${REPOS_DIR}/yardstick/" \
+    RELENG_REPO_DIR="${REPOS_DIR}/releng" \
     STORPERF_REPO_DIR="${REPOS_DIR}/storperf"
 
 RUN apt-get update && apt-get install -y git 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 python-openstackclient==3.11.0 python-heatclient==1.11.0
+RUN pip install appdirs==1.4.0 pyopenssl==17.5.0 python-openstackclient==3.11.0 python-heatclient==1.11.0 ansible==2.4.2
 
 RUN mkdir -p ${REPOS_DIR}
 
 RUN git config --global http.sslVerify false
-RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${YARDSTICK_REPO_DIR}
+##RUN git clone --depth 1 -b $BRANCH https://gerrit.opnfv.org/gerrit/yardstick ${YARDSTICK_REPO_DIR}
+RUN mkdir ${YARDSTICK_REPO_DIR}
+COPY ./ ${YARDSTICK_REPO_DIR}
+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}
 
-WORKDIR ${YARDSTICK_REPO_DIR}
-RUN ${YARDSTICK_REPO_DIR}/install.sh
+RUN ansible-playbook -vvv -e INSTALLATION_MODE="container" ${YARDSTICK_REPO_DIR}/ansible/install.yaml
+
 RUN ${YARDSTICK_REPO_DIR}/docker/supervisor.sh
 
 RUN echo "daemon off;" >> /etc/nginx/nginx.conf
-
 # nginx=5000, rabbitmq=5672
 EXPOSE 5000 5672
 
 ADD http://download.cirros-cloud.net/0.3.5/cirros-0.3.5-x86_64-disk.img ${IMAGE_DIR}
 ADD http://cloud-images.ubuntu.com/xenial/current/xenial-server-cloudimg-amd64-disk1.img ${IMAGE_DIR}
 
-COPY ./exec_tests.sh /usr/local/bin/
+COPY ./docker/exec_tests.sh /usr/local/bin/
 
 ENV NSB_DIR="/opt/nsb_bin"
 ENV PYTHONPATH="${PYTHONPATH}:${NSB_DIR}/trex_client:${NSB_DIR}/trex_client/stl"
index 04985f4..7492934 100755 (executable)
@@ -119,4 +119,4 @@ tar xvf ${NSB_DIR}/trex_client.tar.gz -C ${NSB_DIR}
 rm -f ${NSB_DIR}/trex_client.tar.gz
 
 service nginx restart
-uwsgi -i /etc/yardstick/yardstick.ini
+uwsgi -i /etc/yardstick/yardstick.ini
\ No newline at end of file
index 50fc017..d68263a 100755 (executable)
@@ -71,4 +71,4 @@ cd ${ANSIBLE_SCRIPTS} &&\
 ansible-playbook \
          -e img_property="nsb" \
          -e YARD_IMG_ARCH='amd64' ${extra_args}\
-         -i yardstick-install-inventory.ini nsb_setup.yml
+         -i install-inventory.ini nsb_setup.yml
index 0640d2c..3d8907b 100644 (file)
@@ -7,9 +7,6 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from __future__ import absolute_import
-from __future__ import print_function
-
 import collections
 import logging
 import os
index 4f7ef60..4d7c4f9 100644 (file)
@@ -136,7 +136,7 @@ class NetworkServiceTestCase(scenario_base.Scenario):
     def _get_duration(self):
         options = self.scenario_cfg.get('options', {})
         return options.get('duration',
-                           tprofile_base.TrafficProfile.DEFAULT_DURATION)
+                           tprofile_base.TrafficProfileConfig.DEFAULT_DURATION)
 
     def _fill_traffic_profile(self):
         tprofile = self._get_traffic_profile()
index 869db46..f9fe0e3 100644 (file)
@@ -422,13 +422,18 @@ class ErrorClass(object):
 
 
 class Timer(object):
-    def __init__(self, timeout=None):
+    def __init__(self, timeout=None, raise_exception=True):
         super(Timer, self).__init__()
         self.start = self.delta = None
         self._timeout = int(timeout) if timeout else None
+        self._timeout_flag = False
+        self._raise_exception = raise_exception
 
     def _timeout_handler(self, *args):
-        raise exceptions.TimerTimeout(timeout=self._timeout)
+        self._timeout_flag = True
+        if self._raise_exception:
+            raise exceptions.TimerTimeout(timeout=self._timeout)
+        self.__exit__()
 
     def __enter__(self):
         self.start = datetime.datetime.now()
@@ -445,6 +450,23 @@ class Timer(object):
     def __getattr__(self, item):
         return getattr(self.delta, item)
 
+    def __iter__(self):
+        self._raise_exception = False
+        return self.__enter__()
+
+    def next(self):  # pragma: no cover
+        # NOTE(ralonsoh): Python 2 support.
+        if not self._timeout_flag:
+            return datetime.datetime.now()
+        raise StopIteration()
+
+    def __next__(self):  # pragma: no cover
+        # NOTE(ralonsoh): Python 3 support.
+        return self.next()
+
+    def __del__(self):  # pragma: no cover
+        signal.alarm(0)
+
 
 def read_meminfo(ssh_client):
     """Read "/proc/meminfo" file and parse all keys and values"""
index 4c3b297..f4b5b17 100644 (file)
@@ -21,16 +21,21 @@ class TrafficProfileConfig(object):
 
     This object will parse and validate the traffic profile information.
     """
+
+    DEFAULT_SCHEMA = 'nsb:traffic_profile:0.1'
+    DEFAULT_FRAME_RATE = 100
+    DEFAULT_DURATION = 30
+
     def __init__(self, tp_config):
-        self.schema = tp_config.get('schema', 'nsb:traffic_profile:0.1')
+        self.schema = tp_config.get('schema', self.DEFAULT_SCHEMA)
         self.name = tp_config.get('name')
         self.description = tp_config.get('description')
         tprofile = tp_config['traffic_profile']
         self.traffic_type = tprofile.get('traffic_type')
-        self.frame_rate = tprofile.get('frame_rate')
+        self.frame_rate = tprofile.get('frame_rate', self.DEFAULT_FRAME_RATE)
         self.test_precision = tprofile.get('test_precision')
         self.packet_sizes = tprofile.get('packet_sizes')
-        self.duration = tprofile.get('duration')
+        self.duration = tprofile.get('duration', self.DEFAULT_DURATION)
         self.lower_bound = tprofile.get('lower_bound')
         self.upper_bound = tprofile.get('upper_bound')
         self.step_interval = tprofile.get('step_interval')
@@ -43,7 +48,6 @@ class TrafficProfile(object):
     """
     UPLINK = "uplink"
     DOWNLINK = "downlink"
-    DEFAULT_DURATION = 30
 
     @staticmethod
     def get(tp_config):
index 73806f9..e105c2f 100644 (file)
@@ -95,7 +95,6 @@ class IXIARFC2544Profile(TrexProfile):
                 if not profile_data:
                     continue
                 self.profile_data = profile_data
-                self.get_streams(self.profile_data)
                 self.full_profile.update({vld_id: self.profile_data})
                 for intf in intfs:
                     yield traffic_generator.vnfd_helper.port_num(intf)
index 83020c8..c24e2f6 100644 (file)
 # 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.
-""" RFC2544 Throughput implemenation """
 
-from __future__ import absolute_import
-from __future__ import division
 import logging
 
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
+
+from yardstick.network_services.traffic_profile import trex_traffic_profile
 
-from yardstick.network_services.traffic_profile.trex_traffic_profile \
-    import TrexProfile
 
 LOGGING = logging.getLogger(__name__)
+SRC_PORT = 'sport'
+DST_PORT = 'dport'
+
+
+class PortPgIDMap(object):
+    """Port and pg_id mapping class
+
+    "pg_id" is the identification STL library gives to each stream. In the
+    RFC2544Profile class, the traffic has a STLProfile per port, which contains
+    one or several streams, one per packet size defined in the IMIX test case
+    description.
+
+    Example of port <-> pg_id map:
+        self._port_pg_id_map = {
+            0: [1, 2, 3, 4],
+            1: [5, 6, 7, 8]
+        }
+    """
+
+    def __init__(self):
+        self._pg_id = 0
+        self._last_port = None
+        self._port_pg_id_map = {}
+
+    def add_port(self, port):
+        self._last_port = port
+        self._port_pg_id_map[port] = []
+
+    def get_pg_ids(self, port):
+        return self._port_pg_id_map.get(port)
+
+    def increase_pg_id(self, port=None):
+        port = self._last_port if not port else port
+        if port is None:
+            return
+        pg_id_list = self._port_pg_id_map.get(port)
+        if not pg_id_list:
+            self.add_port(port)
+            pg_id_list = self._port_pg_id_map[port]
+        self._pg_id += 1
+        pg_id_list.append(self._pg_id)
+        return self._pg_id
 
 
-class RFC2544Profile(TrexProfile):
-    """ This class handles rfc2544 implemenation. """
+class RFC2544Profile(trex_traffic_profile.TrexProfile):
+    """TRex RFC2544 traffic profile"""
+
+    TOLERANCE_LIMIT = 0.05
 
     def __init__(self, traffic_generator):
         super(RFC2544Profile, self).__init__(traffic_generator)
         self.generator = None
-        self.max_rate = None
-        self.min_rate = None
-        self.ports = None
-        self.rate = 100
-        self.drop_percent_at_max_tx = None
-        self.throughput_max = None
+        self.rate = self.config.frame_rate
+        self.max_rate = self.config.frame_rate
+        self.min_rate = 0
+        self.drop_percent_max = 0
 
     def register_generator(self, generator):
         self.generator = generator
 
-    def execute_traffic(self, traffic_generator=None):
-        """ Generate the stream and run traffic on the given ports """
+    def stop_traffic(self, traffic_generator=None):
+        """"Stop traffic injection, reset counters and remove streams"""
         if traffic_generator is not None and self.generator is None:
             self.generator = traffic_generator
 
-        if self.ports is not None:
-            return
+        self.generator.client.stop()
+        self.generator.client.reset()
+        self.generator.client.remove_all_streams()
+
+    def execute_traffic(self, traffic_generator=None):
+        """Generate the stream and run traffic on the given ports
+
+        :param traffic_generator: (TrexTrafficGenRFC) traffic generator
+        :return ports: (list of int) indexes of ports
+                port_pg_id: (dict) port indexes and pg_id [1] map
+        [1] https://trex-tgn.cisco.com/trex/doc/cp_stl_docs/api/
+            profile_code.html#stlstream-modes
+        """
+        if traffic_generator is not None and self.generator is None:
+            self.generator = traffic_generator
 
-        self.ports = []
+        port_pg_id = PortPgIDMap()
+        ports = []
         for vld_id, intfs in sorted(self.generator.networks.items()):
             profile_data = self.params.get(vld_id)
-            # no profile for this port
             if not profile_data:
                 continue
-            # correlated traffic doesn't use public traffic?
-            if vld_id.startswith(self.DOWNLINK) and \
-                self.generator.rfc2544_helper.correlated_traffic:
+            if (vld_id.startswith(self.DOWNLINK) and
+                    self.generator.rfc2544_helper.correlated_traffic):
                 continue
             for intf in intfs:
-                port = self.generator.port_num(intf)
-                self.ports.append(port)
-                self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
-        self.max_rate = self.rate
-        self.min_rate = 0
-        self.generator.client.start(ports=self.ports, mult=self.get_multiplier(),
-                                    duration=30, force=True)
-        self.drop_percent_at_max_tx = 0
-        self.throughput_max = 0
-
-    def get_multiplier(self):
-        """ Get the rate at which next iteration to run """
-        self.rate = round((self.max_rate + self.min_rate) / 2.0, 2)
-        multiplier = round(self.rate / self.pps, 2)
-        return str(multiplier)
-
-    def get_drop_percentage(self, generator=None):
-        """ Calculate the drop percentage and run the traffic """
-        if generator is None:
-            generator = self.generator
-        run_duration = self.generator.RUN_DURATION
-        samples = self.generator.generate_samples(self.ports)
-
-        in_packets = sum([value['in_packets'] for value in samples.values()])
-        out_packets = sum([value['out_packets'] for value in samples.values()])
-
-        packet_drop = abs(out_packets - in_packets)
-        drop_percent = 100.0
-        try:
-            drop_percent = round((packet_drop / float(out_packets)) * 100, 5)
-        except ZeroDivisionError:
-            LOGGING.info('No traffic is flowing')
+                port_num = int(self.generator.port_num(intf))
+                ports.append(port_num)
+                port_pg_id.add_port(port_num)
+                profile = self._create_profile(profile_data,
+                                               self.rate, port_pg_id)
+                self.generator.client.add_streams(profile, ports=[port_num])
+
+        self.generator.client.start(ports=ports,
+                                    duration=self.config.duration,
+                                    force=True)
+        return ports, port_pg_id
+
+    def _create_profile(self, profile_data, rate, port_pg_id):
+        """Create a STL profile (list of streams) for a port"""
+        streams = []
+        for packet_name in profile_data:
+            imix = (profile_data[packet_name].
+                    get('outer_l2', {}).get('framesize'))
+            imix_data = self._create_imix_data(imix)
+            self._create_vm(profile_data[packet_name])
+            _streams = self._create_streams(imix_data, rate, port_pg_id)
+            streams.extend(_streams)
+        return trex_stl_streams.STLProfile(streams)
+
+    def _create_imix_data(self, imix):
+        """Generate the IMIX distribution for a STL profile
+
+        The input information is the framesize dictionary in a test case
+        traffic profile definition. E.g.:
+          downlink_0:
+            ipv4:
+              id: 2
+                outer_l2:
+                  framesize:
+                    64B: 10
+                    128B: 20
+                    ...
+
+        This function normalizes the sum of framesize weights to 100 and
+        returns a dictionary of frame sizes in bytes and weight in percentage.
+        E.g.:
+          imix_count = {64: 25, 128: 75}
+
+        :param imix: (dict) IMIX size and weight
+        """
+        imix_count = {}
+        if not imix:
+            return imix_count
+
+        imix_count = {size.upper().replace('B', ''): int(weight)
+                      for size, weight in imix.items()}
+        imix_sum = sum(imix_count.values())
+        if imix_sum <= 0:
+            imix_count = {64: 100}
+            imix_sum = 100
+
+        weight_normalize = float(imix_sum) / 100
+        return {size: float(weight) / weight_normalize
+                for size, weight in imix_count.items()}
+
+    def _create_vm(self, packet_definition):
+        """Create the STL Raw instructions"""
+        self.ether_packet = Pkt.Ether()
+        self.ip_packet = Pkt.IP()
+        self.ip6_packet = None
+        self.udp_packet = Pkt.UDP()
+        self.udp[DST_PORT] = 'UDP.dport'
+        self.udp[SRC_PORT] = 'UDP.sport'
+        self.qinq = False
+        self.vm_flow_vars = []
+        outer_l2 = packet_definition.get('outer_l2')
+        outer_l3v4 = packet_definition.get('outer_l3v4')
+        outer_l3v6 = packet_definition.get('outer_l3v6')
+        outer_l4 = packet_definition.get('outer_l4')
+        if outer_l2:
+            self._set_outer_l2_fields(outer_l2)
+        if outer_l3v4:
+            self._set_outer_l3v4_fields(outer_l3v4)
+        if outer_l3v6:
+            self._set_outer_l3v6_fields(outer_l3v6)
+        if outer_l4:
+            self._set_outer_l4_fields(outer_l4)
+        self.trex_vm = trex_stl_packet_builder_scapy.STLScVmRaw(
+            self.vm_flow_vars)
+
+    def _create_single_packet(self, size=64):
+        size -= 4
+        ether_packet = self.ether_packet
+        ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
+        udp_packet = self.udp_packet
+        if self.qinq:
+            qinq_packet = self.qinq_packet
+            base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
+        else:
+            base_pkt = ether_packet / ip_packet / udp_packet
+        pad = max(0, size - len(base_pkt)) * 'x'
+        return trex_stl_packet_builder_scapy.STLPktBuilder(
+            pkt=base_pkt / pad, vm=self.trex_vm)
+
+    def _create_streams(self, imix_data, rate, port_pg_id):
+        """Create a list of streams per packet size
+
+        The STL TX mode speed of the generated streams will depend on the frame
+        weight and the frame rate. Both the frame weight and the total frame
+        rate are normalized to 100. The STL TX mode speed, defined in
+        percentage, is the combitation of both percentages. E.g.:
+          frame weight = 100
+          rate = 90
+            --> STLTXmode percentage = 10 (%)
+
+          frame weight = 80
+          rate = 50
+            --> STLTXmode percentage = 40 (%)
+
+        :param imix_data: (dict) IMIX size and weight
+        :param rate: (float) normalized [0..100] total weight
+        :param pg_id: (PortPgIDMap) port / pg_id (list) map
+        """
+        streams = []
+        for size, weight in ((int(size), float(weight)) for (size, weight)
+                             in imix_data.items() if float(weight) > 0):
+            packet = self._create_single_packet(size)
+            pg_id = port_pg_id.increase_pg_id()
+            stl_flow = trex_stl_streams.STLFlowLatencyStats(pg_id=pg_id)
+            mode = trex_stl_streams.STLTXCont(percentage=weight * rate / 100)
+            streams.append(trex_stl_client.STLStream(
+                packet=packet, flow_stats=stl_flow, mode=mode))
+        return streams
+
+    def get_drop_percentage(self, samples, tol_low, tol_high,
+                            correlated_traffic):
+        """Calculate the drop percentage and run the traffic"""
+        tx_rate_fps = 0
+        rx_rate_fps = 0
+        for sample in samples:
+            tx_rate_fps += sum(
+                port['tx_throughput_fps'] for port in sample.values())
+            rx_rate_fps += sum(
+                port['rx_throughput_fps'] for port in sample.values())
+        tx_rate_fps = round(float(tx_rate_fps) / len(samples), 2)
+        rx_rate_fps = round(float(rx_rate_fps) / len(samples), 2)
 
         # TODO(esm): RFC2544 doesn't tolerate packet loss, why do we?
-        tolerance_low = generator.rfc2544_helper.tolerance_low
-        tolerance_high = generator.rfc2544_helper.tolerance_high
-
-        tx_rate = out_packets / run_duration
-        rx_rate = in_packets / run_duration
-
-        throughput_max = self.throughput_max
-        drop_percent_at_max_tx = self.drop_percent_at_max_tx
+        out_packets = sum(port['out_packets'] for port in samples[-1].values())
+        in_packets = sum(port['in_packets'] for port in samples[-1].values())
+        drop_percent = 100.0
 
-        if self.drop_percent_at_max_tx is None:
-            self.rate = tx_rate
-            self.first_run = False
+        # https://tools.ietf.org/html/rfc2544#section-26.3
+        if out_packets:
+            drop_percent = round(
+                (float(abs(out_packets - in_packets)) / out_packets) * 100, 5)
 
-        if drop_percent > tolerance_high:
-            # TODO(esm): why don't we discard results that are out of tolerance?
+        tol_high = tol_high if tol_high > self.TOLERANCE_LIMIT else tol_high
+        tol_low = tol_low if tol_low > self.TOLERANCE_LIMIT else tol_low
+        if drop_percent > tol_high:
             self.max_rate = self.rate
-            if throughput_max == 0:
-                throughput_max = rx_rate
-                drop_percent_at_max_tx = drop_percent
-
-        elif drop_percent >= tolerance_low:
-            # TODO(esm): why do we update the samples dict in this case
-            #            and not update our tracking values?
-            throughput_max = rx_rate
-            drop_percent_at_max_tx = drop_percent
-
-        elif drop_percent >= self.drop_percent_at_max_tx:
-            # TODO(esm): why don't we discard results that are out of tolerance?
+        elif drop_percent < tol_low:
             self.min_rate = self.rate
-            self.drop_percent_at_max_tx = drop_percent_at_max_tx = drop_percent
-            self.throughput_max = throughput_max = rx_rate
+        # else:
+            # NOTE(ralonsoh): the test should finish here
+            # pass
+        last_rate = self.rate
+        self.rate = round(float(self.max_rate + self.min_rate) / 2.0, 5)
 
-        else:
-            # TODO(esm): why don't we discard results that are out of tolerance?
-            self.min_rate = self.rate
+        throughput = rx_rate_fps * 2 if correlated_traffic else rx_rate_fps
 
-        generator.clear_client_stats(self.ports)
-        generator.start_client(self.ports, mult=self.get_multiplier(),
-                               duration=run_duration, force=True)
+        if drop_percent > self.drop_percent_max:
+            self.drop_percent_max = drop_percent
 
-        # if correlated traffic update the Throughput
-        if generator.rfc2544_helper.correlated_traffic:
-            throughput_max *= 2
+        latency = {port_num: value['latency']
+                   for port_num, value in samples[-1].items()}
 
-        samples.update({
-            'TxThroughput': tx_rate,
-            'RxThroughput': rx_rate,
+        output = {
+            'TxThroughput': tx_rate_fps,
+            'RxThroughput': rx_rate_fps,
             'CurrentDropPercentage': drop_percent,
-            'Throughput': throughput_max,
-            'DropPercentage': drop_percent_at_max_tx,
-        })
-
-        return samples
-
-    def execute_latency(self, generator=None, samples=None):
-        if generator is not None and self.generator is None:
-            self.generator = generator
-
-        if samples is None:
-            samples = self.generator.generate_samples()
-
-        self.pps, multiplier = self.calculate_pps(samples)
-        self.ports = []
-        self.pg_id = self.params['traffic_profile'].get('pg_id', 1)
-        for vld_id, intfs in sorted(self.generator.networks.items()):
-            profile_data = self.params.get(vld_id)
-            if not profile_data:
-                continue
-            # correlated traffic doesn't use public traffic?
-            if vld_id.startswith(self.DOWNLINK) and \
-                self.generator.rfc2544_helper.correlated_traffic:
-                continue
-            for intf in intfs:
-                port = self.generator.port_num(intf)
-                self.ports.append(port)
-                self.generator.client.add_streams(self.get_streams(profile_data), ports=port)
-
-        self.generator.start_client(ports=self.ports, mult=str(multiplier),
-                                    duration=120, force=True)
-        self.first_run = False
-
-    def calculate_pps(self, samples):
-        pps = round(samples['Throughput'] / 2, 2)
-        multiplier = round(self.rate / self.pps, 2)
-        return pps, multiplier
-
-    def create_single_stream(self, packet_size, pps, isg=0):
-        packet = self._create_single_packet(packet_size)
-        if pps:
-            stl_mode = STLTXCont(pps=pps)
-        else:
-            stl_mode = STLTXCont(pps=self.pps)
-        if self.pg_id:
-            LOGGING.debug("pg_id: %s", self.pg_id)
-            stl_flow_stats = STLFlowLatencyStats(pg_id=self.pg_id)
-            stream = STLStream(isg=isg, packet=packet, mode=stl_mode,
-                               flow_stats=stl_flow_stats)
-            self.pg_id += 1
-        else:
-            stream = STLStream(isg=isg, packet=packet, mode=stl_mode)
-        return stream
+            'Throughput': throughput,
+            'DropPercentage': self.drop_percent_max,
+            'Rate': last_rate,
+            'Latency': latency
+        }
+        return output
index f5e3923..ed0355f 100644 (file)
@@ -19,21 +19,16 @@ from random import SystemRandom
 import ipaddress
 
 import six
-
-from yardstick.common import exceptions as y_exc
-from yardstick.network_services.traffic_profile import base
-from trex_stl_lib.trex_stl_client import STLStream
-from trex_stl_lib.trex_stl_streams import STLFlowLatencyStats
-from trex_stl_lib.trex_stl_streams import STLTXCont
-from trex_stl_lib.trex_stl_streams import STLProfile
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmWrFlowVar
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVarRepeatableRandom
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFlowVar
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLPktBuilder
-from trex_stl_lib.trex_stl_packet_builder_scapy import STLScVmRaw
 from trex_stl_lib.trex_stl_packet_builder_scapy import STLVmFixIpv4
 from trex_stl_lib import api as Pkt
 
+from yardstick.common import exceptions as y_exc
+from yardstick.network_services.traffic_profile import base
+
+
 SRC = 'src'
 DST = 'dst'
 ETHERNET = 'Ethernet'
@@ -342,115 +337,6 @@ class TrexProfile(base.TrafficProfile):
         if 'dstport' in outer_l4:
             self._set_proto_addr(UDP, DST_PORT, outer_l4['dstport'], outer_l4['count'])
 
-    def generate_imix_data(self, packet_definition):
-        """ generate packet size for a given traffic profile """
-        imix_count = {}
-        imix_data = {}
-        if not packet_definition:
-            return imix_count
-        imix = packet_definition.get('framesize')
-        if imix:
-            for size in imix:
-                data = imix[size]
-                imix_data[int(size[:-1])] = int(data)
-            imix_sum = sum(imix_data.values())
-            if imix_sum > 100:
-                raise SystemExit("Error in IMIX data")
-            elif imix_sum < 100:
-                imix_data[64] = imix_data.get(64, 0) + (100 - imix_sum)
-
-            avg_size = 0.0
-            for size in imix_data:
-                count = int(imix_data[size])
-                if count:
-                    avg_size += round(size * count / 100, 2)
-                    pps = round(self.pps * count / 100, 0)
-                    imix_count[size] = pps
-            self.rate = round(1342177280 / avg_size, 0) * 2
-            logging.debug("Imax: %s rate: %s", imix_count, self.rate)
-        return imix_count
-
-    def get_streams(self, profile_data):
-        """ generate trex stream
-        :param profile_data:
-        :type profile_data:
-        """
-        self.streams = []
-        self.pps = self.params['traffic_profile'].get('frame_rate', 100)
-        for packet_name in profile_data:
-            outer_l2 = profile_data[packet_name].get('outer_l2')
-            imix_data = self.generate_imix_data(outer_l2)
-            if not imix_data:
-                imix_data = {64: self.pps}
-            self.generate_vm(profile_data[packet_name])
-            for size in imix_data:
-                self._generate_streams(size, imix_data[size])
-        self._generate_profile()
-        return self.profile
-
-    def generate_vm(self, packet_definition):
-        """ generate  trex vm with flows setup """
-        self.ether_packet = Pkt.Ether()
-        self.ip_packet = Pkt.IP()
-        self.ip6_packet = None
-        self.udp_packet = Pkt.UDP()
-        self.udp[DST_PORT] = 'UDP.dport'
-        self.udp[SRC_PORT] = 'UDP.sport'
-        self.qinq = False
-        self.vm_flow_vars = []
-        outer_l2 = packet_definition.get('outer_l2', None)
-        outer_l3v4 = packet_definition.get('outer_l3v4', None)
-        outer_l3v6 = packet_definition.get('outer_l3v6', None)
-        outer_l4 = packet_definition.get('outer_l4', None)
-        if outer_l2:
-            self._set_outer_l2_fields(outer_l2)
-        if outer_l3v4:
-            self._set_outer_l3v4_fields(outer_l3v4)
-        if outer_l3v6:
-            self._set_outer_l3v6_fields(outer_l3v6)
-        if outer_l4:
-            self._set_outer_l4_fields(outer_l4)
-        self.trex_vm = STLScVmRaw(self.vm_flow_vars)
-
-    def generate_packets(self):
-        """ generate packets from trex TG """
-        base_pkt = self.base_pkt
-        size = self.fsize - 4
-        pad = max(0, size - len(base_pkt)) * 'x'
-        self.packets = [STLPktBuilder(pkt=base_pkt / pad,
-                                      vm=vm) for vm in self.vms]
-
-    def _create_single_packet(self, size=64):
-        size = size - 4
-        ether_packet = self.ether_packet
-        ip_packet = self.ip6_packet if self.ip6_packet else self.ip_packet
-        udp_packet = self.udp_packet
-        if self.qinq:
-            qinq_packet = self.qinq_packet
-            base_pkt = ether_packet / qinq_packet / ip_packet / udp_packet
-        else:
-            base_pkt = ether_packet / ip_packet / udp_packet
-        pad = max(0, size - len(base_pkt)) * 'x'
-        packet = STLPktBuilder(pkt=base_pkt / pad, vm=self.trex_vm)
-        return packet
-
-    def _create_single_stream(self, packet_size, pps, isg=0):
-        packet = self._create_single_packet(packet_size)
-        if self.pg_id:
-            self.pg_id += 1
-            stl_flow = STLFlowLatencyStats(pg_id=self.pg_id)
-            stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps),
-                               flow_stats=stl_flow)
-        else:
-            stream = STLStream(isg=isg, packet=packet, mode=STLTXCont(pps=pps))
-        return stream
-
-    def _generate_streams(self, packet_size, pps):
-        self.streams.append(self._create_single_stream(packet_size, pps))
-
-    def _generate_profile(self):
-        self.profile = STLProfile(self.streams)
-
     @classmethod
     def _count_ip(cls, start_ip, end_ip):
         start = ipaddress.ip_address(six.u(start_ip))
index 0292729..9ff2e7d 100644 (file)
 # 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.
-""" Base class implementation for generic vnf implementation """
 
-from collections import Mapping
 import logging
 from multiprocessing import Queue, Value, Process
 
 import os
 import posixpath
 import re
+import six
 import subprocess
 import time
 
-import six
-
 from trex_stl_lib.trex_stl_client import LoggerApi
 from trex_stl_lib.trex_stl_client import STLClient
 from trex_stl_lib.trex_stl_exceptions import STLError
@@ -388,39 +385,14 @@ class ClientResourceHelper(ResourceHelper):
             LOG.error('TRex client not connected')
             return {}
 
-    def generate_samples(self, ports, key=None, default=None):
-        # needs to be used ports
-        last_result = self.get_stats(ports)
-        key_value = last_result.get(key, default)
-
-        if not isinstance(last_result, Mapping):  # added for mock unit test
-            self._terminated.value = 1
-            return {}
-
-        samples = {}
-        # recalculate port for interface and see if it matches ports provided
-        for intf in self.vnfd_helper.interfaces:
-            name = intf["name"]
-            port = self.vnfd_helper.port_num(name)
-            if port in ports:
-                xe_value = last_result.get(port, {})
-                samples[name] = {
-                    "rx_throughput_fps": float(xe_value.get("rx_pps", 0.0)),
-                    "tx_throughput_fps": float(xe_value.get("tx_pps", 0.0)),
-                    "rx_throughput_mbps": float(xe_value.get("rx_bps", 0.0)),
-                    "tx_throughput_mbps": float(xe_value.get("tx_bps", 0.0)),
-                    "in_packets": int(xe_value.get("ipackets", 0)),
-                    "out_packets": int(xe_value.get("opackets", 0)),
-                }
-                if key:
-                    samples[name][key] = key_value
-        return samples
+    def _get_samples(self, ports, port_pg_id=False):
+        raise NotImplementedError()
 
     def _run_traffic_once(self, traffic_profile):
         traffic_profile.execute_traffic(self)
         self.client_started.value = 1
         time.sleep(self.RUN_DURATION)
-        samples = self.generate_samples(traffic_profile.ports)
+        samples = self._get_samples(traffic_profile.ports)
         time.sleep(self.QUEUE_WAIT_TIME)
         self._queue.put(samples)
 
index 4e9f4bd..07cec67 100644 (file)
 # 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.
-""" Trex traffic generation definitions which implements rfc2544 """
 
-from __future__ import absolute_import
-from __future__ import print_function
-import time
 import logging
-from collections import Mapping
-
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexTrafficGen
-from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
-from yardstick.network_services.vnf_generic.vnf.tg_trex import TrexResourceHelper
-
-LOGGING = logging.getLogger(__name__)
+import time
 
+from yardstick.common import utils
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
 
-class TrexRfc2544ResourceHelper(Rfc2544ResourceHelper):
 
-    def is_done(self):
-        return self.latency and self.iteration.value > 10
+LOGGING = logging.getLogger(__name__)
 
 
-class TrexRfcResourceHelper(TrexResourceHelper):
+class TrexRfcResourceHelper(tg_trex.TrexResourceHelper):
 
-    LATENCY_TIME_SLEEP = 120
-    RUN_DURATION = 30
-    WAIT_TIME = 3
+    SAMPLING_PERIOD = 2
+    TRANSIENT_PERIOD = 10
 
-    def __init__(self, setup_helper, rfc_helper_type=None):
+    def __init__(self, setup_helper):
         super(TrexRfcResourceHelper, self).__init__(setup_helper)
-
-        if rfc_helper_type is None:
-            rfc_helper_type = TrexRfc2544ResourceHelper
-
-        self.rfc2544_helper = rfc_helper_type(self.scenario_helper)
+        self.rfc2544_helper = sample_vnf.Rfc2544ResourceHelper(
+            self.scenario_helper)
 
     def _run_traffic_once(self, traffic_profile):
-        if self._terminated.value:
-            return
-
-        traffic_profile.execute_traffic(self)
         self.client_started.value = 1
-        time.sleep(self.RUN_DURATION)
-        self.client.stop(traffic_profile.ports)
-        time.sleep(self.WAIT_TIME)
-        samples = traffic_profile.get_drop_percentage(self)
-        self._queue.put(samples)
-
-        if not self.rfc2544_helper.is_done():
-            return
-
-        self.client.stop(traffic_profile.ports)
-        self.client.reset(ports=traffic_profile.ports)
-        self.client.remove_all_streams(traffic_profile.ports)
-        traffic_profile.execute_traffic_latency(samples=samples)
-        multiplier = traffic_profile.calculate_pps(samples)[1]
-        for _ in range(5):
-            time.sleep(self.LATENCY_TIME_SLEEP)
-            self.client.stop(traffic_profile.ports)
-            time.sleep(self.WAIT_TIME)
-            last_res = self.client.get_stats(traffic_profile.ports)
-            if not isinstance(last_res, Mapping):
-                self._terminated.value = 1
-                continue
-            self.generate_samples(traffic_profile.ports, 'latency', {})
-            self._queue.put(samples)
-            self.client.start(mult=str(multiplier),
-                              ports=traffic_profile.ports,
-                              duration=120, force=True)
+        ports, port_pg_id = traffic_profile.execute_traffic(self)
+
+        samples = []
+        timeout = int(traffic_profile.config.duration) - self.TRANSIENT_PERIOD
+        time.sleep(self.TRANSIENT_PERIOD)
+        for _ in utils.Timer(timeout=timeout):
+            samples.append(self._get_samples(ports, port_pg_id=port_pg_id))
+            time.sleep(self.SAMPLING_PERIOD)
+
+        traffic_profile.stop_traffic(self)
+        output = traffic_profile.get_drop_percentage(
+            samples, self.rfc2544_helper.tolerance_low,
+            self.rfc2544_helper.tolerance_high,
+            self.rfc2544_helper.correlated_traffic)
+        self._queue.put(output)
 
     def start_client(self, ports, mult=None, duration=None, force=True):
         self.client.start(ports=ports, mult=mult, duration=duration, force=force)
@@ -86,12 +57,8 @@ class TrexRfcResourceHelper(TrexResourceHelper):
     def clear_client_stats(self, ports):
         self.client.clear_stats(ports=ports)
 
-    def collect_kpi(self):
-        self.rfc2544_helper.iteration.value += 1
-        return super(TrexRfcResourceHelper, self).collect_kpi()
-
 
-class TrexTrafficGenRFC(TrexTrafficGen):
+class TrexTrafficGenRFC(tg_trex.TrexTrafficGen):
     """
     This class handles mapping traffic profile and generating
     traffic for rfc2544 testcase.
index 0084a12..80b42e2 100644 (file)
@@ -13,7 +13,6 @@
 # limitations under the License.
 """ Trex acts as traffic generation and vnf definitions based on IETS Spec """
 
-from __future__ import absolute_import
 import logging
 import os
 
@@ -25,6 +24,7 @@ from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTraff
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
 
+
 LOG = logging.getLogger(__name__)
 
 
@@ -165,6 +165,30 @@ class TrexResourceHelper(ClientResourceHelper):
         cmd = "sudo fuser -n tcp %s %s -k > /dev/null 2>&1"
         self.ssh_helper.execute(cmd % (self.SYNC_PORT, self.ASYNC_PORT))
 
+    def _get_samples(self, ports, port_pg_id=None):
+        stats = self.get_stats(ports)
+        samples = {}
+        for pname in (intf['name'] for intf in self.vnfd_helper.interfaces):
+            port_num = self.vnfd_helper.port_num(pname)
+            port_stats = stats.get(port_num, {})
+            samples[pname] = {
+                'rx_throughput_fps': float(port_stats.get('rx_pps', 0.0)),
+                'tx_throughput_fps': float(port_stats.get('tx_pps', 0.0)),
+                'rx_throughput_bps': float(port_stats.get('rx_bps', 0.0)),
+                'tx_throughput_bps': float(port_stats.get('tx_bps', 0.0)),
+                'in_packets': int(port_stats.get('ipackets', 0)),
+                'out_packets': int(port_stats.get('opackets', 0)),
+            }
+
+            pg_id_list = port_pg_id.get_pg_ids(port_num)
+            samples[pname]['latency'] = {}
+            for pg_id in pg_id_list:
+                latency_global = stats.get('latency', {})
+                pg_latency = latency_global.get(pg_id, {}).get('latency')
+                samples[pname]['latency'][pg_id] = pg_latency
+
+        return samples
+
 
 class TrexTrafficGen(SampleVNFTrafficGen):
     """
index 3d6fe18..5ed199a 100644 (file)
@@ -422,7 +422,7 @@ class OvsDeployTestCase(unittest.TestCase):
 
     def setUp(self):
         self._mock_ssh = mock.patch.object(ssh, 'SSH')
-        self.mock_ssh = self._mock_ssh .start()
+        self.mock_ssh = self._mock_ssh.start()
         self.ovs_deploy = model.OvsDeploy(self.mock_ssh,
                                           '/tmp/dpdk-devbind.py',
                                           self.OVS_DETAILS)
@@ -493,5 +493,5 @@ class OvsDeployTestCase(unittest.TestCase):
                     'ovs_version': ovs_version,
                     'dpdk_version': dpdk_version,
                     'proxy': 'test_proxy'})
-            mock_execute.assert_called_with(cmd)
-            mock_env_get.assert_called_with('http_proxy', '')
+            mock_execute.assert_called_once_with(cmd)
+            mock_env_get.assert_has_calls([mock.call('http_proxy', '')])
index d05b912..749f731 100644 (file)
@@ -225,7 +225,7 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         self.assertRaises(y_exc.HeatTemplateError,
                           self.test_context.deploy)
 
-        mock_path_exists.assert_called_once()
+        mock_path_exists.assert_called()
         mock_resources_template.assert_called_once()
 
     @mock.patch.object(os.path, 'exists', return_value=False)
@@ -250,7 +250,7 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
              'yardstick/resources/files/yardstick_key-',
              self.test_context._name_task_id])
         mock_genkeys.assert_called_once_with(key_filename)
-        mock_path_exists.assert_called()
+        mock_path_exists.assert_any_call(key_filename)
 
     @mock.patch.object(heat, 'HeatTemplate')
     @mock.patch.object(os.path, 'exists', return_value=False)
@@ -276,7 +276,7 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
              'yardstick/resources/files/yardstick_key-',
              self.test_context._name])
         mock_genkeys.assert_called_once_with(key_filename)
-        mock_path_exists.assert_called_once_with(key_filename)
+        mock_path_exists.assert_any_call(key_filename)
 
     @mock.patch.object(heat, 'HeatTemplate')
     @mock.patch.object(os.path, 'exists', return_value=False)
@@ -292,7 +292,6 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
         self.test_context._flags.no_setup = True
         self.test_context.template_file = '/bar/baz/some-heat-file'
         self.test_context.get_neutron_info = mock.MagicMock()
-
         self.test_context.deploy()
 
         mock_retrieve_stack.assert_called_once_with(self.test_context._name)
@@ -330,7 +329,7 @@ class HeatContextTestCase(ut_base.BaseUnitTestCase):
              'yardstick/resources/files/yardstick_key-',
              self.test_context._name_task_id])
         mock_genkeys.assert_called_once_with(key_filename)
-        mock_path_exists.assert_called_with(key_filename)
+        mock_path_exists.assert_any_call(key_filename)
 
         mock_call_gen_keys = mock.call.gen_keys(key_filename)
         mock_call_add_resources = (
index 5fd91c8..6247afd 100644 (file)
@@ -24,9 +24,10 @@ from yardstick import ssh
 from yardstick.common import constants
 from yardstick.common import utils
 from yardstick.common import exceptions
+from yardstick.tests.unit import base as ut_base
 
 
-class IterSubclassesTestCase(unittest.TestCase):
+class IterSubclassesTestCase(ut_base.BaseUnitTestCase):
     # Disclaimer: this class is a modified copy from
     # rally/tests/unit/common/plugin/test_discover.py
     # Copyright 2015: Mirantis Inc.
@@ -47,7 +48,7 @@ class IterSubclassesTestCase(unittest.TestCase):
         self.assertEqual([B, C, D], list(utils.itersubclasses(A)))
 
 
-class ImportModulesFromPackageTestCase(unittest.TestCase):
+class ImportModulesFromPackageTestCase(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.walk')
     def test_import_modules_from_package_no_mod(self, mock_walk):
@@ -72,7 +73,7 @@ class ImportModulesFromPackageTestCase(unittest.TestCase):
         mock_import_module.assert_called_once_with('bar.baz')
 
 
-class GetParaFromYaml(unittest.TestCase):
+class GetParaFromYaml(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.environ.get')
     def test_get_param_para_not_found(self, get_env):
@@ -96,7 +97,7 @@ class GetParaFromYaml(unittest.TestCase):
         return file_path
 
 
-class CommonUtilTestCase(unittest.TestCase):
+class CommonUtilTestCase(ut_base.BaseUnitTestCase):
 
     def setUp(self):
         self.data = {
@@ -186,14 +187,14 @@ class CommonUtilTestCase(unittest.TestCase):
         self.assertEqual(mock_open.call_count, mock_open_call_count)
 
 
-class TestMacAddressToHex(unittest.TestCase):
+class TestMacAddressToHex(ut_base.BaseUnitTestCase):
 
     def test_mac_address_to_hex_list(self):
         self.assertEqual(utils.mac_address_to_hex_list("ea:3e:e1:9a:99:e8"),
                          ['0xea', '0x3e', '0xe1', '0x9a', '0x99', '0xe8'])
 
 
-class TranslateToStrTestCase(unittest.TestCase):
+class TranslateToStrTestCase(ut_base.BaseUnitTestCase):
 
     def test_translate_to_str_unicode(self):
         input_str = u'hello'
@@ -219,7 +220,7 @@ class TranslateToStrTestCase(unittest.TestCase):
         self.assertIs(input_value, result)
 
 
-class TestParseCpuInfo(unittest.TestCase):
+class TestParseCpuInfo(ut_base.BaseUnitTestCase):
 
     def test_single_socket_no_hyperthread(self):
         cpuinfo = """\
@@ -804,7 +805,7 @@ power management:
         self.assertEqual(sockets, [0, 1])
 
 
-class ChangeObjToDictTestCase(unittest.TestCase):
+class ChangeObjToDictTestCase(ut_base.BaseUnitTestCase):
 
     def test_change_obj_to_dict(self):
         class A(object):
@@ -817,7 +818,7 @@ class ChangeObjToDictTestCase(unittest.TestCase):
         self.assertEqual(obj_r, obj_s)
 
 
-class SetDictValueTestCase(unittest.TestCase):
+class SetDictValueTestCase(ut_base.BaseUnitTestCase):
 
     def test_set_dict_value(self):
         input_dic = {
@@ -827,7 +828,7 @@ class SetDictValueTestCase(unittest.TestCase):
         self.assertEqual(output_dic.get('welcome', {}).get('to'), 'yardstick')
 
 
-class RemoveFileTestCase(unittest.TestCase):
+class RemoveFileTestCase(ut_base.BaseUnitTestCase):
 
     def test_remove_file(self):
         try:
@@ -837,7 +838,83 @@ class RemoveFileTestCase(unittest.TestCase):
             self.assertTrue(isinstance(e, OSError))
 
 
-class TestUtils(unittest.TestCase):
+class ParseIniFileTestCase(ut_base.BaseUnitTestCase):
+
+    def setUp(self):
+        self._mock_config_parser_type = mock.patch.object(configparser,
+                                                          'ConfigParser')
+        self.mock_config_parser_type = self._mock_config_parser_type.start()
+        self.addCleanup(self._stop_mocks)
+
+    def _stop_mocks(self):
+        self._mock_config_parser_type.stop()
+
+    def test_parse_ini_file(self):
+        defaults = {'default1': 'value1',
+                    'default2': 'value2'}
+        s1 = {'key1': 'value11',
+              'key2': 'value22'}
+        s2 = {'key1': 'value123',
+              'key2': 'value234'}
+
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = True
+        mock_config_parser.sections.return_value = ['s1', 's2']
+        mock_config_parser.items.side_effect = iter([
+            defaults.items(),
+            s1.items(),
+            s2.items(),
+        ])
+
+        expected = {'DEFAULT': defaults,
+                    's1': s1,
+                    's2': s2}
+        result = utils.parse_ini_file('my_path')
+        self.assertDictEqual(expected, result)
+
+    @mock.patch.object(utils, 'logger')
+    def test_parse_ini_file_missing_section_header(self, *args):
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.side_effect = (
+            configparser.MissingSectionHeaderError(
+                mock.Mock(), 321, mock.Mock()))
+
+        with self.assertRaises(configparser.MissingSectionHeaderError):
+            utils.parse_ini_file('my_path')
+
+    def test_parse_ini_file_no_file(self):
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = False
+        with self.assertRaises(RuntimeError):
+            utils.parse_ini_file('my_path')
+
+    def test_parse_ini_file_no_default_section_header(self):
+        s1 = {'key1': 'value11',
+              'key2': 'value22'}
+        s2 = {'key1': 'value123',
+              'key2': 'value234'}
+
+        mock_config_parser = mock.Mock()
+        self.mock_config_parser_type.return_value = mock_config_parser
+        mock_config_parser.read.return_value = True
+        mock_config_parser.sections.return_value = ['s1', 's2']
+        mock_config_parser.items.side_effect = iter([
+            configparser.NoSectionError(mock.Mock()),
+            s1.items(),
+            s2.items(),
+        ])
+
+        expected = {'DEFAULT': {},
+                    's1': s1,
+                    's2': s2}
+        result = utils.parse_ini_file('my_path')
+        self.assertDictEqual(expected, result)
+
+
+class TestUtils(ut_base.BaseUnitTestCase):
 
     @mock.patch('yardstick.common.utils.os.makedirs')
     def test_makedirs(self, *_):
@@ -992,7 +1069,7 @@ class TestUtils(unittest.TestCase):
             utils.validate_non_string_sequence(1, raise_exc=RuntimeError)
 
 
-class TestUtilsIpAddrMethods(unittest.TestCase):
+class TestUtilsIpAddrMethods(ut_base.BaseUnitTestCase):
 
     GOOD_IP_V4_ADDRESS_STR_LIST = [
         u'0.0.0.0',
@@ -1119,7 +1196,7 @@ class TestUtilsIpAddrMethods(unittest.TestCase):
             self.assertEqual(utils.ip_to_hex(value), value)
 
 
-class SafeDecodeUtf8TestCase(unittest.TestCase):
+class SafeDecodeUtf8TestCase(ut_base.BaseUnitTestCase):
 
     @unittest.skipIf(six.PY2,
                      'This test should only be launched with Python 3.x')
@@ -1130,7 +1207,7 @@ class SafeDecodeUtf8TestCase(unittest.TestCase):
         self.assertEqual('this is a byte array', out)
 
 
-class ReadMeminfoTestCase(unittest.TestCase):
+class ReadMeminfoTestCase(ut_base.BaseUnitTestCase):
 
     MEMINFO = (b'MemTotal:       65860500 kB\n'
                b'MemFree:        28690900 kB\n'
@@ -1156,7 +1233,7 @@ class ReadMeminfoTestCase(unittest.TestCase):
         self.assertEqual(self.MEMINFO_DICT, output)
 
 
-class TimerTestCase(unittest.TestCase):
+class TimerTestCase(ut_base.BaseUnitTestCase):
 
     def test__getattr(self):
         with utils.Timer() as timer:
@@ -1174,8 +1251,19 @@ class TimerTestCase(unittest.TestCase):
             with utils.Timer(timeout=1):
                 time.sleep(2)
 
+    def test__enter_with_timeout_no_exception(self):
+        with utils.Timer(timeout=1, raise_exception=False):
+            time.sleep(2)
+
+    def test__iter(self):
+        iterations = []
+        for i in utils.Timer(timeout=2):
+            iterations.append(i)
+            time.sleep(1.1)
+        self.assertEqual(2, len(iterations))
+
 
-class WaitUntilTrueTestCase(unittest.TestCase):
+class WaitUntilTrueTestCase(ut_base.BaseUnitTestCase):
 
     def test_no_timeout(self):
         self.assertIsNone(utils.wait_until_true(lambda: True,
index 45efb82..e66e7fb 100644 (file)
@@ -143,8 +143,6 @@ class TestMultiPortConfig(unittest.TestCase):
     def setUp(self):
         self._mock_open = mock.patch.object(six.moves.builtins, 'open')
         self.mock_open = self._mock_open.start()
-        self._mock_os = mock.patch.object(os, 'path')
-        self.mock_os = self._mock_os.start()
         self._mock_config_parser = mock.patch.object(
             samplevnf_helper, 'ConfigParser')
         self.mock_config_parser = self._mock_config_parser.start()
@@ -153,7 +151,6 @@ class TestMultiPortConfig(unittest.TestCase):
 
     def _cleanup(self):
         self._mock_open.stop()
-        self._mock_os.stop()
         self._mock_config_parser.stop()
 
     def test_validate_ip_and_prefixlen(self):
@@ -185,7 +182,8 @@ class TestMultiPortConfig(unittest.TestCase):
             samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
                 '::1', '129')
 
-    def test___init__(self):
+    @mock.patch.object(os.path, 'isfile', return_value=False)
+    def test___init__(self, *args):
         topology_file = mock.Mock()
         config_tpl = mock.Mock()
         tmp_file = mock.Mock()
@@ -193,8 +191,6 @@ class TestMultiPortConfig(unittest.TestCase):
         opnfv_vnf = samplevnf_helper.MultiPortConfig(
             topology_file, config_tpl, tmp_file, vnfd_mock)
         self.assertEqual(0, opnfv_vnf.swq)
-        self.mock_os.path = mock.MagicMock()
-        self.mock_os.path.isfile = mock.Mock(return_value=False)
         opnfv_vnf = samplevnf_helper.MultiPortConfig(
             topology_file, config_tpl, tmp_file, vnfd_mock)
         self.assertEqual(0, opnfv_vnf.swq)
index cf4888d..55276af 100644 (file)
@@ -77,6 +77,12 @@ class TestDummyProfile(unittest.TestCase):
 class TrafficProfileConfigTestCase(unittest.TestCase):
 
     def test__init(self):
-        tp_config = {'traffic_profile': {'duration': 15}}
+        tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
         tp_config_obj = base.TrafficProfileConfig(tp_config)
-        self.assertEqual(15, tp_config_obj.duration)
+        self.assertEqual({'64B': 100}, tp_config_obj.packet_sizes)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_SCHEMA,
+                         tp_config_obj.schema)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_FRAME_RATE,
+                         tp_config_obj.frame_rate)
+        self.assertEqual(base.TrafficProfileConfig.DEFAULT_DURATION,
+                         tp_config_obj.duration)
index 2684e0b..0cf93f9 100644 (file)
 # 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 mock
 
-from yardstick.tests import STL_MOCKS
-
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.tests.unit import base
 
-if stl_patch:
-    from yardstick.network_services.traffic_profile.trex_traffic_profile \
-        import TrexProfile
-    from yardstick.network_services.traffic_profile.rfc2544 import \
-        RFC2544Profile
 
-
-class TestRFC2544Profile(unittest.TestCase):
+class TestRFC2544Profile(base.BaseUnitTestCase):
     TRAFFIC_PROFILE = {
         "schema": "isb:traffic_profile:0.1",
         "name": "fixed",
         "description": "Fixed traffic profile to run UDP traffic",
         "traffic_profile": {
             "traffic_type": "FixedTraffic",
-            "frame_rate": 100,  # pps
+            "frame_rate": 100,
             "flow_number": 10,
             "frame_size": 64}}
 
@@ -45,233 +38,251 @@ class TestRFC2544Profile(unittest.TestCase):
                'name': 'rfc2544',
                'traffic_profile': {'traffic_type': 'RFC2544Profile',
                                    'frame_rate': 100},
-               'downlink_0': {'ipv4':
-                              {'outer_l2': {'framesize':
-                                            {'64B': '100', '1518B': '0',
-                                             '128B': '0', '1400B': '0',
-                                             '256B': '0', '373b': '0',
-                                             '570B': '0'}},
-                               'outer_l3v4': {'dstip4': '1.1.1.1-1.15.255.255',
-                                              'proto': 'udp',
-                                              'srcip4': '90.90.1.1-90.105.255.255',
-                                              'dscp': 0, 'ttl': 32, 'count': 1},
-                               'outer_l4': {'srcport': '2001',
-                                            'dsrport': '1234', 'count': 1}}},
-               'uplink_0': {'ipv4':
-                            {'outer_l2': {'framesize':
-                                          {'64B': '100', '1518B': '0',
-                                           '128B': '0', '1400B': '0',
-                                           '256B': '0', '373b': '0',
-                                           '570B': '0'}},
-                             'outer_l3v4': {'dstip4': '9.9.1.1-90.105.255.255',
-                                            'proto': 'udp',
-                                            'srcip4': '1.1.1.1-1.15.255.255',
-                                            'dscp': 0, 'ttl': 32, 'count': 1},
-                             'outer_l4': {'dstport': '2001',
-                                          'srcport': '1234', 'count': 1}}},
+               'downlink_0':
+                   {'ipv4':
+                        {'outer_l2':
+                             {'framesize':
+                                  {'64B': '100', '1518B': '0',
+                                   '128B': '0', '1400B': '0',
+                                   '256B': '0', '373b': '0',
+                                   '570B': '0'}},
+                         'outer_l3v4':
+                             {'dstip4': '1.1.1.1-1.15.255.255',
+                              'proto': 'udp',
+                              'srcip4': '90.90.1.1-90.105.255.255',
+                              'dscp': 0, 'ttl': 32, 'count': 1},
+                         'outer_l4':
+                             {'srcport': '2001',
+                              'dsrport': '1234', 'count': 1}}},
+               'uplink_0':
+                   {'ipv4':
+                        {'outer_l2':
+                             {'framesize':
+                                  {'64B': '100', '1518B': '0',
+                                   '128B': '0', '1400B': '0',
+                                   '256B': '0', '373b': '0',
+                                   '570B': '0'}},
+                         'outer_l3v4':
+                             {'dstip4': '9.9.1.1-90.105.255.255',
+                              'proto': 'udp',
+                              'srcip4': '1.1.1.1-1.15.255.255',
+                              'dscp': 0, 'ttl': 32, 'count': 1},
+                         'outer_l4':
+                             {'dstport': '2001',
+                              'srcport': '1234', 'count': 1}}},
                'schema': 'isb:traffic_profile:0.1'}
 
     def test___init__(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        self.assertIsNotNone(r_f_c2544_profile.rate)
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        self.assertEqual(rfc2544_profile.max_rate, rfc2544_profile.rate)
+        self.assertEqual(0, rfc2544_profile.min_rate)
 
-    def test_execute(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client.return_value = True
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.first_run = True
-        self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+    def test_stop_traffic(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        mock_generator = mock.Mock()
+        rfc2544_profile.stop_traffic(traffic_generator=mock_generator)
+        mock_generator.client.stop.assert_called_once()
+        mock_generator.client.reset.assert_called_once()
+        mock_generator.client.remove_all_streams.assert_called_once()
 
-    def test_get_drop_percentage(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client.return_value = True
+    def test_execute_traffic(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        mock_generator = mock.Mock()
+        mock_generator.networks = {
+            'downlink_0': ['xe0', 'xe1'],
+            'uplink_0': ['xe2', 'xe3'],
+            'downlink_1': []}
+        mock_generator.port_num.side_effect = [10, 20, 30, 40]
+        mock_generator.rfc2544_helper.correlated_traffic = False
+        rfc2544_profile.params = {
+            'downlink_0': 'profile1',
+            'uplink_0': 'profile2'}
 
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute_traffic(traffic_generator))
+        with mock.patch.object(rfc2544_profile, '_create_profile') as \
+                mock_create_profile:
+            rfc2544_profile.execute_traffic(traffic_generator=mock_generator)
+        mock_create_profile.assert_has_calls([
+            mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile1', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile2', rfc2544_profile.rate, mock.ANY),
+            mock.call('profile2', rfc2544_profile.rate, mock.ANY)])
+        mock_generator.client.add_streams.assert_has_calls([
+            mock.call(mock.ANY, ports=[10]),
+            mock.call(mock.ANY, ports=[20]),
+            mock.call(mock.ANY, ports=[30]),
+            mock.call(mock.ANY, ports=[40])])
+        mock_generator.client.start(ports=[10, 20, 30, 40],
+                                    duration=rfc2544_profile.config.duration,
+                                    force=True)
 
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {
-                "rx_throughput_fps": 20,
-                "tx_throughput_fps": 20,
-                "rx_throughput_mbps": 10,
-                "tx_throughput_mbps": 10,
-                "in_packets": 1000,
-                "out_packets": 1000,
-            }
+    @mock.patch.object(trex_stl_streams, 'STLProfile')
+    def test__create_profile(self, mock_stl_profile):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        port_pg_id = mock.ANY
+        profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+        rate = 100
+        with mock.patch.object(rfc2544_profile, '_create_imix_data') as \
+                mock_create_imix, \
+                mock.patch.object(rfc2544_profile, '_create_vm') as \
+                mock_create_vm, \
+                mock.patch.object(rfc2544_profile, '_create_streams') as \
+                mock_create_streams:
+            mock_create_imix.return_value = 'imix_data'
+            mock_create_streams.return_value = ['stream1']
+            rfc2544_profile._create_profile(profile_data, rate, port_pg_id)
 
-        expected = {
-            'DropPercentage': 0.0,
-            'RxThroughput': 100 / 3.0,
-            'TxThroughput': 100 / 3.0,
-            'CurrentDropPercentage': 0.0,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20,
-                'in_packets': 1000,
-                'out_packets': 1000,
-                'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10,
-                'rx_throughput_fps': 20,
-            },
-        }
-        traffic_generator.generate_samples.return_value = samples
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
-        self.assertDictEqual(result, expected)
+        mock_create_imix.assert_called_once_with('imix_info')
+        mock_create_vm.assert_called_once_with(
+            {'outer_l2': {'framesize': 'imix_info'}})
+        mock_create_streams.assert_called_once_with('imix_data', 100,
+                                                    port_pg_id)
+        mock_stl_profile.assert_called_once_with(['stream1'])
 
-    def test_get_drop_percentage_update(self):
-        traffic_generator = mock.Mock(autospec=RFC2544Profile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client = mock.Mock(return_value=True)
+    def test__create_imix_data(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        data = {'64B': 50, '128B': 50}
+        self.assertEqual({'64': 50.0, '128': 50.0},
+                         rfc2544_profile._create_imix_data(data))
+        data = {'64B': 1, '128b': 3}
+        self.assertEqual({'64': 25.0, '128': 75.0},
+                         rfc2544_profile._create_imix_data(data))
+        data = {}
+        self.assertEqual({}, rfc2544_profile._create_imix_data(data))
 
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.register_generator(traffic_generator)
-        self.assertIsNone(r_f_c2544_profile.execute_traffic())
+    def test__create_vm(self):
+        packet = {'outer_l2': 'l2_definition'}
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        with mock.patch.object(rfc2544_profile, '_set_outer_l2_fields') as \
+                mock_l2_fileds:
+            rfc2544_profile._create_vm(packet)
+        mock_l2_fileds.assert_called_once_with('l2_definition')
 
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {
-                "rx_throughput_fps": 20,
-                "tx_throughput_fps": 20,
-                "rx_throughput_mbps": 10,
-                "tx_throughput_mbps": 10,
-                "in_packets": 1000,
-                "out_packets": 1002,
-            }
-        expected = {
-            'DropPercentage': 0.1996,
-            'RxThroughput': 33.333333333333336,
-            'TxThroughput': 33.4,
-            'CurrentDropPercentage': 0.1996,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20,
-                'in_packets': 1000,
-                'out_packets': 1002,
-                'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10,
-                'rx_throughput_fps': 20,
-            },
-        }
-        traffic_generator.generate_samples = mock.MagicMock(
-            return_value=samples)
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        result = r_f_c2544_profile.get_drop_percentage(traffic_generator)
-        self.assertDictEqual(expected, result)
+    @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+                       return_value='packet')
+    def test__create_single_packet(self, mock_pktbuilder):
+        size = 128
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        rfc2544_profile.ether_packet = Pkt.Eth()
+        rfc2544_profile.ip_packet = Pkt.IP()
+        rfc2544_profile.udp_packet = Pkt.UDP()
+        rfc2544_profile.trex_vm = 'trex_vm'
+        base_pkt = (rfc2544_profile.ether_packet / rfc2544_profile.ip_packet /
+                    rfc2544_profile.udp_packet)
+        pad = (size - len(base_pkt)) * 'x'
+        output = rfc2544_profile._create_single_packet(size=size)
+        mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+                                                vm='trex_vm')
+        self.assertEqual(output, 'packet')
 
-    def test_get_drop_percentage_div_zero(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "uplink_0": ["xe0"],
-            "downlink_0": ["xe1"],
-        }
-        traffic_generator.client = \
-            mock.Mock(return_value=True)
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        self.assertIsNone(
-            r_f_c2544_profile.execute_traffic(traffic_generator))
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {"rx_throughput_fps": 20,
-                             "tx_throughput_fps": 20,
-                             "rx_throughput_mbps": 10,
-                             "tx_throughput_mbps": 10,
-                             "in_packets": 1000,
-                             "out_packets": 0}
-        r_f_c2544_profile.throughput_max = 0
-        expected = {
-            'DropPercentage': 100.0, 'RxThroughput': 100 / 3.0,
-            'TxThroughput': 0.0, 'CurrentDropPercentage': 100.0,
-            'Throughput': 66.66666666666667,
-            'xe0': {
-                'tx_throughput_fps': 20, 'in_packets': 1000,
-                'out_packets': 0, 'rx_throughput_mbps': 10,
-                'tx_throughput_mbps': 10, 'rx_throughput_fps': 20
-            }
-        }
-        traffic_generator.generate_samples = mock.Mock(return_value=samples)
-        traffic_generator.RUN_DURATION = 30
-        traffic_generator.rfc2544_helper.tolerance_low = 0.0001
-        traffic_generator.rfc2544_helper.tolerance_high = 0.0001
-        self.assertDictEqual(expected,
-                             r_f_c2544_profile.get_drop_percentage(traffic_generator))
+    @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+                       return_value='packet')
+    def test__create_single_packet_qinq(self, mock_pktbuilder):
+        size = 128
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        rfc2544_profile.ether_packet = Pkt.Eth()
+        rfc2544_profile.ip_packet = Pkt.IP()
+        rfc2544_profile.udp_packet = Pkt.UDP()
+        rfc2544_profile.trex_vm = 'trex_vm'
+        rfc2544_profile.qinq = True
+        rfc2544_profile.qinq_packet = Pkt.Dot1Q(vlan=1) / Pkt.Dot1Q(vlan=2)
+        base_pkt = (rfc2544_profile.ether_packet /
+                    rfc2544_profile.qinq_packet / rfc2544_profile.ip_packet /
+                    rfc2544_profile.udp_packet)
+        pad = (size - len(base_pkt)) * 'x'
+        output = rfc2544_profile._create_single_packet(size=size)
+        mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+                                                vm='trex_vm')
+        self.assertEqual(output, 'packet')
+
+    @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+    @mock.patch.object(trex_stl_streams, 'STLTXCont')
+    @mock.patch.object(trex_stl_client, 'STLStream')
+    def test__create_streams(self, mock_stream, mock_txcont, mock_latency):
+        imix_data = {'64': 25, '512': 75}
+        rate = 35
+        port_pg_id = rfc2544.PortPgIDMap()
+        port_pg_id.add_port(10)
+        mock_stream.side_effect = ['stream1', 'stream2']
+        mock_txcont.side_effect = ['txcont1', 'txcont2']
+        mock_latency.side_effect = ['latency1', 'latency2']
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        with mock.patch.object(rfc2544_profile, '_create_single_packet'):
+            output = rfc2544_profile._create_streams(imix_data, rate,
+                                                     port_pg_id)
+        self.assertEqual(['stream1', 'stream2'], output)
+        mock_latency.assert_has_calls([
+            mock.call(pg_id=1), mock.call(pg_id=2)])
+        mock_txcont.assert_has_calls([
+            mock.call(percentage=float(25 * 35) / 100),
+            mock.call(percentage=float(75 * 35) / 100)], any_order=True)
+
+    def test_get_drop_percentage(self):
+        rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+        samples = [
+            {'xe1': {'tx_throughput_fps': 100,
+                     'rx_throughput_fps': 101,
+                     'out_packets': 2000,
+                     'in_packets': 2010},
+             'xe2': {'tx_throughput_fps': 200,
+                     'rx_throughput_fps': 201,
+                     'out_packets': 4000,
+                     'in_packets': 4010}},
+            {'xe1': {'tx_throughput_fps': 106,
+                     'rx_throughput_fps': 108,
+                     'out_packets': 2031,
+                     'in_packets': 2040,
+                     'latency': 'Latency1'},
+             'xe2': {'tx_throughput_fps': 203,
+                     'rx_throughput_fps': 215,
+                     'out_packets': 4025,
+                     'in_packets': 4040,
+                     'latency': 'Latency2'}}
+        ]
+        output = rfc2544_profile.get_drop_percentage(samples, 0, 0, False)
+        expected = {'DropPercentage': 0.3963,
+                    'Latency': {'xe1': 'Latency1', 'xe2': 'Latency2'},
+                    'RxThroughput': 312.5,
+                    'TxThroughput': 304.5,
+                    'CurrentDropPercentage': 0.3963,
+                    'Rate': 100,
+                    'Throughput': 312.5}
+        self.assertEqual(expected, output)
 
-    def test_get_multiplier(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.max_rate = 100
-        r_f_c2544_profile.min_rate = 100
-        self.assertEqual("1.0", r_f_c2544_profile.get_multiplier())
 
-    def test_calculate_pps(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.rate = 100
-        r_f_c2544_profile.pps = 100
-        samples = {'Throughput': 4549093.33}
-        self.assertEqual((2274546.67, 1.0),
-                         r_f_c2544_profile.calculate_pps(samples))
+class PortPgIDMapTestCase(base.BaseUnitTestCase):
 
-    def test_create_single_stream(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile._create_single_packet = mock.MagicMock()
-        r_f_c2544_profile.pg_id = 1
-        self.assertIsNotNone(
-            r_f_c2544_profile.create_single_stream(64, 2274546.67))
+    def test_add_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        self.assertEqual(10, port_pg_id_map._last_port)
+        self.assertEqual([], port_pg_id_map._port_pg_id_map[10])
 
-    def test_create_single_stream_no_pg_id(self):
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile._create_single_packet = mock.MagicMock()
-        r_f_c2544_profile.pg_id = 0
-        self.assertIsNotNone(
-            r_f_c2544_profile.create_single_stream(64, 2274546.67))
+    def test_get_pg_ids(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        port_pg_id_map.increase_pg_id()
+        port_pg_id_map.increase_pg_id()
+        port_pg_id_map.add_port(20)
+        port_pg_id_map.increase_pg_id()
+        self.assertEqual([1, 2], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual([3], port_pg_id_map.get_pg_ids(20))
 
-    def test_execute_latency(self):
-        traffic_generator = mock.Mock(autospec=TrexProfile)
-        traffic_generator.networks = {
-            "private_0": ["xe0"],
-            "public_0": ["xe1"],
-        }
-        traffic_generator.client = \
-            mock.Mock(return_value=True)
-        r_f_c2544_profile = RFC2544Profile(self.TRAFFIC_PROFILE)
-        r_f_c2544_profile.params = self.PROFILE
-        r_f_c2544_profile.first_run = True
-        samples = {}
-        for ifname in range(1):
-            name = "xe{}".format(ifname)
-            samples[name] = {"rx_throughput_fps": 20,
-                             "tx_throughput_fps": 20,
-                             "rx_throughput_mbps": 10,
-                             "tx_throughput_mbps": 10,
-                             "in_packets": 1000,
-                             "out_packets": 0}
+    def test_increase_pg_id_no_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        self.assertIsNone(port_pg_id_map.increase_pg_id())
 
-        samples['Throughput'] = 4549093.33
-        r_f_c2544_profile.calculate_pps = mock.Mock(return_value=[2274546.67,
-                                                                  1.0])
+    def test_increase_pg_id_last_port(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        self.assertEqual(1, port_pg_id_map.increase_pg_id())
+        self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual(10, port_pg_id_map._last_port)
 
-        self.assertIsNone(r_f_c2544_profile.execute_latency(traffic_generator,
-                                                            samples))
+    def test_increase_pg_id(self):
+        port_pg_id_map = rfc2544.PortPgIDMap()
+        port_pg_id_map.add_port(10)
+        port_pg_id_map.increase_pg_id()
+        self.assertEqual(2, port_pg_id_map.increase_pg_id(port=20))
+        self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+        self.assertEqual([2], port_pg_id_map.get_pg_ids(20))
+        self.assertEqual(20, port_pg_id_map._last_port)
index bc83224..628e854 100644 (file)
 
 import ipaddress
 
-import mock
 import six
 import unittest
 
-from yardstick.tests import STL_MOCKS
 from yardstick.common import exceptions as y_exc
-
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import TrexProfile
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import DST
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import ETHERNET
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import IP
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import IPv6
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import UDP
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import SRC_PORT
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import DST_PORT
-    from yardstick.network_services.traffic_profile.trex_traffic_profile import TYPE_OF_SERVICE
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import trex_traffic_profile
 
 
 class TestTrexProfile(unittest.TestCase):
@@ -59,7 +42,7 @@ class TestTrexProfile(unittest.TestCase):
         'name': 'rfc2544',
         'traffic_profile': {'traffic_type': 'RFC2544Profile',
                             'frame_rate': 100},
-        TrafficProfile.DOWNLINK: {
+        tp_base.TrafficProfile.DOWNLINK: {
             'ipv4': {'outer_l2': {'framesize': {'64B': '100',
                                                 '1518B': '0',
                                                 '128B': '0',
@@ -77,7 +60,7 @@ class TestTrexProfile(unittest.TestCase):
                      'outer_l4': {'srcport': '2001',
                                   'dsrport': '1234',
                                   'count': 1}}},
-        TrafficProfile.UPLINK: {
+        tp_base.TrafficProfile.UPLINK: {
             'ipv4':
                 {'outer_l2': {'framesize':
                                   {'64B': '100', '1518B': '0',
@@ -99,7 +82,7 @@ class TestTrexProfile(unittest.TestCase):
         'name': 'rfc2544',
         'traffic_profile': {'traffic_type': 'RFC2544Profile',
                             'frame_rate': 100},
-        TrafficProfile.DOWNLINK: {
+        tp_base.TrafficProfile.DOWNLINK: {
             'ipv6': {'outer_l2': {'framesize':
                                       {'64B': '100', '1518B': '0',
                                        '128B': '0', '1400B': '0',
@@ -118,7 +101,7 @@ class TestTrexProfile(unittest.TestCase):
                      'outer_l4': {'srcport': '2001',
                                   'dsrport': '1234',
                                   'count': 1}}},
-        TrafficProfile.UPLINK: {
+        tp_base.TrafficProfile.UPLINK: {
             'ipv6': {'outer_l2': {'framesize':
                                       {'64B': '100', '1518B': '0',
                                        '128B': '0', '1400B': '0',
@@ -139,66 +122,56 @@ class TestTrexProfile(unittest.TestCase):
                                   'count': 1}}},
         'schema': 'isb:traffic_profile:0.1'}
 
-    def setUp(self):
-        self.trex_profile = TrexProfile(self.PROFILE)
-
     def test___init__(self):
-        self.assertEqual(self.trex_profile.pps, 100)
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        self.assertEqual(trex_profile.pps, 100)
 
     def test_qinq(self):
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
 
-        self.assertIsNone(self.trex_profile.set_qinq(qinq))
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        self.assertIsNone(trex_profile.set_qinq(qinq))
 
         qinq = {"S-VLAN": {"id": "128-130", "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": "512-515", "priority": 0, "cfi": 0}}
-        self.assertIsNone(self.trex_profile.set_qinq(qinq))
+        self.assertIsNone(trex_profile.set_qinq(qinq))
 
     def test__set_outer_l2_fields(self):
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
                 "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
-        outer_l2 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l2']
+        outer_l2 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l2']
         outer_l2['QinQ'] = qinq
-        self.assertIsNone(self.trex_profile._set_outer_l2_fields(outer_l2))
+        self.assertIsNone(trex_profile._set_outer_l2_fields(outer_l2))
 
     def test__set_outer_l3v4_fields(self):
-        outer_l3v4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l3v4 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
         outer_l3v4['proto'] = 'tcp'
-        self.assertIsNone(self.trex_profile._set_outer_l3v4_fields(outer_l3v4))
+        self.assertIsNone(trex_profile._set_outer_l3v4_fields(outer_l3v4))
 
     def test__set_outer_l3v6_fields(self):
-        outer_l3v6 = self.PROFILE_v6[TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l3v6 = self.PROFILE_v6[
+            tp_base.TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
         outer_l3v6['proto'] = 'tcp'
         outer_l3v6['tc'] = 1
         outer_l3v6['hlim'] = 10
-        self.assertIsNone(self.trex_profile._set_outer_l3v6_fields(outer_l3v6))
+        self.assertIsNone(trex_profile._set_outer_l3v6_fields(outer_l3v6))
 
     def test__set_outer_l4_fields(self):
-        outer_l4 = self.PROFILE[TrafficProfile.UPLINK]['ipv4']['outer_l4']
-        self.assertIsNone(self.trex_profile._set_outer_l4_fields(outer_l4))
-
-    def test_get_streams(self):
-        profile_data = self.PROFILE[TrafficProfile.UPLINK]
-        self.assertIsNotNone(self.trex_profile.get_streams(profile_data))
-        self.trex_profile.pg_id = 1
-        self.assertIsNotNone(self.trex_profile.get_streams(profile_data))
-        self.trex_profile.params = self.PROFILE_v6
-        self.trex_profile.profile_data = self.PROFILE_v6[TrafficProfile.UPLINK]
-        self.assertIsNotNone(self.trex_profile.get_streams(profile_data))
-        self.trex_profile.pg_id = 1
-        self.assertIsNotNone(self.trex_profile.get_streams(profile_data))
-
-    def test_generate_packets(self):
-        self.trex_profile.fsize = 10
-        self.trex_profile.base_pkt = [10]
-        self.assertIsNone(self.trex_profile.generate_packets())
-
-    def test_generate_imix_data_error(self):
-        self.assertEqual({}, self.trex_profile.generate_imix_data(False))
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        outer_l4 = self.PROFILE[
+            tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l4']
+        self.assertIsNone(trex_profile._set_outer_l4_fields(outer_l4))
 
     def test__count_ip_ipv4(self):
-        start, end, count = TrexProfile._count_ip('1.1.1.1', '1.2.3.4')
+        start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+            '1.1.1.1', '1.2.3.4')
         self.assertEqual('1.1.1.1', str(start))
         self.assertEqual('1.2.3.4', str(end))
         diff = (int(ipaddress.IPv4Address(six.u('1.2.3.4'))) -
@@ -208,7 +181,8 @@ class TestTrexProfile(unittest.TestCase):
     def test__count_ip_ipv6(self):
         start_ip = '0064:ff9b:0:0:0:0:9810:6414'
         end_ip = '0064:ff9b:0:0:0:0:9810:6420'
-        start, end, count = TrexProfile._count_ip(start_ip, end_ip)
+        start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+            start_ip, end_ip)
         self.assertEqual(0x98106414, start)
         self.assertEqual(0x98106420, end)
         self.assertEqual(0x98106420 - 0x98106414, count)
@@ -217,10 +191,10 @@ class TestTrexProfile(unittest.TestCase):
         start_ip = '0064:ff9b:0:0:0:0:9810:6420'
         end_ip = '0064:ff9b:0:0:0:0:9810:6414'
         with self.assertRaises(y_exc.IPv6RangeError):
-            TrexProfile._count_ip(start_ip, end_ip)
+            trex_traffic_profile.TrexProfile._count_ip(start_ip, end_ip)
 
     def test__dscp_range_action_partial_actual_count_zero(self):
-        traffic_profile = TrexProfile(self.PROFILE)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         dscp_partial = traffic_profile._dscp_range_action_partial()
 
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -228,7 +202,7 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__dscp_range_action_partial_count_greater_than_actual(self):
-        traffic_profile = TrexProfile(self.PROFILE)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         dscp_partial = traffic_profile._dscp_range_action_partial()
 
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
@@ -236,7 +210,7 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__udp_range_action_partial_actual_count_zero(self):
-        traffic_profile = TrexProfile(self.PROFILE)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         traffic_profile.udp['field1'] = 'value1'
         udp_partial = traffic_profile._udp_range_action_partial('field1')
 
@@ -245,46 +219,59 @@ class TestTrexProfile(unittest.TestCase):
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__udp_range_action_partial_count_greater_than_actual(self):
-        traffic_profile = TrexProfile(self.PROFILE)
+        traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
         traffic_profile.udp['field1'] = 'value1'
-        udp_partial = traffic_profile._udp_range_action_partial('field1', 'not_used_count')
-
+        udp_partial = traffic_profile._udp_range_action_partial(
+            'field1', 'not_used_count')
         flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
         udp_partial('1', '10', '100')
         self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
 
     def test__general_single_action_partial(self):
-        self.trex_profile._general_single_action_partial(ETHERNET)(SRC)(
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+        trex_profile._general_single_action_partial(
+            trex_traffic_profile.ETHERNET)(trex_traffic_profile.SRC)(
             self.EXAMPLE_ETHERNET_ADDR)
         self.assertEqual(self.EXAMPLE_ETHERNET_ADDR,
-                         self.trex_profile.ether_packet.src)
+                         trex_profile.ether_packet.src)
 
-        self.trex_profile._general_single_action_partial(IP)(DST)(
-            self.EXAMPLE_IP_ADDR)
-        self.assertEqual(self.EXAMPLE_IP_ADDR, self.trex_profile.ip_packet.dst)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+            trex_traffic_profile.DST)(self.EXAMPLE_IP_ADDR)
+        self.assertEqual(self.EXAMPLE_IP_ADDR, trex_profile.ip_packet.dst)
 
-        self.trex_profile._general_single_action_partial(IPv6)(DST)(
-            self.EXAMPLE_IPv6_ADDR)
-        self.assertEqual(self.EXAMPLE_IPv6_ADDR,
-                         self.trex_profile.ip6_packet.dst)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IPv6)(
+            trex_traffic_profile.DST)(self.EXAMPLE_IPv6_ADDR)
+        self.assertEqual(self.EXAMPLE_IPv6_ADDR, trex_profile.ip6_packet.dst)
 
-        self.trex_profile._general_single_action_partial(UDP)(SRC_PORT)(5060)
-        self.assertEqual(5060, self.trex_profile.udp_packet.sport)
+        trex_profile._general_single_action_partial(trex_traffic_profile.UDP)(
+            trex_traffic_profile.SRC_PORT)(5060)
+        self.assertEqual(5060, trex_profile.udp_packet.sport)
 
-        self.trex_profile._general_single_action_partial(
-            IP)(TYPE_OF_SERVICE)(0)
-        self.assertEqual(0, self.trex_profile.ip_packet.tos)
+        trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+            trex_traffic_profile.TYPE_OF_SERVICE)(0)
+        self.assertEqual(0, trex_profile.ip_packet.tos)
 
     def test__set_proto_addr(self):
+        trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+
         ether_range = "00:00:00:00:00:01-00:00:00:00:00:02"
         ip_range = "1.1.1.2-1.1.1.10"
         ipv6_range = '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
 
-        self.trex_profile._set_proto_addr(ETHERNET, SRC, ether_range)
-        self.trex_profile._set_proto_addr(ETHERNET, DST, ether_range)
-        self.trex_profile._set_proto_addr(IP, SRC, ip_range)
-        self.trex_profile._set_proto_addr(IP, DST, ip_range)
-        self.trex_profile._set_proto_addr(IPv6, SRC, ipv6_range)
-        self.trex_profile._set_proto_addr(IPv6, DST, ipv6_range)
-        self.trex_profile._set_proto_addr(UDP, SRC_PORT, '5060-5090')
-        self.trex_profile._set_proto_addr(UDP, DST_PORT, '5060')
+        trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+                                     trex_traffic_profile.SRC, ether_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+                                     trex_traffic_profile.DST, ether_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IP,
+                                     trex_traffic_profile.SRC, ip_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IP,
+                                     trex_traffic_profile.DST, ip_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+                                     trex_traffic_profile.SRC, ipv6_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+                                     trex_traffic_profile.DST, ipv6_range)
+        trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+                                     trex_traffic_profile.SRC_PORT,
+                                     '5060-5090')
+        trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+                                     trex_traffic_profile.DST_PORT, '5060')
index 01d7930..45e0668 100644 (file)
@@ -11,7 +11,6 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-#
 
 from copy import deepcopy
 
@@ -19,37 +18,29 @@ import unittest
 import mock
 import six
 
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
 from yardstick.benchmark.contexts.base import Context
 from yardstick.common import exceptions as y_exceptions
 from yardstick.common import utils
 from yardstick.network_services.nfvi.resource import ResourceProfile
 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-
-
-class MockError(BaseException):
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
+
+
+class MockError(Exception):
     pass
 
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf import sample_vnf
-    from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFDeployHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SetupEnvHelper
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen
-    from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
-
-
 class TestVnfSshHelper(unittest.TestCase):
 
     VNFD_0 = {
@@ -1003,176 +994,39 @@ class TestClientResourceHelper(unittest.TestCase):
     }
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
-                new_callable=lambda: MockError)
-    def test_get_stats_not_connected(self, mock_state_error, *args):
+    @mock.patch.object(sample_vnf, 'STLError', new_callable=lambda: MockError)
+    def test_get_stats_not_connected(self, mock_stl_error, *args):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.side_effect = mock_state_error
+        client_resource_helper.client = mock.Mock()
+        client_resource_helper.client.get_stats.side_effect = mock_stl_error
 
         self.assertEqual(client_resource_helper.get_stats(), {})
         self.assertEqual(client_resource_helper.client.get_stats.call_count, 1)
 
-    def test_generate_samples(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports)
-        self.assertDictEqual(result, expected)
-
-    def test_generate_samples_with_key(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            'key_name': 'key_value',
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                'key_name': 'key_value',
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                'key_name': 'key_value',
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports, 'key_name')
-        self.assertDictEqual(result, expected)
-
-    def test_generate_samples_with_key_and_default(self):
-        vnfd_helper = VnfdHelper(self.VNFD_0)
-        ssh_helper = mock.Mock()
-        scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
-        client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
-        client_resource_helper.client = mock.MagicMock()
-        client_resource_helper.client.get_stats.return_value = {
-            0: {
-                'rx_pps': 5.5,
-                'tx_pps': 4.9,
-                'rx_bps': 234.78,
-                'tx_bps': 243.11,
-                'ipackets': 34251,
-                'opackets': 52342,
-            },
-            1: {
-                'tx_pps': 5.9,
-                'rx_bps': 434.78,
-                'opackets': 48791,
-            },
-        }
-
-        expected = {
-            'xe0': {
-                'key_name': 'default',
-                "rx_throughput_fps": 5.5,
-                "tx_throughput_fps": 4.9,
-                "rx_throughput_mbps": 234.78,
-                "tx_throughput_mbps": 243.11,
-                "in_packets": 34251,
-                "out_packets": 52342,
-            },
-            'xe1': {
-                'key_name': 'default',
-                "rx_throughput_fps": 0.0,
-                "tx_throughput_fps": 5.9,
-                "rx_throughput_mbps": 434.78,
-                "tx_throughput_mbps": 0.0,
-                "in_packets": 0,
-                "out_packets": 48791,
-            },
-        }
-        ports = vnfd_helper.port_nums(vnfd_helper.port_pairs.all_ports)
-        result = client_resource_helper.generate_samples(ports, 'key_name', 'default')
-        self.assertDictEqual(result, expected)
-
     def test_clear_stats(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
         self.assertIsNone(client_resource_helper.clear_stats())
-        self.assertEqual(client_resource_helper.client.clear_stats.call_count, 1)
+        self.assertEqual(
+            client_resource_helper.client.clear_stats.call_count, 1)
 
     def test_clear_stats_of_ports(self):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
@@ -1183,7 +1037,8 @@ class TestClientResourceHelper(unittest.TestCase):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
@@ -1194,7 +1049,8 @@ class TestClientResourceHelper(unittest.TestCase):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
-        dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+        dpdk_setup_helper = DpdkVnfSetupEnvHelper(
+            vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client_resource_helper.client = mock.Mock()
 
@@ -1221,17 +1077,15 @@ class TestClientResourceHelper(unittest.TestCase):
         self.assertDictEqual(result, expected)
 
     @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.time')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.LOG')
-    @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.STLError',
-                new_callable=lambda: MockError)
-    def test__connect_with_failures(self, mock_error, *args):
+    @mock.patch.object(sample_vnf, 'STLError')
+    def test__connect_with_failures(self, mock_stl_error, *args):
         vnfd_helper = VnfdHelper(self.VNFD_0)
         ssh_helper = mock.Mock()
         scenario_helper = mock.Mock()
         dpdk_setup_helper = DpdkVnfSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
         client_resource_helper = ClientResourceHelper(dpdk_setup_helper)
         client = mock.MagicMock()
-        client.connect.side_effect = mock_error
+        client.connect.side_effect = mock_stl_error(msg='msg')
 
         self.assertIs(client_resource_helper._connect(client), client)
 
@@ -1680,7 +1534,7 @@ class TestSampleVnf(unittest.TestCase):
 
     @mock.patch("yardstick.ssh.SSH")
     def test_instantiate(self, ssh):
-        mock_ssh(ssh)
+        test_base.mock_ssh(ssh)
 
         nodes = {
             'vnf1': 'name1',
@@ -1780,7 +1634,7 @@ class TestSampleVnf(unittest.TestCase):
     @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
     @mock.patch("yardstick.ssh.SSH")
     def test_wait_for_instantiate_empty_queue(self, ssh, *args):
-        mock_ssh(ssh, exec_result=(1, "", ""))
+        test_base.mock_ssh(ssh, exec_result=(1, "", ""))
 
         queue_size_list = [
             0,
index 8b1b8a3..a463fa0 100644 (file)
 # 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 mock
-
-from yardstick.tests import STL_MOCKS
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
 
+from __future__ import absolute_import
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex import TrexTrafficGenRFC, \
-        TrexRfcResourceHelper
-    from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
-    from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base \
-        import FileAbsPath, mock_ssh
+import mock
+import unittest
 
-MODULE_PATH = FileAbsPath(__file__)
-get_file_abspath = MODULE_PATH.get_path
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
 
 
 class TestTrexRfcResouceHelper(unittest.TestCase):
 
-    @mock.patch('yardstick.network_services.helpers.samplevnf_helper.MultiPortConfig')
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
-    @mock.patch(SSH_HELPER)
-    def test__run_traffic_once(self, ssh, *_):
-        mock_ssh(ssh)
+    def test__run_traffic_once(self):
+        mock_setup_helper = mock.Mock()
+        mock_traffic_profile = mock.Mock()
+        mock_traffic_profile.config.duration = 3
+        mock_traffic_profile.execute_traffic.return_value = ('fake_ports',
+                                                             'port_pg_id_map')
+        mock_traffic_profile.get_drop_percentage.return_value = 'percentage'
+        rfc_rh = tg_rfc2544_trex.TrexRfcResourceHelper(mock_setup_helper)
+        rfc_rh.TRANSIENT_PERIOD = 0
+        rfc_rh.rfc2544_helper = mock.Mock()
+
+        with mock.patch.object(rfc_rh, '_get_samples') as mock_get_samples:
+            rfc_rh._run_traffic_once(mock_traffic_profile)
 
-        mock_traffic_profile = mock.MagicMock(autospec=TrafficProfile,
-                                              **{'get_drop_percentage.return_value': {}})
-        sut = TrexRfcResourceHelper(mock.MagicMock(), mock.MagicMock())
-        sut.client = mock.MagicMock()
-        sut._run_traffic_once(mock_traffic_profile)
+        mock_traffic_profile.execute_traffic.assert_called_once_with(rfc_rh)
+        mock_traffic_profile.stop_traffic.assert_called_once_with(rfc_rh)
+        mock_traffic_profile.stop_traffic.assert_called_once()
+        mock_get_samples.assert_has_calls([
+            mock.call('fake_ports', port_pg_id='port_pg_id_map'),
+            mock.call('fake_ports', port_pg_id='port_pg_id_map')])
 
 
 class TestTrexTrafficGenRFC(unittest.TestCase):
@@ -219,33 +214,24 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
         'schema': 'yardstick:task:0.1',
     }
 
-    @mock.patch(SSH_HELPER)
-    def test___init__(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
-
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertEqual(trex_traffic_gen.collect_kpi(), {})
+    def setUp(self):
+        self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+        self.mock_ssh_helper = self._mock_ssh_helper.start()
+        self.addCleanup(self._stop_mocks)
 
-    @mock.patch(SSH_HELPER)
-    def test_listen_traffic(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        self.assertIsNone(trex_traffic_gen.listen_traffic({}))
+    def _stop_mocks(self):
+        self._mock_ssh_helper.stop()
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh):
-        mock_ssh(ssh)
+    def test___init__(self):
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
 
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test_instantiate(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen.resource_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
@@ -274,15 +260,12 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
         scenario_cfg.update({"nodes": ["tg_1", "vnf_1"]})
         self.assertIsNone(trex_traffic_gen.instantiate(scenario_cfg, {}))
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate_error(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test_instantiate_error(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
+        trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
         trex_traffic_gen.resource_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
         scenario_cfg = {
@@ -310,29 +293,3 @@ class TestTrexTrafficGenRFC(unittest.TestCase):
             },
         }
         trex_traffic_gen.instantiate(scenario_cfg, {})
-
-    @mock.patch(SSH_HELPER)
-    def test__start_server(self, ssh):
-        mock_ssh(ssh)
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        trex_traffic_gen.resource_helper = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen._start_server())
-
-    @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_trex.time")
-    @mock.patch(SSH_HELPER)
-    def test__generate_trex_cfg(self, ssh, _):
-        mock_ssh(ssh)
-
-        trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-        trex_traffic_gen.ssh_helper = mock.MagicMock()
-        trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
-
-    def test_terminate(self):
-        with mock.patch(SSH_HELPER) as ssh:
-            ssh_mock = mock.Mock(autospec=ssh.SSH)
-            ssh_mock.execute = mock.Mock(return_value=(0, "", ""))
-            ssh.from_node.return_value = ssh_mock
-            trex_traffic_gen = TrexTrafficGenRFC('vnf1', self.VNFD_0)
-            trex_traffic_gen.resource_helper = mock.MagicMock()
-            self.assertIsNone(trex_traffic_gen.terminate())
index aae3d46..4f87424 100644 (file)
 # 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 unittest
 
-from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
-from yardstick.tests import STL_MOCKS
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
 
 
-SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
 NAME = 'vnf_1'
 
-STLClient = mock.MagicMock()
-stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
-stl_patch.start()
-
-if stl_patch:
-    from yardstick.network_services.vnf_generic.vnf.tg_trex import \
-        TrexTrafficGen, TrexResourceHelper
-    from yardstick.network_services.traffic_profile.base import TrafficProfile
-
 
 class TestTrexTrafficGen(unittest.TestCase):
+
     VNFD = {'vnfd:vnfd-catalog':
             {'vnfd':
              [{'short-name': 'VpeVnf',
@@ -168,7 +160,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens786f0",
-                        "vld_id": TrafficProfile.UPLINK,
+                        "vld_id": tp_base.TrafficProfile.UPLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.0",
                         "local_ip": "152.16.100.19",
@@ -180,7 +172,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                     },
                     "xe1": {
                         "local_iface_name": "ens786f1",
-                        "vld_id": TrafficProfile.DOWNLINK,
+                        "vld_id": tp_base.TrafficProfile.DOWNLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.1",
                         "local_ip": "152.16.40.19",
@@ -236,7 +228,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens513f0",
-                        "vld_id": TrafficProfile.DOWNLINK,
+                        "vld_id": tp_base.TrafficProfile.DOWNLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:02:00.0",
                         "local_ip": "152.16.40.20",
@@ -270,7 +262,7 @@ class TestTrexTrafficGen(unittest.TestCase):
                 "interfaces": {
                     "xe0": {
                         "local_iface_name": "ens785f0",
-                        "vld_id": TrafficProfile.UPLINK,
+                        "vld_id": tp_base.TrafficProfile.UPLINK,
                         "netmask": "255.255.255.0",
                         "vpci": "0000:05:00.0",
                         "local_ip": "152.16.100.20",
@@ -297,36 +289,35 @@ class TestTrexTrafficGen(unittest.TestCase):
         }
     }
 
-    @mock.patch(SSH_HELPER)
-    def test___init__(self, ssh):
-        mock_ssh(ssh)
+    def setUp(self):
+        self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+        self.mock_ssh_helper = self._mock_ssh_helper.start()
+        self.addCleanup(self._stop_mocks)
+
+    def _stop_mocks(self):
+        self._mock_ssh_helper.stop()
+
+    def test___init__(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
-        self.assertIsInstance(
-            trex_traffic_gen.resource_helper, TrexResourceHelper)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+        self.assertIsInstance(trex_traffic_gen.resource_helper,
+                              tg_trex.TrexResourceHelper)
 
-    @mock.patch(SSH_HELPER)
-    def test_collect_kpi(self, ssh):
-        mock_ssh(ssh)
+    def test_collect_kpi(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.resource_helper._queue.put({})
         result = trex_traffic_gen.collect_kpi()
         self.assertEqual({}, result)
 
-    @mock.patch(SSH_HELPER)
-    def test_listen_traffic(self, ssh):
-        mock_ssh(ssh)
+    def test_listen_traffic(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.assertIsNone(trex_traffic_gen.listen_traffic({}))
 
-    @mock.patch(SSH_HELPER)
-    def test_instantiate(self, ssh):
-        mock_ssh(ssh)
-
+    def test_instantiate(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen._tg_process = mock.MagicMock()
         trex_traffic_gen._tg_process.start = mock.Mock()
@@ -335,16 +326,12 @@ class TestTrexTrafficGen(unittest.TestCase):
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+        self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+                                                       self.CONTEXT_CFG))
 
-        self.assertIsNone(trex_traffic_gen.instantiate(
-            self.SCENARIO_CFG, self.CONTEXT_CFG))
-
-    @mock.patch(SSH_HELPER)
-    def test_instantiate_error(self, ssh):
-        mock_ssh(ssh, exec_result=(1, "", ""))
-
+    def test_instantiate_error(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen._start_server = mock.Mock(return_value=0)
         trex_traffic_gen._tg_process = mock.MagicMock()
         trex_traffic_gen._tg_process.start = mock.Mock()
@@ -352,62 +339,53 @@ class TestTrexTrafficGen(unittest.TestCase):
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
-        self.assertIsNone(trex_traffic_gen.instantiate(
-            self.SCENARIO_CFG, self.CONTEXT_CFG))
+        self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+                                                       self.CONTEXT_CFG))
 
-    @mock.patch(SSH_HELPER)
-    def test__start_server(self, ssh):
-        mock_ssh(ssh)
+    def test__start_server(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.scenario_helper.scenario_cfg = {}
         self.assertIsNone(trex_traffic_gen._start_server())
 
-    @mock.patch(SSH_HELPER)
-    def test__start_server_multiple_queues(self, ssh):
-        mock_ssh(ssh)
+    def test__start_server_multiple_queues(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.scenario_helper.scenario_cfg = {
             "options": {NAME: {"queues_per_port": 2}}}
         self.assertIsNone(trex_traffic_gen._start_server())
 
-    @mock.patch(SSH_HELPER)
-    def test__traffic_runner(self, ssh):
-        mock_ssh(ssh)
-
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test__traffic_runner(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.execute_traffic.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        self.sut = TrexTrafficGen(NAME, vnfd)
+        self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.sut.ssh_helper = mock.Mock()
         self.sut.ssh_helper.run = mock.Mock()
-        self.sut._connect_client = mock.Mock(autospec=STLClient)
+        self.sut._connect_client = mock.Mock()
         self.sut._connect_client.get_stats = mock.Mock(return_value="0")
         self.sut.resource_helper.RUN_DURATION = 0
         self.sut.resource_helper.QUEUE_WAIT_TIME = 0
-        # must generate cfg before we can run traffic so Trex port mapping is created
+        # must generate cfg before we can run traffic so Trex port mapping is
+        # created
         self.sut.resource_helper.generate_cfg()
-        self.sut._traffic_runner(mock_traffic_profile)
+        with mock.patch.object(self.sut.resource_helper, 'run_traffic'):
+            self.sut._traffic_runner(mock_traffic_profile)
 
-    @mock.patch(SSH_HELPER)
-    def test__generate_trex_cfg(self, ssh):
-        mock_ssh(ssh)
+    def test__generate_trex_cfg(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
 
-    @mock.patch(SSH_HELPER)
-    def test_build_ports_reversed_pci_ordering(self, ssh):
-        mock_ssh(ssh)
+    def test_build_ports_reversed_pci_ordering(self):
         vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
         vnfd['vdu'][0]['external-interface'] = [
             {'virtual-interface':
@@ -442,26 +420,24 @@ class TestTrexTrafficGen(unittest.TestCase):
               'local_mac': '00:00:00:00:00:01'},
              'vnfd-connection-point-ref': 'xe1',
              'name': 'xe1'}]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.generate_cfg()
         trex_traffic_gen.resource_helper._build_ports()
-        self.assertEqual(
-            sorted(trex_traffic_gen.resource_helper.all_ports), [0, 1])
+        self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports),
+                         [0, 1])
         # there is a gap in ordering
-        self.assertEqual(dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map),
-                         {0: 0, 2: 1})
-
-    @mock.patch(SSH_HELPER)
-    def test_run_traffic(self, ssh):
-        mock_ssh(ssh)
+        self.assertEqual(
+            {0: 0, 2: 1},
+            dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map))
 
-        mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+    def test_run_traffic(self):
+        mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
         mock_traffic_profile.get_traffic_definition.return_value = "64"
         mock_traffic_profile.params = self.TRAFFIC_PROFILE
 
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        self.sut = TrexTrafficGen(NAME, vnfd)
+        self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
         self.sut.ssh_helper = mock.Mock()
         self.sut.ssh_helper.run = mock.Mock()
         self.sut._traffic_runner = mock.Mock(return_value=0)
@@ -470,20 +446,60 @@ class TestTrexTrafficGen(unittest.TestCase):
         self.sut._traffic_process.terminate()
         self.assertIsNotNone(result)
 
-    @mock.patch(SSH_HELPER)
-    def test_terminate(self, ssh):
-        mock_ssh(ssh)
+    def test_terminate(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
         trex_traffic_gen.ssh_helper = mock.MagicMock()
         trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
         self.assertIsNone(trex_traffic_gen.terminate())
 
-    @mock.patch(SSH_HELPER)
-    def test__connect_client(self, ssh):
-        mock_ssh(ssh)
+    def test__connect_client(self):
         vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
-        trex_traffic_gen = TrexTrafficGen(NAME, vnfd)
-        client = mock.Mock(autospec=STLClient)
+        trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+        client = mock.Mock()
         client.connect = mock.Mock(return_value=0)
         self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
+
+
+class TrexResourceHelperTestCase(unittest.TestCase):
+
+    def test__get_samples(self):
+        mock_setup_helper = mock.Mock()
+        trex_rh = tg_trex.TrexResourceHelper(mock_setup_helper)
+        trex_rh.vnfd_helper.interfaces = [
+            {'name': 'interface1'},
+            {'name': 'interface2'}]
+        stats = {
+            10: {'rx_pps': 5, 'ipackets': 200},
+            20: {'rx_pps': 10, 'ipackets': 300},
+            'latency': {1: {'latency': 'latency_port_10_pg_id_1'},
+                        2: {'latency': 'latency_port_10_pg_id_2'},
+                        3: {'latency': 'latency_port_20_pg_id_3'},
+                        4: {'latency': 'latency_port_20_pg_id_4'}}
+        }
+        port_pg_id = rfc2544.PortPgIDMap()
+        port_pg_id.add_port(10)
+        port_pg_id.increase_pg_id()
+        port_pg_id.increase_pg_id()
+        port_pg_id.add_port(20)
+        port_pg_id.increase_pg_id()
+        port_pg_id.increase_pg_id()
+
+        with mock.patch.object(trex_rh, 'get_stats') as mock_get_stats, \
+                mock.patch.object(trex_rh.vnfd_helper, 'port_num') as \
+                mock_port_num:
+            mock_get_stats.return_value = stats
+            mock_port_num.side_effect = [10, 20]
+            output = trex_rh._get_samples([10, 20], port_pg_id=port_pg_id)
+
+        interface = output['interface1']
+        self.assertEqual(5.0, interface['rx_throughput_fps'])
+        self.assertEqual(200, interface['in_packets'])
+        self.assertEqual('latency_port_10_pg_id_1', interface['latency'][1])
+        self.assertEqual('latency_port_10_pg_id_2', interface['latency'][2])
+
+        interface = output['interface2']
+        self.assertEqual(10.0, interface['rx_throughput_fps'])
+        self.assertEqual(300, interface['in_packets'])
+        self.assertEqual('latency_port_20_pg_id_3', interface['latency'][3])
+        self.assertEqual('latency_port_20_pg_id_4', interface['latency'][4])