Merge "Supporting user config task parameters in GUI"
authorJack Chan <chenjiankun1@huawei.com>
Fri, 16 Mar 2018 09:01:07 +0000 (09:01 +0000)
committerGerrit Code Review <gerrit@opnfv.org>
Fri, 16 Mar 2018 09:01:07 +0000 (09:01 +0000)
99 files changed:
ansible/roles/convert_openrc/tasks/main.yml
ansible/roles/infra_check_requirements/tasks/main.yml
ansible/roles/infra_create_network/tasks/create_xml.yml [moved from ansible/roles/infra_create_network/tasks/create_xml.yaml with 85% similarity]
ansible/roles/infra_create_network/tasks/main.yml
ansible/roles/infra_create_vms/tasks/configure_vm.yml
ansible/roles/infra_create_vms/tasks/create_interfaces.yml
ansible/roles/infra_create_vms/tasks/main.yml
api/resources/v2/environments.py
api/urls.py
docs/testing/developer/devguide/devguide_nsb_prox.rst
docs/testing/user/userguide/08-api.rst
docs/testing/user/userguide/11-nsb-overview.rst
docs/testing/user/userguide/opnfv_yardstick_tc019.rst
docs/testing/user/userguide/opnfv_yardstick_tc045.rst
docs/testing/user/userguide/opnfv_yardstick_tc046.rst
docs/testing/user/userguide/opnfv_yardstick_tc047.rst
docs/testing/user/userguide/opnfv_yardstick_tc048.rst
docs/testing/user/userguide/opnfv_yardstick_tc049.rst
docs/testing/user/userguide/opnfv_yardstick_tc053.rst
docs/testing/user/userguide/opnfv_yardstick_tc056.rst
docs/testing/user/userguide/opnfv_yardstick_tc057.rst
docs/testing/user/userguide/opnfv_yardstick_tc058.rst
etc/infra/infra_deploy.yaml.sample
etc/yardstick/nodes/fuel_baremetal/pod.yaml
gui/app/index.html
gui/app/scripts/controllers/container.controller.js
gui/app/scripts/controllers/content.controller.js
gui/app/scripts/controllers/sut.controller.js [new file with mode: 0644]
gui/app/scripts/factory/main.factory.js
gui/app/scripts/router.config.js
gui/app/views/container.html
gui/app/views/layout/sideNav.html
gui/app/views/sut.html [new file with mode: 0644]
samples/dummy.yaml
samples/netperf_soak.yaml [new file with mode: 0644]
samples/vnf_samples/nsut/prox/tc_prox_baremetal_l2fwd-2.yaml
samples/vnf_samples/nsut/prox/tc_prox_baremetal_l2fwd-4.yaml
tests/ci/load_images.sh
tests/ci/prepare_env.sh
tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
yardstick/benchmark/core/task.py
yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash [new file with mode: 0644]
yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash [new file with mode: 0644]
yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash [new file with mode: 0644]
yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash [new file with mode: 0644]
yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash [new file with mode: 0644]
yardstick/benchmark/scenarios/availability/operation_conf.yaml
yardstick/benchmark/scenarios/lib/create_network.py
yardstick/benchmark/scenarios/lib/create_subnet.py
yardstick/benchmark/scenarios/lib/delete_router.py
yardstick/benchmark/scenarios/networking/netperf.py
yardstick/common/ansible_common.py
yardstick/common/exceptions.py
yardstick/common/openstack_utils.py
yardstick/network_services/constants.py
yardstick/network_services/traffic_profile/prox_binsearch.py
yardstick/network_services/vnf_generic/vnf/prox_helpers.py
yardstick/network_services/vnf_generic/vnf/prox_vnf.py
yardstick/network_services/vnf_generic/vnf/sample_vnf.py
yardstick/network_services/vnf_generic/vnf/vnf_ssh_helper.py
yardstick/service/__init__.py [new file with mode: 0644]
yardstick/service/environment.py [new file with mode: 0644]
yardstick/tests/unit/benchmark/contexts/test_heat.py
yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
yardstick/tests/unit/benchmark/contexts/test_node.py
yardstick/tests/unit/benchmark/core/test_task.py
yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
yardstick/tests/unit/common/test_ansible_common.py
yardstick/tests/unit/common/test_openstack_utils.py
yardstick/tests/unit/service/__init__.py [new file with mode: 0644]
yardstick/tests/unit/service/test_environment.py [new file with mode: 0644]
yardstick/tests/unit/test_cmd/commands/test_env.py
yardstick/tests/unit/test_cmd/commands/test_testcase.py

index be621f0..00aa136 100644 (file)
@@ -18,7 +18,7 @@
 - debug: var=openrc
 
 - set_fact:
-    yardstick_url_ip: "{{ openrc.OS_AUTH_URL|urlsplit|attr('hostname') }}"
+    yardstick_url_ip: "{{ openrc.OS_AUTH_URL|urlsplit('hostname') }}"
 
 - debug: var=yardstick_url_ip
 
index 8d05bbd..a11bc56 100644 (file)
     msg: "Failed, not enough CPU, required: {{ vcpu_t }}, available {{ ansible_processor_vcpus }}"
   when: ansible_processor_vcpus < vcpu_t|int
 
+- name: Define default network counter
+  set_fact:
+    num_default_network_detected: 0
+
+- name: Increment counter for every default network detected
+  set_fact:
+    num_default_network_detected: "{{ num_default_network_detected|int + 1 }}"
+  when:
+    - item.default_gateway is defined
+    - item.default_gateway == True
+  with_items: "{{infra_deploy_vars.networks}}"
+
+- name: Fail if more than 1 or 0 default networks
+  fail:
+    msg: "Failed, there must be 1 default network: {{ num_default_network_detected }} detected"
+  when: num_default_network_detected|int != 1
 
 - name: Fail if not enough Disk space
   set_fact:
     xpath: /network
     add_children:
       - name: "{{ item.name }}"
+      - forward:
+          mode: nat
       - bridge
       - ip
     pretty_print: yes
 
+- name: Add new children nodes to "forward" node
+  xml:
+    path: "{{ xml_file }}"
+    xpath: /network/forward
+    add_children:
+      - nat
+    pretty_print: yes
+
+- name: Add new children nodes to "nat" node
+  xml:
+    path: "{{ xml_file }}"
+    xpath: /network/forward/nat
+    add_children:
+      - port:
+          start: "1024"
+          end: "65535"
+    pretty_print: yes
+
 - name: Add "name" attribute to "bridge" node
   xml:
     path: "{{ xml_file }}"
index eba4a3a..025a775 100644 (file)
@@ -18,5 +18,5 @@
     name: infra_deploy_vars
 
 - name: Create XML file
-  include_tasks: create_xml.yaml
+  include_tasks: create_xml.yml
   with_items: "{{ infra_deploy_vars.networks }}"
index 5685e63..c20a0b1 100644 (file)
       - console:
           type: pty
           tty: '/dev/pts/14'
+      - graphics:
+          type: vnc
+          port: '-1'
+          autoport: 'yes'
     pretty_print: yes
 
 - name: Add new children nodes to "disk" node
           name: virtio-disk0
     pretty_print: yes
 
+- name: Add new children nodes to "graphics" node
+  xml:
+    path: "{{ xml_file }}"
+    xpath: /domain/devices/graphics
+    add_children:
+      - listen:
+          type: address
+          address: 0.0.0.0
+    pretty_print: yes
+
 - name: Add new children nodes to "devices" node
   xml:
     path: "{{ xml_file }}"
 
 - name: Populate network-config and add interface to xml file
   include_tasks: create_interfaces.yml
-  extra_vars: "{{ network_config, xml_file , slot_address, mac_address_counter }}"
+  extra_vars: "{{ network_config xml_file slot_address mac_address_counter }}"
   loop_control:
     loop_var: interface_item
   with_items: "{{ node_item.interfaces }}"
   shell: >
     qemu-img convert -O qcow2 {{ node_item.image }} {{ image_dir+node_item.hostname+'.qcow2' }}
 
-- name: Copy and convert the ubuntu image
+- name: Resize image
   shell: >
     qemu-img resize {{ image_dir+node_item.hostname+'.qcow2' }} {{ node_item.disk }}M
 
index 124421b..34bfd1b 100644 (file)
           addresses:
             - {{ interface_item.ip }}/{{ interface_item.netmask }}
 
+- name: Add default gateway
+  blockinfile:
+    path: "{{ network_config }}"
+    insertafter: "{{ interface_item.ip }}"
+    marker: "MARKER"
+    block: |2
+          gateway4: {{ default_bridge.host_ip }}
+  when:
+    - default_bridge is defined
+    - default_bridge.name == interface_item.network
 
 - name: Remove the marker introduced in network-data
   lineinfile:
index 62a023e..4d47f44 100644 (file)
 - set_fact:
     mac_address_counter: 0
 
+- set_fact:
+    default_bridge: "{{ item }}"
+  when:
+    - item.default_gateway is defined
+    - item.default_gateway == True
+  with_items: "{{ infra_deploy_vars.networks }}"
+
 - name: Create XML file
   include_tasks: configure_vm.yml
-  extra_vars: "{{ mac_address_counter }}"
   loop_control:
     loop_var: node_item
   with_items: "{{ infra_deploy_vars.nodes }}"
index 158e98b..7e587be 100644 (file)
@@ -11,6 +11,7 @@ import logging
 
 from oslo_serialization import jsonutils
 from docker import Client
+from docker.errors import APIError
 
 from api import ApiResource
 from api.database.v2.handlers import V2EnvironmentHandler
@@ -20,6 +21,7 @@ from api.database.v2.handlers import V2ContainerHandler
 from yardstick.common.utils import result_handler
 from yardstick.common.utils import change_obj_to_dict
 from yardstick.common import constants as consts
+from yardstick.service.environment import Environment
 
 LOG = logging.getLogger(__name__)
 LOG.setLevel(logging.DEBUG)
@@ -124,10 +126,41 @@ class V2Environment(ApiResource):
                 LOG.debug('container name: %s', container.name)
                 try:
                     client.remove_container(container.name, force=True)
-                except Exception:
+                except APIError:
                     LOG.exception('remove container failed')
                 container_handler.delete_by_uuid(v)
 
         environment_handler.delete_by_uuid(environment_id)
 
         return result_handler(consts.API_SUCCESS, {'environment': environment_id})
+
+
+class V2SUT(ApiResource):
+
+    def get(self, environment_id):
+        try:
+            uuid.UUID(environment_id)
+        except ValueError:
+            return result_handler(consts.API_ERROR, 'invalid environment id')
+
+        environment_handler = V2EnvironmentHandler()
+        try:
+            environment = environment_handler.get_by_uuid(environment_id)
+        except ValueError:
+            return result_handler(consts.API_ERROR, 'no such environment id')
+
+        if not environment.pod_id:
+            return result_handler(consts.API_SUCCESS, {'sut': {}})
+
+        pod_handler = V2PodHandler()
+        try:
+            pod = pod_handler.get_by_uuid(environment.pod_id)
+        except ValueError:
+            return result_handler(consts.API_ERROR, 'no such pod id')
+        else:
+            pod_content = pod.content
+
+        env = Environment(pod=pod_content)
+        sut_info = env.get_sut_info()
+
+        return result_handler(consts.API_SUCCESS, {'sut': sut_info})
index 4b8e39e..9f0abca 100644 (file)
@@ -26,6 +26,7 @@ urlpatterns = [
     Url('/api/v2/yardstick/environments', 'v2_environments'),
     Url('/api/v2/yardstick/environments/action', 'v2_environments'),
     Url('/api/v2/yardstick/environments/<environment_id>', 'v2_environment'),
+    Url('/api/v2/yardstick/environments/<environment_id>/sut', 'v2_sut'),
 
     Url('/api/v2/yardstick/openrcs', 'v2_openrcs'),
     Url('/api/v2/yardstick/openrcs/action', 'v2_openrcs'),
index fc533b2..2262841 100755 (executable)
@@ -251,9 +251,11 @@ Now let's examine the components of the file in detail
    In this case it is ``handle_l2fwd-2.cfg``
 
    A number of additional parameters can be added. This example
-   is taken from VPE::
+   is for VPE::
 
     options:
+      interface_speed_gbps: 10
+
       vnf__0:
         prox_path: /opt/nsb_bin/prox
         prox_config: ``configs/handle_vpe-4.cfg``
@@ -267,6 +269,12 @@ Now let's examine the components of the file in detail
           ``configs/vpe_rules.lua`` : ````
         prox_generate_parameter: True
 
+   ``interface_speed_gbps`` - this specifies the speed of the interface
+   in Gigabits Per Second. This is used to calculate pps(packets per second).
+   If the interfaces are of different speeds, then this specifies the speed
+   of the slowest interface. This parameter is optional. If omitted the
+   interface speed defaults to 10Gbps.
+
    ``prox_files`` - this specified that a number of addition files
    need to be provided for the test to run correctly. This files
    could provide routing information,hashing information or a
index 92fa408..79f5d64 100644 (file)
@@ -35,7 +35,7 @@ Prepare Yardstick test environment
 Example::
 
     {
-        'action': 'prepareYardstickEnv'
+        'action': 'prepare_env'
     }
 
 This is an asynchronous API. You need to call /yardstick/asynctask API to get the task result.
@@ -45,7 +45,7 @@ Start and config an InfluxDB docker container
 Example::
 
     {
-        'action': 'createInfluxDBContainer'
+        'action': 'create_influxdb'
     }
 
 This is an asynchronous API. You need to call /yardstick/asynctask API to get the task result.
@@ -55,7 +55,7 @@ Start and config a Grafana docker container
 Example::
 
     {
-        'action': 'createGrafanaContainer'
+        'action': 'create_grafana'
     }
 
 This is an asynchronous API. You need to call /yardstick/asynctask API to get the task result.
@@ -73,10 +73,15 @@ Method: GET
 Get the status of asynchronous tasks
 Example::
 
-    http://localhost:8888/yardstick/asynctask?task_id=3f3f5e03-972a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/yardstick/asynctask?task_id=3f3f5e03-972a-4847-a5f8-154f1b31db8c
 
 The returned status will be 0(running), 1(finished) and 2(failed).
 
+NOTE::
+
+    <SERVER IP>: The ip of the host where you start your yardstick container
+    <PORT>: The outside port of port mapping which set when you start start yardstick container
+
 
 /yardstick/testcases
 ^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +95,7 @@ Method: GET
 Get a list of released test cases
 Example::
 
-    http://localhost:8888/yardstick/testcases
+    http://<SERVER IP>:<PORT>/yardstick/testcases
 
 
 /yardstick/testcases/release/action
@@ -106,10 +111,10 @@ Run a released test case
 Example::
 
     {
-        'action': 'runTestCase',
+        'action': 'run_test_case',
         'args': {
             'opts': {},
-            'testcase': 'tc002'
+            'testcase': 'opnfv_yardstick_tc002'
         }
     }
 
@@ -129,7 +134,7 @@ Run a sample test case
 Example::
 
     {
-        'action': 'runTestCase',
+        'action': 'run_test_case',
         'args': {
             'opts': {},
             'testcase': 'ping'
@@ -151,7 +156,7 @@ Method: GET
 Get the documentation of a certain test case
 Example::
 
-    http://localhost:8888/yardstick/taskcases/opnfv_yardstick_tc002/docs
+    http://<SERVER IP>:<PORT>/yardstick/taskcases/opnfv_yardstick_tc002/docs
 
 
 /yardstick/testsuites/action
@@ -167,10 +172,10 @@ Run a test suite
 Example::
 
     {
-        'action': 'runTestSuite',
+        'action': 'run_test_suite',
         'args': {
             'opts': {},
-            'testcase': 'smoke'
+            'testsuite': 'opnfv_smoke'
         }
     }
 
@@ -178,6 +183,7 @@ This is an asynchronous API. You need to call /yardstick/results to get the resu
 
 
 /yardstick/tasks/<task_id>/log
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to get the real time log of test case execution.
 
@@ -188,7 +194,7 @@ Method: GET
 Get real time of test case execution
 Example::
 
-    http://localhost:8888/yardstick/tasks/14795be8-f144-4f54-81ce-43f4e3eab33f/log?index=0
+    http://<SERVER IP>:<PORT>/yardstick/tasks/14795be8-f144-4f54-81ce-43f4e3eab33f/log?index=0
 
 
 /yardstick/results
@@ -203,17 +209,18 @@ Method: GET
 Get test results of one task
 Example::
 
-    http://localhost:8888/yardstick/results?task_id=3f3f5e03-972a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/yardstick/results?task_id=3f3f5e03-972a-4847-a5f8-154f1b31db8c
 
 This API will return a list of test case result
 
 
-/api/v2/yardstick/openrcs/action
+/api/v2/yardstick/openrcs
+^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API provides functionality of handling OpenStack credential file (openrc). For Euphrates, it supports:
 
 1. Upload an openrc file for an OpenStack environment;
-2. Update an openrc file;
+2. Update an openrc;
 3. Get openrc file information;
 4. Delete an openrc file.
 
@@ -260,12 +267,21 @@ Example::
     }
 
 
+/api/v2/yardstick/openrcs/<openrc_id>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API provides functionality of handling OpenStack credential file (openrc). For Euphrates, it supports:
+
+1. Get openrc file information;
+2. Delete an openrc file.
+
+
 METHOD: GET
 
 Get openrc file information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/openrcs/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/openrcs/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
 METHOD: DELETE
@@ -274,16 +290,15 @@ METHOD: DELETE
 Delete openrc file
 Example::
 
-    http://localhost:8888/api/v2/yardstick/openrcs/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/openrcs/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
-/api/v2/yardstick/pods/action
+/api/v2/yardstick/pods
+^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API provides functionality of handling Yardstick pod file (pod.yaml). For Euphrates, it supports:
 
 1. Upload a pod file;
-2. Get pod file information;
-3. Delete an openrc file.
 
 Which API to call will depend on the parameters.
 
@@ -303,12 +318,20 @@ Example::
     }
 
 
+/api/v2/yardstick/pods/<pod_id>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API provides functionality of handling Yardstick pod file (pod.yaml). For Euphrates, it supports:
+
+1. Get pod file information;
+2. Delete an openrc file.
+
 METHOD: GET
 
 Get pod file information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/pods/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/pods/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
 METHOD: DELETE
@@ -316,16 +339,15 @@ METHOD: DELETE
 Delete openrc file
 Example::
 
-    http://localhost:8888/api/v2/yardstick/pods/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/pods/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
-/api/v2/yardstick/images/action
+/api/v2/yardstick/images
+^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to Yardstick VM images. For Euphrates, it supports:
 
 1. Load Yardstick VM images;
-2. Get image's information;
-3. Delete images.
 
 Which API to call will depend on the parameters.
 
@@ -337,16 +359,27 @@ Load VM images
 Example::
 
     {
-        'action': 'load_images'
+        'action': 'load_image',
+        'args': {
+            'name': 'yardstick-image'
+        }
     }
 
 
+/api/v2/yardstick/images/<image_id>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to Yardstick VM images. For Euphrates, it supports:
+
+1. Get image's information;
+2. Delete images
+
 METHOD: GET
 
 Get image information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/images/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/images/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
 METHOD: DELETE
@@ -354,19 +387,15 @@ METHOD: DELETE
 Delete images
 Example::
 
-    http://localhost:8888/api/v2/yardstick/images/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/images/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
-/api/v2/yardstick/tasks/action
+/api/v2/yardstick/tasks
+^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to yardstick tasks. For Euphrates, it supports:
 
 1. Create a Yardstick task;
-2. run a Yardstick task;
-3. Add a test case to a task;
-4. Add a test suite to a task;
-5. Get a tasks' information;
-6. Delete a task.
 
 Which API to call will depend on the parameters.
 
@@ -386,20 +415,35 @@ Example::
     }
 
 
+/api/v2/yardstick/tasks/<task_id>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to yardstick tasks. For Euphrates, it supports:
+
+1. Add a environment to a task
+2. Add a test case to a task;
+3. Add a test suite to a task;
+4. run a Yardstick task;
+5. Get a tasks' information;
+6. Delete a task.
+
+
 METHOD: PUT
 
+Add a environment to a task
 
-Run a task
 Example::
 
     {
-        'action': 'run'
+        'action': 'add_environment',
+        'args': {
+            'environment_id': 'e3cadbbb-0419-4fed-96f1-a232daa0422a'
+        }
     }
 
 
 METHOD: PUT
 
-
 Add a test case to a task
 Example::
 
@@ -412,8 +456,8 @@ Example::
     }
 
 
-METHOD: PUT
 
+METHOD: PUT
 
 Add a test suite to a task
 Example::
@@ -427,29 +471,41 @@ Example::
     }
 
 
+METHOD: PUT
+
+Run a task
+
+Example::
+
+    {
+        'action': 'run'
+    }
+
+
+
 METHOD: GET
 
 Get a task's information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/tasks/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/tasks/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
 METHOD: DELETE
 
 Delete a task
+
 Example::
-    http://localhost:8888/api/v2/yardstick/tasks/5g6g3e02-155a-4847-a5f8-154f1b31db8c
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/tasks/5g6g3e02-155a-4847-a5f8-154f1b31db8c
 
 
-/api/v2/yardstick/testcases/action
+/api/v2/yardstick/testcases
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to yardstick testcases. For Euphrates, it supports:
 
 1. Upload a test case;
 2. Get all released test cases' information;
-3. Get a certain released test case's information;
-4. Delete a test case.
 
 Which API to call will depend on the parameters.
 
@@ -474,16 +530,24 @@ METHOD: GET
 Get all released test cases' information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/testcases
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testcases
+
+
+/api/v2/yardstick/testcases/<case_name>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to yardstick testcases. For Euphrates, it supports:
 
+1. Get certain released test case's information;
+2. Delete a test case.
 
 METHOD: GET
 
 
-Get certain released test case's information
+Get certain released test case's information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/testcases/opnfv_yardstick_tc002
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testcases/opnfv_yardstick_tc002
 
 
 METHOD: DELETE
@@ -491,17 +555,16 @@ METHOD: DELETE
 
 Delete a certain test case
 Example::
-    http://localhost:8888/api/v2/yardstick/testcases/opnfv_yardstick_tc002
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testcases/opnfv_yardstick_tc002
 
 
-/api/v2/yardstick/testsuites/action
+/api/v2/yardstick/testsuites
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to yardstick test suites. For Euphrates, it supports:
 
 1. Create a test suite;
-2. Get a certain test suite's information;
-3. Get all test suites;
-4. Delete a test case.
+2. Get all test suites;
 
 Which API to call will depend on the parameters.
 
@@ -526,19 +589,27 @@ Example::
 METHOD: GET
 
 
-Get a certain test suite's information
+Get all test suite
 Example::
 
-    http://localhost:8888/api/v2/yardstick/testsuites/<suite_name>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testsuites
+
+
+/api/v2/yardstick/testsuites
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to yardstick test suites. For Euphrates, it supports:
 
+1. Get certain test suite's information;
+2. Delete a test case.
 
 METHOD: GET
 
 
-Get all test suite
+Get certain test suite's information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/testsuites
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testsuites/<suite_name>
 
 
 METHOD: DELETE
@@ -547,17 +618,16 @@ METHOD: DELETE
 Delete a certain test suite
 Example::
 
-    http://localhost:8888/api/v2/yardstick/testsuites/<suite_name>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/testsuites/<suite_name>
 
 
-/api/v2/yardstick/projects/action
+/api/v2/yardstick/projects
+^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to yardstick test projects. For Euphrates, it supports:
 
 1. Create a Yardstick project;
-2. Get a certain project's information;
-3. Get all projects;
-4. Delete a project.
+2. Get all projects;
 
 Which API to call will depend on the parameters.
 
@@ -579,19 +649,27 @@ Example::
 METHOD: GET
 
 
-Get a certain project's information
+Get all projects' information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/projects/<project_id>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/projects
+
 
+/api/v2/yardstick/projects
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to yardstick test projects. For Euphrates, it supports:
+
+1. Get certain project's information;
+2. Delete a project.
 
 METHOD: GET
 
 
-Get all projects' information
+Get certain project's information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/projects
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/projects/<project_id>
 
 
 METHOD: DELETE
@@ -600,17 +678,16 @@ METHOD: DELETE
 Delete a certain project
 Example::
 
-    http://localhost:8888/api/v2/yardstick/projects/<project_id>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/projects/<project_id>
 
 
-/api/v2/yardstick/containers/action
+/api/v2/yardstick/containers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Description: This API is used to do some work related to Docker containers. For Euphrates, it supports:
 
 1. Create a Grafana Docker container;
 2. Create an InfluxDB Docker container;
-3. Get a certain container's information;
-4. Delete a container.
 
 Which API to call will depend on the parameters.
 
@@ -643,13 +720,21 @@ Example::
     }
 
 
+/api/v2/yardstick/containers/<container_id>
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Description: This API is used to do some work related to Docker containers. For Euphrates, it supports:
+
+1. Get certain container's information;
+2. Delete a container.
+
 METHOD: GET
 
 
-Get certain container's information
+Get certain container's information
 Example::
 
-    http://localhost:8888/api/v2/yardstick/containers/<container_id>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/containers/<container_id>
 
 
 METHOD: DELETE
@@ -658,4 +743,4 @@ METHOD: DELETE
 Delete a certain container
 Example::
 
-    http://localhost:8888/api/v2/yardstick/containers/<container_id>
+    http://<SERVER IP>:<PORT>/api/v2/yardstick/containers/<container_id>
index 8ce90f6..332dba4 100644 (file)
@@ -197,7 +197,9 @@ VNFs supported for chracterization:
 1. CGNAPT - Carrier Grade Network Address and port Translation
 2. vFW - Virtual Firewall
 3. vACL - Access Control List
-5. Prox - Packet pROcessing eXecution engine:
-    - VNF can act as Drop, Basic Forwarding (no touch), L2 Forwarding (change MAC), GRE encap/decap, Load balance based on packet fields, Symmetric load balancing,
+4. Prox - Packet pROcessing eXecution engine:
+    - VNF can act as Drop, Basic Forwarding (no touch),
+      L2 Forwarding (change MAC), GRE encap/decap, Load balance based on
+      packet fields, Symmetric load balancing
     - QinQ encap/decap IPv4/IPv6, ARP, QoS, Routing, Unmpls, Policing, ACL
-6. UDP_Replay
+5. UDP_Replay
index 57e8ddf..8d79e01 100644 (file)
@@ -125,7 +125,12 @@ Yardstick Test Case Description TC019
 +--------------+--------------------------------------------------------------+
 |post-action   | It is the action when the test cases exist. It will check    |
 |              | the status of the specified process on the host, and restart |
-|              | the process if it is not running for next test cases         |
+|              | the process if it is not running for next test cases.        |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index 0b0993c..3781760 100644 (file)
@@ -128,9 +128,14 @@ Yardstick Test Case Description TC045
 |              | Result: The test case is passed or not.                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|post-action   | It is the action when the test cases exist. It will check the|
-|              | status of the specified process on the host, and restart the |
-|              | process if it is not running for next test cases             |
+|post-action   | It is the action when the test cases exist. It will check    |
+|              | the status of the specified process on the host, and restart |
+|              | the process if it is not running for next test cases.        |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index cce6c68..5308c8e 100644 (file)
@@ -127,9 +127,14 @@ Yardstick Test Case Description TC046
 |              | Result: The test case is passed or not.                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|post-action   | It is the action when the test cases exist. It will check the|
-|              | status of the specified process on the host, and restart the |
-|              | process if it is not running for next test cases             |
+|post-action   | It is the action when the test cases exist. It will check    |
+|              | the status of the specified process on the host, and restart |
+|              | the process if it is not running for next test cases.        |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index 95158cf..bb8ffc6 100644 (file)
@@ -128,9 +128,14 @@ Yardstick Test Case Description TC047
 |              | Result: The test case is passed or not.                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|post-action   | It is the action when the test cases exist. It will check the|
-|              | status of the specified process on the host, and restart the |
-|              | process if it is not running for next test cases             |
+|post-action   | It is the action when the test cases exist. It will check    |
+|              | the status of the specified process on the host, and restart |
+|              | the process if it is not running for next test cases.        |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index 21c00d1..1bf6272 100644 (file)
@@ -128,9 +128,14 @@ Yardstick Test Case Description TC048
 |              | Result: The test case is passed or not.                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|post-action   | It is the action when the test cases exist. It will check the|
-|              | status of the specified process on the host, and restart the |
-|              | process if it is not running for next test cases             |
+|post-action   | It is the action when the test cases exist. It will check    |
+|              | the status of the specified process on the host, and restart |
+|              | the process if it is not running for next test case          |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index f58bb99..12ed94b 100644 (file)
@@ -128,9 +128,14 @@ Yardstick Test Case Description TC049
 |              | Result: The test case is passed or not.                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|post-action   | It is the action when the test cases exist. It will check the|
-|              | status of the specified process on the host, and restart the |
-|              | process if it is not running for next test cases             |
+|post-action   | It is the action when the test cases exist. It will check    |
+|              | the status of the specified process on the host, and restart |
+|              | the process if it is not running for next test cases.        |
+|              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
index 3c6bbc6..7308bab 100644 (file)
@@ -135,6 +135,11 @@ Yardstick Test Case Description TC053
 |              | the status of the specified process on the host, and restart |
 |              | the process if it is not running for next test cases.        |
 |              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
+|              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
 |              | execution problem.                                           |
index 09b866c..cd8cc2f 100644 (file)
@@ -142,6 +142,11 @@ Yardstick Test Case Description TC056
 |              | the status of the specified process on the host, and restart |
 |              | the process if it is not running for next test cases.        |
 |              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
+|              |                                                              |
 +--------------+--------------------------------------------------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
 |              | execution problem.                                           |
index bb42b2a..1bb43c9 100644 (file)
@@ -162,8 +162,14 @@ Yardstick Test Case Description TC057
 |post-action   | It is the action when the test cases exist. It will check    |
 |              | the status of the cluster messaging process(corosync) on the |
 |              | host, and restart the process if it is not running for next  |
-|              | test cases                                                   |
+|              | test cases.                                                  |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
+|              |                                                              |
 +--------------+------+----------------------------------+--------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
 |              | execution problem.                                           |
+|              |                                                              |
 +--------------+--------------------------------------------------------------+
index 7c323e9..9e8427b 100644 (file)
@@ -109,8 +109,9 @@ Yardstick Test Case Description TC058
 |conditions    | with cachestat included in the image.                        |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
-|step 1        | Two host VMs are booted, these two hosts are in two different|
-|              | networks, the networks are connected by a virtual router     |
+|step 1        | Two host VMs are booted, these two hosts are in two          |
+|              | different networks, the networks are connected by a virtual  |
+|              | router.                                                      |
 |              |                                                              |
 +--------------+--------------------------------------------------------------+
 |step 1        | start monitors:                                              |
@@ -143,7 +144,13 @@ Yardstick Test Case Description TC058
 |              | Virtual machines and network created in the test case will   |
 |              | be destoryed.                                                |
 |              |                                                              |
+|              | Notice: This post-action uses 'lsb_release' command to check |
+|              | the host linux distribution and determine the OpenStack      |
+|              | service name to restart the process. Lack of 'lsb_release'   |
+|              | on the host may cause failure to restart the process.        |
+|              |                                                              |
 +--------------+------+----------------------------------+--------------------+
 |test verdict  | Fails only if SLA is not passed, or if there is a test case  |
 |              | execution problem.                                           |
+|              |                                                              |
 +--------------+--------------------------------------------------------------+
index bf07a01..8ed7936 100644 (file)
@@ -31,5 +31,11 @@ nodes:
 
 networks:
   - name: management
+    default_gateway: True
     host_ip: 192.168.1.1
     netmask: 255.255.255.0
+
+  - name: traffic
+    default_gateway: False  # This parameter is not mandatory, default value: False
+    host_ip: 192.20.1.1
+    netmask: 255.255.255.0
index 5ce5552..301433d 100644 (file)
@@ -49,3 +49,16 @@ nodes:
     ip: ip5
     user: node_username
     key_filename: node_keyfile
+-
+    name: node6
+    role: Opendaylight
+    ip: ip6
+    user: node_username
+    key_filename: node_keyfile
+-
+    name: node7
+    role: Gateway
+    ip: ip7
+    user: node_username
+    key_filename: node_keyfile
+
index d959b14..2ea1cab 100644 (file)
@@ -93,6 +93,7 @@
     <script src="scripts/controllers/detail.controller.js"></script>
     <script src="scripts/controllers/image.controller.js"></script>
     <script src="scripts/controllers/pod.controller.js"></script>
+    <script src="scripts/controllers/sut.controller.js"></script>
     <script src="scripts/controllers/container.controller.js"></script>
     <script src="scripts/controllers/testcase.controller.js"></script>
     <script src="scripts/controllers/testcasedetail.controller.js"></script>
index 3ad200a..a7d5f03 100644 (file)
@@ -127,10 +127,15 @@ angular.module('yardStickGui2App')
             function chooseResult(name) {
                 $scope.selectContainer = name;
             }
+
             $scope.goBack = function goBack() {
                 $state.go('app.projectList');
             }
 
+            $scope.goNext = function goNext() {
+                $state.go('app.sut', {uuid: $scope.uuid});
+            }
+
             $scope.openDeleteEnv = function openDeleteEnv(id, name) {
                 $scope.deleteName = name;
                 $scope.deleteId = id;
index 0288fa5..90a3f14 100644 (file)
@@ -49,6 +49,7 @@ angular.module('yardStickGui2App')
                 $scope.gotoOpenrcPage = gotoOpenrcPage;
                 $scope.gotoPodPage = gotoPodPage;
                 $scope.gotoContainerPage = gotoContainerPage;
+                $scope.gotoSUTPage = gotoSUTPage;
                 $scope.gotoTestcase = gotoTestcase;
                 $scope.gotoEnviron = gotoEnviron;
                 $scope.gotoSuite = gotoSuite;
@@ -95,6 +96,12 @@ angular.module('yardStickGui2App')
                 $state.go('app.container', { uuid: $scope.uuid });
             }
 
+            function gotoSUTPage() {
+                $scope.path = $location.path();
+                $scope.uuid = $scope.path.split('/').pop();
+                $state.go('app.sut', { uuid: $scope.uuid });
+            }
+
             function gotoTestcase() {
                 $state.go('app.testcase');
             }
diff --git a/gui/app/scripts/controllers/sut.controller.js b/gui/app/scripts/controllers/sut.controller.js
new file mode 100644 (file)
index 0000000..092aabc
--- /dev/null
@@ -0,0 +1,58 @@
+'use strict';
+
+angular.module('yardStickGui2App')
+    .controller('SUTController', ['$scope', '$state', '$stateParams', 'mainFactory', 'Upload', 'toaster', '$location', 'ngDialog',
+        function($scope, $state, $stateParams, mainFactory, Upload, toaster, $location, ngDialog) {
+
+
+            init();
+            $scope.showloading = false;
+            $scope.loadingOPENrc = false;
+
+            function init() {
+
+
+                $scope.uuid = $stateParams.uuid;
+                $scope.sutInfo = {};
+                getItemIdDetail();
+                getSUTDetail();
+
+            }
+
+            function getItemIdDetail() {
+                mainFactory.ItemDetail().get({
+                    'envId': $scope.uuid
+                }).$promise.then(function(response) {
+                    if (response.status == 1) {
+                        $scope.envName = response.result.environment.name;
+                    }else{
+                        mainFactory.errorHandler1(response);
+                    }
+                }, function(error) {
+                    mainFactory.errorHandler2(error);
+                })
+            }
+
+            function getSUTDetail(){
+                mainFactory.SUTDetail().get({
+                    'envId': $scope.uuid
+                }).$promise.then(function(resp){
+                    $scope.sutInfo = resp.result.sut;
+                    console.log($scope.sutInfo);
+                }, function(error){
+                })
+            }
+
+            $scope.goBack = function goBack() {
+                $state.go('app.projectList');
+            }
+
+
+            $scope.goNext = function goNext() {
+                $scope.path = $location.path();
+                $scope.uuid = $scope.path.split('/').pop();
+                $state.go('app.container', { uuid: $scope.uuid });
+            }
+
+        }
+    ]);
index b36838b..f753693 100644 (file)
@@ -58,6 +58,13 @@ angular.module('yardStickGui2App')
                     }
                 })
             },
+            SUTDetail: function() {
+                return $resource(Base_URL + '/api/v2/yardstick/environments/:envId/sut', { envId: "@envId" }, {
+                    'get': {
+                        method: 'GET'
+                    }
+                })
+            },
             ImageDetail: function() {
                 return $resource(Base_URL + '/api/v2/yardstick/images/:image_id', { image_id: "@image_id" }, {
                     'get': {
index da2eb08..75d5372 100644 (file)
@@ -116,6 +116,15 @@ angular.module('yardStickGui2App')
                         label: 'Container Manage'
                     }
                 })
+                .state('app.sut', {
+                    url: '/envsut/:uuid',
+                    templateUrl: 'views/sut.html',
+                    controller: 'SUTController',
+                    params: { uuid: null },
+                    ncyBreadcrumb: {
+                        label: 'SUT Manage'
+                    }
+                })
                 .state('app.projectList', {
                     url: '/project',
                     templateUrl: 'views/projectList.html',
index b3d78bf..ea59029 100644 (file)
@@ -5,7 +5,7 @@
         <div style="width:750px;">
 
             <h3>{{envName}} -- Container
-                <!--<button class="btn btn-default" style="float:right">Go Next</button>-->
+                <button class="btn btn-default" ng-click="goNext()" style="float:right">Next</button>
 
             </h3>
             <!--<p>In this process, you can input your define openrc config or upload a openrc file</p>-->
index 6c44263..2333d22 100644 (file)
@@ -42,6 +42,9 @@
                     <div class="panel-body " style="border:none;text-align: right;cursor:pointer" ng-click="gotoContainerPage()" ng-class="{active:$state.includes('app.container')}">
                         Container
                     </div>
+                    <div class="panel-body " style="border:none;text-align: right;cursor:pointer" ng-click="gotoSUTPage()" ng-class="{active:$state.includes('app.sut')}">
+                        SUT
+                    </div>
                     <div class="panel-body " style="border:none;text-align: right;">
                         Others
                     </div>
     .active.panel-body {
         background-color: #dfe3e4;
     }
-</style>
\ No newline at end of file
+</style>
diff --git a/gui/app/views/sut.html b/gui/app/views/sut.html
new file mode 100644 (file)
index 0000000..8cf1fcd
--- /dev/null
@@ -0,0 +1,33 @@
+<!--sut management-->
+
+<div class="content">
+    <div style="display:flex;flex-direction:row;">
+        <div style="width:750px;">
+
+            <h3>{{envName}} -- SUT
+                <!--<button class="btn btn-default" style="float:right">Go Next</button>-->
+
+            </h3>
+
+            <h2>Hosts</h2>
+            <div ng-repeat="(host, info) in sutInfo">
+                <hr/>
+                <div  class="results-table" style="margin-top:30px;">
+                    <table class="table table-striped table-hover">
+                        <tbody style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
+                            <tr ng-repeat="record in info">
+                                <td>{{ record[0] }}</td>
+                                <td>{{ record[1] }}</td>
+                            </tr>
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</div>
+<toaster-container></toaster-container>
+
+<style>
+</style>
index fde2907..2921f5d 100644 (file)
@@ -22,4 +22,5 @@ scenarios:
 
 context:
   type: Dummy
+  name: Dummy
 
diff --git a/samples/netperf_soak.yaml b/samples/netperf_soak.yaml
new file mode 100644 (file)
index 0000000..a7344da
--- /dev/null
@@ -0,0 +1,71 @@
+##############################################################################
+# Copyright (c) 2018 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+---
+# Bottlenecks long duration test need Yardstick to create VM pairs and use netperf sending messages
+# This yaml file for the above operations based on Netperf mode similiar as netperf.yaml
+# UDP_STREAM is used and out_opt is customized
+
+schema: "yardstick:task:0.1"
+
+{% set tx_msg_size = tx_msg_size or "8K" %}
+{% set rx_msg_size = rx_msg_size or "8K" %}
+{% set test_time = test_time or "10" %}
+{% set out_opt = out_opt or "THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY,LOCAL_CPU_UTIL,REMOTE_CPU_UTIL,LOCAL_BYTES_SENT,REMOTE_BYTES_RECVD" %}
+{% set image_name = image_name or "yardstick-image" %}
+{% set cpu_num = cpu_num or 1 %}
+{% set ram_num = ram_num or 512 %}
+{% set disk_num = disk_num or 7 %}
+
+scenarios:
+-
+  type: Netperf
+  options:
+    testname: 'UDP_STREAM'
+    send_msg_size: {{tx_msg_size}}
+    recv_msg_size: {{rx_msg_size}}
+    duration: {{test_time}}
+    output_opt: {{out_opt}}
+
+  host: netperf-host.demo
+  target: netperf-target.demo
+
+  runner:
+    type: Iteration
+    iterations: 1
+    interval: 1
+    run_step: 'setup,run'
+
+  sla:
+    mean_latency: 100
+    action: monitor
+
+context:
+  name: demo
+  image: {{image_name}}
+  flavor:
+    vcpus: {{cpu_num}}
+    ram: {{ram_num}}
+    disk: {{disk_num}}
+  user: ubuntu
+
+  placement_groups:
+    pgrp1:
+      policy: "availability"
+
+  servers:
+    netperf-host:
+      floating_ip: true
+      placement: "pgrp1"
+    netperf-target:
+      floating_ip: false
+      placement: "pgrp1"
+
+  networks:
+    test:
+      cidr: '10.0.1.0/24'
index b1fef6d..69778ed 100644 (file)
@@ -26,6 +26,8 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_l2fwd-2.cfg"
index e17c5c2..ab067a8 100644 (file)
@@ -26,6 +26,8 @@ scenarios:
     vnf__0: vnf_0.yardstick
 
   options:
+    interface_speed_gbps: 10
+
     vnf__0:
       prox_path: /opt/nsb_bin/prox
       prox_config: "configs/handle_l2fwd-4.cfg"
index caaba9e..d723823 100755 (executable)
@@ -67,6 +67,7 @@ build_yardstick_image()
             cd ${ANSIBLE_SCRIPTS} &&\
             ansible-playbook \
                      -e img_property="normal" \
+                     -e YARD_IMG_ARCH=${YARD_IMG_ARCH} \
                      -vvv -i inventory.ini build_yardstick_image.yml
 
             if [ ! -f "${QCOW_IMAGE}" ]; then
index 886e50e..d7c60d4 100755 (executable)
@@ -72,10 +72,12 @@ if [ "$INSTALLER_TYPE" == "fuel" ]; then
 
     # update "ip" according to the CI env
     ssh -l ubuntu "${INSTALLER_IP}" -i ${SSH_KEY} ${ssh_options} \
-         "sudo salt -C 'ctl* or cmp*' grains.get fqdn_ip4  --out yaml">node_info
+         "sudo salt -C 'ctl* or cmp* or odl01* or gtw*' grains.get fqdn_ip4  --out yaml">node_info
 
-    controller_ips=($(awk '/ctl/{getline; print $2} < node_info'))
-    compute_ips=($(awk '/cmp/{getline; print $2} < node_info'))
+    controller_ips=($(awk '/ctl/{getline; print $2}' < node_info))
+    compute_ips=($(awk '/cmp/{getline; print $2}' < node_info))
+    odl_ip=($(awk '/odl01/{getline; print $2}' < node_info))
+    gateway_ip=($(awk '/gtw/{getline; print $2}' < node_info))
 
     if [[ ${controller_ips[0]} ]]; then
         sed -i "s|ip1|${controller_ips[0]}|" "${pod_yaml}"
@@ -92,6 +94,12 @@ if [ "$INSTALLER_TYPE" == "fuel" ]; then
     if [[ ${compute_ips[1]} ]]; then
         sed -i "s|ip5|${compute_ips[1]}|" "${pod_yaml}"
     fi
+    if [[ ${odl_ip[0]} ]]; then
+        sed -i "s|ip6|${odl_ip[0]}|" "${pod_yaml}"
+    fi
+    if [[ ${gateway_ip[0]} ]]; then
+        sed -i "s|ip7|${gateway_ip[0]}|" "${pod_yaml}"
+    fi
 
     # update 'user' and 'key_filename' according to the CI env
     sed -i "s|node_username|${USER_NAME}|;s|node_keyfile|${SSH_KEY}|" "${pod_yaml}"
index faceeb6..bc48f99 100644 (file)
@@ -24,7 +24,7 @@ import unittest
 from tests.unit import STL_MOCKS
 from yardstick.common import utils
 from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
-
+from yardstick.network_services import constants
 
 STLClient = mock.MagicMock()
 stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
@@ -46,7 +46,6 @@ if stl_patch:
     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxVpeProfileHelper
     from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxlwAFTRProfileHelper
 
-
 class TestCoreTuple(unittest.TestCase):
     def test___init__(self):
         core_tuple = CoreSocketTuple('core 5s6')
@@ -1537,7 +1536,9 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.port_stats.return_value = list(range(10))
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, pkt_size, 25, None)
+        data_helper = ProxDataHelper(
+            vnfd_helper, sut, pkt_size, 25, None,
+            constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
 
         self.assertEqual(data_helper.rx_total, 6)
         self.assertEqual(data_helper.tx_total, 7)
@@ -1551,7 +1552,7 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.port_stats.return_value = list(range(10))
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None)
+        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None, None)
 
         expected = {
             'xe1': {
@@ -1574,13 +1575,15 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.port_stats.return_value = list(range(10))
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, 5.4)
+        data_helper = ProxDataHelper(vnfd_helper, sut, None, None,
+            5.4, constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
         data_helper._totals_and_pps = 12, 32, 4.5
         data_helper.tsc_hz = 9.8
         data_helper.measured_stats = {'delta': TotStatsTuple(6.1, 6.2, 6.3, 6.4)}
         data_helper.latency = 7
 
         self.assertIsNone(data_helper.result_tuple)
+        self.assertEqual(data_helper.line_speed, 10000000000)
 
         expected = ProxTestDataTuple(5.4, 9.8, 6.1, 6.2, 6.3, 7, 12, 32, 4.5)
         with data_helper:
@@ -1595,7 +1598,7 @@ class TestProxDataHelper(unittest.TestCase):
     def test___enter___negative(self):
         vnfd_helper = mock.MagicMock()
 
-        data_helper = ProxDataHelper(vnfd_helper, None, None, None, None)
+        data_helper = ProxDataHelper(vnfd_helper, None, None, None, None, None)
 
         vnfd_helper.port_pairs.all_ports = []
         with self.assertRaises(AssertionError):
@@ -1617,7 +1620,7 @@ class TestProxDataHelper(unittest.TestCase):
         sut = ProxSocketHelper(mock.MagicMock())
         sut.get_all_tot_stats = mock.MagicMock(side_effect=[start, end])
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, 5.4)
+        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, 5.4, None)
 
         self.assertIsNone(data_helper.measured_stats)
 
@@ -1638,7 +1641,7 @@ class TestProxDataHelper(unittest.TestCase):
         sut = mock.MagicMock()
         sut.hz.return_value = '54.6'
 
-        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None)
+        data_helper = ProxDataHelper(vnfd_helper, sut, None, None, None, None)
 
         self.assertIsNone(data_helper.tsc_hz)
 
@@ -1935,7 +1938,8 @@ class TestProxProfileHelper(unittest.TestCase):
 
         helper = ProxProfileHelper(resource_helper)
 
-        helper.run_test(120, 5, 6.5)
+        helper.run_test(120, 5, 6.5,
+                        constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
 
 
 class TestProxMplsProfileHelper(unittest.TestCase):
@@ -2081,8 +2085,12 @@ class TestProxBngProfileHelper(unittest.TestCase):
 
         helper = ProxBngProfileHelper(resource_helper)
 
-        helper.run_test(120, 5, 6.5)
-        helper.run_test(-1000, 5, 6.5)  # negative pkt_size is the only way to make ratio > 1
+        helper.run_test(120, 5, 6.5,
+                        constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+        # negative pkt_size is the only way to make ratio > 1
+        helper.run_test(-1000, 5, 6.5,
+                        constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
 
 
 class TestProxVpeProfileHelper(unittest.TestCase):
index 7f6309a..e7acde6 100644 (file)
@@ -149,7 +149,7 @@ class Task(object):     # pragma: no cover
                  total_end_time - total_start_time)
 
         LOG.info('To generate report, execute command "yardstick report '
-                 'generate %(task_id)s <yaml_name>s"', self.task_id)
+                 'generate %s <YAML_NAME>"', self.task_id)
         LOG.info("Task ALL DONE, exiting")
         return result
 
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/add_server_to_existing_secgroup.bash
new file mode 100644 (file)
index 0000000..3a50626
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2018 Intracom Telecom and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# add server to existing security group
+# parameters: $1 - server name, $2 - security group name
+
+set -e
+
+if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then
+    SECURE="--insecure"
+else
+    SECURE=""
+fi
+
+SECGROUPNAME="$(openstack ${SECURE} security group list -f value -c Name | grep $2)"
+
+openstack ${SECURE} server add security group $1 ${SECGROUPNAME}
+
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_instance_from_image.bash
new file mode 100644 (file)
index 0000000..5e0b1cc
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2018 Intracom Telecom and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# create nova server
+# parameters: $1 - server name, $2 - image name, $3 - flavor name, $4 - network name
+
+set -e
+
+if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then
+    SECURE="--insecure"
+else
+    SECURE=""
+fi
+
+NETNAME="$(openstack ${SECURE} network list -f value -c Name | grep $4)"
+
+openstack ${SECURE} server create $1 --image $2 --flavor $3 --network ${NETNAME}
+
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_instance.bash
new file mode 100644 (file)
index 0000000..008e7f5
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2018 Intracom Telecom and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# delete nova server
+# parameters: $1 - server name
+
+set -e
+
+if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then
+    SECURE="--insecure"
+else
+    SECURE=""
+fi
+
+openstack ${SECURE} server delete $1
+
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/get_server_privateip.bash
new file mode 100644 (file)
index 0000000..7f2bad5
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2018 Intracom Telecom and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# get private ip of a server
+# parameter: $1 - server name
+
+set -e
+
+if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then
+    SECURE="--insecure"
+else
+    SECURE=""
+fi
+
+openstack ${SECURE} server list -f value -c Name -c Networks | grep $1 | awk '{print $2}' | sed -r 's/.*=([0-9\.\:]+)[;,]*/\1/'
+
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/remove_server_from_secgroup.bash
new file mode 100644 (file)
index 0000000..61d0a2b
--- /dev/null
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+##############################################################################
+# Copyright (c) 2018 Intracom Telecom and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+# remove server from existing security group
+# parameters: $1 - server name, $2 - security group name
+
+set -e
+
+if [ $OS_INSECURE ] && [ "$(echo $OS_INSECURE | tr '[:upper:]' '[:lower:]')" = "true" ]; then
+    SECURE="--insecure"
+else
+    SECURE=""
+fi
+
+SECGROUPNAME="$(openstack ${SECURE} security group list -f value -c Name | grep $2)"
+
+openstack ${SECURE} server remove security group $1 ${SECGROUPNAME}
index 0ca8839..5f3f6c9 100644 (file)
@@ -38,3 +38,11 @@ get-vip-host:
 start-service:
   action_script: ha_tools/start_service.bash
   rollback_script: ha_tools/check_process_python.bash
+
+add-server-to-secgroup:
+  action_script: ha_tools/nova/add_server_to_existing_secgroup.bash
+  rollback_script: ha_tools/nova/remove_server_from_secgroup.bash
+
+get-privateip:
+  action_script: ha_tools/nova/get_server_privateip.bash
+  rollback_script: ha_tools/nova/list_servers.bash
index cffff13..7348205 100644 (file)
@@ -7,13 +7,12 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from __future__ import print_function
-from __future__ import absolute_import
-
 import logging
 
 from yardstick.benchmark.scenarios import base
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+
 
 LOG = logging.getLogger(__name__)
 
@@ -28,9 +27,14 @@ class CreateNetwork(base.Scenario):
         self.context_cfg = context_cfg
         self.options = self.scenario_cfg['options']
 
-        self.openstack = self.options.get("openstack_paras", None)
+        self.network_name = self.options["network_name"]
+        self.shared = self.options.get("shared", False)
+        self.admin_state_up = self.options.get("admin_state_up", True)
+        self.external = self.options.get("external", False)
+        self.provider = self.options.get("provider")
+        self.project_id = self.options.get("project_id")
 
-        self.neutron_client = op_utils.get_neutron_client()
+        self.shade_client = openstack_utils.get_shade_client()
 
         self.setup_done = False
 
@@ -45,20 +49,17 @@ class CreateNetwork(base.Scenario):
         if not self.setup_done:
             self.setup()
 
-        openstack_paras = {'network': self.openstack}
-        network_id = op_utils.create_neutron_net(self.neutron_client,
-                                                 openstack_paras)
-        if network_id:
-            result.update({"network_create": 1})
-            LOG.info("Create network successful!")
-        else:
+        network_id = openstack_utils.create_neutron_net(
+            self.shade_client, self.network_name, shared=self.shared,
+            admin_state_up=self.admin_state_up, external=self.external,
+            provider=self.provider, project_id=self.project_id)
+        if not network_id:
             result.update({"network_create": 0})
             LOG.error("Create network failed!")
+            raise exceptions.ScenarioCreateNetworkError
 
-        try:
-            keys = self.scenario_cfg.get('output', '').split()
-        except KeyError:
-            pass
-        else:
-            values = [network_id]
-            return self._push_to_outputs(keys, values)
+        result.update({"network_create": 1})
+        LOG.info("Create network successful!")
+        keys = self.scenario_cfg.get('output', '').split()
+        values = [network_id]
+        return self._push_to_outputs(keys, values)
index c34af8a..e383c99 100644 (file)
@@ -7,13 +7,12 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from __future__ import print_function
-from __future__ import absolute_import
-
 import logging
 
 from yardstick.benchmark.scenarios import base
-import yardstick.common.openstack_utils as op_utils
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+
 
 LOG = logging.getLogger(__name__)
 
@@ -28,9 +27,23 @@ class CreateSubnet(base.Scenario):
         self.context_cfg = context_cfg
         self.options = self.scenario_cfg['options']
 
-        self.openstack = self.options.get("openstack_paras", None)
-
-        self.neutron_client = op_utils.get_neutron_client()
+        self.network_name_or_id = self.options['network_name_or_id']
+        self.cidr = self.options.get('cidr')
+        self.ip_version = self.options.get('ip_version', 4)
+        self.enable_dhcp = self.options.get('enable_dhcp', False)
+        self.subnet_name = self.options.get('subnet_name')
+        self.tenant_id = self.options.get('tenant_id')
+        self.allocation_pools = self.options.get('allocation_pools')
+        self.gateway_ip = self.options.get('gateway_ip')
+        self.disable_gateway_ip = self.options.get('disable_gateway_ip', False)
+        self.dns_nameservers = self.options.get('dns_nameservers')
+        self.host_routes = self.options.get('host_routes')
+        self.ipv6_ra_mode = self.options.get('ipv6_ra_mode')
+        self.ipv6_address_mode = self.options.get('ipv6_address_mode')
+        self.use_default_subnetpool = self.options.get(
+            'use_default_subnetpool', False)
+
+        self.shade_client = openstack_utils.get_shade_client()
 
         self.setup_done = False
 
@@ -45,22 +58,23 @@ class CreateSubnet(base.Scenario):
         if not self.setup_done:
             self.setup()
 
-        openstack_paras = {'subnets': [self.openstack]}
-        subnet_id = op_utils.create_neutron_subnet(self.neutron_client,
-                                                   openstack_paras)
-        if subnet_id:
-            result.update({"subnet_create": 1})
-            LOG.info("Create subnet successful!")
-        else:
+        subnet_id = openstack_utils.create_neutron_subnet(
+            self.shade_client, self.network_name_or_id, cidr=self.cidr,
+            ip_version=self.ip_version, enable_dhcp=self.enable_dhcp,
+            subnet_name=self.subnet_name, tenant_id=self.tenant_id,
+            allocation_pools=self.allocation_pools, gateway_ip=self.gateway_ip,
+            disable_gateway_ip=self.disable_gateway_ip,
+            dns_nameservers=self.dns_nameservers, host_routes=self.host_routes,
+            ipv6_ra_mode=self.ipv6_ra_mode,
+            ipv6_address_mode=self.ipv6_address_mode,
+            use_default_subnetpool=self.use_default_subnetpool)
+        if not subnet_id:
             result.update({"subnet_create": 0})
             LOG.error("Create subnet failed!")
+            raise exceptions.ScenarioCreateSubnetError
 
-        check_result = subnet_id
-
-        try:
-            keys = self.scenario_cfg.get('output', '').split()
-        except KeyError:
-            pass
-        else:
-            values = [check_result]
-            return self._push_to_outputs(keys, values)
+        result.update({"subnet_create": 1})
+        LOG.info("Create subnet successful!")
+        keys = self.scenario_cfg.get('output', '').split()
+        values = [subnet_id]
+        return self._push_to_outputs(keys, values)
index 358fd40..5e7467b 100644 (file)
@@ -7,13 +7,12 @@
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
 
-from __future__ import print_function
-from __future__ import absolute_import
-
 import logging
 
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
 from yardstick.benchmark.scenarios import base
-import yardstick.common.openstack_utils as op_utils
+
 
 LOG = logging.getLogger(__name__)
 
@@ -28,9 +27,9 @@ class DeleteRouter(base.Scenario):
         self.context_cfg = context_cfg
         self.options = self.scenario_cfg['options']
 
-        self.router_id = self.options.get("router_id", None)
+        self.router_id = self.options["router_id"]
 
-        self.neutron_client = op_utils.get_neutron_client()
+        self.shade_client = openstack_utils.get_shade_client()
 
         self.setup_done = False
 
@@ -45,11 +44,12 @@ class DeleteRouter(base.Scenario):
         if not self.setup_done:
             self.setup()
 
-        status = op_utils.delete_neutron_router(self.neutron_client,
-                                                router_id=self.router_id)
-        if status:
-            result.update({"delete_router": 1})
-            LOG.info("Delete router successful!")
-        else:
+        status = openstack_utils.delete_neutron_router(self.shade_client,
+                                                       self.router_id)
+        if not status:
             result.update({"delete_router": 0})
             LOG.error("Delete router failed!")
+            raise exceptions.ScenarioDeleteRouterError
+
+        result.update({"delete_router": 1})
+        LOG.info("Delete router successful!")
index a8d9010..33c02d4 100755 (executable)
@@ -104,7 +104,9 @@ class Netperf(base.Scenario):
         cmd_args = "-H %s -l %s -t %s" % (ipaddr, testlen, testname)
 
         # get test specific options
-        default_args = "-O 'THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY'"
+        output_opt = options.get(
+            "output_opt", "THROUGHPUT,THROUGHPUT_UNITS,MEAN_LATENCY")
+        default_args = "-O %s" % output_opt
         cmd_args += " -- %s" % default_args
         option_pair_list = [("send_msg_size", "-m"),
                             ("recv_msg_size", "-M"),
index be262c2..38d2dd7 100644 (file)
@@ -31,6 +31,7 @@ import six.moves.configparser as ConfigParser
 import yaml
 from six import StringIO
 from chainmap import ChainMap
+from oslo_serialization import jsonutils
 
 from yardstick.common.utils import Timer
 from yardstick.common import constants as consts
@@ -508,6 +509,58 @@ class AnsibleCommon(object):
             timeout = 1200.0
         return timeout
 
+    def _generate_ansible_cfg(self, directory):
+        parser = ConfigParser.ConfigParser()
+        parser.add_section('defaults')
+        parser.set('defaults', 'host_key_checking', 'False')
+
+        cfg_path = os.path.join(directory, 'setup.cfg')
+        with open(cfg_path, 'w') as f:
+            parser.write(f)
+
+    def get_sut_info(self, directory, sut_dir='sut'):
+        if not os.path.isdir(directory):
+            raise OSError('No such directory: %s' % directory)
+
+        self._generate_ansible_cfg(directory)
+
+        prefix = 'tmp'
+        self.gen_inventory_ini_dict()
+        ini_file = self._gen_ansible_inventory_file(directory, prefix=prefix)
+        with ini_file as f:
+            inventory_path = str(f)
+
+        self._exec_get_sut_info_cmd(directory, inventory_path, sut_dir)
+
+        sut_dir = os.path.join(directory, sut_dir)
+        sut_info = self._gen_sut_info_dict(sut_dir)
+
+        return sut_info
+
+    def _exec_get_sut_info_cmd(self, directory, inventory_path, sut_dir):
+        cmd = ['ansible', 'all', '-m', 'setup', '-i',
+               inventory_path, '--tree', sut_dir]
+
+        proc = Popen(cmd, stdout=PIPE, cwd=directory)
+        output, _ = proc.communicate()
+        retcode = proc.wait()
+        LOG.debug("exit status = %s", retcode)
+        if retcode != 0:
+            raise CalledProcessError(retcode, cmd, output)
+
+    def _gen_sut_info_dict(self, sut_dir):
+        sut_info = {}
+
+        if os.path.isdir(sut_dir):
+            root, _, files = next(os.walk(sut_dir))
+            for filename in files:
+                abs_path = os.path.join(root, filename)
+                with open(abs_path) as f:
+                    data = jsonutils.load(f)
+                sut_info[filename] = data
+
+        return sut_info
+
     def execute_ansible(self, playbooks, directory, timeout=None,
                         extra_vars=None, ansible_check=False, prefix='tmp',
                         verbose=False):
index 7f72887..633b36f 100644 (file)
@@ -100,3 +100,23 @@ class TaskReadError(YardstickException):
 
 class TaskRenderError(YardstickException):
     message = 'Failed to render template:\n%(input_task)s'
+
+
+class ScenarioCreateNetworkError(YardstickException):
+    message = 'Create Neutron Network Scenario failed'
+
+
+class ScenarioCreateSubnetError(YardstickException):
+    message = 'Create Neutron Subnet Scenario failed'
+
+
+class ScenarioDeleteRouterError(YardstickException):
+    message = 'Delete Neutron Router Scenario failed'
+
+
+class MissingPodInfoError(YardstickException):
+    message = 'Missing pod args, please check'
+
+
+class UnsupportedPodFormatError(YardstickException):
+    message = 'Failed to load pod info, unsupported format'
index e3f67ba..84bfbbb 100644 (file)
@@ -435,13 +435,29 @@ def get_network_id(shade_client, network_name):
         return networks[0]['id']
 
 
-def create_neutron_net(neutron_client, json_body):      # pragma: no cover
+def create_neutron_net(shade_client, network_name, shared=False,
+                       admin_state_up=True, external=False, provider=None,
+                       project_id=None):
+    """Create a neutron network.
+
+    :param network_name:(string) name of the network being created.
+    :param shared:(bool) whether the network is shared.
+    :param admin_state_up:(bool) set the network administrative state.
+    :param external:(bool) whether this network is externally accessible.
+    :param provider:(dict) a dict of network provider options.
+    :param project_id:(string) specify the project ID this network
+                      will be created on (admin-only).
+    :returns:(string) the network id.
+    """
     try:
-        network = neutron_client.create_network(body=json_body)
-        return network['network']['id']
-    except Exception:  # pylint: disable=broad-except
-        log.error("Error [create_neutron_net(neutron_client)]")
-        raise Exception("operation error")
+        networks = shade_client.create_network(
+            name=network_name, shared=shared, admin_state_up=admin_state_up,
+            external=external, provider=provider, project_id=project_id)
+        return networks['id']
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [create_neutron_net(shade_client)]."
+                  "Exception message, '%s'", o_exc.orig_message)
+        return None
 
 
 def delete_neutron_net(shade_client, network_id):
@@ -452,13 +468,55 @@ def delete_neutron_net(shade_client, network_id):
         return False
 
 
-def create_neutron_subnet(neutron_client, json_body):      # pragma: no cover
+def create_neutron_subnet(shade_client, network_name_or_id, cidr=None,
+                          ip_version=4, enable_dhcp=False, subnet_name=None,
+                          tenant_id=None, allocation_pools=None,
+                          gateway_ip=None, disable_gateway_ip=False,
+                          dns_nameservers=None, host_routes=None,
+                          ipv6_ra_mode=None, ipv6_address_mode=None,
+                          use_default_subnetpool=False):
+    """Create a subnet on a specified network.
+
+    :param network_name_or_id:(string) the unique name or ID of the
+                              attached network. If a non-unique name is
+                              supplied, an exception is raised.
+    :param cidr:(string) the CIDR.
+    :param ip_version:(int) the IP version.
+    :param enable_dhcp:(bool) whether DHCP is enable.
+    :param subnet_name:(string) the name of the subnet.
+    :param tenant_id:(string) the ID of the tenant who owns the network.
+    :param allocation_pools: A list of dictionaries of the start and end
+                            addresses for the allocation pools.
+    :param gateway_ip:(string) the gateway IP address.
+    :param disable_gateway_ip:(bool) whether gateway IP address is enabled.
+    :param dns_nameservers: A list of DNS name servers for the subnet.
+    :param host_routes: A list of host route dictionaries for the subnet.
+    :param ipv6_ra_mode:(string) IPv6 Router Advertisement mode.
+                        Valid values are: 'dhcpv6-stateful',
+                        'dhcpv6-stateless', or 'slaac'.
+    :param ipv6_address_mode:(string) IPv6 address mode.
+                             Valid values are: 'dhcpv6-stateful',
+                             'dhcpv6-stateless', or 'slaac'.
+    :param use_default_subnetpool:(bool) use the default subnetpool for
+                                  ``ip_version`` to obtain a CIDR. It is
+                                  required to pass ``None`` to the ``cidr``
+                                  argument when enabling this option.
+    :returns:(string) the subnet id.
+    """
     try:
-        subnet = neutron_client.create_subnet(body=json_body)
-        return subnet['subnets'][0]['id']
-    except Exception:  # pylint: disable=broad-except
-        log.error("Error [create_neutron_subnet")
-        raise Exception("operation error")
+        subnet = shade_client.create_subnet(
+            network_name_or_id, cidr=cidr, ip_version=ip_version,
+            enable_dhcp=enable_dhcp, subnet_name=subnet_name,
+            tenant_id=tenant_id, allocation_pools=allocation_pools,
+            gateway_ip=gateway_ip, disable_gateway_ip=disable_gateway_ip,
+            dns_nameservers=dns_nameservers, host_routes=host_routes,
+            ipv6_ra_mode=ipv6_ra_mode, ipv6_address_mode=ipv6_address_mode,
+            use_default_subnetpool=use_default_subnetpool)
+        return subnet['id']
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [create_neutron_subnet(shade_client)]. "
+                  "Exception message: %s", o_exc.orig_message)
+        return None
 
 
 def create_neutron_router(neutron_client, json_body):      # pragma: no cover
@@ -470,13 +528,12 @@ def create_neutron_router(neutron_client, json_body):      # pragma: no cover
         raise Exception("operation error")
 
 
-def delete_neutron_router(neutron_client, router_id):      # pragma: no cover
+def delete_neutron_router(shade_client, router_id):
     try:
-        neutron_client.delete_router(router=router_id)
-        return True
-    except Exception:  # pylint: disable=broad-except
-        log.error("Error [delete_neutron_router(neutron_client, '%s')]",
-                  router_id)
+        return shade_client.delete_router(router_id)
+    except exc.OpenStackCloudException as o_exc:
+        log.error("Error [delete_neutron_router(shade_client, '%s')]. "
+                  "Exception message: %s", router_id, o_exc.orig_message)
         return False
 
 
index 79951e3..0064b4f 100644 (file)
@@ -15,3 +15,5 @@
 REMOTE_TMP = "/tmp"
 DEFAULT_VNF_TIMEOUT = 3600
 PROCESS_JOIN_TIMEOUT = 3
+ONE_GIGABIT_IN_BITS = 1000000000
+NIC_GBPS_DEFAULT = 10
index 5700f98..c3277fb 100644 (file)
@@ -20,6 +20,7 @@ import datetime
 import time
 
 from yardstick.network_services.traffic_profile.prox_profile import ProxProfile
+from yardstick.network_services import constants
 
 LOG = logging.getLogger(__name__)
 
@@ -99,9 +100,13 @@ class ProxBinSearchProfile(ProxProfile):
 
         # throughput and packet loss from the most recent successful test
         successful_pkt_loss = 0.0
+        line_speed = traffic_gen.scenario_helper.all_options.get(
+            "interface_speed_gbps", constants.NIC_GBPS_DEFAULT) * constants.ONE_GIGABIT_IN_BITS
         for test_value in self.bounds_iterator(LOG):
             result, port_samples = self._profile_helper.run_test(pkt_size, duration,
-                                                                 test_value, self.tolerated_loss)
+                                                                 test_value,
+                                                                 self.tolerated_loss,
+                                                                 line_speed)
             self.curr_time = time.time()
             diff_time = self.curr_time - self.prev_time
             self.prev_time = self.curr_time
index 29f9c7b..e42431f 100644 (file)
@@ -35,6 +35,7 @@ from yardstick.common.utils import SocketTopology, join_non_strings, try_int
 from yardstick.network_services.helpers.iniparser import ConfigParser
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import DpdkVnfSetupEnvHelper
+from yardstick.network_services import constants
 
 PROX_PORT = 8474
 
@@ -44,7 +45,6 @@ SECTION_CONTENTS = 1
 LOG = logging.getLogger(__name__)
 LOG.setLevel(logging.DEBUG)
 
-TEN_GIGABIT = 1e10
 BITS_PER_BYTE = 8
 RETRY_SECONDS = 60
 RETRY_INTERVAL = 1
@@ -466,13 +466,14 @@ class ProxSocketHelper(object):
                 core_data['current'] = core_data[key1] + core_data[key2]
                 self.set_speed(core_data['cores'], core_data['current'])
 
-    def set_pps(self, cores, pps, pkt_size):
+    def set_pps(self, cores, pps, pkt_size,
+                line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
         """ set packets per second for specific cores on the remote instance """
         msg = "Set packets per sec for core(s) %s to %g%% of line rate (packet size: %d)"
         LOG.debug(msg, cores, pps, pkt_size)
 
         # speed in percent of line-rate
-        speed = float(pps) * (pkt_size + 20) / TEN_GIGABIT / BITS_PER_BYTE
+        speed = float(pps) * (pkt_size + 20) / line_speed / BITS_PER_BYTE
         self._run_template_over_cores("speed {} 0 {}\n", cores, speed)
 
     def lat_stats(self, cores, task=0):
@@ -967,12 +968,13 @@ class ProxResourceHelper(ClientResourceHelper):
 
 class ProxDataHelper(object):
 
-    def __init__(self, vnfd_helper, sut, pkt_size, value, tolerated_loss):
+    def __init__(self, vnfd_helper, sut, pkt_size, value, tolerated_loss, line_speed):
         super(ProxDataHelper, self).__init__()
         self.vnfd_helper = vnfd_helper
         self.sut = sut
         self.pkt_size = pkt_size
         self.value = value
+        self.line_speed = line_speed
         self.tolerated_loss = tolerated_loss
         self.port_count = len(self.vnfd_helper.port_pairs.all_ports)
         self.tsc_hz = None
@@ -1058,9 +1060,7 @@ class ProxDataHelper(object):
         self.tsc_hz = float(self.sut.hz())
 
     def line_rate_to_pps(self):
-        # NOTE: to fix, don't hardcode 10Gb/s
-        return self.port_count * TEN_GIGABIT / BITS_PER_BYTE / (self.pkt_size + 20)
-
+      return self.port_count * self.line_speed  / BITS_PER_BYTE / (self.pkt_size + 20)
 
 class ProxProfileHelper(object):
 
@@ -1139,8 +1139,10 @@ class ProxProfileHelper(object):
 
         return cores
 
-    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
-        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size, value, tolerated_loss)
+    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0,
+                 line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
+        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
+                                     value, tolerated_loss, line_speed)
 
         with data_helper, self.traffic_context(pkt_size, value):
             with data_helper.measure_tot_stats():
@@ -1396,8 +1398,10 @@ class ProxBngProfileHelper(ProxProfileHelper):
         time.sleep(3)
         self.sut.stop(self.all_rx_cores)
 
-    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
-        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size, value, tolerated_loss)
+    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0,
+                 line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
+        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
+                                     value, tolerated_loss, line_speed)
 
         with data_helper, self.traffic_context(pkt_size, value):
             with data_helper.measure_tot_stats():
@@ -1583,8 +1587,10 @@ class ProxVpeProfileHelper(ProxProfileHelper):
         time.sleep(3)
         self.sut.stop(self.all_rx_cores)
 
-    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
-        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size, value, tolerated_loss)
+    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0,
+                 line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
+        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
+                                     value, tolerated_loss, line_speed)
 
         with data_helper, self.traffic_context(pkt_size, value):
             with data_helper.measure_tot_stats():
@@ -1772,8 +1778,10 @@ class ProxlwAFTRProfileHelper(ProxProfileHelper):
         time.sleep(3)
         self.sut.stop(self.all_rx_cores)
 
-    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0):
-        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size, value, tolerated_loss)
+    def run_test(self, pkt_size, duration, value, tolerated_loss=0.0,
+                 line_speed=(constants.ONE_GIGABIT_IN_BITS * constants.NIC_GBPS_DEFAULT)):
+        data_helper = ProxDataHelper(self.vnfd_helper, self.sut, pkt_size,
+                                     value, tolerated_loss, line_speed)
 
         with data_helper, self.traffic_context(pkt_size, value):
             with data_helper.measure_tot_stats():
index 2cdb3f9..285e086 100644 (file)
@@ -22,7 +22,7 @@ from yardstick.common.process import check_if_process_failed
 from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxDpdkVnfSetupEnvHelper
 from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
 from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNF
-from yardstick.network_services.constants import PROCESS_JOIN_TIMEOUT
+from yardstick.network_services import constants
 
 LOG = logging.getLogger(__name__)
 
@@ -136,5 +136,5 @@ class ProxApproxVnf(SampleVNF):
         self._tear_down()
         if self._vnf_process is not None:
             LOG.debug("joining before terminate %s", self._vnf_process.name)
-            self._vnf_process.join(PROCESS_JOIN_TIMEOUT)
+            self._vnf_process.join(constants.PROCESS_JOIN_TIMEOUT)
             self._vnf_process.terminate()
index f16b414..addbd9a 100644 (file)
@@ -32,9 +32,7 @@ from yardstick.benchmark.contexts.base import Context
 from yardstick.common import exceptions as y_exceptions
 from yardstick.common.process import check_if_process_failed
 from yardstick.common import utils
-from yardstick.network_services.constants import DEFAULT_VNF_TIMEOUT
-from yardstick.network_services.constants import PROCESS_JOIN_TIMEOUT
-from yardstick.network_services.constants import REMOTE_TMP
+from yardstick.network_services import constants
 from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper, DpdkNode
 from yardstick.network_services.helpers.samplevnf_helper import MultiPortConfig
 from yardstick.network_services.helpers.samplevnf_helper import PortPairs
@@ -51,8 +49,8 @@ LOG = logging.getLogger(__name__)
 
 class SetupEnvHelper(object):
 
-    CFG_CONFIG = os.path.join(REMOTE_TMP, "sample_config")
-    CFG_SCRIPT = os.path.join(REMOTE_TMP, "sample_script")
+    CFG_CONFIG = os.path.join(constants.REMOTE_TMP, "sample_config")
+    CFG_SCRIPT = os.path.join(constants.REMOTE_TMP, "sample_script")
     DEFAULT_CONFIG_TPL_CFG = "sample.cfg"
     PIPELINE_COMMAND = ''
     VNF_TYPE = "SAMPLE"
@@ -371,7 +369,7 @@ class ClientResourceHelper(ResourceHelper):
         try:
             return self.client.get_stats(*args, **kwargs)
         except STLError:
-            LOG.exception("TRex client not connected")
+            LOG.error('TRex client not connected')
             return {}
 
     def generate_samples(self, ports, key=None, default=None):
@@ -609,8 +607,10 @@ class ScenarioHelper(object):
 
     @property
     def timeout(self):
-        return self.options.get('timeout', DEFAULT_VNF_TIMEOUT)
-
+        test_duration = self.scenario_cfg.get('runner', {}).get('duration',
+            self.options.get('timeout', constants.DEFAULT_VNF_TIMEOUT))
+        test_timeout = self.options.get('timeout', constants.DEFAULT_VNF_TIMEOUT)
+        return test_duration if test_duration > test_timeout else test_timeout
 
 class SampleVNF(GenericVNF):
     """ Class providing file-like API for generic VNF implementation """
@@ -794,7 +794,7 @@ class SampleVNF(GenericVNF):
         if self._vnf_process is not None:
             # be proper and join first before we kill
             LOG.debug("joining before terminate %s", self._vnf_process.name)
-            self._vnf_process.join(PROCESS_JOIN_TIMEOUT)
+            self._vnf_process.join(constants.PROCESS_JOIN_TIMEOUT)
             self._vnf_process.terminate()
         # no terminate children here because we share processes with tg
 
@@ -938,12 +938,12 @@ class SampleVNFTrafficGen(GenericTrafficGen):
         if self._traffic_process is not None:
             # be proper and try to join before terminating
             LOG.debug("joining before terminate %s", self._traffic_process.name)
-            self._traffic_process.join(PROCESS_JOIN_TIMEOUT)
+            self._traffic_process.join(constants.PROCESS_JOIN_TIMEOUT)
             self._traffic_process.terminate()
         if self._tg_process is not None:
             # be proper and try to join before terminating
             LOG.debug("joining before terminate %s", self._tg_process.name)
-            self._tg_process.join(PROCESS_JOIN_TIMEOUT)
+            self._tg_process.join(constants.PROCESS_JOIN_TIMEOUT)
             self._tg_process.terminate()
         # no terminate children here because we share processes with vnf
 
index 8e02cf3..de6fd93 100644 (file)
@@ -17,7 +17,7 @@ import os
 
 from six.moves import StringIO
 
-from yardstick.network_services.constants import REMOTE_TMP
+from yardstick.network_services import constants
 from yardstick.ssh import AutoConnectSSH
 
 LOG = logging.getLogger(__name__)
@@ -46,7 +46,7 @@ class VnfSshHelper(AutoConnectSSH):
         return self.get_class()(self.node, self.bin_path)
 
     def upload_config_file(self, prefix, content):
-        cfg_file = os.path.join(REMOTE_TMP, prefix)
+        cfg_file = os.path.join(constants.REMOTE_TMP, prefix)
         LOG.debug(content)
         file_obj = StringIO(content)
         self.put_file_obj(file_obj, cfg_file)
diff --git a/yardstick/service/__init__.py b/yardstick/service/__init__.py
new file mode 100644 (file)
index 0000000..1c3953d
--- /dev/null
@@ -0,0 +1,12 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+
+
+class Service(object):
+    pass
diff --git a/yardstick/service/environment.py b/yardstick/service/environment.py
new file mode 100644 (file)
index 0000000..324589f
--- /dev/null
@@ -0,0 +1,101 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import tempfile
+import logging
+import collections
+
+from oslo_serialization import jsonutils
+
+from yardstick.service import Service
+from yardstick.common.exceptions import MissingPodInfoError
+from yardstick.common.exceptions import UnsupportedPodFormatError
+from yardstick.common.ansible_common import AnsibleCommon
+
+LOG = logging.getLogger(__name__)
+
+
+class Environment(Service):
+    def __init__(self, pod=None):
+        super(Environment, self).__init__()
+        # pod can be a dict or a json format string
+        self.pod = pod
+
+    def get_sut_info(self):
+        temdir = tempfile.mkdtemp(prefix='sut')
+
+        nodes = self._load_pod_info()
+        ansible = AnsibleCommon(nodes=nodes)
+        ansible.gen_inventory_ini_dict()
+        sut_info = ansible.get_sut_info(temdir)
+
+        return self._format_sut_info(sut_info)
+
+    def _load_pod_info(self):
+        if self.pod is None:
+            raise MissingPodInfoError
+
+        if isinstance(self.pod, collections.Mapping):
+            try:
+                return self.pod['nodes']
+            except KeyError:
+                raise UnsupportedPodFormatError
+
+        try:
+            return jsonutils.loads(self.pod)['nodes']
+        except (ValueError, KeyError):
+            raise UnsupportedPodFormatError
+
+    def _format_sut_info(self, sut_info):
+        return {k: self._format_node_info(v) for k, v in sut_info.items()}
+
+    def _format_node_info(self, node_info):
+        info = []
+        facts = node_info.get('ansible_facts', {})
+
+        info.append(['hostname', facts.get('ansible_hostname')])
+
+        info.append(['product_name', facts.get('ansible_product_name')])
+        info.append(['product_version', facts.get('ansible_product_version')])
+
+        processors = facts.get('ansible_processor', [])
+        try:
+            processor_type = '{} {}'.format(processors[0], processors[1])
+        except IndexError:
+            LOG.exception('No Processor in SUT data')
+            processor_type = None
+
+        info.append(['processor_type', processor_type])
+        info.append(['architecture', facts.get('ansible_architecture')])
+        info.append(['processor_cores', facts.get('ansible_processor_cores')])
+        info.append(['processor_vcpus', facts.get('ansible_processor_vcpus')])
+
+        memory = facts.get('ansible_memtotal_mb')
+        memory = round(memory * 1.0 / 1024, 2) if memory else None
+        info.append(['memory', '{} GB'.format(memory)])
+
+        devices = facts.get('ansible_devices', {})
+        info.extend([self._get_device_info(k, v) for k, v in devices.items()])
+
+        lsb_description = facts.get('ansible_lsb', {}).get('description')
+        info.append(['OS', lsb_description])
+
+        interfaces = facts.get('ansible_interfaces')
+        info.append(['interfaces', interfaces])
+        if isinstance(interfaces, collections.Sequence):
+            info.extend([self._get_interface_info(facts, i) for i in interfaces])
+        info = [i for i in info if i]
+
+        return info
+
+    def _get_interface_info(self, facts, name):
+        mac = facts.get('ansible_{}'.format(name), {}).get('macaddress')
+        return [name, mac] if mac else []
+
+    def _get_device_info(self, name, info):
+        return ['disk_{}'.format(name), info.get('size')]
index c54a7ab..625f97b 100644 (file)
@@ -420,7 +420,7 @@ class HeatContextTestCase(unittest.TestCase):
         self.test_context.key_filename = 'foo/bar/foobar'
         self.test_context.undeploy()
         mock_delete_key.assert_called()
-        self.assertTrue(mock_template.delete.called)
+        mock_template.delete.assert_called_once()
 
     @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
     def test_undeploy_no_teardown(self, mock_template):
index 22153e4..4dd9d40 100644 (file)
@@ -58,10 +58,10 @@ class KubernetesTestCase(unittest.TestCase):
                       mock_delete_services):
 
         self.k8s_context.undeploy()
-        self.assertTrue(mock_delete_ssh.called)
-        self.assertTrue(mock_delete_rcs.called)
-        self.assertTrue(mock_delete_pods.called)
-        self.assertTrue(mock_delete_services.called)
+        mock_delete_ssh.assert_called_once()
+        mock_delete_rcs.assert_called_once()
+        mock_delete_pods.assert_called_once()
+        mock_delete_services.assert_called_once()
 
     @mock.patch.object(kubernetes.KubernetesContext, '_create_services')
     @mock.patch.object(kubernetes.KubernetesContext, '_wait_until_running')
@@ -77,11 +77,11 @@ class KubernetesTestCase(unittest.TestCase):
 
         with mock.patch("yardstick.benchmark.contexts.kubernetes.time"):
             self.k8s_context.deploy()
-        self.assertTrue(mock_set_ssh_key.called)
-        self.assertTrue(mock_create_rcs.called)
-        self.assertTrue(mock_create_services.called)
-        self.assertTrue(mock_get_rc_pods.called)
-        self.assertTrue(mock_wait_until_running.called)
+        mock_set_ssh_key.assert_called_once()
+        mock_create_rcs.assert_called_once()
+        mock_create_services.assert_called_once()
+        mock_get_rc_pods.assert_called_once()
+        mock_wait_until_running.assert_called_once()
 
     @mock.patch.object(kubernetes, 'paramiko', **{"resource_filename.return_value": ""})
     @mock.patch.object(kubernetes, 'pkg_resources', **{"resource_filename.return_value": ""})
@@ -93,8 +93,8 @@ class KubernetesTestCase(unittest.TestCase):
         self.k8s_context._set_ssh_key()
         self.k8s_context._delete_ssh_key()
 
-        self.assertTrue(mock_create.called)
-        self.assertTrue(mock_delete.called)
+        mock_create.assert_called_once()
+        mock_delete.assert_called_once()
 
     @mock.patch.object(kubernetes.k8s_utils, 'read_pod_status')
     def test_wait_until_running(self, mock_read_pod_status):
@@ -136,34 +136,34 @@ class KubernetesTestCase(unittest.TestCase):
     @mock.patch.object(kubernetes.KubernetesContext, '_create_rc')
     def test_create_rcs(self, mock_create_rc):
         self.k8s_context._create_rcs()
-        self.assertTrue(mock_create_rc.called)
+        mock_create_rc.assert_called()
 
     @mock.patch.object(kubernetes.k8s_utils, 'create_replication_controller')
     def test_create_rc(self, mock_create_replication_controller):
         self.k8s_context._create_rc({})
-        self.assertTrue(mock_create_replication_controller.called)
+        mock_create_replication_controller.assert_called_once()
 
     @mock.patch.object(kubernetes.KubernetesContext, '_delete_rc')
     def test_delete_rcs(self, mock_delete_rc):
         self.k8s_context._delete_rcs()
-        self.assertTrue(mock_delete_rc.called)
+        mock_delete_rc.assert_called()
 
     @mock.patch.object(kubernetes.k8s_utils, 'delete_replication_controller')
     def test_delete_rc(self, mock_delete_replication_controller):
         self.k8s_context._delete_rc({})
-        self.assertTrue(mock_delete_replication_controller.called)
+        mock_delete_replication_controller.assert_called_once()
 
     @mock.patch.object(kubernetes.k8s_utils, 'get_node_list')
     def test_get_node_ip(self, mock_get_node_list):
         self.k8s_context._get_node_ip()
-        self.assertTrue(mock_get_node_list.called)
+        mock_get_node_list.assert_called_once()
 
     @mock.patch('yardstick.orchestrator.kubernetes.ServiceObject.create')
     def test_create_services(self, mock_create):
         self.k8s_context._create_services()
-        self.assertTrue(mock_create.called)
+        mock_create.assert_called()
 
     @mock.patch('yardstick.orchestrator.kubernetes.ServiceObject.delete')
     def test_delete_services(self, mock_delete):
         self.k8s_context._delete_services()
-        self.assertTrue(mock_delete.called)
+        mock_delete.assert_called()
index 9761f6d..8b23248 100644 (file)
@@ -176,7 +176,7 @@ class NodeContextTestCase(unittest.TestCase):
             'type': 'script'
         }
         obj.deploy()
-        self.assertTrue(dispatch_script_mock.called)
+        dispatch_script_mock.assert_called_once()
 
     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
     def test_deploy_anisible(self, dispatch_ansible_mock):
@@ -186,7 +186,7 @@ class NodeContextTestCase(unittest.TestCase):
             'type': 'ansible'
         }
         obj.deploy()
-        self.assertTrue(dispatch_ansible_mock.called)
+        dispatch_ansible_mock.assert_called_once()
 
     @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
     def test_undeploy(self, dispatch_script_mock):
@@ -195,7 +195,7 @@ class NodeContextTestCase(unittest.TestCase):
             'type': 'script'
         }
         obj.undeploy()
-        self.assertTrue(dispatch_script_mock.called)
+        dispatch_script_mock.assert_called_once()
 
     @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
     def test_undeploy_anisble(self, dispatch_ansible_mock):
@@ -204,7 +204,7 @@ class NodeContextTestCase(unittest.TestCase):
             'type': 'ansible'
         }
         obj.undeploy()
-        self.assertTrue(dispatch_ansible_mock.called)
+        dispatch_ansible_mock.assert_called_once()
 
     @mock.patch('{}.ssh.SSH._put_file_shell'.format(PREFIX))
     @mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
@@ -224,8 +224,8 @@ class NodeContextTestCase(unittest.TestCase):
         execute_mock.return_value = (0, '', '')
         obj._execute_remote_script('node5', info)
 
-        self.assertTrue(put_file_mock.called)
-        self.assertTrue(execute_mock.called)
+        put_file_mock.assert_called_once()
+        execute_mock.assert_called()
 
     @mock.patch('{}.NodeContext._execute_local_script'.format(PREFIX))
     def test_execute_script_local(self, local_execute_mock):
@@ -234,7 +234,7 @@ class NodeContextTestCase(unittest.TestCase):
         obj = node.NodeContext()
         self.addCleanup(obj._delete_context)
         obj._execute_script(node_name, info)
-        self.assertTrue(local_execute_mock.called)
+        local_execute_mock.assert_called_once()
 
     @mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
     def test_execute_script_remote(self, remote_execute_mock):
@@ -243,7 +243,7 @@ class NodeContextTestCase(unittest.TestCase):
         obj = node.NodeContext()
         self.addCleanup(obj._delete_context)
         obj._execute_script(node_name, info)
-        self.assertTrue(remote_execute_mock.called)
+        remote_execute_mock.assert_called_once()
 
     def test_get_script(self):
         script_args = 'hello.bash'
@@ -276,7 +276,7 @@ class NodeContextTestCase(unittest.TestCase):
             'pwd': 'ubuntu',
         }]
         obj._get_client(node_name_args)
-        self.assertTrue(wait_mock.called)
+        wait_mock.assert_called_once()
 
     def test_get_server(self):
         self.test_context.init(self.attrs)
index 82a90b1..1ce30ea 100644 (file)
@@ -153,7 +153,7 @@ class TaskTestCase(unittest.TestCase):
         runner.get_result.return_value = []
         mock_base_runner.Runner.get.return_value = runner
         t._run([scenario], False, "yardstick.out")
-        self.assertTrue(runner.run.called)
+        runner.run.assert_called_once()
 
     @mock.patch.object(os, 'environ')
     def test_check_precondition(self, mock_os_environ):
index 98d967f..af4f0c8 100644 (file)
@@ -27,7 +27,7 @@ class AddMemoryLoadTestCase(unittest.TestCase):
         mock_from_node().execute.return_value = (0, '0 2048 512', '')
         obj = AddMemoryLoad(scenario_cfg, context_cfg)
         obj.run({})
-        self.assertTrue(mock_from_node.called)
+        mock_from_node.assert_called()
 
     @mock.patch('yardstick.ssh.SSH.from_node')
     def test_add_memory_load_without_load(self, mock_from_node):
@@ -41,7 +41,7 @@ class AddMemoryLoadTestCase(unittest.TestCase):
         }
         obj = AddMemoryLoad(scenario_cfg, context_cfg)
         obj.run({})
-        self.assertTrue(mock_from_node.called)
+        mock_from_node.assert_called_once()
 
     @mock.patch('yardstick.ssh.SSH.from_node')
     def test_add_memory_load_without_args(self, mock_from_node):
@@ -54,4 +54,4 @@ class AddMemoryLoadTestCase(unittest.TestCase):
         }
         obj = AddMemoryLoad(scenario_cfg, context_cfg)
         obj.run({})
-        self.assertTrue(mock_from_node.called)
+        mock_from_node.assert_called_once()
index a61195f..2964ecc 100644 (file)
@@ -23,4 +23,4 @@ class AttachVolumeTestCase(unittest.TestCase):
         args = {"options": options}
         obj = AttachVolume(args, {})
         obj.run({})
-        self.assertTrue(mock_attach_server_volume.called)
+        mock_attach_server_volume.assert_called_once()
index a50e752..270c9d3 100644 (file)
@@ -19,7 +19,7 @@ class CheckNumaInfoTestCase(unittest.TestCase):
         scenario_cfg = {'info1': {}, 'info2': {}}
         obj = CheckNumaInfo(scenario_cfg, {})
         obj.run({})
-        self.assertTrue(mock_check_vm2.called)
+        mock_check_vm2.assert_called_once()
 
     def test_check_vm2_status_length_eq_1(self):
         info1 = {
index 663ca5d..0b175fa 100644 (file)
@@ -26,4 +26,4 @@ class CreateFlavorTestCase(unittest.TestCase):
         args = {"options": options}
         obj = CreateFlavor(args, {})
         obj.run({})
-        self.assertTrue(mock_create_flavor.called)
+        mock_create_flavor.assert_called_once()
index ad4adee..17a4ef2 100644 (file)
@@ -6,25 +6,52 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+
+from oslo_utils import uuidutils
 import unittest
 import mock
 
-from yardstick.benchmark.scenarios.lib.create_network import CreateNetwork
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_network
 
 
 class CreateNetworkTestCase(unittest.TestCase):
 
-    @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
-    @mock.patch('yardstick.common.openstack_utils.create_neutron_net')
-    def test_create_network(self, mock_get_neutron_client, mock_create_neutron_net):
-        options = {
-            'openstack_paras': {
-                'name': 'yardstick_net',
-                'admin_state_up': 'True'
-            }
-        }
-        args = {"options": options}
-        obj = CreateNetwork(args, {})
-        obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_create_neutron_net.called)
+    def setUp(self):
+
+        self._mock_create_neutron_net = mock.patch.object(
+            openstack_utils, 'create_neutron_net')
+        self.mock_create_neutron_net = self._mock_create_neutron_net.start()
+        self._mock_get_shade_client = mock.patch.object(
+            openstack_utils, 'get_shade_client')
+        self.mock_get_shade_client = self._mock_get_shade_client.start()
+        self._mock_log = mock.patch.object(create_network, 'LOG')
+        self.mock_log = self._mock_log.start()
+        self.args = {'options': {'network_name': 'yardstick_net'}}
+        self.result = {}
+
+        self._cnet_obj = create_network.CreateNetwork(self.args, mock.ANY)
+        self.addCleanup(self._stop_mock)
+
+    def _stop_mock(self):
+        self._mock_create_neutron_net.stop()
+        self._mock_get_shade_client.stop()
+        self._mock_log.stop()
+
+    def test_run(self):
+        _uuid = uuidutils.generate_uuid()
+        self._cnet_obj.scenario_cfg = {'output': 'id'}
+        self.mock_create_neutron_net.return_value = _uuid
+        output = self._cnet_obj.run(self.result)
+        self.assertEqual({"network_create": 1}, self.result)
+        self.assertEqual({'id': _uuid}, output)
+        self.mock_log.info.asset_called_once_with('Create network successful!')
+
+    def test_run_fail_exception(self):
+        self.mock_create_neutron_net.return_value = None
+        with self.assertRaises(exceptions.ScenarioCreateNetworkError):
+            self._cnet_obj.run(self.result)
+        self.assertEqual({"network_create": 0}, self.result)
+        self.mock_log.error.assert_called_once_with(
+            'Create network failed!')
index 9a1611c..bea02a6 100644 (file)
@@ -24,4 +24,4 @@ class CreatePortTestCase(unittest.TestCase):
         args = {"options": options}
         obj = CreatePort(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
+        mock_get_neutron_client.assert_called_once()
index 1079214..3469a2a 100644 (file)
@@ -26,5 +26,5 @@ class CreateRouterTestCase(unittest.TestCase):
         args = {"options": options}
         obj = CreateRouter(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_create_neutron_router.called)
+        mock_get_neutron_client.assert_called_once()
+        mock_create_neutron_router.assert_called_once()
index b557673..21158ab 100644 (file)
@@ -26,5 +26,5 @@ class CreateSecGroupTestCase(unittest.TestCase):
         args = {"options": options}
         obj = CreateSecgroup(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_create_security_group_full.called)
+        mock_get_neutron_client.assert_called_once()
+        mock_create_security_group_full.assert_called_once()
index faee98f..9d6d8cb 100644 (file)
@@ -28,7 +28,7 @@ class CreateServerTestCase(unittest.TestCase):
         }
         obj = CreateServer(scenario_cfg, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_get_glance_client.called)
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_create_instance_and_wait_for_active.called)
+        mock_get_nova_client.assert_called_once()
+        mock_get_glance_client.assert_called_once()
+        mock_get_neutron_client.assert_called_once()
+        mock_create_instance_and_wait_for_active.assert_called_once()
index 1536e83..856e985 100644 (file)
@@ -6,27 +6,53 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+
+from oslo_utils import uuidutils
 import unittest
 import mock
 
-from yardstick.benchmark.scenarios.lib.create_subnet import CreateSubnet
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_subnet
 
 
 class CreateSubnetTestCase(unittest.TestCase):
 
-    @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
-    @mock.patch('yardstick.common.openstack_utils.create_neutron_subnet')
-    def test_create_subnet(self, mock_get_neutron_client, mock_create_neutron_subnet):
-        options = {
-            'openstack_paras': {
-                'network_id': '123-123-123',
-                'name': 'yardstick_subnet',
-                'cidr': '10.10.10.0/24',
-                'ip_version': '4'
-            }
-        }
-        args = {"options": options}
-        obj = CreateSubnet(args, {})
-        obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_create_neutron_subnet.called)
+    def setUp(self):
+
+        self._mock_create_neutron_subnet = mock.patch.object(
+            openstack_utils, 'create_neutron_subnet')
+        self.mock_create_neutron_subnet = (
+            self._mock_create_neutron_subnet.start())
+        self._mock_get_shade_client = mock.patch.object(
+            openstack_utils, 'get_shade_client')
+        self.mock_get_shade_client = self._mock_get_shade_client.start()
+        self._mock_log = mock.patch.object(create_subnet, 'LOG')
+        self.mock_log = self._mock_log.start()
+        self.args = {'options': {'network_name_or_id': 'yardstick_net'}}
+        self.result = {"subnet_create": 0}
+
+        self._csubnet_obj = create_subnet.CreateSubnet(self.args, mock.ANY)
+        self.addCleanup(self._stop_mock)
+
+    def _stop_mock(self):
+        self._mock_create_neutron_subnet.stop()
+        self._mock_get_shade_client.stop()
+        self._mock_log.stop()
+
+    def test_run(self):
+        _uuid = uuidutils.generate_uuid()
+        self._csubnet_obj.scenario_cfg = {'output': 'id'}
+        self.mock_create_neutron_subnet.return_value = _uuid
+        output = self._csubnet_obj.run(self.result)
+        self.assertDictEqual({"subnet_create": 1}, self.result)
+        self.assertDictEqual({'id': _uuid}, output)
+        self.mock_log.info.asset_called_once_with('Create subnet successful!')
+
+    def test_run_fail(self):
+        self._csubnet_obj.scenario_cfg = {'output': 'id'}
+        self.mock_create_neutron_subnet.return_value = None
+        with self.assertRaises(exceptions.ScenarioCreateSubnetError):
+            self._csubnet_obj.run(self.result)
+        self.assertDictEqual({"subnet_create": 0}, self.result)
+        self.mock_log.error.assert_called_once_with('Create subnet failed!')
index 4bfec32..30333dd 100644 (file)
@@ -94,7 +94,7 @@ class CreateVolumeTestCase(unittest.TestCase):
         args = {"options": options}
         scenario = create_volume.CreateVolume(args, {})
         scenario.run()
-        self.assertTrue(mock_create_volume.called)
-        self.assertTrue(mock_image_id.called)
-        self.assertTrue(mock_get_glance_client.called)
-        self.assertTrue(mock_get_cinder_client.called)
+        mock_create_volume.assert_called_once()
+        mock_image_id.assert_called_once()
+        mock_get_glance_client.assert_called_once()
+        mock_get_cinder_client.assert_called_once()
index e345afe..24dbf8a 100644 (file)
@@ -23,5 +23,5 @@ class DeleteFlavorTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteFlavor(args, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_delete_flavor.called)
+        mock_get_nova_client.assert_called_once()
+        mock_delete_flavor.assert_called_once()
index be99719..3185ec5 100644 (file)
@@ -23,5 +23,5 @@ class DeleteFloatingIpTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteFloatingIp(args, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_delete_floating_ip.called)
+        mock_get_nova_client.assert_called_once()
+        mock_delete_floating_ip.assert_called_once()
index eb3f9fc..e382d46 100644 (file)
@@ -24,6 +24,6 @@ class DeleteImageTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteImage(args, {})
         obj.run({})
-        self.assertTrue(mock_delete_image.called)
-        self.assertTrue(mock_image_id.called)
-        self.assertTrue(mock_get_glance_client.called)
+        mock_delete_image.assert_called_once()
+        mock_image_id.assert_called_once()
+        mock_get_glance_client.assert_called_once()
index 38cc929..6e790ba 100644 (file)
@@ -23,5 +23,5 @@ class DeleteKeypairTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteKeypair(args, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_delete_keypair.called)
+        mock_get_nova_client.assert_called_once()
+        mock_delete_keypair.assert_called_once()
index 008ed91..9fd3185 100644 (file)
@@ -22,4 +22,4 @@ class DeletePortTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeletePort(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
+        mock_get_neutron_client.assert_called_once()
index 9b31566..b76100f 100644 (file)
@@ -6,22 +6,49 @@
 # which accompanies this distribution, and is available at
 # http://www.apache.org/licenses/LICENSE-2.0
 ##############################################################################
+
+from oslo_utils import uuidutils
 import unittest
 import mock
 
-from yardstick.benchmark.scenarios.lib.delete_router import DeleteRouter
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_router
 
 
 class DeleteRouterTestCase(unittest.TestCase):
 
-    @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
-    @mock.patch('yardstick.common.openstack_utils.delete_neutron_router')
-    def test_delete_router(self, mock_get_neutron_client, mock_delete_neutron_router):
-        options = {
-            'router_id': '123-123-123'
-        }
-        args = {"options": options}
-        obj = DeleteRouter(args, {})
-        obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_delete_neutron_router.called)
+    def setUp(self):
+        self._mock_delete_neutron_router = mock.patch.object(
+            openstack_utils, 'delete_neutron_router')
+        self.mock_delete_neutron_router = (
+            self._mock_delete_neutron_router.start())
+        self._mock_get_shade_client = mock.patch.object(
+            openstack_utils, 'get_shade_client')
+        self.mock_get_shade_client = self._mock_get_shade_client.start()
+        self._mock_log = mock.patch.object(delete_router, 'LOG')
+        self.mock_log = self._mock_log.start()
+        self.args = {'options': {'router_id': uuidutils.generate_uuid()}}
+        self.result = {"delete_router": 0}
+
+        self._del_obj = delete_router.DeleteRouter(self.args, mock.ANY)
+
+        self.addCleanup(self._stop_mock)
+
+    def _stop_mock(self):
+        self._mock_delete_neutron_router.stop()
+        self._mock_get_shade_client.stop()
+        self._mock_log.stop()
+
+    def test_run(self):
+        self.mock_delete_neutron_router.return_value = True
+        self.assertIsNone(self._del_obj.run(self.result))
+        self.assertEqual({"delete_router": 1}, self.result)
+        self.mock_log.info.assert_called_once_with("Delete router successful!")
+
+    def test_run_fail(self):
+        self.mock_delete_neutron_router.return_value = False
+        with self.assertRaises(exceptions.ScenarioDeleteRouterError):
+            self._del_obj.run(self.result)
+        self.assertEqual({"delete_router": 0}, self.result)
+        self.mock_log.error.assert_called_once_with("Delete router failed!")
index e19c38d..0c9cf7c 100644 (file)
@@ -23,5 +23,5 @@ class DeleteRouterGatewayTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteRouterGateway(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_remove_gateway_router.called)
+        mock_get_neutron_client.assert_called_once()
+        mock_remove_gateway_router.assert_called_once()
index 6c4fdd5..9e9c5a5 100644 (file)
@@ -24,5 +24,5 @@ class DeleteRouterInterfaceTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteRouterInterface(args, {})
         obj.run({})
-        self.assertTrue(mock_get_neutron_client.called)
-        self.assertTrue(mock_remove_interface_router.called)
+        mock_get_neutron_client.assert_called_once()
+        mock_remove_interface_router.assert_called_once()
index dedce2d..eee565d 100644 (file)
@@ -23,5 +23,5 @@ class DeleteServerTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteServer(args, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_delete_instance.called)
+        mock_get_nova_client.assert_called_once()
+        mock_delete_instance.assert_called_once()
index 2ea82e2..93f76e8 100644 (file)
@@ -23,5 +23,5 @@ class DeleteVolumeTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DeleteVolume(args, {})
         obj.run({})
-        self.assertTrue(mock_get_cinder_client.called)
-        self.assertTrue(mock_delete_volume.called)
+        mock_get_cinder_client.assert_called_once()
+        mock_delete_volume.assert_called_once()
index 34fbac6..9794d21 100644 (file)
@@ -23,4 +23,4 @@ class DetachVolumeTestCase(unittest.TestCase):
         args = {"options": options}
         obj = DetachVolume(args, {})
         obj.run({})
-        self.assertTrue(mock_detach_volume.called)
+        mock_detach_volume.assert_called_once()
index e9025f3..15a6f7c 100644 (file)
@@ -22,4 +22,4 @@ class GetFlavorTestCase(unittest.TestCase):
         args = {"options": options}
         obj = GetFlavor(args, {})
         obj.run({})
-        self.assertTrue(mock_get_flavor_by_name.called)
+        mock_get_flavor_by_name.assert_called_once()
index aa9f63e..879b2b9 100644 (file)
@@ -25,9 +25,9 @@ class GetMigrateTargetHostTestCase(unittest.TestCase):
                                      mock_get_nova_client):
         obj = GetMigrateTargetHost({}, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_get_current_host_name.called)
-        self.assertTrue(mock_get_migrate_host.called)
+        mock_get_nova_client.assert_called_once()
+        mock_get_current_host_name.assert_called_once()
+        mock_get_migrate_host.assert_called_once()
 
     @mock.patch('{}.openstack_utils.get_nova_client'.format(BASE))
     def test_get_migrate_host(self, mock_get_nova_client):
@@ -39,5 +39,5 @@ class GetMigrateTargetHostTestCase(unittest.TestCase):
         mock_get_nova_client().hosts.list_all.return_value = [A('compute')]
         obj = GetMigrateTargetHost({}, {})
         host = obj._get_migrate_host('host5')
-        self.assertTrue(mock_get_nova_client.called)
+        mock_get_nova_client.assert_called()
         self.assertEqual(host, 'host4')
index 4b2132c..bea978b 100644 (file)
@@ -44,8 +44,8 @@ class GetNumaInfoTestCase(unittest.TestCase):
         }
         obj = GetNumaInfo(scenario_cfg, {})
         obj.run({})
-        self.assertTrue(mock_get_current_host_name.called)
-        self.assertTrue(mock_check_numa_node.called)
+        mock_get_current_host_name.assert_called_once()
+        mock_check_numa_node.assert_called_once()
 
     @mock.patch('yardstick.ssh.SSH.from_node')
     @mock.patch('{}.GetNumaInfo._get_current_host_name'.format(BASE))
index 97b81ed..83ec903 100644 (file)
@@ -25,8 +25,8 @@ class GetServerTestCase(unittest.TestCase):
         }
         obj = GetServer(scenario_cfg, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
-        self.assertTrue(mock_get_server_by_name.called)
+        mock_get_nova_client.assert_called_once()
+        mock_get_server_by_name.assert_called_once()
 
     @mock.patch('yardstick.common.openstack_utils.get_nova_client')
     def test_get_server_with_id(self, mock_get_nova_client):
@@ -39,4 +39,4 @@ class GetServerTestCase(unittest.TestCase):
         mock_get_nova_client().servers.get.return_value = None
         obj = GetServer(scenario_cfg, {})
         obj.run({})
-        self.assertTrue(mock_get_nova_client.called)
+        mock_get_nova_client.assert_called()
index d663638..74144af 100644 (file)
@@ -65,7 +65,7 @@ class IperfTestCase(unittest.TestCase):
         p.target = mock_ssh.SSH.from_node()
 
         p.teardown()
-        self.assertTrue(mock_ssh.SSH.from_node().close.called)
+        mock_ssh.SSH.from_node().close.assert_called()
         mock_ssh.SSH.from_node().execute.assert_called_with("pkill iperf3")
 
     def test_iperf_successful_no_sla(self, mock_ssh):
index b01195f..48d8a60 100644 (file)
@@ -17,6 +17,7 @@ from __future__ import absolute_import
 
 import os
 import tempfile
+import shutil
 from collections import defaultdict
 
 import mock
@@ -246,3 +247,18 @@ class AnsibleCommonTestCase(unittest.TestCase):
             a.execute_ansible('', d, ansible_check=True, verbose=True)
         finally:
             os.rmdir(d)
+
+    def test_get_sut_info(self):
+        d = tempfile.mkdtemp()
+        a = ansible_common.AnsibleCommon({})
+        try:
+            a.get_sut_info(d)
+        finally:
+            shutil.rmtree(d)
+
+    def test_get_sut_info_not_exist(self):
+        a = ansible_common.AnsibleCommon({})
+        try:
+            a.get_sut_info('/hello/world')
+        except OSError:
+            pass
index 4863f05..c6b0f46 100644 (file)
@@ -83,3 +83,81 @@ class DeleteNeutronNetTestCase(unittest.TestCase):
                                                     'network_id')
         self.assertFalse(output)
         mock_logger.error.assert_called_once()
+
+
+class CreateNeutronNetTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.mock_shade_client = mock.Mock()
+        self.network_name = 'name'
+        self.mock_shade_client.create_network = mock.Mock()
+
+    def test_create_neutron_net(self):
+        _uuid = uuidutils.generate_uuid()
+        self.mock_shade_client.create_network.return_value = {'id': _uuid}
+        output = openstack_utils.create_neutron_net(self.mock_shade_client,
+                                                    self.network_name)
+        self.assertEqual(_uuid, output)
+
+    @mock.patch.object(openstack_utils, 'log')
+    def test_create_neutron_net_exception(self, mock_logger):
+        self.mock_shade_client.create_network.side_effect = (
+            exc.OpenStackCloudException('error message'))
+
+        output = openstack_utils.create_neutron_net(self.mock_shade_client,
+                                                    self.network_name)
+        mock_logger.error.assert_called_once()
+        self.assertIsNone(output)
+
+
+class CreateNeutronSubnetTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.mock_shade_client = mock.Mock()
+        self.network_name_or_id = 'name_or_id'
+        self.mock_shade_client.create_subnet = mock.Mock()
+
+    def test_create_neutron_subnet(self):
+        _uuid = uuidutils.generate_uuid()
+        self.mock_shade_client.create_subnet.return_value = {'id': _uuid}
+        output = openstack_utils.create_neutron_subnet(
+            self.mock_shade_client, self.network_name_or_id)
+        self.assertEqual(_uuid, output)
+
+    @mock.patch.object(openstack_utils, 'log')
+    def test_create_neutron_subnet_exception(self, mock_logger):
+        self.mock_shade_client.create_subnet.side_effect = (
+            exc.OpenStackCloudException('error message'))
+
+        output = openstack_utils.create_neutron_subnet(
+            self.mock_shade_client, self.network_name_or_id)
+        mock_logger.error.assert_called_once()
+        self.assertIsNone(output)
+
+
+class DeleteNeutronRouterTestCase(unittest.TestCase):
+
+    def setUp(self):
+        self.mock_shade_client = mock.Mock()
+        self.mock_shade_client.delete_router = mock.Mock()
+
+    def test_delete_neutron_router(self):
+        self.mock_shade_client.delete_router.return_value = True
+        output = openstack_utils.delete_neutron_router(self.mock_shade_client,
+                                                       'router_id')
+        self.assertTrue(output)
+
+    def test_delete_neutron_router_fail(self):
+        self.mock_shade_client.delete_router.return_value = False
+        output = openstack_utils.delete_neutron_router(self.mock_shade_client,
+                                                       'router_id')
+        self.assertFalse(output)
+
+    @mock.patch.object(openstack_utils, 'log')
+    def test_delete_neutron_router_exception(self, mock_logger):
+        self.mock_shade_client.delete_router.side_effect = (
+            exc.OpenStackCloudException('error message'))
+        output = openstack_utils.delete_neutron_router(self.mock_shade_client,
+                                                       'router_id')
+        mock_logger.error.assert_called_once()
+        self.assertFalse(output)
diff --git a/yardstick/tests/unit/service/__init__.py b/yardstick/tests/unit/service/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/yardstick/tests/unit/service/test_environment.py b/yardstick/tests/unit/service/test_environment.py
new file mode 100644 (file)
index 0000000..4af9a39
--- /dev/null
@@ -0,0 +1,49 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+import unittest
+
+import mock
+
+from yardstick.service.environment import Environment
+from yardstick.service.environment import AnsibleCommon
+from yardstick.common.exceptions import UnsupportedPodFormatError
+
+
+class EnvironmentTestCase(unittest.TestCase):
+
+    def test_get_sut_info(self):
+        pod_info = {
+            'nodes': [
+                {
+                    'name': 'node1',
+                    'host_name': 'host1',
+                    'role': 'Controller',
+                    'ip': '10.1.0.50',
+                    'user': 'root',
+                    'passward': 'root'
+                }
+            ]
+        }
+
+        AnsibleCommon.gen_inventory_ini_dict = mock.MagicMock()
+        AnsibleCommon.get_sut_info = mock.MagicMock(return_value={'node1': {}})
+
+        env = Environment(pod=pod_info)
+        env.get_sut_info()
+
+    def test_get_sut_info_pod_str(self):
+        pod_info = 'nodes'
+
+        env = Environment(pod=pod_info)
+        with self.assertRaises(UnsupportedPodFormatError):
+            env.get_sut_info()
+
+
+if __name__ == '__main__':
+    unittest.main()
index 1156b66..57dacbc 100644 (file)
@@ -21,30 +21,30 @@ class EnvCommandTestCase(unittest.TestCase):
     def test_do_influxdb(self, check_status_mock, start_async_task_mock):
         env = EnvCommand()
         env.do_influxdb({})
-        self.assertTrue(start_async_task_mock.called)
-        self.assertTrue(check_status_mock.called)
+        start_async_task_mock.assert_called_once()
+        check_status_mock.assert_called_once()
 
     @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
     @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
     def test_do_grafana(self, check_status_mock, start_async_task_mock):
         env = EnvCommand()
         env.do_grafana({})
-        self.assertTrue(start_async_task_mock.called)
-        self.assertTrue(check_status_mock.called)
+        start_async_task_mock.assert_called_once()
+        check_status_mock.assert_called_once()
 
     @mock.patch('yardstick.cmd.commands.env.EnvCommand._start_async_task')
     @mock.patch('yardstick.cmd.commands.env.EnvCommand._check_status')
     def test_do_prepare(self, check_status_mock, start_async_task_mock):
         env = EnvCommand()
         env.do_prepare({})
-        self.assertTrue(start_async_task_mock.called)
-        self.assertTrue(check_status_mock.called)
+        start_async_task_mock.assert_called_once()
+        check_status_mock.assert_called_once()
 
     @mock.patch('yardstick.cmd.commands.env.HttpClient.post')
     def test_start_async_task(self, post_mock):
         data = {'action': 'create_grafana'}
         EnvCommand()._start_async_task(data)
-        self.assertTrue(post_mock.called)
+        post_mock.assert_called_once()
 
     @mock.patch('yardstick.cmd.commands.env.HttpClient.get')
     @mock.patch('yardstick.cmd.commands.env.EnvCommand._print_status')
index f6f842e..9221676 100644 (file)
@@ -18,4 +18,4 @@ class TestcaseCommandsUT(unittest.TestCase):
     def test_do_list(self, mock_client, mock_print):
         mock_client.get.return_value = {'result': []}
         TestcaseCommands().do_list({})
-        self.assertTrue(mock_print.called)
+        mock_print.assert_called_once()