diff options
40 files changed, 719 insertions, 572 deletions
diff --git a/docs/release/release-notes/release-notes.rst b/docs/release/release-notes/release-notes.rst index 914daa3a4..920e90fbc 100644 --- a/docs/release/release-notes/release-notes.rst +++ b/docs/release/release-notes/release-notes.rst @@ -36,6 +36,9 @@ Version History | December 14, 2018 | 7.1.0 | Yardstick for Gambia release | | | | | +-------------------+-----------+---------------------------------+ +| January 25, 2019 | 7.2.0 | Yardstick for Gambia release | +| | | | ++-------------------+-----------+---------------------------------+ Important Notes @@ -114,19 +117,19 @@ Release Data | **Project** | Yardstick | | | | +--------------------------------+-----------------------+ -| **Repo/tag** | yardstick/opnfv-7.1.0 | +| **Repo/tag** | yardstick/opnfv-7.2.0 | | | | +--------------------------------+-----------------------+ -| **Yardstick Docker image tag** | opnfv-7.1.0 | +| **Yardstick Docker image tag** | opnfv-7.2.0 | | | | +--------------------------------+-----------------------+ -| **Release designation** | Gambia 7.1 | +| **Release designation** | Gambia 7.2 | | | | +--------------------------------+-----------------------+ -| **Release date** | December 14, 2018 | +| **Release date** | January 25, 2019 | | | | +--------------------------------+-----------------------+ -| **Purpose of the delivery** | OPNFV Gambia 7.1.0 | +| **Purpose of the delivery** | OPNFV Gambia 7.2.0 | | | | +--------------------------------+-----------------------+ @@ -272,7 +275,7 @@ List of Scenarios New Test cases -------------- -.. note:: Yardstick Gambia 7.1.0 adds no new test cases. +.. note:: Yardstick Gambia 7.2.0 adds no new test cases. * Generic NFVI test cases @@ -329,7 +332,7 @@ Feature additions Scenario Matrix =============== -For Gambia 7.1.0, Yardstick was tested on the following scenarios: +For Gambia 7.2.0, Yardstick was tested on the following scenarios: +-------------------------+------+---------+----------+------+ | Scenario | Apex | Compass | Fuel-arm | Fuel | @@ -373,33 +376,16 @@ Known Issues/Faults Corrected Faults ---------------- -Gambia 7.1.0: +Gambia 7.2.0: +--------------------+--------------------------------------------------------------------------+ | **JIRA REFERENCE** | **DESCRIPTION** | +====================+==========================================================================+ -| YARDSTICK-1241 | Update NSB PROX devguide. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1458 | NSB NFVi PROX Should report realtime port activity not historical data. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1471 | Add Testcase Prox Standalone SRIOV. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1475 | Adding Testcase for Prox Stanalone OvS-DPDK. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1500 | Adding Testcase for Prox L2FWD PktTouch Stanalone OvS-DPDK. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1517 | Missing opnfv "os-ovn-nofeature-ha" scenario test suite. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-l526 | Run testcase 074 result overridden by job status. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1547 | Adding scale up test case for l3fwd OvS-DPDK. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1560 | Fix pip environment. | -+--------------------+--------------------------------------------------------------------------+ -| YARDSTICK-1561 | L3FWD Gradana Dashboards Out-of-date and incorrect. | +| YARDSTICK-1512 | [dovetail] split the sla check results into process recovery and service | +| | recovery for HA test cases. | +--------------------+--------------------------------------------------------------------------+ -Gambia 7.1.0 known restrictions/issues +Gambia 7.2.0 known restrictions/issues ====================================== diff --git a/docs/testing/user/userguide/12-nsb-overview.rst b/docs/testing/user/userguide/12-nsb-overview.rst index ec4df1cae..70aba1e37 100644 --- a/docs/testing/user/userguide/12-nsb-overview.rst +++ b/docs/testing/user/userguide/12-nsb-overview.rst @@ -56,7 +56,7 @@ NSB extension includes: * Generic data models of Network Services, based on ETSI spec `ETSI GS NFV-TST 001`_ -* Standalone :term:`context` for VNF testing with SRIOV, OVS, OVS-DPDK, etc +* Standalone :term:`context` for VNF testing SRIOV, OVS, OVS-DPDK, etc * Generic VNF configuration models and metrics implemented with Python classes * Traffic generator features and traffic profiles @@ -121,6 +121,13 @@ Network Service framework performs the necessary test steps. It may involve: Components of Network Service ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. TODO: provide a list of components in this section and describe them in + later sub-sections + +.. Components are the methodology, TGs, framework extensions, KPI collection, + Testcases, SampleVNFs +.. Framework extentions include: VNF models, NSPerf Scenario, contexts + * *Models for Network Service benchmarking*: The Network Service benchmarking requires the proper modelling approach. The NSB provides models using Python files and defining of NSDs and VNFDs. @@ -169,6 +176,38 @@ for every combination of test case parameters: * RFC2544 throughput for various loss rate defined (1% is a default) +KPI Collection +^^^^^^^^^^^^^^ + +KPI collection is the process of sampling KPIs at multiple intervals to allow +for investigation into anomalies during runtime. Some KPI intervals are +adjustable. KPIs are collected from traffic generators and NFVI for the SUT. +There is already some reporting in NSB available, but NSB collects all KPIs for +analytics to process. + +Below is an example list of basic KPIs: +* Throughput +* Latency +* Packet delay variation +* Maximum establishment rate +* Maximum tear-down rate +* Maximum simultaneous number of sessions + +Of course, there can be many other KPIs that will be relevant for a specific +NFVI, but in most cases these KPIs are enough to give you a basic picture of +the SUT. NSB also uses :term:`collectd` in order to collect the KPIs. Currently +the following collectd plug-ins are enabled for NSB testcases: + +* Libvirt +* Interface stats +* OvS events +* vSwitch stats +* Huge Pages +* RAM +* CPU usage +* IntelĀ® PMU +* Intel(r) RDT + Graphical Overview ------------------ diff --git a/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_acl-scale-up.yaml b/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_acl-scale-up.yaml new file mode 100644 index 000000000..d71c4cefb --- /dev/null +++ b/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_acl-scale-up.yaml @@ -0,0 +1,111 @@ +# Copyright (c) 2019 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +{% set vports = vports or 2 %} +{% set duration = duration or 300 %} +--- +schema: "yardstick:task:0.1" + +scenarios: +- + type: NSPerf + # + # In case where we know that all the packets generated by the generator + # will bw received. Then use prox_binsearch. + # + # In the case where some or all the packets generated by the generator may + # not be received. Please use prox_acl .. (This generates packets at + # a specific rate and does not change rate. + # + traffic_profile: ../../traffic_profiles/prox_acl.yaml + extra_args: + vports: {{ vports }} + topology: prox-tg-topology-scale-up.yaml + + nodes: + tg__0: tg_0.yardstick + vnf__0: vnf_0.yardstick + + options: + vnf__0: + prox_path: /opt/nsb_bin/prox + prox_config: "configs/handle_acl-{{ vports }}.cfg" + prox_args: + "-t": "" + prox_files: + "configs/acl_rules-2.lua": "" + + tg__0: + prox_path: /opt/nsb_bin/prox + prox_config: "configs/gen_acl-{{ vports }}.cfg" + prox_args: + "-e": "" + "-t": "" + + runner: + type: Duration + # we kill after duration, independent of test duration, so set this high + duration: {{ duration }} + +contexts: + - name: yardstick + type: Node + file: prox_tg_bm.yaml + - name: yardstick + type: StandaloneOvsDpdk + file: /etc/yardstick/nodes/standalone/host_ovs.yaml + vm_deploy: True + ovs_properties: + version: + ovs: 2.8.0 + dpdk: 17.05.2 + pmd_threads: 2 + ram: + socket_0: 2048 + socket_1: 2048 + queues: 4 + vpath: "/usr/local" + flavor: + images: "/var/lib/libvirt/images/yardstick-nsb-image.img" + ram: 16384 + extra_specs: + hw:cpu_sockets: 1 + hw:cpu_cores: 10 + hw:cpu_threads: 2 + servers: + vnf__0: + network_ports: + mgmt: + cidr: '1.1.1.62/24' +{% for port_num in range((vports/2)|int) %} + xe{{ port_num * 2 }}: + - uplink_{{ port_num }} + xe{{ (port_num * 2) + 1 }}: + - downlink_{{ port_num }} +{% endfor %} + networks: +{% for port_num in range((vports/2)|int) %} + uplink_{{ port_num }}: + port_num: {{ networks.uplink[port_num].port_num }} + phy_port: "{{ networks.uplink[port_num].phy_port }}" + vpci: "{{ networks.uplink[port_num].vpci }}" + cidr: "{{ networks.uplink[port_num].cidr }}" + gateway_ip: "{{ networks.uplink[port_num].gateway_ip }}" + downlink_{{ port_num }}: + port_num: {{ networks.downlink[port_num].port_num }} + phy_port: "{{ networks.downlink[port_num].phy_port }}" + vpci: "{{ networks.downlink[port_num].vpci }}" + cidr: "{{ networks.downlink[port_num].cidr }}" + gateway_ip: "{{ networks.downlink[port_num].gateway_ip }}" +{% endfor %} diff --git a/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_l3fwd-scale-up.yaml b/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_l3fwd-scale-up.yaml index 450775805..f9d9b65a8 100644 --- a/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_l3fwd-scale-up.yaml +++ b/samples/vnf_samples/nsut/prox/tc_prox_ovs-dpdk_l3fwd-scale-up.yaml @@ -84,24 +84,24 @@ contexts: network_ports: mgmt: cidr: '1.1.1.62/24' -{% for port_num in range(1,vports,2|int) %} - xe{{ loop.index0 * 2 }}: - - uplink_{{ loop.index0 }} - xe{{ (loop.index0 * 2) + 1 }}: - - downlink_{{ loop.index0 }} +{% for port_num in range((vports/2)|int) %} + xe{{ port_num * 2 }}: + - uplink_{{ port_num }} + xe{{ (port_num * 2) + 1 }}: + - downlink_{{ port_num }} {% endfor %} networks: -{% for port_num in range(1,vports,2|int) %} - uplink_{{ loop.index0 }}: - port_num: {{ networks.uplink[loop.index0].port_num }} - phy_port: "{{ networks.uplink[loop.index0].phy_port }}" - vpci: "{{ networks.uplink[loop.index0].vpci }}" - cidr: "{{ networks.uplink[loop.index0].cidr }}" - gateway_ip: "{{ networks.uplink[loop.index0].gateway_ip }}" - downlink_{{ loop.index0 }}: - port_num: {{ networks.downlink[loop.index0].port_num }} - phy_port: "{{ networks.downlink[loop.index0].phy_port }}" - vpci: "{{ networks.downlink[loop.index0].vpci }}" - cidr: "{{ networks.downlink[loop.index0].cidr }}" - gateway_ip: "{{ networks.downlink[loop.index0].gateway_ip }}" +{% for port_num in range((vports/2)|int) %} + uplink_{{ port_num }}: + port_num: {{ networks.uplink[port_num].port_num }} + phy_port: "{{ networks.uplink[port_num].phy_port }}" + vpci: "{{ networks.uplink[port_num].vpci }}" + cidr: "{{ networks.uplink[port_num].cidr }}" + gateway_ip: "{{ networks.uplink[port_num].gateway_ip }}" + downlink_{{ port_num }}: + port_num: {{ networks.downlink[port_num].port_num }} + phy_port: "{{ networks.downlink[port_num].phy_port }}" + vpci: "{{ networks.downlink[port_num].vpci }}" + cidr: "{{ networks.downlink[port_num].cidr }}" + gateway_ip: "{{ networks.downlink[port_num].gateway_ip }}" {% endfor %} diff --git a/samples/vnf_samples/nsut/prox/tc_prox_sriov_acl-scale-up.yaml b/samples/vnf_samples/nsut/prox/tc_prox_sriov_acl-scale-up.yaml new file mode 100644 index 000000000..7e810886d --- /dev/null +++ b/samples/vnf_samples/nsut/prox/tc_prox_sriov_acl-scale-up.yaml @@ -0,0 +1,101 @@ +# Copyright (c) 2019 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +{% set vports = vports or 2 %} +{% set duration = duration or 300 %} +--- +schema: "yardstick:task:0.1" + +scenarios: +- + type: NSPerf + # + # In case where we know that all the packets generated by the generator + # will bw received. Then use prox_binsearch. + # + # In the case where some or all the packets generated by the generator may + # not be received. Please use prox_acl .. (This generates packets at + # a specific rate and does not change rate. + # + traffic_profile: ../../traffic_profiles/prox_acl.yaml + extra_args: + vports: {{ vports }} + topology: prox-tg-topology-scale-up.yaml + + nodes: + tg__0: tg_0.yardstick + vnf__0: vnf_0.yardstick + + options: + vnf__0: + prox_path: /opt/nsb_bin/prox + prox_config: "configs/handle_acl-{{ vports }}.cfg" + prox_args: + "-t": "" + prox_files: + "configs/acl_rules-2.lua": "" + + tg__0: + prox_path: /opt/nsb_bin/prox + prox_config: "configs/gen_acl-{{ vports }}.cfg" + prox_args: + "-e": "" + "-t": "" + + runner: + type: Duration + # we kill after duration, independent of test duration, so set this high + duration: {{ duration }} + +contexts: + - name: yardstick + type: Node + file: prox_tg_bm.yaml + - name: yardstick + type: StandaloneSriov + file: /etc/yardstick/nodes/standalone/host_sriov.yaml + vm_deploy: True + flavor: + images: "/var/lib/libvirt/images/yardstick-nsb-image.img" + ram: 16384 + extra_specs: + hw:cpu_sockets: 1 + hw:cpu_cores: 10 + hw:cpu_threads: 2 + user: "" + password: "" + servers: + vnf__0: + network_ports: + mgmt: + cidr: '1.1.1.62/24' +{% for port_num in range((vports/2)|int) %} + xe{{ port_num * 2 }}: + - uplink_{{ port_num }} + xe{{ (port_num * 2) + 1 }}: + - downlink_{{ port_num }} +{% endfor %} + networks: +{% for port_num in range((vports/2)|int) %} + uplink_{{ port_num }}: + phy_port: "{{ networks.uplink[port_num].phy_port }}" + vpci: "{{ networks.uplink[port_num].vpci }}" + cidr: "{{ networks.uplink[port_num].cidr }}" + gateway_ip: "{{ networks.uplink[port_num].gateway_ip }}" + downlink_{{ port_num }}: + phy_port: "{{ networks.downlink[port_num].phy_port }}" + vpci: "{{ networks.downlink[port_num].vpci }}" + cidr: "{{ networks.downlink[port_num].cidr }}" + gateway_ip: "{{ networks.downlink[port_num].gateway_ip }}" +{% endfor %} diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1024k_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1024k_Requests-65000_Concurrency.yaml deleted file mode 100644 index a87996c1a..000000000 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1024k_Requests-65000_Concurrency.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2016-2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -schema: yardstick:task:0.1 -scenarios: -- type: NSPerf - traffic_profile: "../../traffic_profiles/http_tests/HTTP_1024k-requests_65000_concurrency.yaml" - topology: vfw_vnf_topology_ixload.yaml - nodes: - tg__0: trafficgen_1.yardstick - vnf__0: vnf.yardstick - options: - framesize: - uplink: {64B: 100} - downlink: {64B: 100} - traffic_type: 4 - rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 - vnf__0: - rules: acl_1rule.yaml - vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1} - nfvi_enable: True - runner: - type: Duration - duration: 2 - ixia_profile: ../../traffic_profiles/vfw/HTTP-vFW_IPv4_2Ports.rxf # Need vlan update -context: - type: Node - name: yardstick - nfvi_type: baremetal - file: /etc/yardstick/nodes/pod_ixia.yaml - diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1b_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1b_Requests-65000_Concurrency.yaml index 7a9a265d6..3596a1d15 100644 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1b_Requests-65000_Concurrency.yaml +++ b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_1b_Requests-65000_Concurrency.yaml @@ -25,7 +25,7 @@ scenarios: simulated_users: uplink: [65000] page_object: - uplink: ["/1b.html"] + uplink: ["/1b.html"] #supports /4k /8k /16k /32k /64k /128k.... framesize: uplink: {64B: 100} downlink: {64B: 100} diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_256k_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_256k_Requests-65000_Concurrency.yaml deleted file mode 100644 index 82cdd6210..000000000 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_256k_Requests-65000_Concurrency.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2016-2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -schema: yardstick:task:0.1 -scenarios: -- type: NSPerf - traffic_profile: "../../traffic_profiles/http_tests/HTTP_256k-requests_65000_concurrency.yaml" - topology: vfw_vnf_topology_ixload.yaml - nodes: - tg__0: trafficgen_1.yardstick - vnf__0: vnf.yardstick - options: - framesize: - uplink: {64B: 100} - downlink: {64B: 100} - traffic_type: 4 - rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 - vnf__0: - rules: acl_1rule.yaml - vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1} - nfvi_enable: True - runner: - type: Duration - duration: 2 - ixia_profile: ../../traffic_profiles/vfw/HTTP-vFW_IPv4_2Ports.rxf # Need vlan update -context: - type: Node - name: yardstick - nfvi_type: baremetal - file: /etc/yardstick/nodes/pod_ixia.yaml - diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_4k_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_4k_Requests-65000_Concurrency.yaml deleted file mode 100644 index 00131b5f9..000000000 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_4k_Requests-65000_Concurrency.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2016-2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -schema: yardstick:task:0.1 -scenarios: -- type: NSPerf - traffic_profile: "../../traffic_profiles/http_tests/HTTP_4k-requests_65000_concurrency.yaml" - topology: vfw_vnf_topology_ixload.yaml - nodes: - tg__0: trafficgen_1.yardstick - vnf__0: vnf.yardstick - options: - framesize: - uplink: {64B: 100} - downlink: {64B: 100} - traffic_type: 4 - rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 - vnf__0: - rules: acl_1rule.yaml - vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1} - nfvi_enable: True - runner: - type: Duration - duration: 2 - ixia_profile: ../../traffic_profiles/vfw/HTTP-vFW_IPv4_2Ports.rxf # Need vlan update -context: - type: Node - name: yardstick - nfvi_type: baremetal - file: /etc/yardstick/nodes/pod_ixia.yaml - diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_512k_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_512k_Requests-65000_Concurrency.yaml deleted file mode 100644 index 8fcd66e31..000000000 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_512k_Requests-65000_Concurrency.yaml +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (c) 2016-2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -schema: yardstick:task:0.1 -scenarios: -- type: NSPerf - traffic_profile: "../../traffic_profiles/http_tests/HTTP_512k-requests_65000_concurrency.yaml" - topology: vfw_vnf_topology_ixload.yaml - nodes: - tg__0: trafficgen_1.yardstick - vnf__0: vnf.yardstick - options: - framesize: - uplink: {64B: 100} - downlink: {64B: 100} - traffic_type: 4 - rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 - vnf__0: - rules: acl_1rule.yaml - vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1} - nfvi_enable: True - runner: - type: Duration - duration: 2 - ixia_profile: ../../traffic_profiles/vfw/HTTP-vFW_IPv4_2Ports.rxf # Need vlan update -context: - type: Node - name: yardstick - nfvi_type: baremetal - file: /etc/yardstick/nodes/pod_ixia.yaml - diff --git a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_64k_Requests-65000_Concurrency.yaml b/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_64k_Requests-65000_Concurrency.yaml deleted file mode 100644 index 3b354243b..000000000 --- a/samples/vnf_samples/nsut/vfw/tc_baremetal_http_ixload_64k_Requests-65000_Concurrency.yaml +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright (c) 2016-2017 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - ---- -schema: yardstick:task:0.1 -scenarios: -- type: NSPerf - traffic_profile: "../../traffic_profiles/http_tests/HTTP_64k-requests_65000_concurrency.yaml" - topology: vfw_vnf_topology_ixload.yaml - nodes: - tg__0: trafficgen_1.yardstick - vnf__0: vnf.yardstick - options: - framesize: - uplink: {64B: 100} - downlink: {64B: 100} - traffic_type: 4 - rfc2544: - allowed_drop_rate: 0.0001 - 0.0001 - vnf__0: - rules: acl_1rule.yaml - vnf_config: {lb_config: 'SW', lb_count: 1, worker_config: '1C/1T', worker_threads: 1} - nfvi_enable: True - runner: - type: Duration - duration: 2 - ixia_profile: ../../traffic_profiles/vfw/HTTP-vFW_IPv4_2Ports.rxf # Need vlan update -context: - type: Node - name: yardstick - nfvi_type: baremetal - file: /etc/yardstick/nodes/pod_ixia.yaml diff --git a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_1024K-requests_65000_concurrency.yaml b/samples/vnf_samples/traffic_profiles/http_tests/HTTP_1024K-requests_65000_concurrency.yaml deleted file mode 100644 index bfc75982f..000000000 --- a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_1024K-requests_65000_concurrency.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schema: "nsb:traffic_profile:0.1" - -name: TrafficProfileGenericHTTP -description: Traffic profile to run HTTP test -traffic_profile: - traffic_type: TrafficProfileGenericHTTP - -#http client specific values -uplink_0: - http_no_requests: "1000" # number of http iterations - http_concurency: "65000" # number of threads to be run - http_locator: "/1024K.bin" # http locator to be read - http_peer_address: "152.40.40.20" # address range of the servers - http_peer_port: "9004" # port range of the server - http_client_address: "152.16.100.20" # address range of the servers - private_subnet_mask: "255.255.255.0" - attacker_tests: "False" # True : If attacker Test, False : Otherwise - -#http server side -downlink_0: - http_locator_image_size: "1024KB" # image size requested by http client - http_bind_address: "152.40.40.20" # where address is bound - http_bind_port: "9004" # when port is bound - public_subnet_mask: "255.255.255.0" diff --git a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_256K-requests_65000_concurrency.yaml b/samples/vnf_samples/traffic_profiles/http_tests/HTTP_256K-requests_65000_concurrency.yaml deleted file mode 100644 index 100257533..000000000 --- a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_256K-requests_65000_concurrency.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schema: "nsb:traffic_profile:0.1" - -name: TrafficProfileGenericHTTP -description: Traffic profile to run HTTP test -traffic_profile: - traffic_type: TrafficProfileGenericHTTP - -#http client specific values -uplink_0: - http_no_requests: "1000" # number of http iterations - http_concurency: "65000" # number of threads to be run - http_locator: "/256K.bin" # http locator to be read - http_peer_address: "152.40.40.20" # address range of the servers - http_peer_port: "9004" # port range of the server - http_client_address: "152.16.100.20" # address range of the servers - private_subnet_mask: "255.255.255.0" - attacker_tests: "False" # True : If attacker Test, False : Otherwise - -#http server side -downlink_0: - http_locator_image_size: "256KB" # image size requested by http client - http_bind_address: "152.40.40.20" # where address is bound - http_bind_port: "9004" # when port is bound - public_subnet_mask: "255.255.255.0" diff --git a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_4K-requests_65000_concurrency.yaml b/samples/vnf_samples/traffic_profiles/http_tests/HTTP_4K-requests_65000_concurrency.yaml deleted file mode 100644 index a62aeb210..000000000 --- a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_4K-requests_65000_concurrency.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schema: "nsb:traffic_profile:0.1" - -name: TrafficProfileGenericHTTP -description: Traffic profile to run HTTP test -traffic_profile: - traffic_type: TrafficProfileGenericHTTP - -#http client specific values -uplink_0: - http_no_requests: "1000" # number of http iterations - http_concurency: "65000" # number of threads to be run - http_locator: "/4K.bin" # http locator to be read - http_peer_address: "152.40.40.20" # address range of the servers - http_peer_port: "9004" # port range of the server - http_client_address: "152.16.100.20" # address range of the servers - private_subnet_mask: "255.255.255.0" - attacker_tests: "False" # True : If attacker Test, False : Otherwise - -#http server side -downlink_0: - http_locator_image_size: "4KB" # image size requested by http client - http_bind_address: "152.40.40.20" # where address is bound - http_bind_port: "9004" # when port is bound - public_subnet_mask: "255.255.255.0" diff --git a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_512K-requests_65000_concurrency.yaml b/samples/vnf_samples/traffic_profiles/http_tests/HTTP_512K-requests_65000_concurrency.yaml deleted file mode 100644 index 9fd76354f..000000000 --- a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_512K-requests_65000_concurrency.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schema: "nsb:traffic_profile:0.1" - -name: TrafficProfileGenericHTTP -description: Traffic profile to run HTTP test -traffic_profile: - traffic_type: TrafficProfileGenericHTTP - -#http client specific values -uplink_0: - http_no_requests: "1000" # number of http iterations - http_concurency: "65000" # number of threads to be run - http_locator: "/512K.bin" # http locator to be read - http_peer_address: "152.40.40.20" # address range of the servers - http_peer_port: "9004" # port range of the server - http_client_address: "152.16.100.20" # address range of the servers - private_subnet_mask: "255.255.255.0" - attacker_tests: "False" # True : If attacker Test, False : Otherwise - -#http server side -downlink_0: - http_locator_image_size: "512KB" # image size requested by http client - http_bind_address: "152.40.40.20" # where address is bound - http_bind_port: "9004" # when port is bound - public_subnet_mask: "255.255.255.0" diff --git a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_64K-requests_65000_concurrency.yaml b/samples/vnf_samples/traffic_profiles/http_tests/HTTP_64K-requests_65000_concurrency.yaml deleted file mode 100644 index 4585b31e9..000000000 --- a/samples/vnf_samples/traffic_profiles/http_tests/HTTP_64K-requests_65000_concurrency.yaml +++ /dev/null @@ -1,24 +0,0 @@ -schema: "nsb:traffic_profile:0.1" - -name: TrafficProfileGenericHTTP -description: Traffic profile to run HTTP test -traffic_profile: - traffic_type: TrafficProfileGenericHTTP - -#http client specific values -uplink_0: - http_no_requests: "1000" # number of http iterations - http_concurency: "65000" # number of threads to be run - http_locator: "/64K.bin" # http locator to be read - http_peer_address: "152.40.40.20" # address range of the servers - http_peer_port: "9004" # port range of the server - http_client_address: "152.16.100.20" # address range of the servers - private_subnet_mask: "255.255.255.0" - attacker_tests: "False" # True : If attacker Test, False : Otherwise - -#http server side -downlink_0: - http_locator_image_size: "64KB" # image size requested by http client - http_bind_address: "152.40.40.20" # where address is bound - http_bind_port: "9004" # when port is bound - public_subnet_mask: "255.255.255.0" diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc019.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc019.yaml index 08037d9fa..1ed3a3ea6 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc019.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc019.yaml @@ -40,8 +40,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc045.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc045.yaml index bc7cd3d28..b23855dc1 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc045.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc045.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc046.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc046.yaml index 3b04cc4bd..5bbe72610 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc046.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc046.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc047.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc047.yaml index d199e5117..a8783d6e8 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc047.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc047.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc048.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc048.yaml index 2bca1fb9d..6a4dc8798 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc048.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc048.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc053.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc053.yaml index c2a4f9ede..7b5f77813 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc053.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc053.yaml @@ -36,8 +36,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 - monitor_type: "openstack-cmd" diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc056.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc056.yaml index 9194d9d4e..41314be27 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc056.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc056.yaml @@ -61,8 +61,6 @@ scenarios: process_name: "{{ attack_process }}" host: {{attack_host}} monitor_time: 30 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc058.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc058.yaml index 06d460032..effb20a48 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc058.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc058.yaml @@ -37,8 +37,6 @@ scenarios: host: {{attack_host}} key: "monitor-recovery" monitor_time: 30 - sla: - max_recover_time: 30 - monitor_type: "general-monitor" diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc088.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc088.yaml index c2f1cbe33..c1b065711 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc088.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc088.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 operations: - diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc089.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc089.yaml index d10650e03..9379d2f75 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc089.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc089.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 operations: - diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc090.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc090.yaml index 41372045d..eaf14f60e 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc090.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc090.yaml @@ -57,8 +57,6 @@ scenarios: host: {{attack_host}} monitor_time: {{monitor_time}} monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc091.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc091.yaml index d952464a1..54ef6f237 100644 --- a/tests/opnfv/test_cases/opnfv_yardstick_tc091.yaml +++ b/tests/opnfv/test_cases/opnfv_yardstick_tc091.yaml @@ -38,8 +38,6 @@ scenarios: host: {{attack_host}} monitor_time: 30 monitor_number: 3 - sla: - max_recover_time: 30 nodes: {{attack_host}}: {{attack_host}}.LF diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py index c3c5451bd..f4c48f4a5 100644 --- a/yardstick/benchmark/contexts/heat.py +++ b/yardstick/benchmark/contexts/heat.py @@ -508,10 +508,12 @@ class HeatContext(Context): pkey = pkg_resources.resource_string( 'yardstick.resources', h_join('files/yardstick_key', self.name)).decode('utf-8') - + key_filename = pkg_resources.resource_filename('yardstick.resources', + h_join('files/yardstick_key', self.name)) result = { "user": server.context.user, "pkey": pkey, + "key_filename": key_filename, "private_ip": server.private_ip, "interfaces": server.interfaces, "routing_table": self.generate_routing_table(server), diff --git a/yardstick/benchmark/core/report.py b/yardstick/benchmark/core/report.py index 0bc392fe5..0819cd497 100644 --- a/yardstick/benchmark/core/report.py +++ b/yardstick/benchmark/core/report.py @@ -10,13 +10,12 @@ """ Handler for yardstick command 'report' """ -import ast import re +import six import uuid import jinja2 from api.utils import influx -from oslo_utils import encodeutils from oslo_utils import uuidutils from yardstick.common import constants as consts from yardstick.common.utils import cliargs @@ -55,11 +54,9 @@ class JSTree(object): def format_for_jstree(self, data): """Format the data into the required format for jsTree. - The data format expected is a list of key-value pairs which represent - the data and label for each metric e.g.: + The data format expected is a list of metric names e.g.: - [{'data': [0, ], 'label': 'tg__0.DropPackets'}, - {'data': [548, ], 'label': 'tg__0.LatencyAvg.5'},] + ['tg__0.DropPackets', 'tg__0.LatencyAvg.5'] This data is converted into the format required for jsTree to group and display the metrics in a hierarchial fashion, including creating a @@ -76,8 +73,8 @@ class JSTree(object): self._created_nodes = ['#'] self.jstree_data = [] - for item in data: - self._create_node(item["label"]) + for metric in data: + self._create_node(metric) return self.jstree_data @@ -115,10 +112,10 @@ class Report(object): else: raise KeyError("Test case not found.") - def _get_tasks(self): - task_cmd = "select * from \"%s\" where task_id= '%s'" - task_query = task_cmd % (self.yaml_name, self.task_id) - query_exec = influx.query(task_query) + def _get_metrics(self): + metrics_cmd = "select * from \"%s\" where task_id = '%s'" + metrics_query = metrics_cmd % (self.yaml_name, self.task_id) + query_exec = influx.query(metrics_query) if query_exec: return query_exec else: @@ -132,38 +129,72 @@ class Report(object): """ self._validate(args.yaml_name[0], args.task_id[0]) - self.db_fieldkeys = self._get_fieldkeys() + db_fieldkeys = self._get_fieldkeys() + # list of dicts of: + # - PY2: unicode key and unicode value + # - PY3: str key and str value - self.db_task = self._get_tasks() + db_metrics = self._get_metrics() + # list of dicts of: + # - PY2: unicode key and { None | unicode | float | long | int } value + # - PY3: str key and { None | str | float | int } value - field_keys = [] - datasets = [] - table_vals = {} + # extract fieldKey entries, and convert them to str where needed + field_keys = [key if isinstance(key, str) # PY3: already str + else key.encode('utf8') # PY2: unicode to str + for key in + [field['fieldKey'] + for field in db_fieldkeys]] - field_keys = [encodeutils.to_utf8(field['fieldKey']) - for field in self.db_fieldkeys] + # extract timestamps + self.Timestamp = [] + for metric in db_metrics: + metric_time = metric['time'] # in RFC3339 format + if not isinstance(metric_time, str): + metric_time = metric_time.encode('utf8') # PY2: unicode to str + metric_time = metric_time[11:] # skip date, keep time + head, _, tail = metric_time.partition('.') # split HH:MM:SS and nsZ + metric_time = head + '.' + tail[:6] # join HH:MM:SS and .us + self.Timestamp.append(metric_time) # HH:MM:SS.micros + + # prepare return values + datasets = [] + table_vals = {'Timestamp': self.Timestamp} + # extract and convert field values for key in field_keys: - self.Timestamp = [] values = [] - for task in self.db_task: - task_time = encodeutils.to_utf8(task['time']) - if not isinstance(task_time, str): - task_time = str(task_time, 'utf8') - if not isinstance(key, str): - key = str(key, 'utf8') - task_time = task_time[11:] - head, _, tail = task_time.partition('.') - task_time = head + "." + tail[:6] - self.Timestamp.append(task_time) - if task[key] is None: - values.append(None) - elif isinstance(task[key], (int, float)): - values.append(task[key]) + for metric in db_metrics: + val = metric.get(key, None) + if val is None: + # keep explicit None or missing entry as is + pass + elif isinstance(val, (int, float)): + # keep plain int or float as is + pass + elif six.PY2 and isinstance(val, + long): # pylint: disable=undefined-variable + # PY2: long value would be rendered with trailing L, + # which JS does not support, so convert it to float + val = float(val) + elif isinstance(val, six.string_types): + s = val + if not isinstance(s, str): + s = s.encode('utf8') # PY2: unicode to str + try: + # convert until failure + val = s + val = float(s) + val = int(s) + if six.PY2 and isinstance(val, + long): # pylint: disable=undefined-variable + val = float(val) # PY2: long to float + except ValueError: + pass else: - values.append(ast.literal_eval(task[key])) + raise ValueError("Cannot convert %r" % val) + values.append(val) datasets.append({'label': key, 'data': values}) - table_vals['Timestamp'] = self.Timestamp table_vals[key] = values return datasets, table_vals @@ -197,8 +228,14 @@ class Report(object): @cliargs("yaml_name", type=str, help=" Yaml file Name", nargs=1) def generate_nsb(self, args): """Start NSB report generation.""" - datasets, table_vals = self._generate_common(args) - jstree_data = JSTree().format_for_jstree(datasets) + _, report_data = self._generate_common(args) + report_time = report_data.pop('Timestamp') + report_keys = sorted(report_data, key=str.lower) + report_tree = JSTree().format_for_jstree(report_keys) + report_meta = { + "testcase": self.yaml_name, + "task_id": self.task_id, + } template_dir = consts.YARDSTICK_ROOT_PATH + "yardstick/common" template_environment = jinja2.Environment( @@ -207,10 +244,11 @@ class Report(object): lstrip_blocks=True) context = { - "Timestamps": self.Timestamp, - "task_id": self.task_id, - "table": table_vals, - "jstree_nodes": jstree_data, + "report_meta": report_meta, + "report_data": report_data, + "report_time": report_time, + "report_keys": report_keys, + "report_tree": report_tree, } template_html = template_environment.get_template("nsb_report.html.j2") diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py index 971bae1e9..8f1f53cde 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_multi.py @@ -62,20 +62,19 @@ class MultiMonitor(basemonitor.BaseMonitor): outage_time = ( last_outage - first_outage if last_outage > first_outage else 0 ) + self._result = {"outage_time": outage_time} LOG.debug("outage_time is: %f", outage_time) max_outage_time = 0 - if "max_outage_time" in self._config["sla"]: - max_outage_time = self._config["sla"]["max_outage_time"] - elif "max_recover_time" in self._config["sla"]: - max_outage_time = self._config["sla"]["max_recover_time"] - else: - raise RuntimeError("'max_outage_time' or 'max_recover_time' " - "config is not found") - self._result = {"outage_time": outage_time} - - if outage_time > max_outage_time: - LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) - return False - else: - return True + if self._config.get("sla"): + if "max_outage_time" in self._config["sla"]: + max_outage_time = self._config["sla"]["max_outage_time"] + elif "max_recover_time" in self._config["sla"]: + max_outage_time = self._config["sla"]["max_recover_time"] + else: + raise RuntimeError("'max_outage_time' or 'max_recover_time' " + "config is not found") + if outage_time > max_outage_time: + LOG.error("SLA failure: %f > %f", outage_time, max_outage_time) + return False + return True diff --git a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py index 8d2f2633c..280e5811d 100644 --- a/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py +++ b/yardstick/benchmark/scenarios/availability/monitor/monitor_process.py @@ -46,12 +46,12 @@ class MonitorProcess(basemonitor.BaseMonitor): def verify_SLA(self): outage_time = self._result.get('outage_time', None) - max_outage_time = self._config["sla"]["max_recover_time"] - if outage_time > max_outage_time: - LOG.info("SLA failure: %f > %f", outage_time, max_outage_time) - return False - else: - return True + if self._config.get("sla"): + max_outage_time = self._config["sla"]["max_recover_time"] + if outage_time > max_outage_time: + LOG.info("SLA failure: %f > %f", outage_time, max_outage_time) + return False + return True def _test(): # pragma: no cover diff --git a/yardstick/common/nsb_report.css b/yardstick/common/nsb_report.css index 2beb91c53..667f865a5 100644 --- a/yardstick/common/nsb_report.css +++ b/yardstick/common/nsb_report.css @@ -9,21 +9,26 @@ ******************************************************************************/ body { - font-size: 16pt; + font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +header { + padding-top: 5px; + text-align: center; + font-weight: bold; } -table { +#tblMetrics { overflow-y: scroll; height: 360px; display: block; } -header { - font-family: Frutiger, "Helvetica Neue", Helvetica, Arial, sans-serif; - clear: left; - text-align: center; +#cnvGraph { + width: 100%; + height: 500px; } -.control-pane { +#divTree { font-size: 10pt; } diff --git a/yardstick/common/nsb_report.html.j2 b/yardstick/common/nsb_report.html.j2 index a3087d746..aa90253f8 100644 --- a/yardstick/common/nsb_report.html.j2 +++ b/yardstick/common/nsb_report.html.j2 @@ -29,53 +29,45 @@ </head> <body> - <div class="container" style="width:80%"> + <div class="container-fluid"> <div class="row"> - <header class="jumbotron"> - <h1>Yardstick User Interface</h1> - <h4>Report of {{task_id}} Generated</h4> + <header> + Testcase: {{report_meta.testcase}}<br> + Task-ID: {{report_meta.task_id}}<br> </header> </div> <div class="row"> - <div class="col-md-2 control-pane"> - <div id="data_selector"></div> + <div class="col-md-2"> + <div id="divTree"></div> </div> - <div class="col-md-10 data-pane"> - <canvas id="cnvGraph" style="width: 100%; height: 500px"></canvas> + <div class="col-md-10"> + <canvas id="cnvGraph"></canvas> </div> </div> <div class="row"> <div class="col-md-12 table-responsive"> - <table class="table table-hover"></table> + <table id="tblMetrics" class="table table-condensed table-hover"></table> </div> </div> </div> <script> - var arr, jstree_data, timestamps; - arr = {{table|safe}}; - timestamps = {{Timestamps|safe}}; - jstree_data = {{jstree_nodes|safe}}; + // Injected metrics, timestamps, keys and hierarchy + var report_data = {{report_data|safe}}; + var report_time = {{report_time|safe}}; + var report_keys = {{report_keys|safe}}; + var report_tree = {{report_tree|safe}}; + // Wait for DOM to be loaded $(function() { - create_table(arr); - create_tree(jstree_data); - var objGraph = create_graph($('#cnvGraph'), timestamps); + var tblMetrics = $('#tblMetrics'); + var cnvGraph = $('#cnvGraph'); + var divTree = $('#divTree'); - $('#data_selector').on('check_node.jstree uncheck_node.jstree', function(e, data) { - var selected_datasets = []; - for (var i = 0; i < data.selected.length; i++) { - var node = data.instance.get_node(data.selected[i]); - if (node.children.length == 0) { - var dataset = { - label: node.id, - data: arr[node.id], - }; - selected_datasets.push(dataset); - } - } - update_graph(objGraph, selected_datasets); - }); + create_table(tblMetrics, report_data, report_time, report_keys); + var objGraph = create_graph(cnvGraph, report_time); + create_tree(divTree, report_tree); + handle_tree(divTree, tblMetrics, objGraph, report_data, report_time); }); </script> </body> diff --git a/yardstick/common/nsb_report.js b/yardstick/common/nsb_report.js index cc5e14ee7..4de1c8e78 100644 --- a/yardstick/common/nsb_report.js +++ b/yardstick/common/nsb_report.js @@ -10,9 +10,9 @@ var None = null; -function create_tree(jstree_data) +function create_tree(divTree, jstree_data) { - $('#data_selector').jstree({ + divTree.jstree({ plugins: ['checkbox'], checkbox: { three_state: false, @@ -29,34 +29,33 @@ function create_tree(jstree_data) }); } -// may need to pass timestamps too... -function create_table(table_data) +function create_table(tblMetrics, table_data, timestamps, table_keys) { - var tab, tr, td, tn, tbody, keys, key, curr_data, val; - // create table - tab = document.getElementsByTagName('table')[0]; - tbody = document.createElement('tbody'); + var tbody = $('<tbody></tbody>'); + var tr0 = $('<tr></tr>'); + var th0 = $('<th></th>'); + var td0 = $('<td></td>'); + var tr; + + // create table headings using timestamps + tr = tr0.clone().append(th0.clone().text('Timestamp')); + timestamps.forEach(function(t) { + tr.append(th0.clone().text(t)); + }); + tbody.append(tr); + // for each metric - keys = Object.keys(table_data); - for (var i = 0; i < keys.length; i++) { - key = keys[i]; - tr = document.createElement('tr'); - td = document.createElement('td'); - tn = document.createTextNode(key); - td.appendChild(tn); - tr.appendChild(td); + table_keys.forEach(function(key) { + tr = tr0.clone().append(td0.clone().text(key)); // add each piece of data as its own column - curr_data = table_data[key]; - for (var j = 0; j < curr_data.length; j++) { - val = curr_data[j]; - td = document.createElement('td'); - tn = document.createTextNode(val === None ? '' : val); - td.appendChild(tn); - tr.appendChild(td); - } - tbody.appendChild(tr); - } - tab.appendChild(tbody); + table_data[key].forEach(function(val) { + tr.append(td0.clone().text(val === None ? '' : val)); + }); + tbody.append(tr); + }); + + // re-create table + tblMetrics.empty().append(tbody); } function create_graph(cnvGraph, timestamps) @@ -144,3 +143,23 @@ function update_graph(objGraph, datasets) objGraph.data.datasets = datasets; objGraph.update(); } + +function handle_tree(divTree, tblMetrics, objGraph, table_data, timestamps) +{ + divTree.on('check_node.jstree uncheck_node.jstree', function(e, data) { + var selected_keys = []; + var selected_datasets = []; + data.selected.forEach(function(sel) { + var node = data.instance.get_node(sel); + if (node.children.length == 0) { + selected_keys.push(node.id); + selected_datasets.push({ + label: node.id, + data: table_data[node.id], + }); + } + }); + create_table(tblMetrics, table_data, timestamps, selected_keys); + update_graph(objGraph, selected_datasets); + }); +} diff --git a/yardstick/tests/functional/benchmark/core/__init__.py b/yardstick/tests/functional/benchmark/core/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/yardstick/tests/functional/benchmark/core/__init__.py diff --git a/yardstick/tests/functional/benchmark/core/test_report.py b/yardstick/tests/functional/benchmark/core/test_report.py new file mode 100644 index 000000000..5f060dd1e --- /dev/null +++ b/yardstick/tests/functional/benchmark/core/test_report.py @@ -0,0 +1,114 @@ +############################################################################## +# Copyright (c) 2018 Intel Corporation. +# +# 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 ast +import tempfile +import unittest + +import mock +from six.moves import configparser + +from yardstick.benchmark import core +from yardstick.benchmark.core import report +from yardstick.cmd.commands import change_osloobj_to_paras + + +GOOD_YAML_NAME = 'fake_name' +GOOD_TASK_ID = "9cbe74b6-df09-4535-8bdc-dc3a43b8a4e2" +GOOD_DB_FIELDKEYS = [ + {u'fieldKey': u'metric1', u'fieldType': u'integer'}, + {u'fieldKey': u'metric4', u'fieldType': u'integer'}, + {u'fieldKey': u'metric2', u'fieldType': u'integer'}, + {u'fieldKey': u'metric3', u'fieldType': u'integer'}, +] +GOOD_DB_METRICS = [ + {u'time': u'2018-08-20T16:49:26.372662016Z', + u'metric1': 1, u'metric2': 0, u'metric3': 8, u'metric4': 5}, + {u'time': u'2018-08-20T16:49:27.374208000Z', + u'metric1': 1, u'metric2': 1, u'metric3': 5, u'metric4': 4}, + {u'time': u'2018-08-20T16:49:28.375742976Z', + u'metric1': 2, u'metric2': 2, u'metric3': 3, u'metric4': 3}, + {u'time': u'2018-08-20T16:49:29.377299968Z', + u'metric1': 3, u'metric2': 3, u'metric3': 2, u'metric4': 2}, + {u'time': u'2018-08-20T16:49:30.378252032Z', + u'metric1': 5, u'metric2': 4, u'metric3': 1, u'metric4': 1}, + {u'time': u'2018-08-20T16:49:30.379359421Z', + u'metric1': 8, u'metric2': 5, u'metric3': 1, u'metric4': 0}, +] + +yardstick_config = """ +[DEFAULT] +dispatcher = influxdb +""" + + +def my_query(query_sql): + get_fieldkeys_cmd = 'show field keys' + get_metrics_cmd = 'select * from' + + if get_fieldkeys_cmd in query_sql: + return GOOD_DB_FIELDKEYS + elif get_metrics_cmd in query_sql: + return GOOD_DB_METRICS + return [] + + +class ReportTestCase(unittest.TestCase): + + @mock.patch.object(report.influx, 'query', new=my_query) + @mock.patch.object(configparser.ConfigParser, + 'read', side_effect=mock.mock_open(read_data=yardstick_config)) + def test_report_generate_nsb_simple(self, *args): + tmpfile = tempfile.NamedTemporaryFile(delete=True) + + args = core.Param({"task_id": [GOOD_TASK_ID], "yaml_name": [GOOD_YAML_NAME]}) + params = change_osloobj_to_paras(args) + + with mock.patch.object(report.consts, 'DEFAULT_HTML_FILE', tmpfile.name): + report.Report().generate_nsb(params) + + data_act = None + time_act = None + keys_act = None + tree_act = None + with open(tmpfile.name) as f: + for l in f.readlines(): + if "var report_data = {" in l: + data_act = ast.literal_eval(l.strip()[18:-1]) + elif "var report_time = [" in l: + time_act = ast.literal_eval(l.strip()[18:-1]) + elif "var report_keys = [" in l: + keys_act = ast.literal_eval(l.strip()[18:-1]) + elif "var report_tree = [" in l: + tree_act = ast.literal_eval(l.strip()[18:-1]) + + data_exp = { + 'metric1': [1, 1, 2, 3, 5, 8], + 'metric2': [0, 1, 2, 3, 4, 5], + 'metric3': [8, 5, 3, 2, 1, 1], + 'metric4': [5, 4, 3, 2, 1, 0], + } + time_exp = [ + '16:49:26.372662', '16:49:27.374208', '16:49:28.375742', + '16:49:29.377299', '16:49:30.378252', '16:49:30.379359', + ] + keys_exp = [ + 'metric1', 'metric2', 'metric3', 'metric4', + ] + tree_exp = [ + {'parent': '#', 'text': 'metric1', 'id': 'metric1'}, + {'parent': '#', 'text': 'metric2', 'id': 'metric2'}, + {'parent': '#', 'text': 'metric3', 'id': 'metric3'}, + {'parent': '#', 'text': 'metric4', 'id': 'metric4'}, + ] + + self.assertEqual(data_exp, data_act) + self.assertEqual(time_exp, time_act) + self.assertEqual(keys_exp, keys_act) + self.assertEqual(tree_exp, tree_act) diff --git a/yardstick/tests/unit/benchmark/core/test_report.py b/yardstick/tests/unit/benchmark/core/test_report.py index 11d017ff0..4683c26b0 100644 --- a/yardstick/tests/unit/benchmark/core/test_report.py +++ b/yardstick/tests/unit/benchmark/core/test_report.py @@ -9,6 +9,7 @@ ############################################################################## import mock +import six import unittest import uuid @@ -19,13 +20,82 @@ from yardstick.cmd.commands import change_osloobj_to_paras GOOD_YAML_NAME = 'fake_name' GOOD_TASK_ID = str(uuid.uuid4()) GOOD_DB_FIELDKEYS = [{'fieldKey': 'fake_key'}] -GOOD_DB_TASK = [{ +GOOD_DB_METRICS = [{ 'fake_key': 1.234, 'time': '0000-00-00T12:34:56.789012Z', }] GOOD_TIMESTAMP = ['12:34:56.789012'] BAD_YAML_NAME = 'F@KE_NAME' BAD_TASK_ID = 'aaaaaa-aaaaaaaa-aaaaaaaaaa-aaaaaa' +MORE_DB_FIELDKEYS = [ + {'fieldKey': 'fake_key'}, + {'fieldKey': 'str_str'}, + {'fieldKey': u'str_unicode'}, + {u'fieldKey': 'unicode_str'}, + {u'fieldKey': u'unicode_unicode'}, + ] +MORE_DB_METRICS = [{ + 'fake_key': None, + 'time': '0000-00-00T00:00:00.000000Z', + }, { + 'fake_key': 123, + 'time': '0000-00-00T00:00:01.000000Z', + }, { + 'fake_key': 4.56, + 'time': '0000-00-00T00:00:02.000000Z', + }, { + 'fake_key': 9876543210987654321, + 'time': '0000-00-00T00:00:03.000000Z', + }, { + 'fake_key': 'str_str value', + 'time': '0000-00-00T00:00:04.000000Z', + }, { + 'fake_key': u'str_unicode value', + 'time': '0000-00-00T00:00:05.000000Z', + }, { + u'fake_key': 'unicode_str value', + 'time': '0000-00-00T00:00:06.000000Z', + }, { + u'fake_key': u'unicode_unicode value', + 'time': '0000-00-00T00:00:07.000000Z', + }, { + 'fake_key': '7.89', + 'time': '0000-00-00T00:00:08.000000Z', + }, { + 'fake_key': '1011', + 'time': '0000-00-00T00:00:09.000000Z', + }, { + 'fake_key': '9876543210123456789', + 'time': '0000-00-00T00:00:10.000000Z', + }] +MORE_TIMESTAMP = ['00:00:%02d.000000' % n for n in range(len(MORE_DB_METRICS))] +MORE_EMPTY_DATA = [None] * len(MORE_DB_METRICS) +MORE_EXPECTED_TABLE_VALS = { + 'Timestamp': MORE_TIMESTAMP, + 'fake_key': [ + None, + 123, + 4.56, + 9876543210987654321 if six.PY3 else 9.876543210987655e+18, + 'str_str value', + 'str_unicode value', + 'unicode_str value', + 'unicode_unicode value', + 7.89, + 1011, + 9876543210123456789 if six.PY3 else 9.876543210123457e+18, + ], + 'str_str': MORE_EMPTY_DATA, + 'str_unicode': MORE_EMPTY_DATA, + 'unicode_str': MORE_EMPTY_DATA, + 'unicode_unicode': MORE_EMPTY_DATA, + } +MORE_EXPECTED_DATASETS = [{ + 'label': key, + 'data': MORE_EXPECTED_TABLE_VALS[key], + } + for key in map(str, [field['fieldKey'] for field in MORE_DB_FIELDKEYS]) + ] class JSTreeTestCase(unittest.TestCase): @@ -47,23 +117,15 @@ class JSTreeTestCase(unittest.TestCase): def test_format_for_jstree(self): data = [ - {'data': [0, ], 'label': 'tg__0.DropPackets'}, - {'data': [548, ], 'label': 'tg__0.LatencyAvg.5'}, - {'data': [1172, ], 'label': 'tg__0.LatencyAvg.6'}, - {'data': [1001, ], 'label': 'tg__0.LatencyMax.5'}, - {'data': [1468, ], 'label': 'tg__0.LatencyMax.6'}, - {'data': [18.11, ], 'label': 'tg__0.RxThroughput'}, - {'data': [18.11, ], 'label': 'tg__0.TxThroughput'}, - {'data': [0, ], 'label': 'tg__1.DropPackets'}, - {'data': [548, ], 'label': 'tg__1.LatencyAvg.5'}, - {'data': [1172, ], 'label': 'tg__1.LatencyAvg.6'}, - {'data': [1001, ], 'label': 'tg__1.LatencyMax.5'}, - {'data': [1468, ], 'label': 'tg__1.LatencyMax.6'}, - {'data': [18.1132084505, ], 'label': 'tg__1.RxThroughput'}, - {'data': [18.1157260383, ], 'label': 'tg__1.TxThroughput'}, - {'data': [9057888, ], 'label': 'vnf__0.curr_packets_in'}, - {'data': [0, ], 'label': 'vnf__0.packets_dropped'}, - {'data': [617825443, ], 'label': 'vnf__0.packets_fwd'}, + 'tg__0.DropPackets', + 'tg__0.LatencyAvg.5', 'tg__0.LatencyAvg.6', + 'tg__0.LatencyMax.5', 'tg__0.LatencyMax.6', + 'tg__0.RxThroughput', 'tg__0.TxThroughput', + 'tg__1.DropPackets', + 'tg__1.LatencyAvg.5', 'tg__1.LatencyAvg.6', + 'tg__1.LatencyMax.5', 'tg__1.LatencyMax.6', + 'tg__1.RxThroughput', 'tg__1.TxThroughput', + 'vnf__0.curr_packets_in', 'vnf__0.packets_dropped', 'vnf__0.packets_fwd', ] expected_output = [ @@ -117,11 +179,11 @@ class ReportTestCase(unittest.TestCase): self.assertEqual(GOOD_TASK_ID, str(self.rep.task_id)) def test__validate_invalid_yaml_name(self): - with self.assertRaisesRegexp(ValueError, "yaml*"): + with six.assertRaisesRegex(self, ValueError, "yaml*"): self.rep._validate(BAD_YAML_NAME, GOOD_TASK_ID) def test__validate_invalid_task_id(self): - with self.assertRaisesRegexp(ValueError, "task*"): + with six.assertRaisesRegex(self, ValueError, "task*"): self.rep._validate(GOOD_YAML_NAME, BAD_TASK_ID) @mock.patch.object(influx, 'query') @@ -141,42 +203,51 @@ class ReportTestCase(unittest.TestCase): mock_query.return_value = [] self.rep.yaml_name = GOOD_YAML_NAME self.rep.task_id = GOOD_TASK_ID - self.assertRaisesRegexp(KeyError, "Test case", self.rep._get_fieldkeys) + six.assertRaisesRegex(self, KeyError, "Test case", self.rep._get_fieldkeys) @mock.patch.object(influx, 'query') - def test__get_tasks(self, mock_query): - mock_query.return_value = GOOD_DB_TASK + def test__get_metrics(self, mock_query): + mock_query.return_value = GOOD_DB_METRICS self.rep.yaml_name = GOOD_YAML_NAME self.rep.task_id = GOOD_TASK_ID - self.assertEqual(GOOD_DB_TASK, self.rep._get_tasks()) + self.assertEqual(GOOD_DB_METRICS, self.rep._get_metrics()) @mock.patch.object(influx, 'query') - def test__get_tasks_task_not_found(self, mock_query): + def test__get_metrics_task_not_found(self, mock_query): mock_query.return_value = [] self.rep.yaml_name = GOOD_YAML_NAME self.rep.task_id = GOOD_TASK_ID - self.assertRaisesRegexp(KeyError, "Task ID", self.rep._get_tasks) + six.assertRaisesRegex(self, KeyError, "Task ID", self.rep._get_metrics) - @mock.patch.object(report.Report, '_get_tasks') + @mock.patch.object(report.Report, '_get_metrics') + @mock.patch.object(report.Report, '_get_fieldkeys') + def test__generate_common(self, mock_keys, mock_metrics): + mock_metrics.return_value = MORE_DB_METRICS + mock_keys.return_value = MORE_DB_FIELDKEYS + datasets, table_vals = self.rep._generate_common(self.param) + self.assertEqual(MORE_EXPECTED_DATASETS, datasets) + self.assertEqual(MORE_EXPECTED_TABLE_VALS, table_vals) + + @mock.patch.object(report.Report, '_get_metrics') @mock.patch.object(report.Report, '_get_fieldkeys') @mock.patch.object(report.Report, '_validate') - def test_generate(self, mock_valid, mock_keys, mock_tasks): - mock_tasks.return_value = GOOD_DB_TASK + def test_generate(self, mock_valid, mock_keys, mock_metrics): + mock_metrics.return_value = GOOD_DB_METRICS mock_keys.return_value = GOOD_DB_FIELDKEYS self.rep.generate(self.param) mock_valid.assert_called_once_with(GOOD_YAML_NAME, GOOD_TASK_ID) - mock_tasks.assert_called_once_with() + mock_metrics.assert_called_once_with() mock_keys.assert_called_once_with() self.assertEqual(GOOD_TIMESTAMP, self.rep.Timestamp) - @mock.patch.object(report.Report, '_get_tasks') + @mock.patch.object(report.Report, '_get_metrics') @mock.patch.object(report.Report, '_get_fieldkeys') @mock.patch.object(report.Report, '_validate') - def test_generate_nsb(self, mock_valid, mock_keys, mock_tasks): - mock_tasks.return_value = GOOD_DB_TASK + def test_generate_nsb(self, mock_valid, mock_keys, mock_metrics): + mock_metrics.return_value = GOOD_DB_METRICS mock_keys.return_value = GOOD_DB_FIELDKEYS self.rep.generate_nsb(self.param) mock_valid.assert_called_once_with(GOOD_YAML_NAME, GOOD_TASK_ID) - mock_tasks.assert_called_once_with() + mock_metrics.assert_called_once_with() mock_keys.assert_called_once_with() self.assertEqual(GOOD_TIMESTAMP, self.rep.Timestamp) diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py index e9c680257..dc3a4b99a 100644 --- a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py +++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py @@ -63,3 +63,20 @@ class MultiMonitorServiceTestCase(unittest.TestCase): ins.start_monitor() ins.wait_monitor() ins.verify_SLA() + + def test__monitor_multi_no_sla(self, mock_open, mock_ssh): + monitor_cfg = { + 'monitor_type': 'general-monitor', + 'monitor_number': 3, + 'key': 'service-status', + 'monitor_key': 'service-status', + 'host': 'node1', + 'monitor_time': 0.1, + 'parameter': {'serviceName': 'haproxy'} + } + ins = monitor_multi.MultiMonitor( + monitor_cfg, self.context, {"nova-api": 10}) + mock_ssh.SSH.from_node().execute.return_value = (0, "running", '') + ins.start_monitor() + ins.wait_monitor() + self.assertTrue(ins.verify_SLA()) diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py index a6d2ca398..8c73bf221 100644 --- a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py +++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py @@ -55,3 +55,19 @@ class MonitorProcessTestCase(unittest.TestCase): ins.monitor_func() ins._result = {"outage_time": 10} ins.verify_SLA() + + def test__monitor_process_no_sla(self, mock_ssh): + + monitor_cfg = { + 'monitor_type': 'process', + 'process_name': 'nova-api', + 'host': "node1", + 'monitor_time': 1, + } + ins = monitor_process.MonitorProcess(monitor_cfg, self.context, {"nova-api": 10}) + + mock_ssh.SSH.from_node().execute.return_value = (0, "0", '') + ins.setup() + ins.monitor_func() + ins._result = {"outage_time": 10} + self.assertTrue(ins.verify_SLA()) |