aboutsummaryrefslogtreecommitdiffstats
path: root/yardstick/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'yardstick/tests/unit')
-rw-r--r--yardstick/tests/unit/__init__.py23
-rw-r--r--yardstick/tests/unit/apiserver/__init__.py58
-rw-r--r--yardstick/tests/unit/apiserver/resources/__init__.py0
-rw-r--r--yardstick/tests/unit/apiserver/resources/test_env_action.py35
-rw-r--r--yardstick/tests/unit/apiserver/resources/v1/__init__.py0
-rw-r--r--yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py35
-rw-r--r--yardstick/tests/unit/apiserver/resources/v2/__init__.py0
-rw-r--r--yardstick/tests/unit/apiserver/resources/v2/test_images.py46
-rw-r--r--yardstick/tests/unit/apiserver/utils/__init__.py0
-rw-r--r--yardstick/tests/unit/apiserver/utils/test_influx.py91
-rw-r--r--yardstick/tests/unit/base.py23
-rw-r--r--yardstick/tests/unit/benchmark/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/contexts/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample.yaml21
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml32
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_ovs.yaml63
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_sample.yaml33
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_sample_new.yaml96
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_sample_new_sriov.yaml82
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_sample_ovs.yaml104
-rw-r--r--yardstick/tests/unit/benchmark/contexts/nodes_sample_ovsdpdk.yaml104
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml37
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml40
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml33
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml40
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_model.py640
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py500
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py362
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml135
-rw-r--r--yardstick/tests/unit/benchmark/contexts/standalone_sample.yaml112
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_base.py174
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_dummy.py86
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_heat.py893
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_kubernetes.py273
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_model.py586
-rw-r--r--yardstick/tests/unit/benchmark/contexts/test_node.py392
-rw-r--r--yardstick/tests/unit/benchmark/core/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/core/no_constraint_no_args_scenario_sample.yaml21
-rw-r--r--yardstick/tests/unit/benchmark/core/no_constraint_with_args_scenario_sample.yaml23
-rw-r--r--yardstick/tests/unit/benchmark/core/test_plugin.py148
-rw-r--r--yardstick/tests/unit/benchmark/core/test_report.py584
-rw-r--r--yardstick/tests/unit/benchmark/core/test_task.py644
-rw-r--r--yardstick/tests/unit/benchmark/core/test_testcase.py35
-rw-r--r--yardstick/tests/unit/benchmark/core/with_constraint_no_args_scenario_sample.yaml24
-rw-r--r--yardstick/tests/unit/benchmark/core/with_constraint_with_args_scenario_sample.yaml26
-rw-r--r--yardstick/tests/unit/benchmark/runner/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_arithmetic.py446
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_base.py119
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_duration.py315
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_iteration.py45
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_proxduration.py286
-rw-r--r--yardstick/tests/unit/benchmark/runner/test_search.py192
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py93
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py56
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py53
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_baseattacker.py36
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py119
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_baseoperation.py79
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py89
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_director.py106
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_command.py95
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py82
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py82
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py73
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py74
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py118
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_scenario_general.py76
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_serviceha.py131
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/availability/test_util.py56
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt5
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output1.txt9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output2.txt2
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt3
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py95
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py64
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py262
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py167
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py192
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py109
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py60
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py158
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py236
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py75
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py76
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py163
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/dummy/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py32
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/energy/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_chassis_output.txt14
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_power_metrics.txt300
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/energy/test_energy.py182
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py56
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py78
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py76
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py63
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py29
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_floating_ip.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py55
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py27
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py59
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py59
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py58
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py58
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py27
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py55
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py52
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py51
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py54
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py25
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py54
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py27
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py56
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py54
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py52
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py43
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py103
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py57
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py33
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/imix_voice.yaml41
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output_udp.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/ipv4_1flow_Packets_vpe.yaml18
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/ipv4_throughput_vpe.yaml101
-rwxr-xr-xyardstick/tests/unit/benchmark/scenarios/networking/netperf_sample_output.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output1.txt9
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output2.txt13
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py190
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py353
-rwxr-xr-xyardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py122
-rwxr-xr-xyardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py122
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py225
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py59
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py105
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py107
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py117
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py453
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py136
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py194
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py68
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py873
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py196
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py181
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/tg_trex_tpl.yaml75
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/networking/vpe_vnf_topology.yaml50
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/parser/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py70
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/__init__.py0
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/fio_read_sample_output.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/fio_rw_sample_output.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/fio_write_sample_output.json1
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py63
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py280
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py99
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py513
-rw-r--r--yardstick/tests/unit/benchmark/scenarios/test_base.py135
-rw-r--r--yardstick/tests/unit/common/__init__.py0
-rw-r--r--yardstick/tests/unit/common/banned_modules/__init__.py0
-rw-r--r--yardstick/tests/unit/common/banned_modules/banned_module.py17
-rw-r--r--yardstick/tests/unit/common/banned_modules/importing_module.py21
-rw-r--r--yardstick/tests/unit/common/config_sample.yaml10
-rw-r--r--yardstick/tests/unit/common/messaging/__init__.py0
-rw-r--r--yardstick/tests/unit/common/messaging/test_consumer.py54
-rw-r--r--yardstick/tests/unit/common/messaging/test_payloads.py82
-rw-r--r--yardstick/tests/unit/common/messaging/test_producer.py53
-rw-r--r--yardstick/tests/unit/common/test_ansible_common.py241
-rw-r--r--yardstick/tests/unit/common/test_exceptions.py28
-rw-r--r--yardstick/tests/unit/common/test_httpClient.py35
-rw-r--r--yardstick/tests/unit/common/test_import_tools.py46
-rw-r--r--yardstick/tests/unit/common/test_kubernetes_utils.py447
-rw-r--r--yardstick/tests/unit/common/test_openstack_utils.py730
-rw-r--r--yardstick/tests/unit/common/test_packages.py88
-rw-r--r--yardstick/tests/unit/common/test_process.py152
-rw-r--r--yardstick/tests/unit/common/test_template_format.py52
-rw-r--r--yardstick/tests/unit/common/test_utils.py1463
-rw-r--r--yardstick/tests/unit/common/test_yaml_loader.py24
-rw-r--r--yardstick/tests/unit/dispatcher/__init__.py0
-rw-r--r--yardstick/tests/unit/dispatcher/test_influxdb.py104
-rw-r--r--yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py63
-rw-r--r--yardstick/tests/unit/network_services/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/collector/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/collector/test_publisher.py36
-rw-r--r--yardstick/tests/unit/network_services/collector/test_subscriber.py120
-rw-r--r--yardstick/tests/unit/network_services/helpers/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/helpers/acl_vnf_topology_ixia.yaml50
-rw-r--r--yardstick/tests/unit/network_services/helpers/test_cpu.py215
-rw-r--r--yardstick/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py632
-rw-r--r--yardstick/tests/unit/network_services/helpers/test_iniparser.py223
-rw-r--r--yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py1044
-rw-r--r--yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py2164
-rw-r--r--yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py91
-rw-r--r--yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py100
-rw-r--r--yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py44
-rw-r--r--yardstick/tests/unit/network_services/libs/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/libs/ixia_libs/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py1057
-rw-r--r--yardstick/tests/unit/network_services/nfvi/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/nfvi/test_collectd.py150
-rw-r--r--yardstick/tests/unit/network_services/nfvi/test_resource.py319
-rw-r--r--yardstick/tests/unit/network_services/test_utils.py141
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_base.py112
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_fixed.py117
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_http.py47
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_http_ixload.py452
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py1024
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py136
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_pktgen.py63
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_acl.py74
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py302
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_irq.py57
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py130
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_prox_ramp.py95
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py341
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_sip.py51
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py277
-rw-r--r--yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py890
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/test_vnfdgen.py277
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/__init__.py0
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/tc_baremetal_rfc2544_ipv4_1flow_64B.yaml41
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py518
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py68
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_base.py236
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py412
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py92
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py2151
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py2825
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py828
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py513
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_router_vnf.py262
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py1532
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_imsbench_sipp.py481
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py287
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py1951
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py298
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_pktgen.py66
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py441
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py1265
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py312
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py516
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex_vpp.py1130
-rwxr-xr-xyardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py652
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py470
-rwxr-xr-xyardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py651
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py371
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py713
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py744
-rw-r--r--yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py1723
-rw-r--r--yardstick/tests/unit/orchestrator/__init__.py0
-rw-r--r--yardstick/tests/unit/orchestrator/test_heat.py417
-rw-r--r--yardstick/tests/unit/orchestrator/test_kubernetes.py643
-rw-r--r--yardstick/tests/unit/service/__init__.py0
-rw-r--r--yardstick/tests/unit/service/test_environment.py46
-rw-r--r--yardstick/tests/unit/test_cmd/__init__.py0
-rw-r--r--yardstick/tests/unit/test_cmd/commands/__init__.py0
-rw-r--r--yardstick/tests/unit/test_cmd/commands/test_env.py69
-rw-r--r--yardstick/tests/unit/test_cmd/commands/test_testcase.py21
-rw-r--r--yardstick/tests/unit/test_cmd/test_NSBperf.py132
-rw-r--r--yardstick/tests/unit/test_ssh.py684
272 files changed, 56515 insertions, 0 deletions
diff --git a/yardstick/tests/unit/__init__.py b/yardstick/tests/unit/__init__.py
new file mode 100644
index 000000000..c05f91c81
--- /dev/null
+++ b/yardstick/tests/unit/__init__.py
@@ -0,0 +1,23 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+
+import mock
+
+from yardstick import tests
+
+
+mock_stl = mock.patch.dict(sys.modules, tests.STL_MOCKS)
+mock_stl.start()
diff --git a/yardstick/tests/unit/apiserver/__init__.py b/yardstick/tests/unit/apiserver/__init__.py
new file mode 100644
index 000000000..44d163429
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/__init__.py
@@ -0,0 +1,58 @@
+##############################################################################
+# Copyright (c) 2017
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+"""Tests for yardstick/api/server.py"""
+from __future__ import absolute_import
+
+import mock
+import os
+import socket
+import unittest
+import tempfile
+
+from oslo_serialization import jsonutils
+
+from yardstick.common import constants as consts
+
+
+class APITestCase(unittest.TestCase):
+ """Tests for the YardStick API server"""
+ def setUp(self):
+ self.db_fd, self.db_path = tempfile.mkstemp()
+ consts.SQLITE = 'sqlite:///{}'.format(self.db_path)
+
+ # server calls gethostbyname which takes 4 seconds, and we should mock
+ # it anyway
+ self.socket_mock = mock.patch.dict("sys.modules", {"socket": mock.MagicMock(
+ **{"gethostbyname.return_value": "127.0.0.1",
+ "gethostname.return_value": "localhost"})})
+ self.socket_mock.start()
+ try:
+ from api import server
+ except socket.gaierror:
+ self.app = None
+ return
+
+ server.app.config['TESTING'] = True
+ self.app = server.app.test_client()
+
+ server.init_db()
+
+ def tearDown(self):
+ os.close(self.db_fd)
+ os.unlink(self.db_path)
+ self.socket_mock.stop()
+
+ def _post(self, url, data):
+ headers = {'Content-Type': 'application/json'}
+ resp = self.app.post(url, data=jsonutils.dumps(data), headers=headers)
+ return jsonutils.loads(resp.data)
+
+ def _get(self, url):
+ resp = self.app.get(url)
+ return jsonutils.loads(resp.data)
diff --git a/yardstick/tests/unit/apiserver/resources/__init__.py b/yardstick/tests/unit/apiserver/resources/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/__init__.py
diff --git a/yardstick/tests/unit/apiserver/resources/test_env_action.py b/yardstick/tests/unit/apiserver/resources/test_env_action.py
new file mode 100644
index 000000000..657841669
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/test_env_action.py
@@ -0,0 +1,35 @@
+##############################################################################
+# Copyright (c) 2017 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 time
+import unittest
+
+from yardstick.tests.unit.apiserver import APITestCase
+
+
+class EnvTestCase(APITestCase):
+
+ def test_create_grafana(self):
+ if self.app is None:
+ unittest.skip('host config error')
+ return
+
+ url = 'yardstick/env/action'
+ data = {'action': 'create_grafana'}
+ resp = self._post(url, data)
+
+ time.sleep(0)
+
+ task_id = resp['result']['task_id']
+ url = '/yardstick/asynctask?task_id={}'.format(task_id)
+ resp = self._get(url)
+
+ time.sleep(0)
+
+ self.assertIn(u'status', resp)
diff --git a/yardstick/tests/unit/apiserver/resources/v1/__init__.py b/yardstick/tests/unit/apiserver/resources/v1/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v1/__init__.py
diff --git a/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py b/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py
new file mode 100644
index 000000000..85c045f44
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v1/test_testsuites.py
@@ -0,0 +1,35 @@
+##############################################################################
+# 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
+##############################################################################
+import mock
+
+import unittest
+
+from yardstick.tests.unit.apiserver import APITestCase
+from api.utils.thread import TaskThread
+
+
+class TestsuiteTestCase(APITestCase):
+
+ def test_run_test_suite(self):
+ if self.app is None:
+ unittest.skip('host config error')
+ return
+
+ TaskThread.start = mock.MagicMock()
+
+ url = 'yardstick/testsuites/action'
+ data = {
+ 'action': 'run_test_suite',
+ 'args': {
+ 'opts': {},
+ 'testsuite': 'opnfv_smoke'
+ }
+ }
+ resp = self._post(url, data)
+ self.assertEqual(resp.get('status'), 1)
diff --git a/yardstick/tests/unit/apiserver/resources/v2/__init__.py b/yardstick/tests/unit/apiserver/resources/v2/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v2/__init__.py
diff --git a/yardstick/tests/unit/apiserver/resources/v2/test_images.py b/yardstick/tests/unit/apiserver/resources/v2/test_images.py
new file mode 100644
index 000000000..ab131eec5
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/resources/v2/test_images.py
@@ -0,0 +1,46 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd.
+#
+# 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 mock
+
+import unittest
+
+from yardstick.tests.unit.apiserver import APITestCase
+from api.resources.v2.images import format_image_info
+
+
+class V2ImagesTestCase(APITestCase):
+ @mock.patch('yardstick.common.openstack_utils.list_images')
+ @mock.patch('yardstick.common.utils.source_env')
+ def test_get(self, _, mock_list_images):
+ if self.app is None:
+ unittest.skip('host config error')
+ return
+
+ single_image = mock.MagicMock()
+ single_image.name = 'yardstick-image'
+ single_image.size = 16384
+ single_image.status = 'active'
+ single_image.updated_at = '2018-04-08'
+
+ mock_list_images.return_value = [single_image]
+ url = 'api/v2/yardstick/images'
+ resp = self._get(url)
+ self.assertEqual(resp.get('status'), 1)
+
+
+class FormatImageInfoTestCase(unittest.TestCase):
+ def test_format_image_info(self):
+ image = mock.MagicMock()
+ image.name = 'yardstick-image'
+ image.size = 1048576
+ image.status = 'active'
+ image.updated_at = '2018-04-08'
+
+ image_dict = format_image_info(image)
+ self.assertEqual(image_dict.get('size'), 1)
diff --git a/yardstick/tests/unit/apiserver/utils/__init__.py b/yardstick/tests/unit/apiserver/utils/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/utils/__init__.py
diff --git a/yardstick/tests/unit/apiserver/utils/test_influx.py b/yardstick/tests/unit/apiserver/utils/test_influx.py
new file mode 100644
index 000000000..3a97ff292
--- /dev/null
+++ b/yardstick/tests/unit/apiserver/utils/test_influx.py
@@ -0,0 +1,91 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+# Copyright (c) 2019 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
+##############################################################################
+
+from influxdb import client as influxdb_client
+import mock
+from six.moves import configparser
+
+from api.utils import influx
+from yardstick.common import constants
+from yardstick.common import exceptions
+from yardstick import dispatcher
+from yardstick.tests.unit import base
+
+
+class GetDataDbClientTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(influx, '_get_influxdb_client',
+ return_value='fake_client')
+ @mock.patch.object(influx.ConfigParser, 'ConfigParser')
+ def test_get_data_db_client(self, mock_parser, mock_get_client):
+ _mock_parser = mock.Mock()
+ mock_parser.return_value = _mock_parser
+
+ self.assertEqual('fake_client', influx.get_data_db_client())
+ _mock_parser.read.assert_called_once_with(constants.CONF_FILE)
+ mock_get_client.assert_called_once_with(_mock_parser, None)
+
+ @mock.patch.object(influx.logger, 'error')
+ @mock.patch.object(influx, '_get_influxdb_client',
+ return_value='fake_client')
+ @mock.patch.object(influx.ConfigParser, 'ConfigParser')
+ def test_get_data_db_client_parsing_error(
+ self, mock_parser, mock_get_client, *args):
+ _mock_parser = mock.Mock()
+ mock_parser.return_value = _mock_parser
+ mock_parser.NoOptionError = configparser.NoOptionError
+ mock_get_client.side_effect = configparser.NoOptionError('option',
+ 'section')
+ with self.assertRaises(configparser.NoOptionError):
+ influx.get_data_db_client()
+
+ _mock_parser.read.assert_called_once_with(constants.CONF_FILE)
+ mock_get_client.assert_called_once_with(_mock_parser, None)
+
+
+class GetIpTestCase(base.BaseUnitTestCase):
+
+ def test_get_url(self):
+ url = 'http://localhost:8086/hello'
+ output = influx._get_ip(url)
+
+ result = 'localhost'
+ self.assertEqual(result, output)
+
+
+class GetInfluxdbTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(influxdb_client, 'InfluxDBClient',
+ return_value='idb_client')
+ @mock.patch.object(influx, '_get_ip', return_value='fake_ip')
+ def test_get_influxdb_client(self, mock_get_ip, mock_client):
+ mock_parser = mock.Mock()
+ mock_parser.get.side_effect = [dispatcher.INFLUXDB, 'target', 'user',
+ 'pass', 'db_name']
+
+ self.assertEqual('idb_client',
+ influx._get_influxdb_client(mock_parser))
+ mock_client.assert_called_once_with('fake_ip', constants.INFLUXDB_PORT,
+ 'user', 'pass', 'db_name')
+ mock_get_ip.assert_called_once_with('target')
+ mock_parser.get.assert_has_calls([
+ mock.call('DEFAULT', 'dispatcher'),
+ mock.call('dispatcher_influxdb', 'target'),
+ mock.call('dispatcher_influxdb', 'username'),
+ mock.call('dispatcher_influxdb', 'password'),
+ mock.call('dispatcher_influxdb', 'db_name')])
+
+ def test_get_influxdb_client_no_influxdb_client(self):
+ mock_parser = mock.Mock()
+ mock_parser.get.return_value = dispatcher.FILE
+
+ with self.assertRaises(exceptions.InfluxDBConfigurationMissing):
+ influx._get_influxdb_client(mock_parser)
+ mock_parser.get.assert_called_once_with('DEFAULT', 'dispatcher')
diff --git a/yardstick/tests/unit/base.py b/yardstick/tests/unit/base.py
new file mode 100644
index 000000000..b943efc2b
--- /dev/null
+++ b/yardstick/tests/unit/base.py
@@ -0,0 +1,23 @@
+# Copyright 2018 Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import abc
+
+import six
+import unittest
+
+
+@six.add_metaclass(abc.ABCMeta)
+class BaseUnitTestCase(unittest.TestCase):
+ """Base class for unit tests"""
diff --git a/yardstick/tests/unit/benchmark/__init__.py b/yardstick/tests/unit/benchmark/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/__init__.py
diff --git a/yardstick/tests/unit/benchmark/contexts/__init__.py b/yardstick/tests/unit/benchmark/contexts/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/__init__.py
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample.yaml
new file mode 100644
index 000000000..dbdd3700d
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample.yaml
@@ -0,0 +1,21 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml
new file mode 100644
index 000000000..306915ca1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_new.yaml
@@ -0,0 +1,32 @@
+nodes:
+-
+ name: sriov
+ role: Sriov1
+ ip: 10.123.123.122
+ user: root
+ auth_type: password
+ password: password
+ vf_macs:
+ - "00:00:00:00:00:00"
+ - "00:00:00:00:00:00"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+-
+ name: sriov
+ role: Sriov1
+ ip: 10.123.123.111
+ user: root
+ auth_type: password
+ password: password
+ vf_macs:
+ - "00:00:00:00:00:00"
+ - "00:00:00:00:00:00"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_ovs.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_ovs.yaml
new file mode 100644
index 000000000..65449c91c
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_duplicate_sample_ovs.yaml
@@ -0,0 +1,63 @@
+# Copyright (c) 2016 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+nodes:
+-
+ name: ovs
+ role: test
+ ip: 10.223.197.222
+ user: root
+ auth_type: password
+ password: intel123
+ vpath: "/usr/local/"
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure ovs
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+-
+ name: ovs
+ role: test
+ ip: 10.223.197.112
+ user: root
+ auth_type: password
+ password: intel123
+ vpath: "/usr/local/"
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure ovs
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_sample.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_sample.yaml
new file mode 100644
index 000000000..8d50c3aea
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_sample.yaml
@@ -0,0 +1,33 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node2
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node3
+ role: Compute
+ ip: 10.229.47.139
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node4
+ role: Baremetal
+ ip: 10.229.47.140
+ user: root
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_sample_new.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_sample_new.yaml
new file mode 100644
index 000000000..a400bec03
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_sample_new.yaml
@@ -0,0 +1,96 @@
+# 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.
+
+nodes:
+-
+ name: trafficgen_1
+ role: TrafficGen
+ ip: 10.123.123.123
+ user: root
+ auth_type: password
+ password: password
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.0"
+ driver: ixgbe
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.1"
+ driver: ixgbe
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+-
+ name: sriov
+ role: Sriov
+ ip: 10.123.123.122
+ user: root
+ auth_type: password
+ password: password
+ vf_macs:
+ - "00:00:00:00:00:00"
+ - "00:00:00:00:00:00"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+ name: vnf
+ role: vnf
+ ip: 10.123.123.121
+ user: root
+ auth_type: password
+ password: password
+ host: 10.123.123.121 #BM host == ip, SRIOV & ovs-dpdk host == compute node.
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:06:00.0"
+ driver: i40e
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:06:00.1"
+ driver: i40e
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
+
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_sample_new_sriov.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_sample_new_sriov.yaml
new file mode 100644
index 000000000..55ff2e778
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_sample_new_sriov.yaml
@@ -0,0 +1,82 @@
+nodes:
+-
+ name: trafficgen_1
+ role: TrafficGen
+ ip: 10.123.123.123
+ user: root
+ auth_type: password
+ password: password
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.0"
+ driver: ixgbe
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.1"
+ driver: ixgbe
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+-
+ name: sriov
+ role: Sriov1
+ ip: 10.123.123.122
+ user: root
+ auth_type: password
+ password: password
+ vf_macs:
+ - "00:00:00:00:00:00"
+ - "00:00:00:00:00:00"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+ name: vnf
+ role: vnf
+ ip: 10.123.123.121
+ user: root
+ auth_type: password
+ password: password
+ host: 10.123.123.121 #BM host == ip, SRIOV & ovs-dpdk host == compute node.
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:06:00.0"
+ driver: i40e
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:06:00.1"
+ driver: i40e
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:00"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
+
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovs.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovs.yaml
new file mode 100644
index 000000000..b1da1ea9f
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovs.yaml
@@ -0,0 +1,104 @@
+# Copyright (c) 2016 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nodes:
+-
+ name: trafficgen_1
+ role: TrafficGen
+ ip: 10.223.197.182
+ user: root
+ auth_type: password
+ password: intel123
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.0"
+ driver: ixgbe
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "90:e2:ba:77:ce:68"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.1"
+ driver: ixgbe
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "90:e2:ba:77:ce:69"
+-
+ name: ovs
+ role: Ovsdpdk
+ ip: 10.223.197.222
+ user: root
+ auth_type: password
+ password: intel123
+ vpath: "/usr/local/"
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure ovs
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+ name: vnf
+ role: vnf
+ ip: 10.223.197.155
+ user: root
+ auth_type: password
+ password: intel123
+ host: 10.223.197.140
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:04.0"
+ driver: virtio-pci
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:03"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:05.0"
+ driver: virtio-pci
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:04"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
diff --git a/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovsdpdk.yaml b/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovsdpdk.yaml
new file mode 100644
index 000000000..c02849a05
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/nodes_sample_ovsdpdk.yaml
@@ -0,0 +1,104 @@
+# Copyright (c) 2016 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+nodes:
+-
+ name: trafficgen_1
+ role: TrafficGen
+ ip: 10.223.197.182
+ user: root
+ auth_type: password
+ password: intel123
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.0"
+ driver: ixgbe
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "90:e2:ba:77:ce:68"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:03:00.1"
+ driver: ixgbe
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "90:e2:ba:77:ce:69"
+-
+ name: ovs
+ role: Ovsdpdk1
+ ip: 10.223.197.222
+ user: root
+ auth_type: password
+ password: intel123
+ vpath: "/usr/local/"
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure ovs
+ - "0000:06:00.0"
+ - "0000:06:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu1.img"
+
+-
+ name: vnf
+ role: vnf
+ ip: 10.223.197.155
+ user: root
+ auth_type: password
+ password: intel123
+ host: 10.223.197.140
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:04.0"
+ driver: virtio-pci
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:03"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:05.0"
+ driver: virtio-pci
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:04"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/__init__.py b/yardstick/tests/unit/benchmark/contexts/standalone/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/__init__.py
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml
new file mode 100644
index 000000000..2e501a6af
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_duplicate_sample.yaml
@@ -0,0 +1,37 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
+
+-
+ name: node5
+ role: Sriov
+ ip: 10.229.47.140
+ user: root
+ password: password
+ key_filename: /root/.yardstick_key
+
+-
+ name: node5
+ role: OvsDpdk
+ ip: 10.229.47.140
+ user: root
+ password: password
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml
new file mode 100644
index 000000000..0f51dbe63
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_ovs_dpdk_sample.yaml
@@ -0,0 +1,40 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node2
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node3
+ role: Compute
+ ip: 10.229.47.139
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node4
+ role: Baremetal
+ ip: 10.229.47.140
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node5
+ role: OvsDpdk
+ ip: 10.229.47.140
+ user: root
+ password: password
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml
new file mode 100644
index 000000000..8d50c3aea
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sample.yaml
@@ -0,0 +1,33 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node2
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node3
+ role: Compute
+ ip: 10.229.47.139
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node4
+ role: Baremetal
+ ip: 10.229.47.140
+ user: root
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml
new file mode 100644
index 000000000..1c43b8725
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/nodes_sriov_sample.yaml
@@ -0,0 +1,40 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+nodes:
+-
+ name: node1
+ role: Controller
+ ip: 10.229.47.137
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node2
+ role: Controller
+ ip: 10.229.47.138
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node3
+ role: Compute
+ ip: 10.229.47.139
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node4
+ role: Baremetal
+ ip: 10.229.47.140
+ user: root
+ key_filename: /root/.yardstick_key
+-
+ name: node5
+ role: Sriov
+ ip: 10.229.47.140
+ user: root
+ password: password
+ key_filename: /root/.yardstick_key
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
new file mode 100644
index 000000000..e76a3ca27
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_model.py
@@ -0,0 +1,640 @@
+# 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.
+
+import copy
+import os
+import uuid
+
+import mock
+import netaddr
+import unittest
+from xml.etree import ElementTree
+
+from yardstick import ssh
+from yardstick.benchmark.contexts.standalone import model
+from yardstick.common import exceptions
+from yardstick import constants
+from yardstick.network_services import utils
+
+
+XML_SAMPLE = """<?xml version="1.0"?>
+<domain type="kvm">
+ <devices>
+ </devices>
+</domain>
+"""
+
+XML_SAMPLE_INTERFACE = """<?xml version="1.0"?>
+<domain type="kvm">
+ <devices>
+ <interface>
+ </interface>
+ </devices>
+</domain>
+"""
+
+
+class ModelLibvirtTestCase(unittest.TestCase):
+
+ XML_STR = model.VM_TEMPLATE.format(
+ vm_name="vm_name",
+ random_uuid=uuid.uuid4(),
+ mac_addr="00:01:02:03:04:05",
+ memory=2048, vcpu=2, cpu=2,
+ numa_cpus=0 - 10,
+ socket=1, threads=1,
+ vm_image="/var/lib/libvirt/images/yardstick-nsb-image.img",
+ cpuset=2 - 10, cputune='', machine='pc')
+
+ def setUp(self):
+ self.pci_address_str = '0001:04:03.2'
+ self.pci_address = utils.PciAddress(self.pci_address_str)
+ self.mac = '00:00:00:00:00:01'
+ self._mock_ssh = mock.Mock()
+ self.mock_ssh = self._mock_ssh.start()
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_ssh.stop()
+
+ # TODO: Remove mocking of yardstick.ssh.SSH (here and elsewhere)
+ # In this case, we are mocking a param to be passed into other methods
+ # It can be a generic Mock() with return values set for the right methods
+ def test_check_if_vm_exists_and_delete(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution.
+ model.Libvirt.check_if_vm_exists_and_delete('vm-0', ssh_mock)
+
+ def test_virsh_create_vm(self):
+ self.mock_ssh.execute = mock.Mock(return_value=(0, 0, 0))
+ model.Libvirt.virsh_create_vm(self.mock_ssh, 'vm-0')
+ self.mock_ssh.execute.assert_called_once_with('virsh create vm-0')
+
+ def test_virsh_create_vm_error(self):
+ self.mock_ssh.execute = mock.Mock(return_value=(1, 0, 'error_create'))
+ with self.assertRaises(exceptions.LibvirtCreateError) as exc:
+ model.Libvirt.virsh_create_vm(self.mock_ssh, 'vm-0')
+ self.assertEqual('Error creating the virtual machine. Error: '
+ 'error_create.', str(exc.exception))
+ self.mock_ssh.execute.assert_called_once_with('virsh create vm-0')
+
+ def test_virsh_destroy_vm(self):
+ self.mock_ssh.execute = mock.Mock(return_value=(0, 0, 0))
+ model.Libvirt.virsh_destroy_vm('vm-0', self.mock_ssh)
+ self.mock_ssh.execute.assert_called_once_with('virsh destroy vm-0')
+
+ @mock.patch.object(model, 'LOG')
+ def test_virsh_destroy_vm_error(self, mock_logger):
+ self.mock_ssh.execute = mock.Mock(return_value=(1, 0, 'error_destroy'))
+ mock_logger.warning = mock.Mock()
+ model.Libvirt.virsh_destroy_vm('vm-0', self.mock_ssh)
+ mock_logger.warning.assert_called_once_with(
+ 'Error destroying VM %s. Error: %s', 'vm-0', 'error_destroy')
+ self.mock_ssh.execute.assert_called_once_with('virsh destroy vm-0')
+
+ def test_add_interface_address(self):
+ xml = ElementTree.ElementTree(
+ element=ElementTree.fromstring(XML_SAMPLE_INTERFACE))
+ interface = xml.find('devices').find('interface')
+ result = model.Libvirt._add_interface_address(interface, self.pci_address)
+ self.assertEqual('pci', result.get('type'))
+ self.assertEqual('0x{}'.format(self.pci_address.domain),
+ result.get('domain'))
+ self.assertEqual('0x{}'.format(self.pci_address.bus),
+ result.get('bus'))
+ self.assertEqual('0x{}'.format(self.pci_address.slot),
+ result.get('slot'))
+ self.assertEqual('0x{}'.format(self.pci_address.function),
+ result.get('function'))
+
+ def test_add_ovs_interfaces(self):
+ xml_input = copy.deepcopy(XML_SAMPLE)
+ xml_output = model.Libvirt.add_ovs_interface(
+ '/usr/local', 0, self.pci_address_str, self.mac, xml_input, 4)
+
+ root = ElementTree.fromstring(xml_output)
+ et_out = ElementTree.ElementTree(element=root)
+ interface = et_out.find('devices').find('interface')
+ self.assertEqual('vhostuser', interface.get('type'))
+ mac = interface.find('mac')
+ self.assertEqual(self.mac, mac.get('address'))
+ source = interface.find('source')
+ self.assertEqual('unix', source.get('type'))
+ self.assertEqual('/usr/local/var/run/openvswitch/dpdkvhostuser0',
+ source.get('path'))
+ self.assertEqual('client', source.get('mode'))
+ _model = interface.find('model')
+ self.assertEqual('virtio', _model.get('type'))
+ driver = interface.find('driver')
+ self.assertEqual('4', driver.get('queues'))
+ host = driver.find('host')
+ self.assertEqual('off', host.get('mrg_rxbuf'))
+ self.assertIsNotNone(interface.find('address'))
+
+ def test_add_sriov_interfaces(self):
+ xml_input = copy.deepcopy(XML_SAMPLE)
+ vm_pci = '0001:05:04.2'
+ xml_output = model.Libvirt.add_sriov_interfaces(
+ vm_pci, self.pci_address_str, self.mac, xml_input)
+ root = ElementTree.fromstring(xml_output)
+ et_out = ElementTree.ElementTree(element=root)
+ interface = et_out.find('devices').find('interface')
+ self.assertEqual('yes', interface.get('managed'))
+ self.assertEqual('hostdev', interface.get('type'))
+ mac = interface.find('mac')
+ self.assertEqual(self.mac, mac.get('address'))
+ source = interface.find('source')
+ source_address = source.find('address')
+ self.assertIsNotNone(source.find('address'))
+
+ self.assertEqual('pci', source_address.get('type'))
+ self.assertEqual('0x' + self.pci_address_str.split(':')[0],
+ source_address.get('domain'))
+ self.assertEqual('0x' + self.pci_address_str.split(':')[1],
+ source_address.get('bus'))
+ self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[0],
+ source_address.get('slot'))
+ self.assertEqual('0x' + self.pci_address_str.split(':')[2].split('.')[1],
+ source_address.get('function'))
+
+ interface_address = interface.find('address')
+ self.assertEqual('pci', interface_address.get('type'))
+ self.assertEqual('0x' + vm_pci.split(':')[0],
+ interface_address.get('domain'))
+ self.assertEqual('0x' + vm_pci.split(':')[1],
+ interface_address.get('bus'))
+ self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[0],
+ interface_address.get('slot'))
+ self.assertEqual('0x' + vm_pci.split(':')[2].split('.')[1],
+ interface_address.get('function'))
+
+ def test_add_cdrom(self):
+ xml_input = copy.deepcopy(XML_SAMPLE)
+ xml_output = model.Libvirt.add_cdrom('/var/lib/libvirt/images/data.img', xml_input)
+
+ root = ElementTree.fromstring(xml_output)
+ et_out = ElementTree.ElementTree(element=root)
+ disk = et_out.find('devices').find('disk')
+ self.assertEqual('file', disk.get('type'))
+ self.assertEqual('cdrom', disk.get('device'))
+ driver = disk.find('driver')
+ self.assertEqual('qemu', driver.get('name'))
+ self.assertEqual('raw', driver.get('type'))
+ source = disk.find('source')
+ self.assertEqual('/var/lib/libvirt/images/data.img', source.get('file'))
+ target = disk.find('target')
+ self.assertEqual('hdb', target.get('dev'))
+ self.assertIsNotNone(disk.find('readonly'))
+
+ def test_gen_cdrom_image(self):
+ self.mock_ssh.execute = mock.Mock(return_value=(0, 0, 0))
+ root = ElementTree.fromstring(self.XML_STR)
+ hostname = root.find('name').text
+ meta_data = "/tmp/meta-data"
+ user_data = "/tmp/user-data"
+ network_data = "/tmp/network-config"
+ file_path = "/tmp/cdrom-0.img"
+ key_filename = "id_rsa"
+ pub_key_str = "KEY"
+ user = 'root'
+ mac = "00:11:22:33:44:55"
+ ip = "1.1.1.7/24"
+ user_config = [" - name: {user_name}",
+ " ssh_authorized_keys:",
+ " - {pub_key_str}"]
+
+ user_conf = os.linesep.join(user_config).format(pub_key_str=pub_key_str, user_name=user)
+ with mock.patch('six.moves.builtins.open', mock.mock_open(read_data=pub_key_str),
+ create=True) as mock_file:
+ with open(key_filename, "r") as h:
+ result = h.read()
+ model.Libvirt.gen_cdrom_image(self.mock_ssh, file_path, hostname, user, key_filename,
+ mac, ip)
+ mock_file.assert_called_with(".".join([key_filename, "pub"]), "r")
+ self.assertEqual(result, pub_key_str)
+
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call("touch %s" % meta_data),
+ mock.call(model.USER_DATA_TEMPLATE.format(user_file=user_data, host=hostname,
+ user_config=user_conf)),
+ mock.call(model.NETWORK_DATA_TEMPLATE.format(network_file=network_data,
+ mac_address=mac, ip_address=ip)),
+ mock.call("genisoimage -output {0} -volid cidata"
+ " -joliet -r {1} {2} {3}".format(file_path, meta_data, user_data,
+ network_data)),
+ mock.call("rm {0} {1} {2}".format(meta_data, user_data, network_data))
+ ])
+
+ def test_create_snapshot_qemu(self):
+ self.mock_ssh.execute = mock.Mock(return_value=(0, 0, 0))
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index, base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
+
+ @mock.patch.object(os.path, 'basename', return_value='base_image')
+ @mock.patch.object(os.path, 'normpath')
+ @mock.patch.object(os, 'access', return_value=True)
+ def test_create_snapshot_qemu_no_image_remote(self,
+ mock_os_access, mock_normpath, mock_basename):
+ self.mock_ssh.execute = mock.Mock(
+ side_effect=[(0, 0, 0), (1, 0, 0), (0, 0, 0), (0, 0, 0)])
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+ mock_normpath.return_value = base_image
+
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index, base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('mv -- "/tmp/%s" "%s"' % ('base_image', base_image)),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
+ mock_os_access.assert_called_once_with(base_image, os.R_OK)
+ mock_normpath.assert_called_once_with(base_image)
+ mock_basename.assert_has_calls([mock.call(base_image)])
+ self.mock_ssh.put_file.assert_called_once_with(base_image,
+ '/tmp/base_image')
+
+ @mock.patch.object(model.Libvirt, 'gen_cdrom_image')
+ def test_check_update_key(self, mock_gen_cdrom_image):
+ node = {
+ 'user': 'defuser',
+ 'key_filename': '/home/ubuntu/id_rsa',
+ 'ip': '1.1.1.7',
+ 'netmask': '255.255.255.0'}
+ cdrom_img = "/var/lib/libvirt/images/data.img"
+ id_name = 'fake_name'
+ key_filename = node.get('key_filename')
+ root = ElementTree.fromstring(self.XML_STR)
+ hostname = root.find('name').text
+ mac = "00:11:22:33:44:55"
+ ip = "{0}/{1}".format(node.get('ip'), node.get('netmask'))
+ ip = "{0}/{1}".format(node.get('ip'), netaddr.IPNetwork(ip).prefixlen)
+ model.StandaloneContextHelper.check_update_key(self.mock_ssh, node, hostname, id_name,
+ cdrom_img, mac)
+ mock_gen_cdrom_image.assert_called_once_with(self.mock_ssh, cdrom_img, hostname,
+ node.get('user'), key_filename, mac, ip)
+
+ @mock.patch.object(os, 'access', return_value=False)
+ def test_create_snapshot_qemu_no_image_local(self, mock_os_access):
+ self.mock_ssh.execute = mock.Mock(side_effect=[(0, 0, 0), (1, 0, 0)])
+ base_image = '/tmp/base_image'
+
+ with self.assertRaises(exceptions.LibvirtQemuImageBaseImageNotPresent):
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, 3, base_image)
+ mock_os_access.assert_called_once_with(base_image, os.R_OK)
+
+ def test_create_snapshot_qemu_error_qemuimg_command(self):
+ self.mock_ssh.execute = mock.Mock(
+ side_effect=[(0, 0, 0), (0, 0, 0), (1, 0, 0)])
+ index = 1
+ vm_image = '/var/lib/libvirt/images/%s.qcow2' % index
+ base_image = '/tmp/base_image'
+
+ with self.assertRaises(exceptions.LibvirtQemuImageCreateError):
+ model.Libvirt.create_snapshot_qemu(self.mock_ssh, index,
+ base_image)
+ self.mock_ssh.execute.assert_has_calls([
+ mock.call('rm -- "%s"' % vm_image),
+ mock.call('test -r %s' % base_image),
+ mock.call('qemu-img create -f qcow2 -o backing_file=%s %s' %
+ (base_image, vm_image))
+ ])
+
+ @mock.patch.object(model.Libvirt, 'pin_vcpu_for_perf', return_value='4,5')
+ @mock.patch.object(model.Libvirt, 'create_snapshot_qemu',
+ return_value='qemu_image')
+ def test_build_vm_xml(self, mock_create_snapshot_qemu,
+ mock_pin_vcpu_for_perf):
+ extra_specs = {'hw:cpu_cores': '4',
+ 'hw:cpu_sockets': '3',
+ 'hw:cpu_threads': '2',
+ 'cputune': 'cool'}
+ flavor = {'ram': '1024',
+ 'extra_specs': extra_specs,
+ 'hw_socket': '1',
+ 'images': 'images'}
+ mac = model.StandaloneContextHelper.get_mac_address(0x00)
+ _uuid = uuid.uuid4()
+ connection = mock.Mock()
+ cdrom_img = '/tmp/cdrom-0.img'
+ with mock.patch.object(model.StandaloneContextHelper,
+ 'get_mac_address', return_value=mac) as \
+ mock_get_mac_address, \
+ mock.patch.object(uuid, 'uuid4', return_value=_uuid):
+ xml_out, mac = model.Libvirt.build_vm_xml(
+ connection, flavor, 'vm_name', 100, cdrom_img)
+
+ xml_ref = model.VM_TEMPLATE.format(vm_name='vm_name',
+ random_uuid=_uuid, mac_addr=mac, memory='1024', vcpu='8', cpu='4',
+ numa_cpus='0-7', socket='3', threads='2',
+ vm_image='qemu_image', cpuset='4,5', cputune='cool',
+ machine='pc-i440fx-xenial')
+ xml_ref = model.Libvirt.add_cdrom(cdrom_img, xml_ref)
+ self.assertEqual(xml_out, xml_ref)
+ mock_get_mac_address.assert_called_once_with(0x00)
+ mock_create_snapshot_qemu.assert_called_once_with(
+ connection, 100, 'images')
+ mock_pin_vcpu_for_perf.assert_called_once_with(connection, '1')
+
+ # TODO: Edit this test to test state instead of output
+ # update_interrupts_hugepages_perf does not return anything
+ def test_update_interrupts_hugepages_perf(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): 'update_interrupts_hugepages_perf' always return
+ # None, this check is trivial.
+ #status = Libvirt.update_interrupts_hugepages_perf(ssh_mock)
+ #self.assertIsNone(status)
+ model.Libvirt.update_interrupts_hugepages_perf(ssh_mock)
+
+ @mock.patch.object(model, 'CpuSysCores')
+ @mock.patch.object(model.Libvirt, 'update_interrupts_hugepages_perf')
+ def test_pin_vcpu_for_perf(self, *args):
+ # NOTE(ralonsoh): test mocked methods/variables.
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ status = model.Libvirt.pin_vcpu_for_perf(ssh_mock, 4)
+ self.assertIsNotNone(status)
+
+
+class StandaloneContextHelperTestCase(unittest.TestCase):
+
+ NODE_SAMPLE = "nodes_sample.yaml"
+ NODE_SRIOV_SAMPLE = "nodes_sriov_sample.yaml"
+
+ NETWORKS = {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'private_0': {
+ 'phy_port': "0000:05:00.0",
+ 'vpci': "0000:00:07.0",
+ 'cidr': '152.16.100.10/24',
+ 'gateway_ip': '152.16.100.20'},
+ 'public_0': {
+ 'phy_port': "0000:05:00.1",
+ 'vpci': "0000:00:08.0",
+ 'cidr': '152.16.40.10/24',
+ 'gateway_ip': '152.16.100.20'}
+ }
+
+ def setUp(self):
+ self.helper = model.StandaloneContextHelper()
+
+ def test___init__(self):
+ self.assertIsNone(self.helper.file_path)
+
+ def test_install_req_libs(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "a", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ model.StandaloneContextHelper.install_req_libs(ssh_mock)
+
+ def test_get_kernel_module(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "i40e", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ model.StandaloneContextHelper.get_kernel_module(
+ ssh_mock, "05:00.0", None)
+
+ @mock.patch.object(model.StandaloneContextHelper, 'get_kernel_module')
+ def test_get_nic_details(self, mock_get_kernel_module):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = mock.Mock(return_value=(1, "i40e ixgbe", ""))
+ ssh.return_value = ssh_mock
+ mock_get_kernel_module.return_value = "i40e"
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ model.StandaloneContextHelper.get_nic_details(
+ ssh_mock, self.NETWORKS, 'dpdk-devbind.py')
+
+ def test_get_virtual_devices(self):
+ pattern = "PCI_SLOT_NAME=0000:05:00.0"
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, pattern, ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ model.StandaloneContextHelper.get_virtual_devices(
+ ssh_mock, '0000:00:05.0')
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test_parse_pod_file(self):
+ self.helper.file_path = self._get_file_abspath("dummy")
+ self.assertRaises(IOError, self.helper.parse_pod_file,
+ self.helper.file_path)
+
+ self.helper.file_path = self._get_file_abspath(self.NODE_SAMPLE)
+ self.assertRaises(TypeError, self.helper.parse_pod_file,
+ self.helper.file_path)
+
+ self.helper.file_path = self._get_file_abspath(self.NODE_SRIOV_SAMPLE)
+ self.assertIsNotNone(self.helper.parse_pod_file(self.helper.file_path))
+
+ def test_get_mac_address(self):
+ status = model.StandaloneContextHelper.get_mac_address()
+ self.assertIsNotNone(status)
+
+ @mock.patch('yardstick.ssh.SSH')
+ def test_get_mgmt_ip(self, *args):
+ # NOTE(ralonsoh): test mocked methods/variables.
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = mock.Mock(
+ return_value=(1, "1.2.3.4 00:00:00:00:00:01", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ status = model.StandaloneContextHelper.get_mgmt_ip(
+ ssh_mock, "00:00:00:00:00:01", "1.1.1.1/24", {})
+ self.assertIsNotNone(status)
+
+ @mock.patch('yardstick.ssh.SSH')
+ def test_get_mgmt_ip_no(self, *args):
+ # NOTE(ralonsoh): test mocked methods/variables.
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "", ""))
+ ssh.return_value = ssh_mock
+ # NOTE(ralonsoh): this test doesn't cover function execution. This test
+ # should also check mocked function calls.
+ model.WAIT_FOR_BOOT = 0
+ status = model.StandaloneContextHelper.get_mgmt_ip(
+ ssh_mock, "99", "1.1.1.1/24", {})
+ self.assertIsNone(status)
+
+
+class ServerTestCase(unittest.TestCase):
+
+ NETWORKS = {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'private_0': {
+ 'phy_port': "0000:05:00.0",
+ 'vpci': "0000:00:07.0",
+ 'driver': 'i40e',
+ 'mac': '',
+ 'cidr': '152.16.100.10/24',
+ 'gateway_ip': '152.16.100.20'},
+ 'public_0': {
+ 'phy_port': "0000:05:00.1",
+ 'vpci': "0000:00:08.0",
+ 'driver': 'i40e',
+ 'mac': '',
+ 'cidr': '152.16.40.10/24',
+ 'gateway_ip': '152.16.100.20'}
+ }
+
+ def setUp(self):
+ self.server = model.Server()
+
+ def test___init__(self):
+ self.assertIsNotNone(self.server)
+
+ def test_build_vnf_interfaces(self):
+ vnf = {
+ "network_ports": {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'xe0': ['private_0'],
+ 'xe1': ['public_0'],
+ }
+ }
+ status = model.Server.build_vnf_interfaces(vnf, self.NETWORKS)
+ self.assertIsNotNone(status)
+
+ def test_generate_vnf_instance(self):
+ vnf = {
+ "network_ports": {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'xe0': ['private_0'],
+ 'xe1': ['public_0'],
+ }
+ }
+ status = self.server.generate_vnf_instance(
+ {}, self.NETWORKS, '1.1.1.1/24', 'vm-0', vnf, '00:00:00:00:00:01')
+ self.assertIsNotNone(status)
+
+
+class OvsDeployTestCase(unittest.TestCase):
+
+ OVS_DETAILS = {'version': {'ovs': 'ovs_version', 'dpdk': 'dpdk_version'}}
+
+ def setUp(self):
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+ self.ovs_deploy = model.OvsDeploy(self.mock_ssh,
+ '/tmp/dpdk-devbind.py',
+ self.OVS_DETAILS)
+ self._mock_path_isfile = mock.patch.object(os.path, 'isfile')
+ self._mock_path_join = mock.patch.object(os.path, 'join')
+ self.mock_path_isfile = self._mock_path_isfile.start()
+ self.mock_path_join = self._mock_path_join.start()
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_ssh.stop()
+ self._mock_path_isfile.stop()
+ self._mock_path_join.stop()
+
+ @mock.patch.object(model.StandaloneContextHelper, 'install_req_libs')
+ def test_prerequisite(self, mock_install_req_libs):
+ pkgs = ["git", "build-essential", "pkg-config", "automake",
+ "autotools-dev", "libltdl-dev", "cmake", "libnuma-dev",
+ "libpcap-dev"]
+ self.ovs_deploy.prerequisite()
+ mock_install_req_libs.assert_called_once_with(
+ self.ovs_deploy.connection, pkgs)
+
+ def test_ovs_deploy_no_file(self):
+ self.mock_path_isfile.return_value = False
+ mock_file = mock.Mock()
+ self.mock_path_join.return_value = mock_file
+
+ self.ovs_deploy.ovs_deploy()
+ self.mock_path_isfile.assert_called_once_with(mock_file)
+ self.mock_path_join.assert_called_once_with(
+ constants.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/scripts/install/',
+ self.ovs_deploy.OVS_DEPLOY_SCRIPT)
+
+ @mock.patch.object(os.environ, 'get', return_value='test_proxy')
+ def test_ovs_deploy(self, mock_env_get):
+ self.mock_path_isfile.return_value = True
+ mock_deploy_file = mock.Mock()
+ mock_remove_ovs_deploy = mock.Mock()
+ self.mock_path_join.side_effect = [mock_deploy_file,
+ mock_remove_ovs_deploy]
+ dpdk_version = self.OVS_DETAILS['version']['dpdk']
+ ovs_version = self.OVS_DETAILS['version']['ovs']
+
+ with mock.patch.object(self.ovs_deploy.connection, 'put') as \
+ mock_put, \
+ mock.patch.object(self.ovs_deploy.connection, 'execute') as \
+ mock_execute, \
+ mock.patch.object(self.ovs_deploy, 'prerequisite'):
+ mock_execute.return_value = (0, 0, 0)
+ self.ovs_deploy.ovs_deploy()
+
+ self.mock_path_isfile.assert_called_once_with(mock_deploy_file)
+ self.mock_path_join.assert_has_calls([
+ mock.call(constants.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/scripts/install/',
+ self.ovs_deploy.OVS_DEPLOY_SCRIPT),
+ mock.call(self.ovs_deploy.bin_path,
+ self.ovs_deploy.OVS_DEPLOY_SCRIPT)
+ ])
+ mock_put.assert_called_once_with(mock_deploy_file,
+ mock_remove_ovs_deploy)
+ cmd = ("sudo -E %(remote_ovs_deploy)s --ovs='%(ovs_version)s' "
+ "--dpdk='%(dpdk_version)s' -p='%(proxy)s'" %
+ {'remote_ovs_deploy': mock_remove_ovs_deploy,
+ 'ovs_version': ovs_version,
+ 'dpdk_version': dpdk_version,
+ 'proxy': 'test_proxy'})
+ mock_execute.assert_called_once_with(cmd)
+ mock_env_get.assert_has_calls([mock.call('http_proxy', '')])
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
new file mode 100644
index 000000000..413bb68b7
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_ovs_dpdk.py
@@ -0,0 +1,500 @@
+# 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.
+
+import io
+import os
+
+import mock
+import six
+import unittest
+
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts.standalone import model
+from yardstick.benchmark.contexts.standalone import ovs_dpdk
+from yardstick.common import exceptions
+from yardstick.common import utils as common_utils
+from yardstick.network_services import utils
+
+
+class OvsDpdkContextTestCase(unittest.TestCase):
+
+ NODES_SAMPLE = "nodes_sample.yaml"
+ NODES_ovs_dpdk_SAMPLE = "nodes_ovs_dpdk_sample.yaml"
+ NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
+
+ NETWORKS = {
+ 'private_0': {
+ 'phy_port': "0000:05:00.0",
+ 'vpci': "0000:00:07.0",
+ 'cidr': '152.16.100.10/24',
+ 'interface': 'if0',
+ 'mac': "00:00:00:00:00:01",
+ 'vf_pci': {'vf_pci': 0},
+ 'gateway_ip': '152.16.100.20'},
+ 'public_0': {
+ 'phy_port': "0000:05:00.1",
+ 'vpci': "0000:00:08.0",
+ 'cidr': '152.16.40.10/24',
+ 'interface': 'if0',
+ 'vf_pci': {'vf_pci': 0},
+ 'mac': "00:00:00:00:00:01",
+ 'gateway_ip': '152.16.100.20'},
+ }
+
+ def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_ovs_dpdk_SAMPLE)
+ }
+ self.ovs_dpdk = ovs_dpdk.OvsDpdkContext()
+ self._mock_log = mock.patch.object(ovs_dpdk, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._remove_contexts)
+ self.addCleanup(self._stop_mocks)
+
+ @staticmethod
+ def _remove_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+ base.Context.list = []
+
+ def _stop_mocks(self):
+ self._mock_log.stop()
+
+ @mock.patch('yardstick.benchmark.contexts.standalone.model.Server')
+ @mock.patch('yardstick.benchmark.contexts.standalone.model.StandaloneContextHelper')
+ def test___init__(self, mock_helper, mock_server):
+ self.ovs_dpdk.helper = mock_helper
+ self.ovs_dpdk.vnf_node = mock_server
+ self.assertIsNone(self.ovs_dpdk.file_path)
+ self.assertTrue(self.ovs_dpdk.first_run)
+
+ def test_init(self):
+ ATTRS = {
+ 'name': contexts.CONTEXT_STANDALONEOVSDPDK,
+ 'task_id': '1234567890',
+ 'file': 'pod',
+ 'flavor': {},
+ 'servers': {},
+ 'networks': {},
+ }
+
+ self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
+ return_value=[{}, {}, {}])
+ self.assertIsNone(self.ovs_dpdk.init(ATTRS))
+
+ def test_setup_ovs(self):
+ fake_path = '/fake_path'
+ fake_dpdk_nic_bind = 'dpdk_tool.py'
+ self.ovs_dpdk.ovs_properties = {'vpath': fake_path}
+ self.ovs_dpdk.dpdk_devbind = fake_dpdk_nic_bind
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.connection.execute = mock.Mock(return_value=(0, 0, 0))
+ create_from = fake_path + '/etc/openvswitch/conf.db'
+ create_to = fake_path + '/share/openvswitch/vswitch.ovsschema'
+ cmd_list = [
+ 'killall -r "ovs.*" -q | true',
+ 'mkdir -p {0}/etc/openvswitch'.format(fake_path),
+ 'mkdir -p {0}/var/run/openvswitch'.format(fake_path),
+ 'rm {0}/etc/openvswitch/conf.db | true'.format(fake_path),
+ 'ovsdb-tool create {0} {1}'.format(create_from, create_to),
+ 'modprobe vfio-pci',
+ 'chmod a+x /dev/vfio',
+ 'chmod 0666 /dev/vfio/*',
+ '{0} --force -b vfio-pci {1}'.format(fake_dpdk_nic_bind,
+ self.ovs_dpdk.networks['private_0']['phy_port']),
+ '{0} --force -b vfio-pci {1}'.format(fake_dpdk_nic_bind,
+ self.ovs_dpdk.networks['public_0']['phy_port'])
+ ]
+ calls = [mock.call(cmd, timeout=self.ovs_dpdk.CMD_TIMEOUT)
+ for cmd in cmd_list]
+
+ self.ovs_dpdk.setup_ovs()
+ self.ovs_dpdk.connection.execute.assert_has_calls(calls,
+ any_order=True)
+
+ def test_setup_ovs_exception(self):
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.connection.execute = mock.Mock(return_value=(1, 0, 0))
+
+ with self.assertRaises(exceptions.OVSSetupError):
+ self.ovs_dpdk.setup_ovs()
+
+ def test_start_ovs_serverswitch(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ self.ovs_dpdk.connection = ssh_mock
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {}
+ self.ovs_dpdk.wait_for_vswitchd = 0
+ self.assertIsNone(self.ovs_dpdk.start_ovs_serverswitch())
+
+ def test_setup_ovs_bridge_add_flows(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ self.ovs_dpdk.connection = ssh_mock
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {
+ 'version': {'ovs': '2.7.0'}
+ }
+ self.ovs_dpdk.wait_for_vswitchd = 0
+ self.assertIsNone(self.ovs_dpdk.setup_ovs_bridge_add_flows())
+ self.ovs_dpdk.ovs_properties.update(
+ {'dpdk_pmd-rxq-affinity': {'0': "0:1"}})
+ self.ovs_dpdk.ovs_properties.update(
+ {'vhost_pmd-rxq-affinity': {'0': "0:1"}})
+ self.NETWORKS['private_0'].update({'port_num': '0'})
+ self.NETWORKS['public_0'].update({'port_num': '1'})
+ self.ovs_dpdk.setup_ovs_bridge_add_flows()
+
+ @mock.patch("yardstick.ssh.SSH")
+ def test_cleanup_ovs_dpdk_env(self, mock_ssh):
+ mock_ssh.execute.return_value = 0, "a", ""
+ self.ovs_dpdk.connection = mock_ssh
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {
+ 'version': {'ovs': '2.7.0'}
+ }
+ self.ovs_dpdk.wait_for_vswitchd = 0
+ self.assertIsNone(self.ovs_dpdk.cleanup_ovs_dpdk_env())
+
+ @mock.patch.object(utils, 'get_nsb_option')
+ @mock.patch.object(model.OvsDeploy, 'ovs_deploy')
+ def test_check_ovs_dpdk_env(self, mock_ovs_deploy, mock_get_nsb_option):
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.connection.execute = mock.Mock(
+ return_value=(1, 0, 0))
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {
+ 'version': {'ovs': '2.7.0', 'dpdk': '16.11.1'}
+ }
+ self.ovs_dpdk.wait_for_vswitchd = 0
+ self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock()
+ mock_get_nsb_option.return_value = 'fake_path'
+
+ self.ovs_dpdk.check_ovs_dpdk_env()
+ mock_ovs_deploy.assert_called_once()
+ mock_get_nsb_option.assert_called_once_with('bin_path')
+
+ def test_check_ovs_dpdk_env_wrong_version(self):
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.connection.execute = mock.Mock(
+ return_value=(1, 0, 0))
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {
+ 'version': {'ovs': '0.0.1', 'dpdk': '9.8.7'}
+ }
+ self.ovs_dpdk.wait_for_vswitchd = 0
+ self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock()
+
+ with self.assertRaises(exceptions.OVSUnsupportedVersion):
+ self.ovs_dpdk.check_ovs_dpdk_env()
+
+ @mock.patch('yardstick.ssh.SSH')
+ def test_deploy(self, *args):
+ self.ovs_dpdk.vm_deploy = False
+ self.assertIsNone(self.ovs_dpdk.deploy())
+
+ self.ovs_dpdk.vm_deploy = True
+ self.ovs_dpdk.host_mgmt = {}
+ self.ovs_dpdk.install_req_libs = mock.Mock()
+ self.ovs_dpdk.helper.get_nic_details = mock.Mock(return_value={})
+ self.ovs_dpdk.check_ovs_dpdk_env = mock.Mock(return_value={})
+ self.ovs_dpdk.setup_ovs = mock.Mock(return_value={})
+ self.ovs_dpdk.start_ovs_serverswitch = mock.Mock(return_value={})
+ self.ovs_dpdk.setup_ovs_bridge_add_flows = mock.Mock(return_value={})
+ self.ovs_dpdk.setup_ovs_dpdk_context = mock.Mock(return_value={})
+ self.ovs_dpdk.wait_for_vnfs_to_start = mock.Mock(return_value={})
+ # TODO(elfoley): This test should check states/sideeffects instead of
+ # output.
+ self.assertIsNone(self.ovs_dpdk.deploy())
+
+ @mock.patch.object(model.Libvirt, 'check_if_vm_exists_and_delete')
+ def test_undeploy(self, mock_libvirt):
+ self.ovs_dpdk.vm_deploy = True
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.vm_names = ['vm-0', 'vm-1']
+ self.ovs_dpdk.drivers = ['vm-0', 'vm-1']
+ self.ovs_dpdk.cleanup_ovs_dpdk_env = mock.Mock()
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.undeploy()
+ mock_libvirt.assert_has_calls([
+ mock.call(self.ovs_dpdk.vm_names[0], self.ovs_dpdk.connection),
+ mock.call(self.ovs_dpdk.vm_names[1], self.ovs_dpdk.connection)
+ ])
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test__get_server_with_dic_attr_name(self):
+
+ self.ovs_dpdk.init(self.attrs)
+
+ attr_name = {'name': 'foo.bar'}
+ result = self.ovs_dpdk._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_not_found(self):
+
+ self.ovs_dpdk.helper.parse_pod_file = mock.Mock(
+ return_value=[{}, {}, {}])
+ self.ovs_dpdk.init(self.attrs)
+
+ attr_name = 'bar.foo'
+ result = self.ovs_dpdk._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_mismatch(self):
+
+ self.ovs_dpdk.init(self.attrs)
+
+ attr_name = 'bar.foo1'
+ result = self.ovs_dpdk._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_duplicate(self):
+
+ self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
+
+ self.ovs_dpdk.init(self.attrs)
+
+ attr_name = 'node1.foo-12345678'
+ with self.assertRaises(ValueError):
+ self.ovs_dpdk._get_server(attr_name)
+
+ def test__get_server_found(self):
+
+ self.ovs_dpdk.init(self.attrs)
+
+ attr_name = 'node1.foo-12345678'
+ result = self.ovs_dpdk._get_server(attr_name)
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ def test__get_physical_node_for_server(self):
+ attrs = self.attrs
+ attrs.update({'servers': {'server1': {}}})
+ self.ovs_dpdk.init(attrs)
+
+ # When server is not from this context
+ result = self.ovs_dpdk._get_physical_node_for_server('server1.another-context')
+ self.assertIsNone(result)
+
+ # When node_name is not from this context
+ result = self.ovs_dpdk._get_physical_node_for_server('fake.foo-12345678')
+ self.assertIsNone(result)
+
+ result = self.ovs_dpdk._get_physical_node_for_server('server1.foo-12345678')
+ self.assertEqual(result, 'node5.foo')
+
+ # TODO(elfoley): Split this test for networks that exist and networks that
+ # don't
+ def test__get_network(self):
+ network1 = {
+ 'name': 'net_1',
+ 'vld_id': 'vld111',
+ 'segmentation_id': 'seg54',
+ 'network_type': 'type_a',
+ 'physical_network': 'phys',
+ }
+ network2 = {
+ 'name': 'net_2',
+ 'vld_id': 'vld999',
+ }
+ self.ovs_dpdk.networks = {
+ 'a': network1,
+ 'b': network2,
+ }
+
+ # Tests for networks that do not exist
+ attr_name = {}
+ self.assertIsNone(self.ovs_dpdk._get_network(attr_name))
+
+ attr_name = {'vld_id': 'vld777'}
+ self.assertIsNone(self.ovs_dpdk._get_network(attr_name))
+
+ self.assertIsNone(self.ovs_dpdk._get_network(None))
+
+ # TODO(elfoley): Split this test
+ attr_name = 'vld777'
+ self.assertIsNone(self.ovs_dpdk._get_network(attr_name))
+
+ # Tests for networks that exist
+ attr_name = {'vld_id': 'vld999'}
+ expected = {
+ "name": 'net_2',
+ "vld_id": 'vld999',
+ "segmentation_id": None,
+ "network_type": None,
+ "physical_network": None,
+ }
+ result = self.ovs_dpdk._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ attr_name = 'a'
+ expected = network1
+ result = self.ovs_dpdk._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ def test_configure_nics_for_ovs_dpdk(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ self.ovs_dpdk.vm_deploy = True
+ self.ovs_dpdk.connection = ssh_mock
+ self.ovs_dpdk.vm_names = ['vm-0', 'vm-1']
+ self.ovs_dpdk.drivers = []
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.helper.get_mac_address = mock.Mock(return_value="")
+ self.ovs_dpdk.get_vf_datas = mock.Mock(return_value="")
+ self.assertIsNone(self.ovs_dpdk.configure_nics_for_ovs_dpdk())
+
+ @mock.patch.object(model.Libvirt, 'add_ovs_interface')
+ def test__enable_interfaces(self, mock_add_ovs_interface):
+ self.ovs_dpdk.vm_deploy = True
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.vm_names = ['vm-0', 'vm-1']
+ self.ovs_dpdk.drivers = []
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.ovs_properties = {'vpath': 'fake_path'}
+ self.ovs_dpdk.get_vf_datas = mock.Mock(return_value="")
+ self.ovs_dpdk._enable_interfaces(0, ["private_0"], 'test')
+ mock_add_ovs_interface.assert_called_once_with(
+ 'fake_path', 0, self.NETWORKS['private_0']['vpci'],
+ self.NETWORKS['private_0']['mac'], 'test', 1)
+
+ @mock.patch.object(ovs_dpdk.OvsDpdkContext, '_check_hugepages')
+ @mock.patch.object(common_utils, 'setup_hugepages')
+ @mock.patch.object(model.StandaloneContextHelper, 'check_update_key')
+ @mock.patch.object(model.Libvirt, 'write_file')
+ @mock.patch.object(model.Libvirt, 'build_vm_xml')
+ @mock.patch.object(model.Libvirt, 'check_if_vm_exists_and_delete')
+ @mock.patch.object(model.Libvirt, 'virsh_create_vm')
+ def test_setup_ovs_dpdk_context(self, mock_create_vm, mock_check_if_exists,
+ mock_build_xml, mock_write_file,
+ mock_check_update_key,
+ mock_setup_hugepages,
+ mock__check_hugepages):
+ self.ovs_dpdk.vm_deploy = True
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk.vm_names = ['vm-0', 'vm-1']
+ self.ovs_dpdk.drivers = []
+ self.ovs_dpdk.servers = {
+ 'vnf_0': {
+ 'network_ports': {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'xe0': ['private_0'],
+ 'xe1': ['public_0']
+ }
+ }
+ }
+ self.ovs_dpdk.networks = self.NETWORKS
+ self.ovs_dpdk.host_mgmt = {}
+ self.ovs_dpdk.vm_flavor = {'ram': '1024'}
+ self.ovs_dpdk.file_path = '/var/lib/libvirt/images/cdrom-0.img'
+ self.ovs_dpdk.configure_nics_for_ovs_dpdk = mock.Mock(return_value="")
+ self.ovs_dpdk._name_task_id = 'fake_name'
+ xml_str = 'vm-0'
+ self.ovs_dpdk.mac = '00:00:00:00:00:01'
+ mock_build_xml.return_value = (xml_str, self.ovs_dpdk.mac)
+ self.ovs_dpdk._enable_interfaces = mock.Mock(return_value=xml_str)
+ vnf_instance = mock.Mock()
+ vnf_instance_2 = mock.Mock()
+ mock_check_update_key.return_value = vnf_instance_2
+ self.ovs_dpdk.vnf_node.generate_vnf_instance = mock.Mock(
+ return_value=vnf_instance)
+
+ self.assertEqual([vnf_instance_2],
+ self.ovs_dpdk.setup_ovs_dpdk_context())
+ mock_setup_hugepages.assert_called_once_with(self.ovs_dpdk.connection,
+ (1024 + 4096) * 1024) # ram + dpdk_socket0_mem + dpdk_socket1_mem
+ mock__check_hugepages.assert_called_once()
+ mock_create_vm.assert_called_once_with(
+ self.ovs_dpdk.connection, '/tmp/vm_ovs_0.xml')
+ mock_check_if_exists.assert_called_once_with(
+ 'vm-0', self.ovs_dpdk.connection)
+ mock_build_xml.assert_called_once_with(
+ self.ovs_dpdk.connection, self.ovs_dpdk.vm_flavor, 'vm-0', 0, self.ovs_dpdk.file_path)
+ mock_write_file.assert_called_once_with('/tmp/vm_ovs_0.xml', xml_str)
+ mock_check_update_key.assert_called_once_with(self.ovs_dpdk.connection,
+ vnf_instance,
+ xml_str,
+ self.ovs_dpdk._name_task_id,
+ self.ovs_dpdk.file_path,
+ self.ovs_dpdk.mac)
+
+ @mock.patch.object(io, 'BytesIO')
+ def test__check_hugepages(self, mock_bytesio):
+ data = six.BytesIO('HugePages_Total: 20\n'
+ 'HugePages_Free: 20\n'
+ 'HugePages_Rsvd: 0\n'
+ 'HugePages_Surp: 0\n'
+ 'Hugepagesize: 1048576 kB'.encode())
+ mock_bytesio.return_value = data
+ self.ovs_dpdk.connection = mock.Mock()
+ self.ovs_dpdk._check_hugepages()
+
+ @mock.patch.object(io, 'BytesIO')
+ def test__check_hugepages_no_info(self, mock_bytesio):
+ data = six.BytesIO(''.encode())
+ mock_bytesio.return_value = data
+ self.ovs_dpdk.connection = mock.Mock()
+ with self.assertRaises(exceptions.OVSHugepagesInfoError):
+ self.ovs_dpdk._check_hugepages()
+
+ @mock.patch.object(io, 'BytesIO')
+ def test__check_hugepages_no_total_hp(self, mock_bytesio):
+ data = six.BytesIO('HugePages_Total: 0\n'
+ 'HugePages_Free: 0\n'
+ 'HugePages_Rsvd: 0\n'
+ 'HugePages_Surp: 0\n'
+ 'Hugepagesize: 1048576 kB'.encode())
+ mock_bytesio.return_value = data
+ self.ovs_dpdk.connection = mock.Mock()
+ with self.assertRaises(exceptions.OVSHugepagesNotConfigured):
+ self.ovs_dpdk._check_hugepages()
+
+ @mock.patch.object(io, 'BytesIO')
+ def test__check_hugepages_no_free_hp(self, mock_bytesio):
+ data = six.BytesIO('HugePages_Total: 20\n'
+ 'HugePages_Free: 0\n'
+ 'HugePages_Rsvd: 0\n'
+ 'HugePages_Surp: 0\n'
+ 'Hugepagesize: 1048576 kB'.encode())
+ mock_bytesio.return_value = data
+ self.ovs_dpdk.connection = mock.Mock()
+ with self.assertRaises(exceptions.OVSHugepagesZeroFree) as exc:
+ self.ovs_dpdk._check_hugepages()
+ self.assertEqual('There are no HugePages free in this system. Total '
+ 'HugePages configured: 20', exc.exception.msg)
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
new file mode 100644
index 000000000..0809a983a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone/test_sriov.py
@@ -0,0 +1,362 @@
+# 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.
+
+import os
+
+import mock
+import unittest
+
+from yardstick import ssh
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts.standalone import model
+from yardstick.benchmark.contexts.standalone import sriov
+from yardstick.common import utils
+
+
+class SriovContextTestCase(unittest.TestCase):
+
+ NODES_SAMPLE = "nodes_sample.yaml"
+ NODES_SRIOV_SAMPLE = "nodes_sriov_sample.yaml"
+ NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
+
+ ATTRS = {
+ 'name': contexts.CONTEXT_STANDALONESRIOV,
+ 'task_id': '1234567890',
+ 'file': 'pod',
+ 'flavor': {},
+ 'servers': {},
+ 'networks': {},
+ }
+
+ NETWORKS = {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'private_0': {
+ 'phy_port': "0000:05:00.0",
+ 'vpci': "0000:00:07.0",
+ 'cidr': '152.16.100.10/24',
+ 'interface': 'if0',
+ 'mac': "00:00:00:00:00:01",
+ 'vf_pci': {'vf_pci': 0},
+ 'gateway_ip': '152.16.100.20'},
+ 'public_0': {
+ 'phy_port': "0000:05:00.1",
+ 'vpci': "0000:00:08.0",
+ 'cidr': '152.16.40.10/24',
+ 'interface': 'if0',
+ 'vf_pci': {'vf_pci': 0},
+ 'mac': "00:00:00:00:00:01",
+ 'gateway_ip': '152.16.100.20'},
+ }
+
+ def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_SRIOV_SAMPLE),
+ }
+ self.sriov = sriov.SriovContext()
+ self.addCleanup(self._remove_contexts)
+
+ @staticmethod
+ def _remove_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+ base.Context.list = []
+
+ @mock.patch.object(model, 'StandaloneContextHelper')
+ @mock.patch.object(model, 'Libvirt')
+ @mock.patch.object(model, 'Server')
+ def test___init__(self, mock_helper, mock_libvirt, mock_server):
+ # pylint: disable=unused-argument
+ # NOTE(ralonsoh): this test doesn't cover function execution.
+ self.sriov.helper = mock_helper
+ self.sriov.vnf_node = mock_server
+ self.assertIsNone(self.sriov.file_path)
+ self.assertTrue(self.sriov.first_run)
+
+ def test_init(self):
+ self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}])
+ self.assertIsNone(self.sriov.init(self.ATTRS))
+
+ @mock.patch.object(ssh, 'SSH', return_value=(0, "a", ""))
+ def test_deploy(self, *args):
+ # NOTE(ralonsoh): this test doesn't cover function execution.
+ self.sriov.vm_deploy = False
+ self.assertIsNone(self.sriov.deploy())
+
+ self.sriov.vm_deploy = True
+ self.sriov.host_mgmt = {}
+ self.sriov.install_req_libs = mock.Mock()
+ self.sriov.get_nic_details = mock.Mock(return_value={})
+ self.sriov.setup_sriov_context = mock.Mock(return_value={})
+ self.sriov.wait_for_vnfs_to_start = mock.Mock(return_value={})
+ self.assertIsNone(self.sriov.deploy())
+
+ @mock.patch.object(ssh, 'SSH', return_value=(0, "a", ""))
+ @mock.patch.object(model, 'Libvirt')
+ def test_undeploy(self, mock_libvirt, mock_ssh):
+ # pylint: disable=unused-argument
+ # NOTE(ralonsoh): the pylint exception should be removed.
+ self.sriov.vm_deploy = False
+ self.assertIsNone(self.sriov.undeploy())
+
+ self.sriov.vm_deploy = True
+ self.sriov.connection = mock_ssh
+ self.sriov.vm_names = ['vm-0', 'vm-1']
+ self.sriov.drivers = ['vm-0', 'vm-1']
+ self.assertIsNone(self.sriov.undeploy())
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test__get_server_with_dic_attr_name(self):
+
+ self.sriov.init(self.attrs)
+
+ attr_name = {'name': 'foo.bar'}
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_not_found(self):
+
+ self.sriov.helper.parse_pod_file = mock.Mock(return_value=[{}, {}, {}])
+ self.sriov.init(self.attrs)
+
+ attr_name = 'bar.foo'
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_mismatch(self):
+
+ self.sriov.init(self.attrs)
+
+ attr_name = 'bar.foo1'
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_duplicate(self):
+
+ self.attrs['file'] = self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
+
+ self.sriov.init(self.attrs)
+
+ attr_name = 'node1.foo-12345678'
+ with self.assertRaises(ValueError):
+ self.sriov._get_server(attr_name)
+
+ def test__get_server_found(self):
+
+ self.sriov.init(self.attrs)
+
+ attr_name = 'node1.foo-12345678'
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ def test__get_physical_node_for_server(self):
+ attrs = self.attrs
+ attrs.update({'servers': {'server1': {}}})
+ self.sriov.init(attrs)
+
+ # When server is not from this context
+ result = self.sriov._get_physical_node_for_server('server1.another-context')
+ self.assertIsNone(result)
+
+ # When node_name is not from this context
+ result = self.sriov._get_physical_node_for_server('fake.foo-12345678')
+ self.assertIsNone(result)
+
+ result = self.sriov._get_physical_node_for_server('server1.foo-12345678')
+ self.assertEqual(result, 'node5.foo')
+
+ def test__get_server_no_task_id(self):
+ self.attrs['flags'] = {'no_setup': True}
+ self.sriov.init(self.attrs)
+
+ attr_name = 'node1.foo'
+ result = self.sriov._get_server(attr_name)
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ # TODO(elfoley): Split this test
+ # There are at least two sets of inputs/outputs
+ def test__get_network(self):
+ network1 = {
+ 'name': 'net_1',
+ 'vld_id': 'vld111',
+ 'segmentation_id': 'seg54',
+ 'network_type': 'type_a',
+ 'physical_network': 'phys',
+ }
+ network2 = {
+ 'name': 'net_2',
+ 'vld_id': 'vld999',
+ }
+ self.sriov.networks = {
+ 'a': network1,
+ 'b': network2,
+ }
+
+ attr_name = {}
+ self.assertIsNone(self.sriov._get_network(attr_name))
+
+ attr_name = {'vld_id': 'vld777'}
+ self.assertIsNone(self.sriov._get_network(attr_name))
+
+ self.assertIsNone(self.sriov._get_network(None))
+
+ attr_name = 'vld777'
+ self.assertIsNone(self.sriov._get_network(attr_name))
+
+ attr_name = {'vld_id': 'vld999'}
+ expected = {
+ "name": 'net_2',
+ "vld_id": 'vld999',
+ "segmentation_id": None,
+ "network_type": None,
+ "physical_network": None,
+ }
+ result = self.sriov._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ attr_name = 'a'
+ expected = network1
+ result = self.sriov._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ def test_configure_nics_for_sriov(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ self.sriov.vm_deploy = True
+ self.sriov.connection = ssh_mock
+ self.sriov.vm_names = ['vm-0', 'vm-1']
+ self.sriov.drivers = []
+ self.sriov.networks = self.NETWORKS
+ self.sriov.helper.get_mac_address = mock.Mock(return_value="")
+ self.sriov._get_vf_data = mock.Mock(return_value="")
+ self.assertIsNone(self.sriov.configure_nics_for_sriov())
+
+ @mock.patch.object(ssh, 'SSH', return_value=(0, "a", ""))
+ @mock.patch.object(model.Libvirt, 'add_sriov_interfaces',
+ return_value='out_xml')
+ def test__enable_interfaces(self, mock_add_sriov, mock_ssh):
+ self.sriov.vm_deploy = True
+ self.sriov.connection = mock_ssh
+ self.sriov.vm_names = ['vm-0', 'vm-1']
+ self.sriov.drivers = []
+ self.sriov.networks = self.NETWORKS
+ self.assertEqual(
+ 'out_xml',
+ self.sriov._enable_interfaces(0, 0, ['private_0'], 'test'))
+ mock_add_sriov.assert_called_once_with(
+ '0000:00:0a.0', 0, self.NETWORKS['private_0']['mac'], 'test')
+
+ @mock.patch.object(utils, 'setup_hugepages')
+ @mock.patch.object(model.StandaloneContextHelper, 'check_update_key')
+ @mock.patch.object(model.Libvirt, 'build_vm_xml')
+ @mock.patch.object(model.Libvirt, 'check_if_vm_exists_and_delete')
+ @mock.patch.object(model.Libvirt, 'write_file')
+ @mock.patch.object(model.Libvirt, 'virsh_create_vm')
+ def test_setup_sriov_context(self, mock_create_vm, mock_write_file,
+ mock_check, mock_build_vm_xml,
+ mock_check_update_key, mock_setup_hugepages):
+ self.sriov.servers = {
+ 'vnf_0': {
+ 'network_ports': {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'xe0': ['private_0'],
+ 'xe1': ['public_0']
+ }
+ }
+ }
+ connection = mock.Mock()
+ self.sriov.connection = connection
+ self.sriov.host_mgmt = {'ip': '1.2.3.4'}
+ self.sriov.vm_flavor = {'ram': '1024'}
+ self.sriov.networks = 'networks'
+ self.sriov.configure_nics_for_sriov = mock.Mock()
+ self.sriov._name_task_id = 'fake_name'
+ cfg = '/tmp/vm_sriov_0.xml'
+ vm_name = 'vm-0'
+ mac = '00:00:00:00:00:01'
+ xml_out = mock.Mock()
+ mock_build_vm_xml.return_value = (xml_out, mac)
+ mock_check_update_key.return_value = 'node_2'
+ cdrom_img = '/var/lib/libvirt/images/cdrom-0.img'
+
+ with mock.patch.object(self.sriov, 'vnf_node') as mock_vnf_node, \
+ mock.patch.object(self.sriov, '_enable_interfaces') as \
+ mock_enable_interfaces:
+ mock_enable_interfaces.return_value = 'out_xml'
+ mock_vnf_node.generate_vnf_instance = mock.Mock(
+ return_value='node_1')
+ nodes_out = self.sriov.setup_sriov_context()
+ mock_setup_hugepages.assert_called_once_with(connection, 1024*1024)
+ mock_check_update_key.assert_called_once_with(connection, 'node_1', vm_name,
+ self.sriov._name_task_id, cdrom_img,
+ mac)
+ self.assertEqual(['node_2'], nodes_out)
+ mock_vnf_node.generate_vnf_instance.assert_called_once_with(
+ self.sriov.vm_flavor, 'networks', '1.2.3.4', 'vnf_0',
+ self.sriov.servers['vnf_0'], '00:00:00:00:00:01')
+ mock_build_vm_xml.assert_called_once_with(
+ connection, self.sriov.vm_flavor, vm_name, 0, cdrom_img)
+ mock_create_vm.assert_called_once_with(connection, cfg)
+ mock_check.assert_called_once_with(vm_name, connection)
+ mock_write_file.assert_called_once_with(cfg, 'out_xml')
+ mock_enable_interfaces.assert_has_calls([
+ mock.call(0, mock.ANY, ['private_0'], mock.ANY),
+ mock.call(0, mock.ANY, ['public_0'], mock.ANY)], any_order=True)
+
+ def test__get_vf_data(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(0, "a", ""))
+ ssh.return_value = ssh_mock
+ self.sriov.vm_deploy = True
+ self.sriov.connection = ssh_mock
+ self.sriov.vm_names = ['vm-0', 'vm-1']
+ self.sriov.drivers = []
+ self.sriov.servers = {
+ 'vnf_0': {
+ 'network_ports': {
+ 'mgmt': {'cidr': '152.16.100.10/24'},
+ 'xe0': ['private_0'],
+ 'xe1': ['public_0']
+ }
+ }
+ }
+ self.sriov.networks = self.NETWORKS
+ self.sriov.helper.get_virtual_devices = mock.Mock(
+ return_value={'0000:00:01.0': ''})
+ self.assertIsNotNone(self.sriov._get_vf_data(
+ '0000:00:01.0', '00:00:00:00:00:01', 'if0'))
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml
new file mode 100644
index 000000000..e468d0465
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml
@@ -0,0 +1,135 @@
+# 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.
+#
+---
+# Sample config file about the POD information, including the
+# name/IP/user/ssh key of Bare Metal and Controllers/Computes
+#
+# The options of this config file include:
+# name: the name of this node
+# role: node's role, support role: Master/Controller/Comupte/BareMetal
+# ip: the node's IP address
+# user: the username for login
+# key_filename:the path of the private key file for login
+
+nodes:
+-
+ name: node1
+ role: TrafficGen
+ ip: 1.1.1.1
+ user: root
+ password: r00t
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:05:00.0"
+ driver: i40e
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:01"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:05:00.1"
+ driver: i40e
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:02"
+-
+ name: node2
+ role: nfvi_node
+ class: OvsDpdk
+ ip: 1.1.1.2
+ user: root
+ password: r00t
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:05:00.0"
+ - "0000:05:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu.qcow2"
+-
+ name: node2
+ role: nfvi_node
+ class: OvsDpdk
+ ip: 1.1.1.5
+ user: root
+ password: r00t
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:05:00.0"
+ - "0000:05:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu.qcow2"
+
+-
+ name: node3
+ role: vnf
+ ip: 1.1.1.3
+ user: root
+ password: r00t
+ host: 1.1.1.1
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:04.0"
+ driver: virtio-pci
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:05"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:05.0"
+ driver: virtio-pci
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:06"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
diff --git a/yardstick/tests/unit/benchmark/contexts/standalone_sample.yaml b/yardstick/tests/unit/benchmark/contexts/standalone_sample.yaml
new file mode 100644
index 000000000..95e12d62f
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/standalone_sample.yaml
@@ -0,0 +1,112 @@
+# 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.
+#
+---
+# Sample config file about the POD information, including the
+# name/IP/user/ssh key of Bare Metal and Controllers/Computes
+#
+# The options of this config file include:
+# name: the name of this node
+# role: node's role, support role: Master/Controller/Comupte/BareMetal
+# ip: the node's IP address
+# user: the username for login
+# key_filename:the path of the private key file for login
+
+nodes:
+-
+ name: node1
+ role: TrafficGen
+ ip: 1.1.1.1
+ user: root
+ password: r00t
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:05:00.0"
+ driver: i40e
+ dpdk_port_num: 0
+ local_ip: "152.16.100.20"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:01"
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:05:00.1"
+ driver: i40e
+ dpdk_port_num: 1
+ local_ip: "152.16.100.21"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:02"
+-
+ name: node2
+ role: nfvi_node
+ class: OvsDpdk
+ ip: 1.1.1.2
+ user: root
+ password: r00t
+ vports:
+ - dpdkvhostuser0
+ - dpdkvhostuser1
+ vports_mac:
+ - "00:00:00:00:00:03"
+ - "00:00:00:00:00:04"
+ phy_ports: # Physical ports to configure sriov
+ - "0000:05:00.0"
+ - "0000:05:00.1"
+ flow:
+ - ovs-ofctl add-flow br0 in_port=1,action=output:3
+ - ovs-ofctl add-flow br0 in_port=3,action=output:1
+ - ovs-ofctl add-flow br0 in_port=4,action=output:2
+ - ovs-ofctl add-flow br0 in_port=2,action=output:4
+ phy_driver: i40e # kernel driver
+ images: "/var/lib/libvirt/images/ubuntu.qcow2"
+
+-
+ name: node3
+ role: vnf
+ ip: 1.1.1.3
+ user: root
+ password: r00t
+ host: 1.1.1.1
+ interfaces:
+ xe0: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:04.0"
+ driver: virtio-pci
+ dpdk_port_num: 0
+ local_ip: "152.16.100.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:05"
+
+ xe1: # logical name from topology.yaml and vnfd.yaml
+ vpci: "0000:00:05.0"
+ driver: virtio-pci
+ dpdk_port_num: 1
+ local_ip: "152.16.40.19"
+ netmask: "255.255.255.0"
+ local_mac: "00:00:00:00:00:06"
+ routing_table:
+ - network: "152.16.100.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.100.20"
+ if: "xe0"
+ - network: "152.16.40.20"
+ netmask: "255.255.255.0"
+ gateway: "152.16.40.20"
+ if: "xe1"
+ nd_route_tbl:
+ - network: "0064:ff9b:0:0:0:0:9810:6414"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:6414"
+ if: "xe0"
+ - network: "0064:ff9b:0:0:0:0:9810:2814"
+ netmask: "112"
+ gateway: "0064:ff9b:0:0:0:0:9810:2814"
+ if: "xe1"
diff --git a/yardstick/tests/unit/benchmark/contexts/test_base.py b/yardstick/tests/unit/benchmark/contexts/test_base.py
new file mode 100644
index 000000000..5fd7352f5
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_base.py
@@ -0,0 +1,174 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import errno
+
+import mock
+
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts.base import Context
+from yardstick.common import yaml_loader
+from yardstick.tests.unit import base as ut_base
+from yardstick.common.constants import YARDSTICK_ROOT_PATH
+
+
+class DummyContextClass(Context):
+
+ __context_type__ = "Dummy"
+
+ def __init__(self, host_name_separator='.'):
+ super(DummyContextClass, self).__init__\
+ (host_name_separator=host_name_separator)
+ self.nodes = []
+ self.controllers = []
+ self.computes = []
+ self.baremetals = []
+
+ def _get_network(self, *args):
+ pass
+
+ def _get_server(self, *args):
+ pass
+
+ def deploy(self):
+ pass
+
+ def undeploy(self):
+ pass
+
+ def _get_physical_nodes(self):
+ pass
+
+ def _get_physical_node_for_server(self, server_name):
+ pass
+
+
+class FlagsTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self.flags = base.Flags()
+
+ def test___init__(self):
+ self.assertFalse(self.flags.no_setup)
+ self.assertFalse(self.flags.no_teardown)
+ self.assertEqual({'verify': False}, self.flags.os_cloud_config)
+
+ def test___init__with_flags(self):
+ flags = base.Flags(no_setup=True)
+ self.assertTrue(flags.no_setup)
+ self.assertFalse(flags.no_teardown)
+
+ def test_parse(self):
+ self.flags.parse(no_setup=True, no_teardown='False',
+ os_cloud_config={'verify': True})
+
+ self.assertTrue(self.flags.no_setup)
+ self.assertEqual('False', self.flags.no_teardown)
+ self.assertEqual({'verify': True}, self.flags.os_cloud_config)
+
+ def test_parse_forbidden_flags(self):
+ self.flags.parse(foo=42)
+ with self.assertRaises(AttributeError):
+ _ = self.flags.foo
+
+
+class ContextTestCase(ut_base.BaseUnitTestCase):
+
+ @staticmethod
+ def _remove_ctx(ctx_obj):
+ if ctx_obj in base.Context.list:
+ base.Context.list.remove(ctx_obj)
+
+ def test_split_host_name(self):
+ ctx_obj = DummyContextClass()
+ self.addCleanup(self._remove_ctx, ctx_obj)
+ config_name = 'host_name.ctx_name'
+ self.assertEqual(('host_name', 'ctx_name'),
+ ctx_obj.split_host_name(config_name))
+
+ def test_split_host_name_wrong_separator(self):
+ ctx_obj = DummyContextClass()
+ self.addCleanup(self._remove_ctx, ctx_obj)
+ config_name = 'host_name-ctx_name'
+ self.assertEqual((None, None),
+ ctx_obj.split_host_name(config_name))
+
+ def test_split_host_name_other_separator(self):
+ ctx_obj = DummyContextClass(host_name_separator='-')
+ self.addCleanup(self._remove_ctx, ctx_obj)
+ config_name = 'host_name-ctx_name'
+ self.assertEqual(('host_name', 'ctx_name'),
+ ctx_obj.split_host_name(config_name))
+
+ def test_get_physical_nodes(self):
+ ctx_obj = DummyContextClass()
+ self.addCleanup(self._remove_ctx, ctx_obj)
+
+ result = Context.get_physical_nodes()
+
+ self.assertEqual(result, {None: None})
+
+ @mock.patch.object(Context, 'get_context_from_server')
+ def test_get_physical_node_from_server(self, mock_get_ctx):
+ ctx_obj = DummyContextClass()
+ self.addCleanup(self._remove_ctx, ctx_obj)
+
+ mock_get_ctx.return_value = ctx_obj
+
+ result = Context.get_physical_node_from_server("mock_server")
+
+ mock_get_ctx.assert_called_once()
+ self.assertIsNone(result)
+
+ @mock.patch.object(yaml_loader, 'read_yaml_file')
+ def test_read_pod_file(self, mock_read_yaml_file):
+ attrs = {'name': 'foo',
+ 'task_id': '12345678',
+ 'file': 'pod.yaml'
+ }
+
+ ctx_obj = DummyContextClass()
+ cfg = {"nodes": [
+ {
+ "name": "node1",
+ "role": "Controller",
+ "ip": "10.229.47.137",
+ "user": "root",
+ "key_filename": "/root/.yardstick_key"
+ },
+ {
+ "name": "node2",
+ "role": "Compute",
+ "ip": "10.229.47.139",
+ "user": "root",
+ "key_filename": "/root/.yardstick_key"
+ }
+ ]
+ }
+
+ mock_read_yaml_file.return_value = cfg
+ result = ctx_obj.read_pod_file(attrs)
+ self.assertEqual(result, cfg)
+
+ mock_read_yaml_file.side_effect = IOError(errno.EPERM, '')
+ with self.assertRaises(IOError):
+ ctx_obj.read_pod_file(attrs)
+
+ mock_read_yaml_file.side_effect = IOError(errno.ENOENT, '')
+ with self.assertRaises(IOError):
+ ctx_obj.read_pod_file(attrs)
+
+ file_path = os.path.join(YARDSTICK_ROOT_PATH, 'pod.yaml')
+ self.assertEqual(ctx_obj.file_path, file_path)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_dummy.py b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
new file mode 100644
index 000000000..33832375f
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_dummy.py
@@ -0,0 +1,86 @@
+##############################################################################
+# Copyright (c) 2015 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
+
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts import dummy
+
+
+class DummyContextTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ }
+ self.test_context = dummy.DummyContext()
+ self.addCleanup(self._delete_contexts)
+
+ @staticmethod
+ def _delete_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+
+ def test___init__(self):
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+ self.assertIsNone(self.test_context._name)
+ self.assertIsNone(self.test_context._task_id)
+
+ def test_init(self):
+ self.test_context.init(self.attrs)
+ self.assertEqual(self.test_context._name, 'foo')
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo-12345678')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_flags_no_setup(self):
+ self.attrs['flags'] = {'no_setup': True, 'no_teardown': False}
+
+ self.test_context.init(self.attrs)
+
+ self.assertEqual(self.test_context._name, 'foo')
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertTrue(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_flags_no_teardown(self):
+ self.attrs['flags'] = {'no_setup': False, 'no_teardown': True}
+
+ self.test_context.init(self.attrs)
+
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertTrue(self.test_context._flags.no_teardown)
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test__get_server(self):
+ self.test_context.init(self.attrs)
+ self.test_context.deploy()
+
+ result = self.test_context._get_server(None)
+ self.assertEqual(result, None)
+
+ self.test_context.undeploy()
+
+ def test__get_physical_nodes(self):
+ result = self.test_context._get_physical_nodes()
+ self.assertIsNone(result)
+
+ def test__get_physical_node_for_server(self):
+ result = self.test_context._get_physical_node_for_server("fake")
+ self.assertIsNone(result)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_heat.py b/yardstick/tests/unit/benchmark/contexts/test_heat.py
new file mode 100644
index 000000000..96946cded
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_heat.py
@@ -0,0 +1,893 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+from collections import OrderedDict
+import logging
+import os
+
+import mock
+import unittest
+import collections
+
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts import heat
+from yardstick.benchmark.contexts import model
+from yardstick.common import constants as consts
+from yardstick.common import exceptions as y_exc
+from yardstick.common import openstack_utils
+from yardstick.common import yaml_loader
+from yardstick import ssh
+
+
+LOG = logging.getLogger(__name__)
+
+
+class HeatContextTestCase(unittest.TestCase):
+
+ HEAT_POD_SAMPLE = {
+ "nodes": [
+ {
+ "name": "node1",
+ "role": "Controller",
+ "ip": "10.229.47.137",
+ "user": "root",
+ "key_filename": "/root/.yardstick_key"
+ },
+ {
+ "name": "node2",
+ "role": "Compute",
+ "ip": "10.229.47.139",
+ "user": "root",
+ "key_filename": "/root/.yardstick_key"
+ }
+ ]
+ }
+
+ def __init__(self, *args, **kwargs):
+
+ super(HeatContextTestCase, self).__init__(*args, **kwargs)
+
+ def setUp(self):
+ self.test_context = heat.HeatContext()
+ self.addCleanup(self._remove_contexts)
+ self.mock_context = mock.Mock(spec=heat.HeatContext())
+
+ def _remove_contexts(self):
+ if self.test_context in self.test_context.list:
+ self.test_context._delete_context()
+
+ def test___init__(self):
+ self.assertIsNone(self.test_context._name)
+ self.assertIsNone(self.test_context._task_id)
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+ self.assertIsNone(self.test_context.stack)
+ self.assertEqual(self.test_context.networks, OrderedDict())
+ self.assertEqual(self.test_context.servers, [])
+ self.assertEqual(self.test_context.placement_groups, [])
+ self.assertEqual(self.test_context.server_groups, [])
+ self.assertIsNone(self.test_context.keypair_name)
+ self.assertIsNone(self.test_context.secgroup_name)
+ self.assertIsNone(self.test_context.security_group)
+ self.assertEqual(self.test_context._server_map, {})
+ self.assertIsNone(self.test_context._image)
+ self.assertIsNone(self.test_context._flavor)
+ self.assertIsNone(self.test_context._user)
+ self.assertIsNone(self.test_context.template_file)
+ self.assertIsNone(self.test_context.heat_parameters)
+ self.assertIsNone(self.test_context.key_filename)
+ self.assertTrue(self.test_context.yardstick_gen_key_file)
+
+ @mock.patch.object(yaml_loader, 'read_yaml_file')
+ @mock.patch('yardstick.benchmark.contexts.heat.PlacementGroup')
+ @mock.patch('yardstick.benchmark.contexts.heat.ServerGroup')
+ @mock.patch('yardstick.benchmark.contexts.heat.Network')
+ @mock.patch('yardstick.benchmark.contexts.heat.Server')
+ def test_init(self, mock_server, mock_network, mock_sg, mock_pg,
+ mock_read_yaml):
+
+ mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
+ pgs = {'pgrp1': {'policy': 'availability'}}
+ sgs = {'servergroup1': {'policy': 'affinity'}}
+ networks = {'bar': {'cidr': '10.0.1.0/24'}}
+ servers = {'baz': {'floating_ip': True, 'placement': 'pgrp1'}}
+ attrs = {'name': 'foo',
+ 'file': 'pod.yaml',
+ 'task_id': '1234567890',
+ 'placement_groups': pgs,
+ 'server_groups': sgs,
+ 'networks': networks,
+ 'servers': servers}
+
+ with mock.patch.object(openstack_utils, 'get_shade_client'), \
+ mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+ self.test_context.init(attrs)
+
+ self.assertFalse(self.test_context._flags.no_setup)
+ self.assertFalse(self.test_context._flags.no_teardown)
+ self.assertEqual(self.test_context._name, "foo")
+ self.assertEqual(self.test_context._task_id, '1234567890')
+ self.assertEqual(self.test_context.name, "foo-12345678")
+ self.assertEqual(self.test_context.keypair_name, "foo-12345678-key")
+ self.assertEqual(self.test_context.secgroup_name, "foo-12345678-secgroup")
+
+ mock_pg.assert_called_with('pgrp1', self.test_context,
+ pgs['pgrp1']['policy'])
+ mock_sg.assert_called_with('servergroup1', self.test_context,
+ sgs['servergroup1']['policy'])
+ self.assertEqual(len(self.test_context.placement_groups), 1)
+ self.assertEqual(len(self.test_context.server_groups), 1)
+
+ mock_network.assert_called_with(
+ 'bar', self.test_context, networks['bar'])
+ self.assertEqual(len(self.test_context.networks), 1)
+
+ mock_server.assert_called_with('baz', self.test_context,
+ servers['baz'])
+ self.assertEqual(len(self.test_context.servers), 1)
+
+ def test_init_no_name_or_task_id(self):
+ attrs = {}
+ self.assertRaises(KeyError, self.test_context.init, attrs)
+
+ def test_name(self):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.assertEqual(self.test_context.name, 'foo-12345678')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_name_flags(self):
+ self.test_context._flags = base.Flags(
+ **{"no_setup": True, "no_teardown": True})
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+
+ self.assertEqual(self.test_context.name, 'foo')
+ self.assertEqual(self.test_context.assigned_name, 'foo')
+
+ def test_init_no_setup_no_teardown(self):
+
+ attrs = {'name': 'foo',
+ 'task_id': '1234567890',
+ 'placement_groups': {},
+ 'server_groups': {},
+ 'networks': {},
+ 'servers': {},
+ 'file': "pod.yaml",
+ 'flags': {
+ 'no_setup': True,
+ 'no_teardown': True,
+ },
+ }
+
+ with mock.patch.object(openstack_utils, 'get_shade_client'), \
+ mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+ self.test_context.init(attrs)
+
+ self.assertTrue(self.test_context._flags.no_setup)
+ self.assertTrue(self.test_context._flags.no_teardown)
+
+ def test_init_key_filename(self):
+ attrs = {'name': 'foo',
+ 'file': 'pod.yaml',
+ 'task_id': '1234567890',
+ 'server_groups': {},
+ 'networks': {},
+ 'servers': {},
+ 'heat_template': "/root/clearwater.yaml",
+ 'key_filename': '/etc/yardstick/yardstick.pem'}
+
+ with mock.patch.object(openstack_utils, 'get_shade_client'), \
+ mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+ self.test_context.init(attrs)
+
+ self.assertIsNotNone(self.test_context.key_filename)
+ self.assertFalse(self.test_context.yardstick_gen_key_file)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_resources_to_template_no_servers(self, mock_template):
+ self.test_context._name = 'ctx'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.keypair_name = "ctx-key"
+ self.test_context.secgroup_name = "ctx-secgroup"
+ self.test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
+ netattrs = {'cidr': '10.0.0.0/24', 'provider': None,
+ 'external_network': 'ext_net'}
+
+ self.test_context.networks = OrderedDict(
+ {"mynet": model.Network("mynet", self.test_context,
+ netattrs)})
+
+ self.test_context._add_resources_to_template(mock_template)
+ mock_template.add_keypair.assert_called_with(
+ "ctx-key",
+ "ctx-12345678")
+ mock_template.add_security_group.assert_called_with("ctx-secgroup", None)
+ mock_template.add_network.assert_called_with(
+ "ctx-12345678-mynet", 'physnet1', None, None, None, None)
+ mock_template.add_router.assert_called_with(
+ "ctx-12345678-mynet-router",
+ netattrs["external_network"],
+ "ctx-12345678-mynet-subnet")
+ mock_template.add_router_interface.assert_called_with(
+ "ctx-12345678-mynet-router-if0",
+ "ctx-12345678-mynet-router",
+ "ctx-12345678-mynet-subnet")
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test_attrs_get(self, *args):
+ image, flavor, user = expected_tuple = 'foo1', 'foo2', 'foo3'
+ self.assertNotEqual(self.test_context.image, image)
+ self.assertNotEqual(self.test_context.flavor, flavor)
+ self.assertNotEqual(self.test_context.user, user)
+ self.test_context._image = image
+ self.test_context._flavor = flavor
+ self.test_context._user = user
+ attr_tuple = self.test_context.image, self.test_context.flavor, self.test_context.user
+ self.assertEqual(attr_tuple, expected_tuple)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test_attrs_set_negative(self, *args):
+ with self.assertRaises(AttributeError):
+ self.test_context.image = 'foo'
+
+ with self.assertRaises(AttributeError):
+ self.test_context.flavor = 'foo'
+
+ with self.assertRaises(AttributeError):
+ self.test_context.user = 'foo'
+
+ def test__create_new_stack(self):
+ template = mock.Mock()
+ self.test_context._create_new_stack(template)
+ template.create.assert_called_once()
+
+ def test__create_new_stack_stack_create_failed(self):
+ template = mock.Mock()
+ template.create.side_effect = y_exc.HeatTemplateError
+
+ self.assertRaises(y_exc.HeatTemplateError,
+ self.test_context._create_new_stack,
+ template)
+
+ def test__create_new_stack_keyboard_interrupt(self):
+ template = mock.Mock()
+ template.create.side_effect = KeyboardInterrupt
+ self.assertRaises(y_exc.StackCreationInterrupt,
+ self.test_context._create_new_stack,
+ template)
+
+ @mock.patch.object(os.path, 'exists', return_value=True)
+ @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ def test_deploy_stack_creation_failed(self, mock_create,
+ mock_resources_template, mock_path_exists):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = 'foo-12345678'
+ mock_create.side_effect = y_exc.HeatTemplateError
+ self.assertRaises(y_exc.HeatTemplateError,
+ self.test_context.deploy)
+
+ mock_path_exists.assert_called()
+ mock_resources_template.assert_called_once()
+
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat, 'HeatTemplate')
+ def test_deploy(self, mock_template, mock_genkeys, mock_path_exists):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.heat_parameters = {'image': 'cirros'}
+ self.test_context.get_neutron_info = mock.MagicMock()
+ self.test_context.deploy()
+
+ mock_template.assert_called_with(
+ 'foo-12345678', template_file='/bar/baz/some-heat-file',
+ heat_parameters={'image': 'cirros'},
+ os_cloud_config=self.test_context._flags.os_cloud_config)
+ self.assertIsNotNone(self.test_context.stack)
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name_task_id])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ def test_deploy_no_setup(self, mock_create_new_stack,
+ mock_retrieve_existing_stack, mock_genkeys, mock_path_exists,
+ *args):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.heat_parameters = {'image': 'cirros'}
+ self.test_context.get_neutron_info = mock.MagicMock()
+ self.test_context._flags.no_setup = True
+ self.test_context.deploy()
+
+ mock_create_new_stack.assert_not_called()
+ mock_retrieve_existing_stack.assert_called_with(self.test_context.name)
+ self.assertIsNotNone(self.test_context.stack)
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ @mock.patch.object(heat.HeatContext, '_retrieve_existing_stack',
+ return_value=None)
+ def test_deploy_try_retrieve_context_does_not_exist(self,
+ mock_retrieve_stack, mock_create_new_stack, mock_genkeys,
+ mock_path_exists, *args):
+ self.test_context._name = 'demo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._flags.no_setup = True
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.get_neutron_info = mock.MagicMock()
+ self.test_context.deploy()
+
+ mock_retrieve_stack.assert_called_once_with(self.test_context._name)
+ mock_create_new_stack.assert_called()
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
+
+ @mock.patch.object(heat, 'HeatTemplate', return_value='heat_template')
+ @mock.patch.object(heat.HeatContext, '_add_resources_to_template')
+ @mock.patch.object(os.path, 'exists', return_value=False)
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ def test_deploy_ssh_key_before_adding_resources(self, mock_genkeys,
+ mock_path_exists, mock_add_resources, *args):
+ mock_manager = mock.Mock()
+ mock_manager.attach_mock(mock_add_resources,
+ '_add_resources_to_template')
+ mock_manager.attach_mock(mock_genkeys, 'gen_keys')
+ mock_manager.reset_mock()
+ self.test_context._name_task_id = 'demo-12345678'
+ self.test_context.get_neutron_info = mock.Mock()
+ with mock.patch.object(self.test_context, '_create_new_stack') as \
+ mock_create_stack, \
+ mock.patch.object(self.test_context, 'get_neutron_info') as \
+ mock_neutron_info:
+ self.test_context.deploy()
+
+ mock_neutron_info.assert_called_once()
+ mock_create_stack.assert_called_once()
+ key_filename = ''.join(
+ [consts.YARDSTICK_ROOT_PATH,
+ 'yardstick/resources/files/yardstick_key-',
+ self.test_context._name_task_id])
+ mock_genkeys.assert_called_once_with(key_filename)
+ mock_path_exists.assert_any_call(key_filename)
+
+ mock_call_gen_keys = mock.call.gen_keys(key_filename)
+ mock_call_add_resources = (
+ mock.call._add_resources_to_template('heat_template'))
+ self.assertTrue(mock_manager.mock_calls.index(mock_call_gen_keys) <
+ mock_manager.mock_calls.index(mock_call_add_resources))
+
+ @mock.patch.object(heat, 'HeatTemplate')
+ @mock.patch.object(ssh.SSH, 'gen_keys')
+ @mock.patch.object(heat.HeatContext, '_create_new_stack')
+ def test_deploy_with_key_filename_provided(self, mock_create_new_stack,
+ mock_gen_keys, *args):
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.template_file = '/bar/baz/some-heat-file'
+ self.test_context.heat_parameters = {'image': 'cirros'}
+ self.test_context.yardstick_gen_key_file = False
+ self.test_context.key_filename = '/etc/yardstick/yardstick.pem'
+ self.test_context.get_neutron_info = mock.MagicMock()
+ self.test_context.deploy()
+
+ mock_create_new_stack.assert_called()
+ mock_gen_keys.assert_not_called()
+
+ def test_check_for_context(self):
+ pass
+ # check that the context exists
+
+ def test_add_server_port(self):
+ network1 = mock.MagicMock()
+ network2 = mock.MagicMock()
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.stack = mock.MagicMock()
+ self.test_context.networks = {
+ 'a': network1,
+ 'c': network2,
+ }
+ self.test_context.stack.outputs = {
+ u'b': u'10.20.30.45',
+ u'b-subnet_id': 1,
+ u'foo-12345678-a-subnet-cidr': u'10.20.0.0/15',
+ u'foo-12345678-a-subnet-gateway_ip': u'10.20.30.1',
+ u'b-mac_address': u'00:01',
+ u'b-device_id': u'dev21',
+ u'b-network_id': u'net789',
+ u'd': u'40.30.20.15',
+ u'd-subnet_id': 2,
+ u'foo-12345678-c-subnet-cidr': u'40.30.0.0/18',
+ u'foo-12345678-c-subnet-gateway_ip': u'40.30.20.254',
+ u'd-mac_address': u'00:10',
+ u'd-device_id': u'dev43',
+ u'd-network_id': u'net987',
+ u'e': u'40.30.20.15',
+ u'e-subnet_id': 2,
+ u'e-mac_address': u'00:10',
+ u'e-device_id': u'dev43',
+ u'e-network_id': u'net987',
+ }
+ server = mock.MagicMock()
+ server.private_ip = None
+ server.ports = OrderedDict([
+ ('a', [{'stack_name': 'b', 'port': 'port_a'}]),
+ ('c', [{'stack_name': 'd', 'port': 'port_c'},
+ {'stack_name': 'e', 'port': 'port_f'}]),
+ ])
+
+ expected = {
+ "private_ip": '10.20.30.45',
+ "subnet_id": 1,
+ "subnet_cidr": '10.20.0.0/15',
+ "network": '10.20.0.0',
+ "netmask": '255.254.0.0',
+ "name": "port_a",
+ "gateway_ip": '10.20.30.1',
+ "mac_address": '00:01',
+ "device_id": 'dev21',
+ "network_id": 'net789',
+ "network_name": 'a',
+ "local_mac": '00:01',
+ "local_ip": '10.20.30.45',
+ }
+ self.test_context.add_server_port(server)
+ self.assertEqual(server.private_ip, '10.20.30.45')
+ self.assertEqual(len(server.interfaces), 3)
+ self.assertDictEqual(server.interfaces['port_a'], expected)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.os')
+ @mock.patch.object(heat.HeatContext, '_delete_key_file')
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test_undeploy(self, mock_template, mock_delete_key, *args):
+ self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ # mock_os.path.exists.return_value = True
+ self.test_context.key_filename = 'foo/bar/foobar'
+ self.test_context.undeploy()
+ mock_delete_key.assert_called()
+ mock_template.delete.assert_called_once()
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test_undeploy_no_teardown(self, mock_template):
+ self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._flags.no_teardown = True
+ self.test_context.undeploy()
+
+ mock_template.delete.assert_not_called()
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ @mock.patch('yardstick.benchmark.contexts.heat.os')
+ def test_undeploy_key_filename(self, mock_os, mock_template):
+ self.test_context.stack = mock_template
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id)
+ mock_os.path.exists.return_value = True
+ self.test_context.key_filename = 'foo/bar/foobar'
+ self.assertIsNone(self.test_context.undeploy())
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_found_dict(self, *args):
+ """
+ Use HeatContext._get_server to get a server that matches
+ based on a dictionary input.
+ """
+ foo2_server = mock.Mock()
+ foo2_server.key_filename = None
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.key_filename = None
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = '127.0.0.3'
+ baz3_server.context.user = 'zab'
+
+ self.test_context._name = 'bar'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context._user = 'bot'
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.test_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ }
+
+ attr_name = {
+ 'name': 'foo.bar-12345678',
+ 'private_ip_attr': 'private_ip',
+ 'public_ip_attr': 'public_ip',
+ }
+ self.test_context.key_uuid = 'foo-42'
+ result = self.test_context._get_server(attr_name)
+ self.assertEqual(result['user'], 'bot')
+ self.assertEqual(result['ip'], '127.0.0.1')
+ self.assertEqual(result['private_ip'], '10.0.0.1')
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_found_dict_no_attrs(self, *args):
+ """
+ Use HeatContext._get_server to get a server that matches
+ based on a dictionary input.
+ """
+ foo2_server = mock.Mock()
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = '127.0.0.3'
+ baz3_server.context.user = 'zab'
+
+ self.test_context._name = 'bar'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context._user = 'bot'
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.test_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ }
+
+ attr_name = {
+ 'name': 'foo.bar-12345678',
+ }
+
+ self.test_context.key_uuid = 'foo-42'
+ result = self.test_context._get_server(attr_name)
+ self.assertEqual(result['user'], 'bot')
+ # no private ip attr mapping in the map results in None value in the result
+ self.assertIsNone(result['private_ip'])
+ # no public ip attr mapping in the map results in no value in the result
+ self.assertNotIn('ip', result)
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_found_not_dict(self, *args):
+ """
+ Use HeatContext._get_server to get a server that matches
+ based on a non-dictionary input
+ """
+ foo2_server = mock.Mock()
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = None
+ baz3_server.context.user = 'zab'
+
+ self.test_context._name = 'bar1'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = 'bar1-12345678'
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.test_context.generate_routing_table = mock.MagicMock(return_value=[])
+
+ self.test_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ }
+
+ attr_name = 'baz3'
+ result = self.test_context._get_server(attr_name)
+ self.assertEqual(result['user'], 'zab')
+ self.assertEqual(result['private_ip'], '10.0.0.3')
+ # no public_ip on the server results in no value in the result
+ self.assertNotIn('public_ip', result)
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_none_found_not_dict(self, *args):
+ """
+ Use HeatContext._get_server to not get a server due to
+ None value associated with the match to a non-dictionary
+ input
+ """
+ foo2_server = mock.Mock()
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = None
+ baz3_server.context.user = 'zab'
+
+ self.test_context._name = 'bar1'
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.test_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ 'wow4': None,
+ }
+
+ self.test_context.key_uuid = 'foo-42'
+ attr_name = 'wow4'
+ result = self.test_context._get_server(attr_name)
+ self.assertIsNone(result)
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_not_found_dict(self, *args):
+ """
+ Use HeatContext._get_server to not get a server for lack
+ of a match to a dictionary input
+ """
+ foo2_server = mock.Mock()
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = None
+ baz3_server.context.user = 'zab'
+
+ self.test_context._name = 'bar1'
+ self.test_context._task_id = '1235467890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.test_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ }
+
+ self.test_context.key_uuid = 'foo-42'
+ attr_name = {
+ 'name': 'foo.wow4',
+ 'private_ip_attr': 'private_ip',
+ 'public_ip_attr': 'public_ip',
+ }
+ result = self.test_context._get_server(attr_name)
+ self.assertIsNone(result)
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_not_found_not_dict(self, *args):
+ """
+ Use HeatContext._get_server to not get a server for lack
+ of a match to a non-dictionary input
+ """
+ foo2_server = mock.Mock()
+ foo2_server.private_ip = '10.0.0.2'
+ foo2_server.public_ip = '127.0.0.2'
+ foo2_server.context.user = 'oof'
+
+ baz3_server = mock.Mock()
+ baz3_server.private_ip = '10.0.0.3'
+ baz3_server.public_ip = None
+ baz3_server.context.user = 'zab'
+
+ self.mock_context._name = 'bar1'
+ self.test_context.stack = mock.Mock()
+ self.mock_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ }
+ self.mock_context._server_map = {
+ 'baz3': baz3_server,
+ 'foo2': foo2_server,
+ }
+
+ self.test_context.key_uuid = 'foo-42'
+ attr_name = 'foo.wow4'
+ result = self.test_context._get_server(attr_name)
+ self.assertIsNone(result)
+
+ @mock.patch("yardstick.benchmark.contexts.heat.pkg_resources")
+ def test__get_server_found_dict_found_interfaces_dict(self, *args):
+ """
+ Use HeatContext._get_server to get a server that matches
+ based on a dictionary input.
+ """
+ self.test_context._name = 'bar'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context._user = 'bot'
+ self.test_context.stack = mock.Mock()
+ self.test_context.stack.outputs = {
+ 'private_ip': '10.0.0.1',
+ 'public_ip': '127.0.0.1',
+ 'local_mac_addr': '64:00:6a:18:0f:d6',
+ 'private_netmask': '255.255.255.0',
+ 'private_net_name': 'private_network',
+ 'private_net_gateway': '127.0.0.254'
+ }
+
+ attr_name = {
+ 'name': 'foo.bar-12345678',
+ 'private_ip_attr': 'private_ip',
+ 'public_ip_attr': 'public_ip',
+ 'interfaces': {
+ 'data_net': {
+ 'local_ip': 'private_ip',
+ 'local_mac': 'local_mac_addr',
+ 'netmask': 'private_netmask',
+ 'network': 'private_net_name',
+ 'gateway_ip': 'private_net_gateway'
+ }
+ }
+ }
+ self.test_context.key_uuid = 'foo-42'
+ result = self.test_context._get_server(attr_name)
+ self.assertIsInstance(result['interfaces'], collections.Mapping)
+ for key in attr_name.get("interfaces").keys():
+ self.assertEqual(result['interfaces'][key]['local_ip'], '10.0.0.1')
+ self.assertEqual(result['interfaces'][key]['local_mac'], '64:00:6a:18:0f:d6')
+ self.assertEqual(result['interfaces'][key]['netmask'], '255.255.255.0')
+ self.assertEqual(result['interfaces'][key]['gateway_ip'], '127.0.0.254')
+
+ # TODO: Split this into more granular tests
+ def test__get_network(self):
+ network1 = mock.MagicMock()
+ network1.name = 'net_1'
+ network1.vld_id = 'vld111'
+ network1.segmentation_id = 'seg54'
+ network1.network_type = 'type_a'
+ network1.physical_network = 'phys'
+
+ network2 = mock.MagicMock()
+ network2.name = 'net_2'
+ network2.segmentation_id = 'seg45'
+ network2.network_type = 'type_b'
+ network2.physical_network = 'virt'
+
+ self.test_context.networks = {
+ 'a': network1,
+ 'b': network2,
+ }
+
+ attr_name = None
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = {}
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = {'network_type': 'nosuch'}
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = 'vld777'
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = {'segmentation_id': 'seg45'}
+ expected = {
+ "name": 'net_2',
+ "segmentation_id": 'seg45',
+ "network_type": 'type_b',
+ "physical_network": 'virt',
+ }
+ result = self.test_context._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ attr_name = 'a'
+ expected = {
+ "name": 'net_1',
+ "segmentation_id": 'seg54',
+ "network_type": 'type_a',
+ "physical_network": 'phys',
+ }
+ result = self.test_context._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test__get_physical_nodes(self):
+ self.test_context.nodes = {}
+ nodes = self.test_context._get_physical_nodes()
+ self.assertEquals(nodes, {})
+
+ @mock.patch.object(yaml_loader, 'read_yaml_file')
+ def test__get_physical_node_for_server(self, mock_read_yaml):
+ attrs = {'name': 'foo',
+ 'task_id': '12345678',
+ 'file': "pod.yaml",
+ 'servers': {'vnf': {}},
+ 'networks': {'mgmt': {'cidr': '10.0.1.0/24'}}
+ }
+
+ with mock.patch.object(openstack_utils, 'get_shade_client'), \
+ mock.patch.object(openstack_utils, 'get_shade_operator_client'):
+ mock_read_yaml.return_value = self.HEAT_POD_SAMPLE
+ self.test_context.init(attrs)
+
+ with mock.patch('yardstick.common.openstack_utils.get_server') as mock_get_server:
+ mock_get_server.return_value = {'vnf': {}}
+
+ # When server is not from this context
+ result = self.test_context._get_physical_node_for_server('node1.foo-context')
+ self.assertIsNone(result)
+
+ # When node_name is not from this context
+ result = self.test_context._get_physical_node_for_server('fake.foo-12345678')
+ self.assertIsNone(result)
+
+ mock_munch = mock.Mock()
+ mock_munch.toDict = mock.Mock(return_value={
+ 'OS-EXT-SRV-ATTR:hypervisor_hostname': 'hypervisor_hostname'
+ })
+ mock_get_server.return_value = mock_munch
+
+ hypervisor = mock.Mock()
+ hypervisor.hypervisor_hostname = 'hypervisor_hostname'
+ hypervisor.host_ip = '10.229.47.137'
+
+ self.test_context.operator_client.list_hypervisors = mock.Mock(
+ return_value=[hypervisor])
+
+ mock_get_server.return_value = mock_munch
+
+ result = self.test_context._get_physical_node_for_server('vnf.foo-12345678')
+ self.assertEqual(result, 'node1.foo')
diff --git a/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
new file mode 100644
index 000000000..b526e7cc7
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_kubernetes.py
@@ -0,0 +1,273 @@
+##############################################################################
+# Copyright (c) 2015 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 collections
+import time
+
+import mock
+import unittest
+
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts import kubernetes
+from yardstick.common import constants
+from yardstick.common import exceptions
+from yardstick.common import kubernetes_utils as k8s_utils
+from yardstick.orchestrator import kubernetes as orchestrator_kubernetes
+
+
+CONTEXT_CFG = {
+ 'type': contexts.CONTEXT_KUBERNETES,
+ 'name': 'k8s',
+ 'task_id': '1234567890',
+ 'servers': {
+ 'host': {
+ 'image': 'openretriever/yardstick',
+ 'command': '/bin/bash',
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; '
+ 'service ssh restart;while true ; do sleep 10000; done']
+ },
+ 'target': {
+ 'image': 'openretriever/yardstick',
+ 'command': '/bin/bash',
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; '
+ 'service ssh restart;while true ; do sleep 10000; done']
+ }
+ },
+ 'networks': {
+ 'flannel': {
+ 'args': 'flannel_args',
+ 'plugin': 'flannel'
+ },
+ 'sriov01': {
+ 'args': 'sriov_args',
+ 'plugin': 'sriov'
+ },
+ }
+}
+
+
+class NodePort(object):
+ def __init__(self):
+ self.node_port = 30000
+ self.port = constants.SSH_PORT
+ self.name = 'port_name'
+ self.protocol = 'TCP'
+ self.target_port = constants.SSH_PORT
+
+
+class Service(object):
+ def __init__(self):
+ self.ports = [NodePort()]
+
+
+class Status(object):
+ def __init__(self):
+ self.pod_ip = '172.16.10.131'
+
+
+class Pod(object):
+ def __init__(self):
+ self.status = Status()
+
+
+class KubernetesTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.k8s_context = kubernetes.KubernetesContext()
+ self.addCleanup(self._remove_contexts)
+ self.k8s_context.init(CONTEXT_CFG)
+
+ @staticmethod
+ def _remove_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+ base.Context.list = []
+
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_services')
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_ssh_key')
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_rcs')
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_pods')
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_networks')
+ @mock.patch.object(kubernetes.KubernetesContext, '_delete_crd')
+ def test_undeploy(self, mock_delete_pods, mock_delete_rcs,
+ mock_delete_ssh, mock_delete_services,
+ mock_delete_networks, mock_delete_crd):
+
+ self.k8s_context.undeploy()
+ 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_delete_networks.assert_called_once()
+ mock_delete_crd.assert_called_once()
+
+ @mock.patch.object(kubernetes.KubernetesContext, '_create_services')
+ @mock.patch.object(kubernetes.KubernetesContext, '_wait_until_running')
+ @mock.patch.object(orchestrator_kubernetes.KubernetesTemplate,
+ 'get_rc_pods')
+ @mock.patch.object(kubernetes.KubernetesContext, '_create_rcs')
+ @mock.patch.object(kubernetes.KubernetesContext, '_set_ssh_key')
+ @mock.patch.object(kubernetes.KubernetesContext, '_create_networks')
+ @mock.patch.object(kubernetes.KubernetesContext, '_create_crd')
+ def test_deploy(self, mock_set_ssh_key, mock_create_rcs, mock_get_rc_pods,
+ mock_wait_until_running, mock_create_services,
+ mock_create_networks, mock_create_crd):
+
+ with mock.patch.object(time, 'sleep'):
+ self.k8s_context.deploy()
+ 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_create_networks.assert_called_once()
+ mock_create_crd.assert_called_once()
+
+ @mock.patch.object(kubernetes, 'paramiko', **{"resource_filename.return_value": ""})
+ @mock.patch.object(kubernetes, 'pkg_resources', **{"resource_filename.return_value": ""})
+ @mock.patch.object(kubernetes, 'utils')
+ @mock.patch.object(kubernetes, 'open', create=True)
+ @mock.patch.object(k8s_utils, 'delete_config_map')
+ @mock.patch.object(k8s_utils, 'create_config_map')
+ def test_ssh_key(self, mock_create, mock_delete, *args):
+ self.k8s_context._set_ssh_key()
+ self.k8s_context._delete_ssh_key()
+
+ mock_create.assert_called_once()
+ mock_delete.assert_called_once()
+
+ @mock.patch.object(k8s_utils, 'read_pod_status')
+ def test_wait_until_running(self, mock_read_pod_status):
+
+ self.k8s_context.template.pods = ['server']
+ mock_read_pod_status.return_value = 'Running'
+ self.k8s_context._wait_until_running()
+
+ @mock.patch.object(k8s_utils, 'get_pod_by_name')
+ @mock.patch.object(kubernetes.KubernetesContext, '_get_node_ip')
+ def test_get_server(self, mock_get_node_ip, mock_get_pod_by_name):
+ mock_get_pod_by_name.return_value = Pod()
+ mock_get_node_ip.return_value = '172.16.10.131'
+ with mock.patch.object(self.k8s_context, '_get_service_ports') as \
+ mock_get_sports:
+ mock_get_sports.return_value = [
+ {'port': constants.SSH_PORT, 'node_port': 30000}]
+ server = self.k8s_context._get_server('server_name')
+ self.assertEqual('server_name', server['name'])
+ self.assertEqual(30000, server['ssh_port'])
+
+ @mock.patch.object(kubernetes.KubernetesContext, '_create_rc')
+ def test_create_rcs(self, mock_create_rc):
+ self.k8s_context._create_rcs()
+ mock_create_rc.assert_called()
+
+ @mock.patch.object(k8s_utils, 'create_replication_controller')
+ def test_create_rc(self, mock_create_replication_controller):
+ self.k8s_context._create_rc({})
+ 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()
+ mock_delete_rc.assert_called()
+
+ @mock.patch.object(k8s_utils, 'delete_replication_controller')
+ def test_delete_rc(self, mock_delete_replication_controller):
+ self.k8s_context._delete_rc({})
+ mock_delete_replication_controller.assert_called_once()
+
+ @mock.patch.object(k8s_utils, 'get_node_list')
+ def test_get_node_ip(self, mock_get_node_list):
+ self.k8s_context._get_node_ip()
+ mock_get_node_list.assert_called_once()
+
+ @mock.patch.object(orchestrator_kubernetes.ServiceNodePortObject, 'create')
+ def test_create_services(self, mock_create):
+ self.k8s_context._create_services()
+ mock_create.assert_called()
+
+ @mock.patch.object(orchestrator_kubernetes.ServiceNodePortObject, 'delete')
+ def test_delete_services(self, mock_delete):
+ self.k8s_context._delete_services()
+ mock_delete.assert_called()
+
+ def test_init(self):
+ self.k8s_context._delete_context()
+ with mock.patch.object(orchestrator_kubernetes, 'KubernetesTemplate',
+ return_value='fake_template') as mock_k8stemplate:
+ self.k8s_context = kubernetes.KubernetesContext()
+ self.k8s_context.init(CONTEXT_CFG)
+ mock_k8stemplate.assert_called_once_with(self.k8s_context.name,
+ CONTEXT_CFG)
+ self.assertEqual('fake_template', self.k8s_context.template)
+ self.assertEqual(2, len(self.k8s_context._networks))
+ self.assertIn('flannel', self.k8s_context._networks.keys())
+ self.assertIn('sriov01', self.k8s_context._networks.keys())
+
+ def test__get_physical_nodes(self):
+ result = self.k8s_context._get_physical_nodes()
+ self.assertIsNone(result)
+
+ def test__get_physical_node_for_server(self):
+ result = self.k8s_context._get_physical_node_for_server("fake")
+ self.assertIsNone(result)
+
+ def test__get_network(self):
+ networks = collections.OrderedDict([('n1', 'data1'), ('n2', 'data2')])
+ self.k8s_context._networks = networks
+ self.assertEqual({'name': 'n1'}, self.k8s_context._get_network('n1'))
+ self.assertEqual({'name': 'n2'}, self.k8s_context._get_network('n2'))
+ self.assertIsNone(self.k8s_context._get_network('n3'))
+
+ @mock.patch.object(orchestrator_kubernetes.KubernetesTemplate,
+ 'get_rc_by_name')
+ def test__get_interfaces(self, mock_get_rc):
+ rc = orchestrator_kubernetes.ReplicationControllerObject('rc_name')
+ rc._networks = ['net1', 'net2']
+ mock_get_rc.return_value = rc
+ expected = {'net1': {'network_name': 'net1',
+ 'local_mac': None,
+ 'local_ip': None},
+ 'net2': {'network_name': 'net2',
+ 'local_mac': None,
+ 'local_ip': None}}
+ self.assertEqual(expected, self.k8s_context._get_interfaces('rc_name'))
+
+ @mock.patch.object(orchestrator_kubernetes.KubernetesTemplate,
+ 'get_rc_by_name')
+ def test__get_interfaces_no_networks(self, mock_get_rc):
+ rc = orchestrator_kubernetes.ReplicationControllerObject('rc_name')
+ mock_get_rc.return_value = rc
+ self.assertEqual({}, self.k8s_context._get_interfaces('rc_name'))
+
+ @mock.patch.object(orchestrator_kubernetes.KubernetesTemplate,
+ 'get_rc_by_name', return_value=None)
+ def test__get_interfaces_no_rc(self, *args):
+ self.assertEqual({}, self.k8s_context._get_interfaces('rc_name'))
+
+ @mock.patch.object(k8s_utils, 'get_service_by_name',
+ return_value=Service())
+ def test__get_service_ports(self, mock_get_service_by_name):
+ name = 'rc_name'
+ service_ports = self.k8s_context._get_service_ports(name)
+ mock_get_service_by_name.assert_called_once_with(name + '-service')
+ expected = {'node_port': 30000,
+ 'port': constants.SSH_PORT,
+ 'name': 'port_name',
+ 'protocol': 'TCP',
+ 'target_port': constants.SSH_PORT}
+ self.assertEqual(expected, service_ports[0])
+
+ @mock.patch.object(k8s_utils, 'get_service_by_name',
+ return_value=None)
+ def test__get_service_ports_exception(self, *args):
+ name = 'rc_name'
+ with self.assertRaises(exceptions.KubernetesServiceObjectNotDefined):
+ self.k8s_context._get_service_ports(name)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_model.py b/yardstick/tests/unit/benchmark/contexts/test_model.py
new file mode 100644
index 000000000..20cc00b4e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_model.py
@@ -0,0 +1,586 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.contexts.model
+
+from __future__ import absolute_import
+import unittest
+import mock
+
+from yardstick.benchmark.contexts import model
+
+
+class ObjectTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_context = mock.Mock()
+
+ def test_construct(self):
+
+ test_object = model.Object('foo', self.mock_context)
+
+ self.assertEqual(test_object.name, 'foo')
+ self.assertEqual(test_object._context, self.mock_context)
+ self.assertIsNone(test_object.stack_name)
+ self.assertIsNone(test_object.stack_id)
+
+ def test_dn(self):
+
+ self.mock_context.name = 'bar'
+ test_object = model.Object('foo', self.mock_context)
+
+ self.assertEqual('foo.bar', test_object.dn)
+
+
+class PlacementGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_context = mock.Mock()
+ self.mock_context.name = 'bar'
+
+ def tearDown(self):
+ model.PlacementGroup.map = {}
+
+ def test_sucessful_construct(self):
+
+ test_pg = model.PlacementGroup('foo', self.mock_context, 'affinity')
+
+ self.assertEqual(test_pg.name, 'foo')
+ self.assertEqual(test_pg.members, set())
+ self.assertEqual(test_pg.stack_name, 'bar-foo')
+ self.assertEqual(test_pg.policy, 'affinity')
+
+ test_map = {'foo': test_pg}
+ self.assertEqual(model.PlacementGroup.map, test_map)
+
+ def test_wrong_policy_in_construct(self):
+
+ self.assertRaises(ValueError, model.PlacementGroup, 'foo',
+ self.mock_context, 'baz')
+
+ def test_add_member(self):
+
+ test_pg = model.PlacementGroup('foo', self.mock_context, 'affinity')
+ test_pg.add_member('foo')
+
+ self.assertEqual(test_pg.members, set(['foo']))
+
+ def test_get_name_successful(self):
+
+ model.PlacementGroup.map = {'foo': True}
+ self.assertTrue(model.PlacementGroup.get('foo'))
+
+ def test_get_name_unsuccessful(self):
+
+ self.assertIsNone(model.PlacementGroup.get('foo'))
+
+
+class RouterTestCase(unittest.TestCase):
+
+ def test_construct(self):
+
+ mock_context = mock.Mock()
+ mock_context.name = 'baz'
+ test_router = model.Router('foo', 'bar', mock_context, 'qux')
+
+ self.assertEqual(test_router.stack_name, 'baz-bar-foo')
+ self.assertEqual(test_router.stack_if_name, 'baz-bar-foo-if0')
+ self.assertEqual(test_router.external_gateway_info, 'qux')
+
+
+class NetworkTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_context = mock.Mock()
+ self.mock_context.name = 'bar'
+
+ def tearDown(self):
+ model.Network.list = []
+
+ def test_construct_no_external_network(self):
+
+ attrs = {'cidr': '10.0.0.0/24'}
+ test_network = model.Network('foo', self.mock_context, attrs)
+
+ self.assertEqual(test_network.stack_name, 'bar-foo')
+ self.assertEqual(test_network.subnet_stack_name, 'bar-foo-subnet')
+ self.assertEqual(test_network.subnet_cidr, attrs['cidr'])
+ self.assertIsNone(test_network.router)
+ self.assertIn(test_network, model.Network.list)
+
+ def test_construct_has_external_network(self):
+
+ attrs = {'external_network': 'ext_net'}
+ test_network = model.Network('foo', self.mock_context, attrs)
+ exp_router = model.Router('router', 'foo', self.mock_context,
+ 'ext_net')
+
+ self.assertEqual(test_network.router.stack_name, exp_router.stack_name)
+ self.assertEqual(test_network.router.stack_if_name,
+ exp_router.stack_if_name)
+ self.assertEqual(test_network.router.external_gateway_info,
+ exp_router.external_gateway_info)
+
+ def test_has_route_to(self):
+
+ attrs = {'external_network': 'ext_net'}
+ test_network = model.Network('foo', self.mock_context, attrs)
+
+ self.assertTrue(test_network.has_route_to('ext_net'))
+
+ def test_has_no_route_to(self):
+
+ attrs = {}
+ test_network = model.Network('foo', self.mock_context, attrs)
+
+ self.assertFalse(test_network.has_route_to('ext_net'))
+
+ @mock.patch('yardstick.benchmark.contexts.model.Network.has_route_to')
+ def test_find_by_route_to(self, mock_has_route_to):
+
+ mock_network = mock.Mock()
+ model.Network.list = [mock_network]
+ mock_has_route_to.return_value = True
+
+ self.assertIs(mock_network, model.Network.find_by_route_to('foo'))
+
+ def test_find_external_network(self):
+
+ mock_network = mock.Mock()
+ mock_network.router = mock.Mock() #pylint ignore assignment-from-none
+ mock_network.router.external_gateway_info = 'ext_net'
+ model.Network.list = [mock_network]
+
+ self.assertEqual(model.Network.find_external_network(), 'ext_net')
+
+ def test_construct_gateway_ip_is_null(self):
+
+ attrs = {'gateway_ip': 'null'}
+ test_network = model.Network('foo', self.mock_context, attrs)
+ self.assertEqual(test_network.gateway_ip, 'null')
+
+ def test_construct_gateway_ip_is_none(self):
+
+ attrs = {'gateway_ip': None}
+ test_network = model.Network('foo', self.mock_context, attrs)
+ self.assertEqual(test_network.gateway_ip, 'null')
+
+ def test_construct_gateway_ip_is_absent(self):
+
+ attrs = {}
+ test_network = model.Network('foo', self.mock_context, attrs)
+ self.assertIsNone(test_network.gateway_ip)
+
+
+class ServerTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_context = mock.Mock()
+ self.mock_context.name = 'bar'
+ self.mock_context.keypair_name = 'some-keys'
+ self.mock_context.secgroup_name = 'some-secgroup'
+ self.mock_context.user = "some-user"
+ netattrs = {'cidr': '10.0.0.0/24', 'provider': None, 'external_network': 'ext_net'}
+ self.mock_context.networks = [model.Network("some-network", self.mock_context, netattrs)]
+
+ def test_construct_defaults(self):
+
+ attrs = None
+ test_server = model.Server('foo', self.mock_context, attrs)
+
+ self.assertEqual(test_server.stack_name, 'foo.bar')
+ self.assertEqual(test_server.keypair_name, 'some-keys')
+ self.assertEqual(test_server.secgroup_name, 'some-secgroup')
+ self.assertEqual(test_server.placement_groups, [])
+ self.assertIsNone(test_server.server_group)
+ self.assertEqual(test_server.instances, 1)
+ self.assertIsNone(test_server.floating_ip)
+ self.assertIsNone(test_server._image)
+ self.assertIsNone(test_server._flavor)
+ self.assertIn(test_server, model.Server.list)
+
+ @mock.patch('yardstick.benchmark.contexts.model.PlacementGroup')
+ def test_construct_get_wrong_placement_group(self, mock_pg):
+
+ attrs = {'placement': 'baz'}
+ mock_pg.get.return_value = None
+
+ self.assertRaises(ValueError, model.Server, 'foo',
+ self.mock_context, attrs)
+
+ @mock.patch('yardstick.benchmark.contexts.model.PlacementGroup')
+ def test_construct_get_wrong_server_group(self, mock_sg):
+
+ attrs = {'server_group': 'baz'}
+ mock_sg.get.return_value = None
+
+ self.assertRaises(ValueError, model.Server, 'foo',
+ self.mock_context, attrs)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance(self, mock_template):
+ attrs = {'image': 'some-image', 'flavor': 'some-flavor', 'floating_ip': '192.168.1.10',
+ 'floating_ip_assoc': 'some-vm',
+ 'availability_zone': 'zone'}
+ test_server = model.Server('foo', self.mock_context, attrs)
+
+ self.mock_context.flavors = ['flavor1', 'flavor2', 'some-flavor']
+
+ mock_network = mock.Mock()
+ mock_network.name = 'some-network'
+ mock_network.stack_name = 'some-network-stack'
+ mock_network.allowed_address_pairs = ["1", "2"]
+ mock_network.vnic_type = 'normal'
+ mock_network.subnet_stack_name = 'some-network-stack-subnet'
+ mock_network.provider = 'sriov'
+ mock_network.net_flags = {}
+ mock_network.external_network = 'ext_net'
+ mock_network.router = model.Router('some-router', 'some-network', self.mock_context,
+ 'ext_net')
+
+ test_server._add_instance(mock_template, 'some-server',
+ [mock_network], 'hints')
+
+ mock_template.add_port.assert_called_with(
+ 'some-server-some-network-port',
+ mock_network,
+ sec_group_id=self.mock_context.secgroup_name,
+ provider=mock_network.provider,
+ allowed_address_pairs=mock_network.allowed_address_pairs)
+
+ mock_template.add_floating_ip.assert_called_with(
+ 'some-server-fip',
+ mock_network.external_network,
+ 'some-server-some-network-port',
+ 'bar-some-network-some-router-if0',
+ 'some-secgroup'
+ )
+
+ mock_template.add_floating_ip_association.assert_called_with(
+ 'some-server-fip-assoc',
+ 'some-server-fip',
+ 'some-server-some-network-port'
+ )
+
+ mock_template.add_server.assert_called_with(
+ 'some-server', 'some-image',
+ flavor='some-flavor',
+ flavors=['flavor1', 'flavor2', 'some-flavor'],
+ ports=['some-server-some-network-port'],
+ user=self.mock_context.user,
+ key_name=self.mock_context.keypair_name,
+ user_data='',
+ scheduler_hints='hints',
+ availability_zone='zone')
+
+ def test_override_ip(self):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': [
+ {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
+ ],
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.interfaces = {
+ "xe0": {
+ "local_ip": "1.2.3.4",
+ "netmask": "255.255.255.0",
+ },
+ "xe1": {
+ "local_ip": "1.2.3.5",
+ "netmask": "255.255.255.0"
+ }
+ }
+ test_server.network_ports = network_ports
+
+ test_server.override_ip("uplink_0", {"port": "xe0"})
+ self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][0]["xe0"])
+
+ def test_override_ip_multiple(self):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': [
+ {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
+ {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
+ ],
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.interfaces = {
+ "xe0": {
+ "local_ip": "1.2.3.4",
+ "netmask": "255.255.255.0",
+ },
+ "xe1": {
+ "local_ip": "1.2.3.5",
+ "netmask": "255.255.255.0"
+ }
+ }
+ test_server.network_ports = network_ports
+ test_server.override_ip("uplink_0", {"port": "xe0"})
+ self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][0]["xe0"])
+
+ def test_override_ip_mixed(self):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': [
+ 'xe0',
+ {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
+ ],
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.interfaces = {
+ "xe0": {
+ "local_ip": "1.2.3.4",
+ "netmask": "255.255.255.0",
+ },
+ "xe1": {
+ "local_ip": "1.2.3.5",
+ "netmask": "255.255.255.0"
+ }
+ }
+ test_server.network_ports = network_ports
+ test_server.override_ip("uplink_0", {"port": "xe0"})
+ self.assertEqual(test_server.interfaces["xe0"], network_ports["uplink_0"][1]["xe0"])
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_with_ip_override_invalid_syntax(self, mock_template):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': 'xe0',
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.network_ports = network_ports
+ context = type("Context", (object,), {})
+ # can't use Mock because Mock.name is reserved
+ context.name = "context"
+ networks = [model.Network(n, context, {}) for n in network_ports]
+
+ with self.assertRaises(SyntaxError):
+ test_server._add_instance(mock_template, 'some-server',
+ networks, 'hints')
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_with_ip_override(self, mock_template):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': [
+ {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
+ ],
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.network_ports = network_ports
+ context = type("Context", (object,), {})
+ # can't use Mock because Mock.name is reserved
+ context.name = "context"
+ networks = [model.Network(n, context, {}) for n in network_ports]
+
+ test_server._add_instance(mock_template, 'some-server',
+ networks, 'hints')
+ self.assertEqual(test_server.ports, {
+ 'downlink_0': [{'port': 'xe1', 'stack_name': 'some-server-xe1-port'}],
+ 'mgmt': [{'port': 'mgmt', 'stack_name': 'some-server-mgmt-port'}],
+ 'uplink_0': [{'port': 'xe0', 'stack_name': 'some-server-xe0-port'}]
+ })
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_with_multiple_ip_override(self, mock_template):
+ network_ports = {
+ 'mgmt': ['mgmt'],
+ 'uplink_0': [
+ {'xe0': {'local_ip': '10.44.0.20', 'netmask': '255.255.255.0'}},
+ {'xe0': {'local_ip': '10.44.0.21', 'netmask': '255.255.255.0'}},
+ ],
+ 'downlink_0': [
+ {'xe1': {'local_ip': '10.44.0.30', 'netmask': '255.255.255.0'}},
+ ],
+ }
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+ test_server.network_ports = network_ports
+ context = type("Context", (object,), {})
+ # can't use Mock because Mock.name is reserved
+ context.name = "context"
+ networks = [model.Network(n, context, {}) for n in network_ports]
+
+ test_server._add_instance(mock_template, 'some-server',
+ networks, 'hints')
+ self.assertEqual(test_server.ports, {
+ 'downlink_0': [{'port': 'xe1', 'stack_name': 'some-server-xe1-port'}],
+ 'mgmt': [{'port': 'mgmt', 'stack_name': 'some-server-mgmt-port'}],
+ 'uplink_0': [{'port': 'xe0', 'stack_name': 'some-server-xe0-port'},
+ # this is not an error, we can produce this, it is left to Heat
+ # to detect duplicate ports and error
+ {'port': 'xe0', 'stack_name': 'some-server-xe0-port'}]
+ })
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_with_user_data(self, mock_template):
+ user_data = "USER_DATA"
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ 'user_data': user_data,
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+
+ test_server._add_instance(mock_template, 'some-server',
+ [], 'hints')
+
+ mock_template.add_server.assert_called_with(
+ 'some-server', 'some-image',
+ flavor='some-flavor',
+ flavors=self.mock_context.flavors,
+ ports=[],
+ user=self.mock_context.user,
+ key_name=self.mock_context.keypair_name,
+ user_data=user_data,
+ scheduler_hints='hints',
+ availability_zone=None)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_with_availablity_zone(self, mock_template):
+ attrs = {
+ 'image': 'some-image', 'flavor': 'some-flavor',
+ 'availability_zone': 'zone',
+ }
+ test_server = model.Server('foo', self.mock_context, attrs)
+
+ test_server._add_instance(mock_template, 'some-server',
+ [], 'hints')
+
+ mock_template.add_server.assert_called_with(
+ 'some-server', 'some-image',
+ flavor='some-flavor',
+ flavors=self.mock_context.flavors,
+ ports=[],
+ user=self.mock_context.user,
+ key_name=self.mock_context.keypair_name,
+ user_data='',
+ scheduler_hints='hints',
+ availability_zone='zone')
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_plus_flavor(self, mock_template):
+
+ user_data = ''
+ attrs = {
+ 'image': 'some-image', 'flavor': 'flavor1',
+ 'flavors': ['flavor2'], 'user_data': user_data
+ }
+ test_server = model.Server('ServerFlavor-2', self.mock_context, attrs)
+
+ self.mock_context.flavors = ['flavor2']
+ mock_network = mock.Mock()
+ mock_network.allowed_address_pairs = ["1", "2"]
+ mock_network.vnic_type = 'normal'
+ mock_network.net_flags = {}
+ mock_network.configure_mock(name='some-network', stack_name='some-network-stack',
+ subnet_stack_name='some-network-stack-subnet',
+ provider='some-provider')
+
+ test_server._add_instance(mock_template, 'ServerFlavor-2',
+ [mock_network], 'hints')
+
+ mock_template.add_port.assert_called_with(
+ 'ServerFlavor-2-some-network-port',
+ mock_network,
+ provider=mock_network.provider,
+ sec_group_id=self.mock_context.secgroup_name,
+ allowed_address_pairs=mock_network.allowed_address_pairs)
+
+ mock_template.add_server.assert_called_with(
+ 'ServerFlavor-2', 'some-image',
+ flavor='flavor1',
+ flavors=['flavor2'],
+ ports=['ServerFlavor-2-some-network-port'],
+ user=self.mock_context.user,
+ key_name=self.mock_context.keypair_name,
+ user_data=user_data,
+ scheduler_hints='hints',
+ availability_zone=None)
+
+ @mock.patch('yardstick.benchmark.contexts.heat.HeatTemplate')
+ def test__add_instance_misc(self, mock_template):
+
+ user_data = ''
+ attrs = {
+ 'image': 'some-image', 'flavor': 'flavor1',
+ 'flavors': ['flavor2'], 'user_data': user_data
+ }
+ test_server = model.Server('ServerFlavor-3', self.mock_context, attrs)
+
+ self.mock_context.flavors = ['flavor2']
+ self.mock_context.flavor = {'vcpus': 4}
+ mock_network = mock.Mock()
+ mock_network.name = 'some-network'
+ mock_network.stack_name = 'some-network-stack'
+ mock_network.subnet_stack_name = 'some-network-stack-subnet'
+ mock_network.net_flags = {}
+
+ test_server._add_instance(mock_template, 'ServerFlavor-3',
+ [mock_network], 'hints')
+
+ mock_template.add_port(
+ 'ServerFlavor-3-some-network-port',
+ mock_network.stack_name,
+ mock_network.subnet_stack_name,
+ sec_group_id=self.mock_context.secgroup_name)
+
+ mock_template.add_flavor(
+ vcpus=4,
+ ram=2048,
+ disk=1)
+
+ mock_template.add_flavor(
+ vcpus=4,
+ ram=2048,
+ disk=1,
+ extra_specs={'cat': 1, 'dog': 2, 'dragon': 1000})
+
+ mock_template.add_server.assert_called_with(
+ 'ServerFlavor-3', 'some-image',
+ flavor='flavor1',
+ flavors=['flavor2'],
+ ports=['ServerFlavor-3-some-network-port'],
+ user=self.mock_context.user,
+ key_name=self.mock_context.keypair_name,
+ user_data=user_data,
+ scheduler_hints='hints',
+ availability_zone=None)
diff --git a/yardstick/tests/unit/benchmark/contexts/test_node.py b/yardstick/tests/unit/benchmark/contexts/test_node.py
new file mode 100644
index 000000000..da16074d9
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/contexts/test_node.py
@@ -0,0 +1,392 @@
+##############################################################################
+# Copyright (c) 2015-2017 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 os
+import errno
+
+import mock
+import unittest
+
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts import node
+from yardstick.common import constants as consts
+from yardstick.common import exceptions
+from yardstick.common import yaml_loader
+
+
+class NodeContextTestCase(unittest.TestCase):
+
+ PREFIX = 'yardstick.benchmark.contexts.node'
+
+ NODES_SAMPLE = "nodes_sample.yaml"
+ NODES_DUPLICATE_SAMPLE = "nodes_duplicate_sample.yaml"
+
+ def setUp(self):
+ self.test_context = node.NodeContext()
+ self.addCleanup(self._remove_contexts)
+ self.os_path_join = os.path.join
+ self.attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ @staticmethod
+ def _remove_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+ base.Context.list = []
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = self.os_path_join(curr_path, filename)
+ return file_path
+
+ def test___init__(self):
+ self.assertIsNone(self.test_context._name)
+ self.assertIsNone(self.test_context.file_path)
+ self.assertEqual(self.test_context.nodes, [])
+ self.assertEqual(self.test_context.controllers, [])
+ self.assertEqual(self.test_context.computes, [])
+ self.assertEqual(self.test_context.baremetals, [])
+ self.assertEqual(self.test_context.env, {})
+ self.assertEqual(self.test_context.attrs, {})
+
+ @mock.patch.object(yaml_loader, 'read_yaml_file')
+ @mock.patch('{}.os.path.join'.format(PREFIX))
+ def test_init_negative(self, mock_path_join, read_mock):
+ special_path = '/foo/bar/error_file'
+ error_path = self._get_file_abspath("error_file")
+
+ def path_join(*args):
+ if args == (consts.YARDSTICK_ROOT_PATH, error_path):
+ return special_path
+ return self.os_path_join(*args)
+
+ # we can't count mock_path_join calls because
+ # it can catch join calls for .pyc files.
+ mock_path_join.side_effect = path_join
+ read_calls = 0
+
+ with self.assertRaises(KeyError):
+ self.test_context.init({})
+
+ self.assertEqual(read_mock.call_count, read_calls)
+
+ attrs = {
+ 'name': 'foo',
+ 'task_id': '1234567890',
+ 'file': error_path,
+ }
+ read_mock.side_effect = IOError(errno.EBUSY, 'busy')
+ with self.assertRaises(IOError) as raised:
+ self.test_context.init(attrs)
+
+ read_calls += 1
+ self.assertEqual(read_mock.call_count, read_calls)
+ self.assertIn(attrs['file'], self.test_context.file_path)
+ self.assertEqual(raised.exception.errno, errno.EBUSY)
+ self.assertEqual(str(raised.exception), str(read_mock.side_effect))
+
+ read_mock.side_effect = IOError(errno.ENOENT, 'not found')
+ with self.assertRaises(IOError) as raised:
+ self.test_context.init(attrs)
+
+ read_calls += 2
+ self.assertEqual(read_mock.call_count, read_calls)
+ self.assertEqual(self.test_context.file_path, special_path)
+ self.assertEqual(raised.exception.errno, errno.ENOENT)
+ self.assertEqual(str(raised.exception), str(read_mock.side_effect))
+
+ def test__dispatch_script(self):
+ self.test_context.init(self.attrs)
+
+ self.test_context.env = {'bash': [{'script': 'dummy'}]}
+ self.test_context._execute_script = mock.Mock()
+ self.assertEqual(self.test_context._dispatch_script('bash'), None)
+
+ def test__dispatch_ansible(self):
+ self.test_context.init(self.attrs)
+
+ self.test_context.env = {'ansible': [{'script': 'dummy'}]}
+ self.test_context._do_ansible_job = mock.Mock()
+ self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
+ self.test_context.env = {}
+ self.assertEqual(self.test_context._dispatch_ansible('ansible'), None)
+
+ @mock.patch("{}.AnsibleCommon".format(PREFIX))
+ def test__do_ansible_job(self, *args):
+ self.assertIsNone(self.test_context._do_ansible_job('dummy'))
+
+ def test_init(self):
+ self.test_context.init(self.attrs)
+
+ self.assertEqual(self.test_context.name, "foo-12345678")
+ self.assertEqual(len(self.test_context.nodes), 4)
+ self.assertEqual(len(self.test_context.controllers), 2)
+ self.assertEqual(len(self.test_context.computes), 1)
+ self.assertEqual(self.test_context.computes[0]["name"], "node3")
+ self.assertEqual(len(self.test_context.baremetals), 1)
+ self.assertEqual(self.test_context.baremetals[0]["name"], "node4")
+
+ def test__get_server_with_dict_attr_name(self):
+ self.test_context.init(self.attrs)
+ result = self.test_context._get_server({'name': 'node1.foo-12345678'})
+
+ self.assertIsNone(result, None)
+
+ def test__get_server_not_found(self):
+ self.test_context.init(self.attrs)
+
+ self.assertIsNone(self.test_context._get_server('bar.foo-12345678'))
+
+ def test__get_server_mismatch(self):
+ self.test_context.init(self.attrs)
+
+ self.assertIsNone(self.test_context._get_server('bar.foo1'))
+
+ def test__get_server_duplicate(self):
+ self.attrs['file'] = self._get_file_abspath(
+ self.NODES_DUPLICATE_SAMPLE)
+ self.test_context.init(self.attrs)
+
+ with self.assertRaises(ValueError):
+ self.test_context._get_server('node1.foo-12345678')
+
+ def test__get_server_found(self):
+ self.test_context.init(self.attrs)
+
+ result = self.test_context._get_server('node1.foo-12345678')
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ def test__get_physical_nodes(self):
+ self.test_context.init(self.attrs)
+ nodes = self.test_context._get_physical_nodes()
+ self.assertEqual(nodes, self.test_context.nodes)
+
+ def test__get_physical_node_for_server(self):
+ self.test_context.init(self.attrs)
+
+ # When server is not from this context
+ result = self.test_context._get_physical_node_for_server('node1.another-context')
+ self.assertIsNone(result)
+
+ # When node_name is not from this context
+ result = self.test_context._get_physical_node_for_server('fake.foo-12345678')
+ self.assertIsNone(result)
+
+ result = self.test_context._get_physical_node_for_server('node1.foo-12345678')
+ self.assertEqual(result, 'node1.foo')
+
+ def test_update_collectd_options_for_node(self):
+ self.test_context.init(self.attrs)
+ options = {'collectd': {'interval': 5}}
+
+ with self.assertRaises(exceptions.ContextUpdateCollectdForNodeError):
+ self.test_context.update_collectd_options_for_node(options, 'fake.foo-12345678')
+
+ self.test_context.update_collectd_options_for_node(options, 'node1.foo-12345678')
+
+ node_collectd_options = [node for node in self.test_context.nodes
+ if node['name'] == 'node1'][0]['collectd']
+
+ self.assertEqual(node_collectd_options, options)
+
+ @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
+ def test_deploy(self, dispatch_script_mock):
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj.env = {
+ 'type': 'script'
+ }
+ obj.deploy()
+ dispatch_script_mock.assert_called_once()
+
+ @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
+ def test_deploy_anisible(self, dispatch_ansible_mock):
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj.env = {
+ 'type': 'ansible'
+ }
+ obj.deploy()
+ dispatch_ansible_mock.assert_called_once()
+
+ @mock.patch('{}.NodeContext._dispatch_script'.format(PREFIX))
+ def test_undeploy(self, dispatch_script_mock):
+ obj = node.NodeContext()
+ obj.env = {
+ 'type': 'script'
+ }
+ obj.undeploy()
+ dispatch_script_mock.assert_called_once()
+
+ @mock.patch('{}.NodeContext._dispatch_ansible'.format(PREFIX))
+ def test_undeploy_anisble(self, dispatch_ansible_mock):
+ obj = node.NodeContext()
+ obj.env = {
+ 'type': 'ansible'
+ }
+ obj.undeploy()
+ dispatch_ansible_mock.assert_called_once()
+
+ @mock.patch('{}.ssh.SSH._put_file_shell'.format(PREFIX))
+ @mock.patch('{}.ssh.SSH.execute'.format(PREFIX))
+ def test_execute_remote_script(self, execute_mock, put_file_mock):
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj.env = {'prefix': 'yardstick.benchmark.scenarios.compute'}
+ node_name_args = 'node5'
+ obj.nodes = [{
+ 'name': node_name_args,
+ 'user': 'ubuntu',
+ 'ip': '10.10.10.10',
+ 'pwd': 'ubuntu',
+ }]
+
+ info = {'script': 'computecapacity.bash'}
+ execute_mock.return_value = (0, '', '')
+ obj._execute_remote_script('node5', info)
+
+ 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):
+ node_name = 'local'
+ info = {}
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj._execute_script(node_name, info)
+ local_execute_mock.assert_called_once()
+
+ @mock.patch('{}.NodeContext._execute_remote_script'.format(PREFIX))
+ def test_execute_script_remote(self, remote_execute_mock):
+ node_name = 'node5'
+ info = {}
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj._execute_script(node_name, info)
+ remote_execute_mock.assert_called_once()
+
+ def test_get_script(self):
+ script_args = 'hello.bash'
+ info_args = {
+ 'script': script_args
+ }
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ script, options = obj._get_script(info_args)
+ self.assertEqual(script_args, script)
+ self.assertEqual('', options)
+
+ def test_node_info(self):
+ node_name_args = 'node5'
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj.nodes = [{'name': node_name_args, 'check': node_name_args}]
+ node_info = obj._get_node_info(node_name_args)
+ self.assertEqual(node_info.get('check'), node_name_args)
+
+ @mock.patch('{}.ssh.SSH.wait'.format(PREFIX))
+ def test_get_client(self, wait_mock):
+ node_name_args = 'node5'
+ obj = node.NodeContext()
+ self.addCleanup(obj._delete_context)
+ obj.nodes = [{
+ 'name': node_name_args,
+ 'user': 'ubuntu',
+ 'ip': '10.10.10.10',
+ 'pwd': 'ubuntu',
+ }]
+ obj._get_client(node_name_args)
+ wait_mock.assert_called_once()
+
+ def test_get_server(self):
+ self.test_context.init(self.attrs)
+ self.test_context._name = 'foo'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.assertEqual('foo-12345678', self.test_context.name)
+ self.assertIsNotNone(self.test_context._task_id)
+
+ result = self.test_context.get_server('node1.foo-12345678')
+
+ self.assertEqual(result['ip'], '10.229.47.137')
+ self.assertEqual(result['name'], 'node1.foo-12345678')
+ self.assertEqual(result['user'], 'root')
+ self.assertEqual(result['key_filename'], '/root/.yardstick_key')
+
+ def test_get_server_server_not_in_context(self):
+ self.test_context.init(self.attrs)
+
+ with self.assertRaises(ValueError):
+ self.test_context.get_server('my2.foo-12345678')
+
+ def test_get_context_from_server(self):
+ self.test_context._name = 'vnf1'
+ self.test_context._task_id = '1234567890'
+ self.test_context._name_task_id = '{}-{}'.format(
+ self.test_context._name, self.test_context._task_id[:8])
+ self.test_context.nodes = [{'name': 'my', 'value': 100}]
+ self.test_context.attrs = {'attr1': 200}
+
+ self.assertIs(
+ self.test_context.get_context_from_server('my.vnf1-12345678'),
+ self.test_context)
+
+ # TODO: Split this into more granular tests
+ def test__get_network(self):
+ network1 = {
+ 'name': 'net_1',
+ 'vld_id': 'vld111',
+ 'segmentation_id': 'seg54',
+ 'network_type': 'type_a',
+ 'physical_network': 'phys',
+ }
+ network2 = {
+ 'name': 'net_2',
+ 'vld_id': 'vld999',
+ }
+ self.test_context.networks = {
+ 'a': network1,
+ 'b': network2,
+ }
+
+ attr_name = {}
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = {'vld_id': 'vld777'}
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ self.assertIsNone(self.test_context._get_network(None))
+
+ attr_name = 'vld777'
+ self.assertIsNone(self.test_context._get_network(attr_name))
+
+ attr_name = {'vld_id': 'vld999'}
+ expected = {
+ "name": 'net_2',
+ "vld_id": 'vld999',
+ "segmentation_id": None,
+ "network_type": None,
+ "physical_network": None,
+ }
+ result = self.test_context._get_network(attr_name)
+ self.assertDictEqual(result, expected)
+
+ attr_name = 'a'
+ expected = network1
+ result = self.test_context._get_network(attr_name)
+ self.assertDictEqual(result, expected)
diff --git a/yardstick/tests/unit/benchmark/core/__init__.py b/yardstick/tests/unit/benchmark/core/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/__init__.py
diff --git a/yardstick/tests/unit/benchmark/core/no_constraint_no_args_scenario_sample.yaml b/yardstick/tests/unit/benchmark/core/no_constraint_no_args_scenario_sample.yaml
new file mode 100644
index 000000000..44c4a31ff
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/no_constraint_no_args_scenario_sample.yaml
@@ -0,0 +1,21 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+---
+# Huawei US bare daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "os-nosdn-nofeature-ha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc037.yaml
+-
+ file_name: opnfv_yardstick_tc043.yaml
+
diff --git a/yardstick/tests/unit/benchmark/core/no_constraint_with_args_scenario_sample.yaml b/yardstick/tests/unit/benchmark/core/no_constraint_with_args_scenario_sample.yaml
new file mode 100644
index 000000000..ced13f19e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/no_constraint_with_args_scenario_sample.yaml
@@ -0,0 +1,23 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+---
+# Huawei US bare daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "os-nosdn-nofeature-ha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc037.yaml
+-
+ file_name: opnfv_yardstick_tc043.yaml
+ task_args:
+ huawei-pod1: '{"host": "node1.LF","target": "node2.LF"}'
+
diff --git a/yardstick/tests/unit/benchmark/core/test_plugin.py b/yardstick/tests/unit/benchmark/core/test_plugin.py
new file mode 100644
index 000000000..53621316b
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/test_plugin.py
@@ -0,0 +1,148 @@
+##############################################################################
+# 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 copy
+import os
+import pkg_resources
+
+import mock
+import six
+import testtools
+
+from yardstick import ssh
+from yardstick.benchmark.core import plugin
+from yardstick.tests import fixture
+
+
+class PluginTestCase(testtools.TestCase):
+
+ FILE = """
+schema: "yardstick:plugin:0.1"
+
+plugins:
+ name: sample
+
+deployment:
+ ip: 10.1.0.50
+ user: root
+ password: root
+"""
+
+ NAME = 'sample'
+ DEPLOYMENT = {'ip': '10.1.0.50', 'user': 'root', 'password': 'root'}
+
+ def setUp(self):
+ super(PluginTestCase, self).setUp()
+ self.plugin_parser = plugin.PluginParser(mock.Mock())
+ self.plugin = plugin.Plugin()
+ self.useFixture(fixture.PluginParserFixture(PluginTestCase.FILE))
+
+ self._mock_ssh_from_node = mock.patch.object(ssh.SSH, 'from_node')
+ self.mock_ssh_from_node = self._mock_ssh_from_node.start()
+ self.mock_ssh_obj = mock.Mock()
+ self.mock_ssh_from_node.return_value = self.mock_ssh_obj
+ self.mock_ssh_obj.wait = mock.Mock()
+ self.mock_ssh_obj._put_file_shell = mock.Mock()
+ self._mock_log_info = mock.patch.object(plugin.LOG, 'info')
+ self.mock_log_info = self._mock_log_info.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_ssh_from_node.stop()
+ self._mock_log_info.stop()
+
+ @mock.patch.object(six.moves.builtins, 'print')
+ def test_install(self, *args):
+ args = mock.Mock()
+ args.input_file = [mock.Mock()]
+ with mock.patch.object(self.plugin, '_install_setup') as \
+ mock_install, \
+ mock.patch.object(self.plugin, '_run') as mock_run:
+ self.plugin.install(args)
+ mock_install.assert_called_once_with(PluginTestCase.NAME,
+ PluginTestCase.DEPLOYMENT)
+ mock_run.assert_called_once_with(PluginTestCase.NAME)
+
+ @mock.patch.object(six.moves.builtins, 'print')
+ def test_remove(self, *args):
+ args = mock.Mock()
+ args.input_file = [mock.Mock()]
+ with mock.patch.object(self.plugin, '_remove_setup') as \
+ mock_remove, \
+ mock.patch.object(self.plugin, '_run') as mock_run:
+ self.plugin.remove(args)
+ mock_remove.assert_called_once_with(PluginTestCase.NAME,
+ PluginTestCase.DEPLOYMENT)
+ mock_run.assert_called_once_with(PluginTestCase.NAME)
+
+ @mock.patch.object(pkg_resources, 'resource_filename',
+ return_value='script')
+ def test__install_setup(self, mock_resource_filename):
+ plugin_name = 'plugin_name'
+ self.plugin._install_setup(plugin_name, PluginTestCase.DEPLOYMENT)
+ mock_resource_filename.assert_called_once_with(
+ 'yardstick.resources', 'scripts/install/' + plugin_name + '.bash')
+ self.mock_ssh_from_node.assert_called_once_with(
+ PluginTestCase.DEPLOYMENT)
+ self.mock_ssh_obj.wait.assert_called_once_with(timeout=600)
+ self.mock_ssh_obj._put_file_shell.assert_called_once_with(
+ 'script', '~/{0}.sh'.format(plugin_name))
+
+ @mock.patch.object(pkg_resources, 'resource_filename',
+ return_value='script')
+ @mock.patch.object(os, 'environ', return_value='1.2.3.4')
+ def test__install_setup_with_ip_local(self, mock_os_environ,
+ mock_resource_filename):
+ plugin_name = 'plugin_name'
+ deployment = copy.deepcopy(PluginTestCase.DEPLOYMENT)
+ deployment['ip'] = 'local'
+ self.plugin._install_setup(plugin_name, deployment)
+ mock_os_environ.__getitem__.assert_called_once_with('JUMP_HOST_IP')
+ mock_resource_filename.assert_called_once_with(
+ 'yardstick.resources',
+ 'scripts/install/' + plugin_name + '.bash')
+ self.mock_ssh_from_node.assert_called_once_with(
+ deployment, overrides={'ip': os.environ["JUMP_HOST_IP"]})
+ self.mock_ssh_obj.wait.assert_called_once_with(timeout=600)
+ self.mock_ssh_obj._put_file_shell.assert_called_once_with(
+ 'script', '~/{0}.sh'.format(plugin_name))
+
+ @mock.patch.object(pkg_resources, 'resource_filename',
+ return_value='script')
+ def test__remove_setup(self, mock_resource_filename):
+ plugin_name = 'plugin_name'
+ self.plugin._remove_setup(plugin_name, PluginTestCase.DEPLOYMENT)
+ mock_resource_filename.assert_called_once_with(
+ 'yardstick.resources',
+ 'scripts/remove/' + plugin_name + '.bash')
+ self.mock_ssh_from_node.assert_called_once_with(
+ PluginTestCase.DEPLOYMENT)
+ self.mock_ssh_obj.wait.assert_called_once_with(timeout=600)
+ self.mock_ssh_obj._put_file_shell.assert_called_once_with(
+ 'script', '~/{0}.sh'.format(plugin_name))
+
+ @mock.patch.object(pkg_resources, 'resource_filename',
+ return_value='script')
+ @mock.patch.object(os, 'environ', return_value='1.2.3.4')
+ def test__remove_setup_with_ip_local(self, mock_os_environ,
+ mock_resource_filename):
+ plugin_name = 'plugin_name'
+ deployment = copy.deepcopy(PluginTestCase.DEPLOYMENT)
+ deployment['ip'] = 'local'
+ self.plugin._remove_setup(plugin_name, deployment)
+ mock_os_environ.__getitem__.assert_called_once_with('JUMP_HOST_IP')
+ mock_resource_filename.assert_called_once_with(
+ 'yardstick.resources',
+ 'scripts/remove/' + plugin_name + '.bash')
+ self.mock_ssh_from_node.assert_called_once_with(
+ deployment, overrides={'ip': os.environ["JUMP_HOST_IP"]})
+ self.mock_ssh_obj.wait.assert_called_once_with(timeout=600)
+ self.mock_ssh_obj._put_file_shell.mock_os_environ(
+ 'script', '~/{0}.sh'.format(plugin_name))
diff --git a/yardstick/tests/unit/benchmark/core/test_report.py b/yardstick/tests/unit/benchmark/core/test_report.py
new file mode 100644
index 000000000..89fb1e90a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/test_report.py
@@ -0,0 +1,584 @@
+##############################################################################
+# Copyright (c) 2017 Rajesh Kudaka.
+# Copyright (c) 2018-2019 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 mock
+import six
+import unittest
+import uuid
+
+from api.utils import influx
+from yardstick.benchmark.core import report
+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_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,
+ None,
+ None,
+ None,
+ None,
+ 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):
+
+ def setUp(self):
+ self.jstree = report.JSTree()
+
+ def test__create_node(self):
+ _id = "tg__0.DropPackets"
+
+ expected_data = [
+ {"id": "tg__0", "text": "tg__0", "parent": "#"},
+ {"id": "tg__0.DropPackets", "text": "DropPackets", "parent": "tg__0"}
+ ]
+ self.jstree._create_node(_id)
+
+ self.assertEqual(self.jstree._created_nodes, ['#', 'tg__0', 'tg__0.DropPackets'])
+ self.assertEqual(self.jstree.jstree_data, expected_data)
+
+ def test_format_for_jstree(self):
+ data = [
+ '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 = [
+ {"id": "tg__0", "text": "tg__0", "parent": "#"},
+ {"id": "tg__0.DropPackets", "text": "DropPackets", "parent": "tg__0"},
+ {"id": "tg__0.LatencyAvg", "text": "LatencyAvg", "parent": "tg__0"},
+ {"id": "tg__0.LatencyAvg.5", "text": "5", "parent": "tg__0.LatencyAvg"},
+ {"id": "tg__0.LatencyAvg.6", "text": "6", "parent": "tg__0.LatencyAvg"},
+ {"id": "tg__0.LatencyMax", "text": "LatencyMax", "parent": "tg__0"},
+ {"id": "tg__0.LatencyMax.5", "text": "5", "parent": "tg__0.LatencyMax"},
+ {"id": "tg__0.LatencyMax.6", "text": "6", "parent": "tg__0.LatencyMax"},
+ {"id": "tg__0.RxThroughput", "text": "RxThroughput", "parent": "tg__0"},
+ {"id": "tg__0.TxThroughput", "text": "TxThroughput", "parent": "tg__0"},
+ {"id": "tg__1", "text": "tg__1", "parent": "#"},
+ {"id": "tg__1.DropPackets", "text": "DropPackets", "parent": "tg__1"},
+ {"id": "tg__1.LatencyAvg", "text": "LatencyAvg", "parent": "tg__1"},
+ {"id": "tg__1.LatencyAvg.5", "text": "5", "parent": "tg__1.LatencyAvg"},
+ {"id": "tg__1.LatencyAvg.6", "text": "6", "parent": "tg__1.LatencyAvg"},
+ {"id": "tg__1.LatencyMax", "text": "LatencyMax", "parent": "tg__1"},
+ {"id": "tg__1.LatencyMax.5", "text": "5", "parent": "tg__1.LatencyMax"},
+ {"id": "tg__1.LatencyMax.6", "text": "6", "parent": "tg__1.LatencyMax"},
+ {"id": "tg__1.RxThroughput", "text": "RxThroughput", "parent": "tg__1"},
+ {"id": "tg__1.TxThroughput", "text": "TxThroughput", "parent": "tg__1"},
+ {"id": "vnf__0", "text": "vnf__0", "parent": "#"},
+ {"id": "vnf__0.curr_packets_in", "text": "curr_packets_in", "parent": "vnf__0"},
+ {"id": "vnf__0.packets_dropped", "text": "packets_dropped", "parent": "vnf__0"},
+ {"id": "vnf__0.packets_fwd", "text": "packets_fwd", "parent": "vnf__0"},
+ ]
+
+ result = self.jstree.format_for_jstree(data)
+ self.assertEqual(expected_output, result)
+
+
+class ReportTestCase(unittest.TestCase):
+
+ def setUp(self):
+ super(ReportTestCase, self).setUp()
+ self.param = change_osloobj_to_paras({})
+ self.param.yaml_name = [GOOD_YAML_NAME]
+ self.param.task_id = [GOOD_TASK_ID]
+ self.rep = report.Report()
+
+ def test___init__(self):
+ self.assertEqual([], self.rep.Timestamp)
+ self.assertEqual("", self.rep.yaml_name)
+ self.assertEqual("", self.rep.task_id)
+
+ def test__validate(self):
+ self.rep._validate(GOOD_YAML_NAME, GOOD_TASK_ID)
+ self.assertEqual(GOOD_YAML_NAME, self.rep.yaml_name)
+ self.assertEqual(GOOD_TASK_ID, str(self.rep.task_id))
+
+ def test__validate_invalid_yaml_name(self):
+ with six.assertRaisesRegex(self, ValueError, "yaml*"):
+ self.rep._validate(BAD_YAML_NAME, GOOD_TASK_ID)
+
+ def test__validate_invalid_task_id(self):
+ with six.assertRaisesRegex(self, ValueError, "task*"):
+ self.rep._validate(GOOD_YAML_NAME, BAD_TASK_ID)
+
+ @mock.patch.object(influx, 'query')
+ def test__get_fieldkeys(self, mock_query):
+ mock_query.return_value = GOOD_DB_FIELDKEYS
+ self.rep.yaml_name = GOOD_YAML_NAME
+ self.rep.task_id = GOOD_TASK_ID
+ self.assertEqual(GOOD_DB_FIELDKEYS, self.rep._get_fieldkeys())
+
+ @mock.patch.object(influx, 'query')
+ def test__get_fieldkeys_nodbclient(self, mock_query):
+ mock_query.side_effect = RuntimeError
+ self.assertRaises(RuntimeError, self.rep._get_fieldkeys)
+
+ @mock.patch.object(influx, 'query')
+ def test__get_fieldkeys_testcase_not_found(self, mock_query):
+ mock_query.return_value = []
+ self.rep.yaml_name = GOOD_YAML_NAME
+ self.rep.task_id = GOOD_TASK_ID
+ six.assertRaisesRegex(self, KeyError, "Test case", self.rep._get_fieldkeys)
+
+ @mock.patch.object(influx, 'query')
+ 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_METRICS, self.rep._get_metrics())
+
+ @mock.patch.object(influx, '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
+ six.assertRaisesRegex(self, KeyError, "Task ID", self.rep._get_metrics)
+
+ @mock.patch.object(influx, 'query')
+ def test__get_task_start_time(self, mock_query):
+ self.rep.yaml_name = GOOD_YAML_NAME
+ self.rep.task_id = GOOD_TASK_ID
+ mock_query.return_value = [{
+ u'free.memory0.used': u'9789088',
+ u'free.memory0.available': u'22192984',
+ u'free.memory0.shared': u'219152',
+ u'time': u'2019-01-22T16:20:14.568075776Z',
+ }]
+ expected = "2019-01-22T16:20:14.568075776Z"
+
+ self.assertEqual(
+ expected,
+ self.rep._get_task_start_time()
+ )
+
+ def test__get_task_start_time_task_not_found(self):
+ pass
+
+ @mock.patch.object(influx, 'query')
+ def test__get_task_end_time(self, mock_query):
+ self.rep.yaml_name = GOOD_YAML_NAME
+ self.rep.task_id = GOOD_TASK_ID
+ # TODO(elfoley): write this test!
+ mock_query.return_value = [{
+
+ }]
+
+ @mock.patch.object(influx, 'query')
+ def test__get_baro_metrics(self, mock_query):
+ self.rep.yaml_name = GOOD_YAML_NAME
+ self.rep.task_id = GOOD_TASK_ID
+ self.rep._get_task_start_time = mock.Mock(return_value=0)
+ self.rep._get_task_end_time = mock.Mock(return_value=0)
+
+ influx_return_values = ([{
+ u'value': 324050, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:25.383698038Z',
+ u'type_instance': u'user', u'type': u'cpu',
+ }, {
+ u'value': 193798, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:25.383712594Z',
+ u'type_instance': u'system', u'type': u'cpu',
+ }, {
+ u'value': 324051, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:35.383696624Z',
+ u'type_instance': u'user', u'type': u'cpu',
+ }, {
+ u'value': 193800, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:35.383713481Z',
+ u'type_instance': u'system', u'type': u'cpu',
+ }, {
+ u'value': 324054, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:45.3836966789Z',
+ u'type_instance': u'user', u'type': u'cpu',
+ }, {
+ u'value': 193801, u'instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:45.383716296Z',
+ u'type_instance': u'system', u'type': u'cpu',
+ }],
+ [{
+ u'value': 3598453000, u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:25.383698038Z',
+ u'type_instance': u'0', u'type': u'cpufreq',
+ }, {
+ u'value': 3530250000, u'type_instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:35.383712594Z', u'type': u'cpufreq',
+ }, {
+ u'value': 3600281000, u'type_instance': u'0', u'host': u'myhostname',
+ u'time': u'2018-12-19T14:11:45.383696624Z', u'type': u'cpufreq',
+ }],
+ )
+
+ def ret_vals(vals):
+ for x in vals:
+ yield x
+ while True:
+ yield []
+
+ mock_query.side_effect = ret_vals(influx_return_values)
+
+ BARO_EXPECTED_METRICS = {
+ 'Timestamp': [
+ '14:11:25.3836', '14:11:25.3837',
+ '14:11:35.3836', '14:11:35.3837',
+ '14:11:45.3836', '14:11:45.3837'],
+ 'myhostname.cpu_value.cpu.user.0': {
+ '14:11:25.3836': 324050,
+ '14:11:35.3836': 324051,
+ '14:11:45.3836': 324054,
+ },
+ 'myhostname.cpu_value.cpu.system.0': {
+ '14:11:25.3837': 193798,
+ '14:11:35.3837': 193800,
+ '14:11:45.3837': 193801,
+ },
+ 'myhostname.cpufreq_value.cpufreq.0': {
+ '14:11:25.3836': 3598453000,
+ '14:11:35.3837': 3530250000,
+ '14:11:45.3836': 3600281000,
+ }
+ }
+ self.assertEqual(
+ BARO_EXPECTED_METRICS,
+ self.rep._get_baro_metrics()
+ )
+
+ def test__get_timestamps(self):
+
+ metrics = MORE_DB_METRICS
+ self.assertEqual(
+ MORE_TIMESTAMP,
+ self.rep._get_timestamps(metrics)
+ )
+
+ def test__format_datasets(self):
+ metric_name = "free.memory0.used"
+ metrics = [{
+ u'free.memory1.free': u'1958664',
+ u'free.memory0.used': u'9789560',
+ }, {
+ u'free.memory1.free': u'1958228',
+ u'free.memory0.used': u'9789790',
+ }, {
+ u'free.memory1.free': u'1956156',
+ u'free.memory0.used': u'9791092',
+ }, {
+ u'free.memory1.free': u'1956280',
+ u'free.memory0.used': u'9790796',
+ }]
+ self.assertEqual(
+ [9789560, 9789790, 9791092, 9790796,],
+ self.rep._format_datasets(metric_name, metrics)
+ )
+
+ def test__format_datasets_val_none(self):
+ metric_name = "free.memory0.used"
+ metrics = [{
+ u'free.memory1.free': u'1958664',
+ u'free.memory0.used': 9876543109876543210,
+ }, {
+ u'free.memory1.free': u'1958228',
+ }, {
+ u'free.memory1.free': u'1956156',
+ u'free.memory0.used': u'9791092',
+ }, {
+ u'free.memory1.free': u'1956280',
+ u'free.memory0.used': u'9790796',
+ }]
+
+ exp0 = 9876543109876543210 if six.PY3 else 9.876543109876543e+18
+ self.assertEqual(
+ [exp0, None, 9791092, 9790796],
+ self.rep._format_datasets(metric_name, metrics)
+ )
+
+ def test__format_datasets_val_incompatible(self):
+ metric_name = "free.memory0.used"
+ metrics = [{
+ u'free.memory0.used': "some incompatible value",
+ }, {
+ }]
+ self.assertEqual(
+ [None, None],
+ self.rep._format_datasets(metric_name, metrics)
+ )
+
+ def test__combine_times(self):
+ yard_times = [
+ '00:00:00.000000',
+ '00:00:01.000000',
+ '00:00:02.000000',
+ '00:00:06.000000',
+ '00:00:08.000000',
+ '00:00:09.000000',
+ ]
+ baro_times = [
+ '00:00:01.000000',
+ '00:00:03.000000',
+ '00:00:04.000000',
+ '00:00:05.000000',
+ '00:00:07.000000',
+ '00:00:10.000000',
+ ]
+ expected_combo = [
+ '00:00:00.000000',
+ '00:00:01.000000',
+ '00:00:02.000000',
+ '00:00:03.000000',
+ '00:00:04.000000',
+ '00:00:05.000000',
+ '00:00:06.000000',
+ '00:00:07.000000',
+ '00:00:08.000000',
+ '00:00:09.000000',
+ '00:00:10.000000',
+ ]
+
+ actual_combo = self.rep._combine_times(yard_times, baro_times)
+ self.assertEqual(len(expected_combo), len(actual_combo))
+
+ self.assertEqual(
+ expected_combo,
+ actual_combo,
+ )
+
+ def test__combine_times_2(self):
+ time1 = ['14:11:25.383698', '14:11:25.383712', '14:11:35.383696',]
+ time2 = [
+ '16:20:14.568075', '16:20:24.575083',
+ '16:20:34.580989', '16:20:44.586801', ]
+ time_exp = [
+ '14:11:25.383698', '14:11:25.383712', '14:11:35.383696',
+ '16:20:14.568075', '16:20:24.575083', '16:20:34.580989',
+ '16:20:44.586801',
+ ]
+ self.assertEqual(time_exp, self.rep._combine_times(time1, time2))
+
+ def test__combine_metrics(self):
+ BARO_METRICS = {
+ 'myhostname.cpu_value.cpu.user.0': {
+ '14:11:25.3836': 324050, '14:11:35.3836': 324051,
+ '14:11:45.3836': 324054,
+ },
+ 'myhostname.cpu_value.cpu.system.0': {
+ '14:11:25.3837': 193798, '14:11:35.3837': 193800,
+ '14:11:45.3837': 193801,
+ }
+ }
+ BARO_TIMES = [
+ '14:11:25.3836', '14:11:25.3837', '14:11:35.3836',
+ '14:11:35.3837', '14:11:45.3836', '14:11:45.3837',
+ ]
+ YARD_METRICS = {
+ 'free.memory9.free': {
+ '16:20:14.5680': 1958244, '16:20:24.5750': 1955964,
+ '16:20:34.5809': 1956040, '16:20:44.5868': 1956428,
+ },
+ 'free.memory7.used': {
+ '16:20:14.5680': 9789068, '16:20:24.5750': 9791284,
+ '16:20:34.5809': 9791228, '16:20:44.5868': 9790692,
+ },
+ 'free.memory2.total':{
+ '16:20:14.5680': 32671288, '16:20:24.5750': 32671288,
+ '16:20:34.5809': 32671288, '16:20:44.5868': 32671288,
+ },
+ 'free.memory7.free': {
+ '16:20:14.5680': 1958368, '16:20:24.5750': 1956104,
+ '16:20:34.5809': 1956040, '16:20:44.5868': 1956552,
+ },
+ 'free.memory1.used': {
+ '16:20:14.5680': 9788872, '16:20:24.5750': 9789212,
+ '16:20:34.5809': 9791168, '16:20:44.5868': 9790996,
+ },
+ }
+ YARD_TIMES = [
+ '16:20:14.5680', '16:20:24.5750',
+ '16:20:34.5809', '16:20:44.5868',
+ ]
+
+ expected_output = {
+ 'myhostname.cpu_value.cpu.user.0': [{
+ 'x': '14:11:25.3836', 'y': 324050, }, {
+ 'x': '14:11:35.3836', 'y': 324051, }, {
+ 'x': '14:11:45.3836', 'y': 324054, }],
+ 'myhostname.cpu_value.cpu.system.0' : [{
+ 'x': '14:11:25.3837', 'y': 193798, }, {
+ 'x': '14:11:35.3837', 'y': 193800, }, {
+ 'x': '14:11:45.3837', 'y': 193801, }],
+ 'free.memory9.free': [{
+ 'x': '16:20:14.5680', 'y': 1958244, }, {
+ 'x': '16:20:24.5750', 'y': 1955964, }, {
+ 'x': '16:20:34.5809', 'y': 1956040, }, {
+ 'x': '16:20:44.5868', 'y': 1956428, }],
+ 'free.memory7.used': [{
+ 'x': '16:20:14.5680', 'y': 9789068, }, {
+ 'x': '16:20:24.5750', 'y': 9791284, }, {
+ 'x': '16:20:34.5809', 'y': 9791228, }, {
+ 'x': '16:20:44.5868', 'y': 9790692, }],
+ 'free.memory2.total': [{
+ 'x': '16:20:14.5680', 'y': 32671288, }, {
+ 'x': '16:20:24.5750', 'y': 32671288, }, {
+ 'x': '16:20:34.5809', 'y': 32671288, }, {
+ 'x': '16:20:44.5868', 'y': 32671288, }],
+ 'free.memory7.free': [{
+ 'x': '16:20:14.5680', 'y': 1958368, }, {
+ 'x': '16:20:24.5750', 'y': 1956104, }, {
+ 'x': '16:20:34.5809', 'y': 1956040, }, {
+ 'x': '16:20:44.5868', 'y': 1956552, }],
+ 'free.memory1.used': [{
+ 'x': '16:20:14.5680', 'y': 9788872, }, {
+ 'x': '16:20:24.5750', 'y': 9789212, }, {
+ 'x': '16:20:34.5809', 'y': 9791168, }, {
+ 'x': '16:20:44.5868', 'y': 9790996, }],
+ }
+
+ actual_output, _, _ = self.rep._combine_metrics(
+ BARO_METRICS, BARO_TIMES, YARD_METRICS, YARD_TIMES
+ )
+ self.assertEquals(
+ sorted(expected_output.keys()),
+ sorted(actual_output.keys())
+ )
+
+ self.assertEquals(
+ expected_output,
+ actual_output,
+ )
+
+ @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_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_metrics.assert_called_once_with()
+ mock_keys.assert_called_once_with()
+ self.assertEqual(GOOD_TIMESTAMP, self.rep.Timestamp)
+
+ @mock.patch.object(report.Report, '_get_baro_metrics')
+ @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_metrics, mock_baro_metrics):
+
+ mock_metrics.return_value = GOOD_DB_METRICS
+ mock_keys.return_value = GOOD_DB_FIELDKEYS
+ BARO_METRICS = {
+ # TODO: is timestamp needed here?
+ 'Timestamp': [
+ '14:11:25.383698', '14:11:25.383712', '14:11:35.383696',
+ '14:11:35.383713', '14:11:45.383700', '14:11:45.383716'],
+ 'myhostname.cpu_value.cpu.user.0': {
+ '14:11:25.383698': 324050,
+ '14:11:35.383696': 324051,
+ '14:11:45.383700': 324054,
+ },
+ 'myhostname.cpu_value.cpu.system.0': {
+ '14:11:25.383712': 193798,
+ '14:11:35.383713': 193800,
+ '14:11:45.383716': 193801,
+ }
+ }
+ mock_baro_metrics.return_value = BARO_METRICS
+
+ self.rep.generate_nsb(self.param)
+ mock_valid.assert_called_once_with(GOOD_YAML_NAME, GOOD_TASK_ID)
+ 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/core/test_task.py b/yardstick/tests/unit/benchmark/core/test_task.py
new file mode 100644
index 000000000..0f09b3e59
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/test_task.py
@@ -0,0 +1,644 @@
+##############################################################################
+# Copyright (c) 2015 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 copy
+import io
+import logging
+import os
+import sys
+
+import mock
+import six
+from six.moves import builtins
+import unittest
+import uuid
+import collections
+
+from yardstick.benchmark.contexts import base
+from yardstick.benchmark.contexts import dummy
+from yardstick.benchmark.core import task
+from yardstick.common import constants as consts
+from yardstick.common import exceptions
+from yardstick.common import task_template
+from yardstick.common import utils
+
+
+class TaskTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_log = mock.patch.object(task, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_log.stop()
+
+ @mock.patch.object(base, 'Context')
+ def test_parse_nodes_with_context_same_context(self, mock_context):
+ scenario_cfg = {
+ "nodes": {
+ "host": "node1.LF",
+ "target": "node2.LF"
+ }
+ }
+ server_info = {
+ "ip": "10.20.0.3",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ mock_context.get_server.return_value = server_info
+
+ context_cfg = task.parse_nodes_with_context(scenario_cfg)
+
+ self.assertEqual(context_cfg["host"], server_info)
+ self.assertEqual(context_cfg["target"], server_info)
+
+ def test_set_dispatchers(self):
+ t = task.Task()
+ output_config = {"DEFAULT": {"dispatcher": "file, http"}}
+ t._set_dispatchers(output_config)
+ self.assertEqual(output_config, output_config)
+
+ @mock.patch.object(task, 'DispatcherBase')
+ def test__do_output(self, mock_dispatcher):
+ t = task.Task()
+ output_config = {"DEFAULT": {"dispatcher": "file, http"}}
+
+ dispatcher1 = mock.MagicMock()
+ dispatcher1.__dispatcher_type__ = 'file'
+
+ dispatcher2 = mock.MagicMock()
+ dispatcher2.__dispatcher_type__ = 'http'
+
+ mock_dispatcher.get = mock.MagicMock(return_value=[dispatcher1,
+ dispatcher2])
+ self.assertIsNone(t._do_output(output_config, {}))
+
+ @mock.patch.object(base, 'Context')
+ def test_parse_networks_from_nodes(self, mock_context):
+ nodes = {
+ 'node1': {
+ 'interfaces': {
+ 'mgmt': {
+ 'network_name': 'mgmt',
+ },
+ 'xe0': {
+ 'network_name': 'uplink_0',
+ },
+ 'xe1': {
+ 'network_name': 'downlink_0',
+ },
+ },
+ },
+ 'node2': {
+ 'interfaces': {
+ 'mgmt': {
+ 'network_name': 'mgmt',
+ },
+ 'uplink_0': {
+ 'network_name': 'uplink_0',
+ },
+ 'downlink_0': {
+ 'network_name': 'downlink_0',
+ },
+ },
+ },
+ }
+
+ mock_context.get_network.side_effect = iter([
+ None,
+ {
+ 'name': 'mgmt',
+ 'network_type': 'flat',
+ },
+ {},
+ {
+ 'name': 'uplink_0',
+ 'subnet_cidr': '10.20.0.0/16',
+ },
+ {
+ 'name': 'downlink_0',
+ 'segmentation_id': '1001',
+ },
+ {
+ 'name': 'uplink_1',
+ },
+ ])
+
+ # one for each interface
+ expected_get_network_calls = 6
+ expected = {
+ 'mgmt': {'name': 'mgmt', 'network_type': 'flat'},
+ 'uplink_0': {'name': 'uplink_0', 'subnet_cidr': '10.20.0.0/16'},
+ 'uplink_1': {'name': 'uplink_1'},
+ 'downlink_0': {'name': 'downlink_0', 'segmentation_id': '1001'},
+ }
+
+ networks = task.get_networks_from_nodes(nodes)
+ self.assertEqual(mock_context.get_network.call_count, expected_get_network_calls)
+ self.assertDictEqual(networks, expected)
+
+ @mock.patch.object(base, 'Context')
+ @mock.patch.object(task, 'base_runner')
+ def test_run(self, mock_base_runner, *args):
+ scenario = {
+ 'host': 'athena.demo',
+ 'target': 'ares.demo',
+ 'runner': {
+ 'duration': 60,
+ 'interval': 1,
+ 'type': 'Duration'
+ },
+ 'type': 'Ping'
+ }
+
+ t = task.Task()
+ runner = mock.Mock()
+ runner.join.return_value = 0
+ runner.get_output.return_value = {}
+ runner.get_result.return_value = []
+ mock_base_runner.Runner.get.return_value = runner
+ t._run([scenario], False, "yardstick.out")
+ runner.run.assert_called_once()
+
+ @mock.patch.object(base, 'Context')
+ @mock.patch.object(task, 'base_runner')
+ def test_run_ProxDuration(self, mock_base_runner, *args):
+ scenario = {
+ 'host': 'athena.demo',
+ 'target': 'ares.demo',
+ 'runner': {
+ 'duration': 60,
+ 'interval': 1,
+ 'sampled': 'yes',
+ 'confirmation': 1,
+ 'type': 'ProxDuration'
+ },
+ 'type': 'Ping'
+ }
+
+ t = task.Task()
+ runner = mock.Mock()
+ runner.join.return_value = 0
+ runner.get_output.return_value = {}
+ runner.get_result.return_value = []
+ mock_base_runner.Runner.get.return_value = runner
+ t._run([scenario], False, "yardstick.out")
+ runner.run.assert_called_once()
+
+ @mock.patch.object(os, 'environ')
+ def test_check_precondition(self, mock_os_environ):
+ cfg = {
+ 'precondition': {
+ 'installer_type': 'compass',
+ 'deploy_scenarios': 'os-nosdn',
+ 'pod_name': 'huawei-pod1'
+ }
+ }
+
+ t = task.TaskParser('/opt')
+ mock_os_environ.get.side_effect = ['compass',
+ 'os-nosdn',
+ 'huawei-pod1']
+ result = t._check_precondition(cfg)
+ self.assertTrue(result)
+
+ def test_parse_suite_no_constraint_no_args(self):
+ SAMPLE_SCENARIO_PATH = "no_constraint_no_args_scenario_sample.yaml"
+ t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
+ with mock.patch.object(os, 'environ',
+ new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
+ task_files, task_args, task_args_fnames = t.parse_suite()
+
+ self.assertEqual(task_files[0], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
+ self.assertEqual(task_files[1], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
+ self.assertIsNone(task_args[0])
+ self.assertIsNone(task_args[1])
+ self.assertIsNone(task_args_fnames[0])
+ self.assertIsNone(task_args_fnames[1])
+
+ def test_parse_suite_no_constraint_with_args(self):
+ SAMPLE_SCENARIO_PATH = "no_constraint_with_args_scenario_sample.yaml"
+ t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
+ with mock.patch.object(os, 'environ',
+ new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
+ task_files, task_args, task_args_fnames = t.parse_suite()
+
+ self.assertEqual(task_files[0], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
+ self.assertEqual(task_files[1], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
+ self.assertIsNone(task_args[0])
+ self.assertEqual(task_args[1],
+ '{"host": "node1.LF","target": "node2.LF"}')
+ self.assertIsNone(task_args_fnames[0])
+ self.assertIsNone(task_args_fnames[1])
+
+ def test_parse_suite_with_constraint_no_args(self):
+ SAMPLE_SCENARIO_PATH = "with_constraint_no_args_scenario_sample.yaml"
+ t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
+ with mock.patch.object(os, 'environ',
+ new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
+ task_files, task_args, task_args_fnames = t.parse_suite()
+ self.assertEqual(task_files[0], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
+ self.assertEqual(task_files[1], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
+ self.assertIsNone(task_args[0])
+ self.assertIsNone(task_args[1])
+ self.assertIsNone(task_args_fnames[0])
+ self.assertIsNone(task_args_fnames[1])
+
+ def test_parse_suite_with_constraint_with_args(self):
+ SAMPLE_SCENARIO_PATH = "with_constraint_with_args_scenario_sample.yaml"
+ t = task.TaskParser(self._get_file_abspath(SAMPLE_SCENARIO_PATH))
+ with mock.patch('os.environ',
+ new={'NODE_NAME': 'huawei-pod1', 'INSTALLER_TYPE': 'compass'}):
+ task_files, task_args, task_args_fnames = t.parse_suite()
+
+ self.assertEqual(task_files[0], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc037.yaml'))
+ self.assertEqual(task_files[1], self.change_to_abspath(
+ 'tests/opnfv/test_cases/opnfv_yardstick_tc043.yaml'))
+ self.assertIsNone(task_args[0])
+ self.assertEqual(task_args[1],
+ '{"host": "node1.LF","target": "node2.LF"}')
+ self.assertIsNone(task_args_fnames[0])
+ self.assertIsNone(task_args_fnames[1])
+
+ def test_parse_options(self):
+ options = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': '$network'
+ },
+ 'nodes': ['node1', '$node'],
+ 'host': '$host'
+ }
+
+ t = task.Task()
+ t.outputs = {
+ 'network': 'ext-net',
+ 'node': 'node2',
+ 'host': 'server.yardstick'
+ }
+
+ expected_result = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': 'ext-net'
+ },
+ 'nodes': ['node1', 'node2'],
+ 'host': 'server.yardstick'
+ }
+
+ actual_result = t._parse_options(options)
+ self.assertEqual(expected_result, actual_result)
+
+ def test_parse_options_no_teardown(self):
+ options = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': '$network'
+ },
+ 'nodes': ['node1', '$node'],
+ 'host': '$host',
+ 'contexts' : {'name': "my-context",
+ 'no_teardown': True}
+ }
+
+ t = task.Task()
+ t.outputs = {
+ 'network': 'ext-net',
+ 'node': 'node2',
+ 'host': 'server.yardstick'
+ }
+
+ expected_result = {
+ 'openstack': {
+ 'EXTERNAL_NETWORK': 'ext-net'
+ },
+ 'nodes': ['node1', 'node2'],
+ 'host': 'server.yardstick',
+ 'contexts': {'name': 'my-context',
+ 'no_teardown': True,
+ }
+ }
+
+ actual_result = t._parse_options(options)
+ self.assertEqual(expected_result, actual_result)
+
+ @mock.patch.object(builtins, 'open', side_effect=mock.mock_open())
+ @mock.patch.object(task, 'utils')
+ @mock.patch.object(logging, 'root')
+ def test_set_log(self, mock_logging_root, *args):
+ task_obj = task.Task()
+ task_obj.task_id = 'task_id'
+ task_obj._set_log()
+ mock_logging_root.addHandler.assert_called()
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def change_to_abspath(self, filepath):
+ return os.path.join(consts.YARDSTICK_ROOT_PATH, filepath)
+
+
+class TaskParserTestCase(unittest.TestCase):
+
+ TASK = """
+{% set value1 = value1 or 'var1' %}
+{% set value2 = value2 or 'var2' %}
+key1: {{ value1 }}
+key2:
+ - {{ value2 }}"""
+
+ TASK_RENDERED_1 = u"""
+
+
+key1: var1
+key2:
+ - var2"""
+
+ TASK_RENDERED_2 = u"""
+
+
+key1: var3
+key2:
+ - var4"""
+
+ def setUp(self):
+ self.parser = task.TaskParser('fake/path')
+ self.scenario = {
+ 'host': 'athena.demo',
+ 'target': 'kratos.demo',
+ 'targets': [
+ 'ares.demo', 'mars.demo'
+ ],
+ 'options': {
+ 'server_name': {
+ 'host': 'jupiter.demo',
+ 'target': 'saturn.demo',
+ },
+ },
+ 'nodes': {
+ 'tg__0': 'tg_0.demo',
+ 'vnf__0': 'vnf_0.demo',
+ }
+ }
+
+ @staticmethod
+ def _remove_contexts():
+ for context in base.Context.list:
+ context._delete_context()
+ base.Context.list = []
+
+ def test__change_node_names(self):
+
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890',
+ 'servers': [
+ 'athena', 'kratos',
+ 'ares', 'mars',
+ 'jupiter', 'saturn',
+ 'tg_0', 'vnf_0'
+ ]
+ }
+
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+
+ expected_scenario = {
+ 'host': 'athena.demo-12345678',
+ 'target': 'kratos.demo-12345678',
+ 'targets': [
+ 'ares.demo-12345678', 'mars.demo-12345678'
+ ],
+ 'options': {
+ 'server_name': {
+ 'host': 'jupiter.demo-12345678',
+ 'target': 'saturn.demo-12345678',
+ },
+ },
+ 'nodes': {
+ 'tg__0': 'tg_0.demo-12345678',
+ 'vnf__0': 'vnf_0.demo-12345678',
+ }
+ }
+
+ scenario = copy.deepcopy(self.scenario)
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertEqual(scenario, expected_scenario)
+
+ def test__change_node_names_context_not_found(self):
+ scenario = copy.deepcopy(self.scenario)
+ self.assertRaises(exceptions.ScenarioConfigContextNameNotFound,
+ self.parser._change_node_names,
+ scenario, [])
+
+ def test__change_node_names_context_name_unchanged(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890',
+ 'flags': {
+ 'no_setup': True,
+ 'no_teardown': True
+ }
+ }
+
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+
+ scenario = copy.deepcopy(self.scenario)
+ expected_scenario = copy.deepcopy(self.scenario)
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertEqual(scenario, expected_scenario)
+
+ def test__change_node_names_options_empty(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890'
+ }
+
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+ scenario = copy.deepcopy(self.scenario)
+ scenario['options'] = None
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertIsNone(scenario['options'])
+
+ def test__change_node_names_options_server_name_empty(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890'
+ }
+
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+ scenario = copy.deepcopy(self.scenario)
+ scenario['options']['server_name'] = None
+
+ self.parser._change_node_names(scenario, [my_context])
+ self.assertIsNone(scenario['options']['server_name'])
+
+ def test__change_node_names_target_map(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890'
+ }
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+ scenario = copy.deepcopy(self.scenario)
+ scenario['nodes'] = {
+ 'tg__0': {
+ 'name': 'tg__0.demo',
+ 'public_ip_attr': "1.1.1.1",
+ },
+ 'vnf__0': {
+ 'name': 'vnf__0.demo',
+ 'public_ip_attr': "2.2.2.2",
+ }
+ }
+ self.parser._change_node_names(scenario, [my_context])
+ for target in scenario['nodes'].values():
+ self.assertIsInstance(target, collections.Mapping)
+
+ def test__change_node_names_not_target_map(self):
+ ctx_attrs = {
+ 'name': 'demo',
+ 'task_id': '1234567890'
+ }
+ my_context = dummy.DummyContext()
+ self.addCleanup(self._remove_contexts)
+ my_context.init(ctx_attrs)
+ scenario = copy.deepcopy(self.scenario)
+ self.parser._change_node_names(scenario, [my_context])
+ for target in scenario['nodes'].values():
+ self.assertNotIsInstance(target, collections.Mapping)
+
+ def test__parse_tasks(self):
+ task_obj = task.Task()
+ _uuid = uuid.uuid4()
+ task_obj.task_id = _uuid
+ task_files = ['/directory/task_file_name.yml']
+ mock_parser = mock.Mock()
+ mock_parser.parse_task.return_value = {'rendered': 'File content'}
+ mock_args = mock.Mock()
+ mock_args.render_only = False
+
+ tasks = task_obj._parse_tasks(mock_parser, task_files, mock_args,
+ ['arg1'], ['file_arg1'])
+ self.assertEqual(
+ [{'rendered': 'File content', 'case_name': 'task_file_name'}],
+ tasks)
+ mock_parser.parse_task.assert_called_once_with(
+ _uuid, 'arg1', 'file_arg1')
+
+ @mock.patch.object(sys, 'exit')
+ @mock.patch.object(utils, 'write_file')
+ @mock.patch.object(utils, 'makedirs')
+ def test__parse_tasks_render_only(self, mock_makedirs, mock_write_file,
+ mock_exit):
+ task_obj = task.Task()
+ _uuid = uuid.uuid4()
+ task_obj.task_id = _uuid
+ task_files = ['/directory/task_file_name.yml']
+ mock_parser = mock.Mock()
+ mock_parser.parse_task.return_value = {'rendered': 'File content'}
+ mock_args = mock.Mock()
+ mock_args.render_only = '/output_directory'
+
+ task_obj._parse_tasks(mock_parser, task_files, mock_args,
+ ['arg1'], ['file_arg1'])
+ mock_makedirs.assert_called_once_with('/output_directory')
+ mock_write_file.assert_called_once_with(
+ '/output_directory/000-task_file_name.yml', 'File content')
+ mock_exit.assert_called_once_with(0)
+
+ def test__render_task_no_args(self):
+ task_parser = task.TaskParser('task_file')
+ task_str = io.StringIO(six.text_type(self.TASK))
+ with mock.patch.object(six.moves.builtins, 'open',
+ return_value=task_str) as mock_open:
+ parsed, rendered = task_parser._render_task(None, None)
+
+ self.assertEqual(self.TASK_RENDERED_1, rendered)
+ self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
+ mock_open.assert_called_once_with('task_file')
+
+ def test__render_task_arguments(self):
+ task_parser = task.TaskParser('task_file')
+ task_str = io.StringIO(six.text_type(self.TASK))
+ with mock.patch.object(six.moves.builtins, 'open',
+ return_value=task_str) as mock_open:
+ parsed, rendered = task_parser._render_task('value1: "var1"', None)
+
+ self.assertEqual(self.TASK_RENDERED_1, rendered)
+ self.assertEqual({'key1': 'var1', 'key2': ['var2']}, parsed)
+ mock_open.assert_called_once_with('task_file')
+
+ def test__render_task_file_arguments(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ io.StringIO(six.text_type(self.TASK))
+ )
+ parsed, rendered = task_parser._render_task('value1: "var3"',
+ 'args_file')
+
+ self.assertEqual(self.TASK_RENDERED_2, rendered)
+ self.assertEqual({'key1': 'var3', 'key2': ['var4']}, parsed)
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+
+ @mock.patch.object(builtins, 'print')
+ def test__render_task_error_arguments(self, *args):
+ with self.assertRaises(exceptions.TaskRenderArgumentError):
+ task.TaskParser('task_file')._render_task('value1="var3"', None)
+
+ def test__render_task_error_task_file(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ IOError()
+ )
+ with self.assertRaises(exceptions.TaskReadError):
+ task_parser._render_task('value1: "var3"', 'args_file')
+
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+
+ def test__render_task_render_error(self):
+ task_parser = task.TaskParser('task_file')
+ with mock.patch.object(six.moves.builtins, 'open') as mock_open, \
+ mock.patch.object(task_template.TaskTemplate, 'render',
+ side_effect=TypeError) as mock_render:
+ mock_open.side_effect = (
+ io.StringIO(six.text_type('value2: var4')),
+ io.StringIO(six.text_type(self.TASK))
+ )
+ with self.assertRaises(exceptions.TaskRenderError):
+ task_parser._render_task('value1: "var3"', 'args_file')
+
+ mock_open.assert_has_calls([mock.call('args_file'),
+ mock.call('task_file')])
+ mock_render.assert_has_calls(
+ [mock.call(self.TASK, value1='var3', value2='var4')])
diff --git a/yardstick/tests/unit/benchmark/core/test_testcase.py b/yardstick/tests/unit/benchmark/core/test_testcase.py
new file mode 100644
index 000000000..077848d77
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/test_testcase.py
@@ -0,0 +1,35 @@
+##############################################################################
+# Copyright (c) 2015 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 mock
+from six.moves import builtins
+
+from yardstick.benchmark.core import testcase
+from yardstick.tests.unit import base as ut_base
+
+
+class Arg(object):
+
+ def __init__(self):
+ self.casename = ('opnfv_yardstick_tc001', )
+
+
+class TestcaseTestCase(ut_base.BaseUnitTestCase):
+
+ def test_list_all(self):
+ t = testcase.Testcase()
+ result = t.list_all("")
+ self.assertIsInstance(result, list)
+
+ @mock.patch.object(builtins, 'print')
+ def test_show(self, *args):
+ t = testcase.Testcase()
+ casename = Arg()
+ result = t.show(casename)
+ self.assertTrue(result)
diff --git a/yardstick/tests/unit/benchmark/core/with_constraint_no_args_scenario_sample.yaml b/yardstick/tests/unit/benchmark/core/with_constraint_no_args_scenario_sample.yaml
new file mode 100644
index 000000000..168d4b01a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/with_constraint_no_args_scenario_sample.yaml
@@ -0,0 +1,24 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+---
+# Huawei US bare daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "os-nosdn-nofeature-ha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc037.yaml
+-
+ file_name: opnfv_yardstick_tc043.yaml
+ constraint:
+ installer: compass
+ pod: huawei-pod1
+
diff --git a/yardstick/tests/unit/benchmark/core/with_constraint_with_args_scenario_sample.yaml b/yardstick/tests/unit/benchmark/core/with_constraint_with_args_scenario_sample.yaml
new file mode 100644
index 000000000..299e5de56
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/core/with_constraint_with_args_scenario_sample.yaml
@@ -0,0 +1,26 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+---
+# Huawei US bare daily task suite
+
+schema: "yardstick:suite:0.1"
+
+name: "os-nosdn-nofeature-ha"
+test_cases_dir: "tests/opnfv/test_cases/"
+test_cases:
+-
+ file_name: opnfv_yardstick_tc037.yaml
+-
+ file_name: opnfv_yardstick_tc043.yaml
+ constraint:
+ installer: compass
+ pod: huawei-pod1
+ task_args:
+ huawei-pod1: '{"host": "node1.LF","target": "node2.LF"}'
+
diff --git a/yardstick/tests/unit/benchmark/runner/__init__.py b/yardstick/tests/unit/benchmark/runner/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/__init__.py
diff --git a/yardstick/tests/unit/benchmark/runner/test_arithmetic.py b/yardstick/tests/unit/benchmark/runner/test_arithmetic.py
new file mode 100644
index 000000000..35d935cd5
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_arithmetic.py
@@ -0,0 +1,446 @@
+##############################################################################
+# Copyright (c) 2018 Nokia 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 mock
+import unittest
+import multiprocessing
+import os
+import time
+
+from yardstick.benchmark.runners import arithmetic
+from yardstick.common import exceptions as y_exc
+
+
+class ArithmeticRunnerTest(unittest.TestCase):
+ class MyMethod(object):
+ SLA_VALIDATION_ERROR_SIDE_EFFECT = 1
+ BROAD_EXCEPTION_SIDE_EFFECT = 2
+
+ def __init__(self, side_effect=0):
+ self.count = 101
+ self.side_effect = side_effect
+
+ def __call__(self, data):
+ self.count += 1
+ data['my_key'] = self.count
+ if self.side_effect == self.SLA_VALIDATION_ERROR_SIDE_EFFECT:
+ raise y_exc.SLAValidationError(case_name='My Case',
+ error_msg='my error message')
+ elif self.side_effect == self.BROAD_EXCEPTION_SIDE_EFFECT:
+ raise y_exc.YardstickException
+ return self.count
+
+ def setUp(self):
+ self.scenario_cfg = {
+ 'runner': {
+ 'interval': 0,
+ 'iter_type': 'nested_for_loops',
+ 'iterators': [
+ {
+ 'name': 'stride',
+ 'start': 64,
+ 'stop': 128,
+ 'step': 64
+ },
+ {
+ 'name': 'size',
+ 'start': 500,
+ 'stop': 2000,
+ 'step': 500
+ }
+ ]
+ },
+ 'type': 'some_type'
+ }
+
+ self.benchmark = mock.Mock()
+ self.benchmark_cls = mock.Mock(return_value=self.benchmark)
+
+ def _assert_defaults__worker_process_run_setup_and_teardown(self):
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_called_once()
+
+ @mock.patch.object(os, 'getpid')
+ @mock.patch.object(multiprocessing, 'Process')
+ def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+ mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ runner = arithmetic.ArithmeticRunner({})
+ benchmark_cls = mock.Mock()
+ runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+ {})
+ mock_multiprocessing_process.assert_called_once_with(
+ name='Arithmetic-some_type-101',
+ target=arithmetic._worker_process,
+ args=(runner.result_queue, benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, runner.aborted, runner.output_queue))
+
+ @mock.patch.object(os, 'getpid')
+ def test__worker_process_runner_id(self, mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.assertEqual(self.scenario_cfg['runner']['runner_id'], 101)
+
+ @mock.patch.object(time, 'sleep')
+ def test__worker_process_calls_nested_for_loops(self, mock_time_sleep):
+ self.scenario_cfg['runner']['interval'] = 99
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.benchmark.my_method.assert_has_calls([mock.call({})] * 8)
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ mock_time_sleep.assert_has_calls([mock.call(99)] * 8)
+ self.assertEqual(mock_time_sleep.call_count, 8)
+
+ @mock.patch.object(time, 'sleep')
+ def test__worker_process_calls_tuple_loops(self, mock_time_sleep):
+ self.scenario_cfg['runner']['interval'] = 99
+ self.scenario_cfg['runner']['iter_type'] = 'tuple_loops'
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.benchmark.my_method.assert_has_calls([mock.call({})] * 2)
+ self.assertEqual(self.benchmark.my_method.call_count, 2)
+ mock_time_sleep.assert_has_calls([mock.call(99)] * 2)
+ self.assertEqual(mock_time_sleep.call_count, 2)
+
+ def test__worker_process_stored_options_nested_for_loops(self):
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_stored_options_tuple_loops(self):
+ self.scenario_cfg['runner']['iter_type'] = 'tuple_loops'
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 1000})
+
+ def test__worker_process_aborted_set_early(self):
+ aborted = multiprocessing.Event()
+ aborted.set()
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ aborted, mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.scenario_cfg['options'], {})
+ self.benchmark.my_method.assert_not_called()
+
+ def test__worker_process_output_queue_nested_for_loops(self):
+ self.benchmark.my_method = self.MyMethod()
+
+ output_queue = multiprocessing.Queue()
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ result = []
+ while not output_queue.empty():
+ result.append(output_queue.get())
+ self.assertListEqual(result, [102, 103, 104, 105, 106, 107, 108, 109])
+
+ def test__worker_process_output_queue_tuple_loops(self):
+ self.scenario_cfg['runner']['iter_type'] = 'tuple_loops'
+ self.benchmark.my_method = self.MyMethod()
+
+ output_queue = multiprocessing.Queue()
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 103)
+ result = []
+ while not output_queue.empty():
+ result.append(output_queue.get())
+ self.assertListEqual(result, [102, 103])
+
+ def test__worker_process_queue_nested_for_loops(self):
+ self.benchmark.my_method = self.MyMethod()
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+
+ def test__worker_process_queue_tuple_loops(self):
+ self.scenario_cfg['runner']['iter_type'] = 'tuple_loops'
+ self.benchmark.my_method = self.MyMethod()
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 103)
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+
+ def test__worker_process_except_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_on_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+ self.assertEqual(count, 8)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_except_sla_validation_error_sla_cfg_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_sla_validation_error_sla_cfg_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertEqual(result['errors'],
+ ('My Case SLA validation failed. '
+ 'Error: my error message',))
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+ self.assertGreater(result['timestamp'], timestamp)
+ timestamp = result['timestamp']
+ self.assertEqual(count, 8)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.my_method.assert_called_once()
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_not_called()
+
+ def test__worker_process_output_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ with self.assertRaisesRegexp(
+ y_exc.SLAValidationError,
+ 'My Case SLA validation failed. Error: my error message'):
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.assertEqual(self.benchmark.my_method.count, 102)
+ self.benchmark.teardown.assert_not_called()
+ self.assertTrue(queue.empty())
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_broad_exception_no_sla_cfg_early_exit(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.benchmark.my_method.assert_called_once()
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 64, 'size': 500})
+
+ def test__worker_process_output_on_broad_exception_no_sla_cfg(self):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 102)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 64, 'size': 500})
+ self.assertEqual(queue.qsize(), 1)
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['data'], {'my_key': 102})
+ self.assertRegexpMatches(
+ result['errors'],
+ 'YardstickException: An unknown exception occurred.')
+ self.assertEqual(result['sequence'], 1)
+ self.assertTrue(output_queue.empty())
+
+ def test__worker_process_broad_exception_sla_cfg_not_none(self):
+ self.scenario_cfg['sla'] = {'action': 'some action'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+
+ def test__worker_process_output_on_broad_exception_sla_cfg_not_none(self):
+ self.scenario_cfg['sla'] = {'action': 'some action'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ output_queue = multiprocessing.Queue()
+ timestamp = time.time()
+ arithmetic._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.01)
+
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.count, 109)
+ self.assertDictEqual(self.scenario_cfg['options'],
+ {'stride': 128, 'size': 2000})
+ self.assertTrue(output_queue.empty())
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertRegexpMatches(
+ result['errors'],
+ 'YardstickException: An unknown exception occurred.')
+ self.assertEqual(result['sequence'], count)
+
+ def test__worker_process_benchmark_teardown_on_broad_exception(self):
+ self.benchmark.teardown = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ with self.assertRaises(SystemExit) as raised:
+ arithmetic._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ self.assertEqual(raised.exception.code, 1)
+ self._assert_defaults__worker_process_run_setup_and_teardown()
+ self.assertEqual(self.benchmark.my_method.call_count, 8)
diff --git a/yardstick/tests/unit/benchmark/runner/test_base.py b/yardstick/tests/unit/benchmark/runner/test_base.py
new file mode 100644
index 000000000..07d6f1843
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_base.py
@@ -0,0 +1,119 @@
+##############################################################################
+# Copyright (c) 2017 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 time
+
+import mock
+import subprocess
+
+from yardstick.benchmark.runners import base as runner_base
+from yardstick.benchmark.runners import iteration
+from yardstick.tests.unit import base as ut_base
+
+
+class ActionTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self._mock_log = mock.patch.object(runner_base.log, 'error')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_log.stop()
+
+ @mock.patch.object(subprocess, 'check_output')
+ def test__execute_shell_command(self, mock_subprocess):
+ mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+ self.assertEqual(runner_base._execute_shell_command("")[0], -1)
+
+ @mock.patch.object(subprocess, 'check_output')
+ def test__single_action(self, mock_subprocess):
+ mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+ runner_base._single_action(0, 'echo', mock.Mock())
+
+ @mock.patch.object(subprocess, 'check_output')
+ def test__periodic_action(self, mock_subprocess):
+ mock_subprocess.side_effect = subprocess.CalledProcessError(-1, '')
+ runner_base._periodic_action(0, 'echo', mock.Mock())
+
+
+class ScenarioOutputTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self.output_queue = mock.Mock()
+ self.scenario_output = runner_base.ScenarioOutput(self.output_queue,
+ sequence=1)
+
+ @mock.patch.object(time, 'time')
+ def test_push(self, mock_time):
+ mock_time.return_value = 2
+ data = {"value1": 1}
+ self.scenario_output.push(data)
+ self.output_queue.put.assert_called_once_with({'timestamp': 2,
+ 'sequence': 1,
+ 'data': data}, True, 10)
+
+ def test_push_no_timestamp(self):
+ self.scenario_output["value1"] = 1
+ self.scenario_output.push(None, False)
+ self.output_queue.put.assert_called_once_with({'sequence': 1,
+ 'value1': 1}, True, 10)
+
+
+class RunnerTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ config = {
+ 'output_config': {
+ 'DEFAULT': {
+ 'dispatcher': 'file'
+ }
+ }
+ }
+ self.runner = iteration.IterationRunner(config)
+
+ @mock.patch("yardstick.benchmark.runners.iteration.multiprocessing")
+ def test_get_output(self, *args):
+ self.runner.output_queue.put({'case': 'opnfv_yardstick_tc002'})
+ self.runner.output_queue.put({'criteria': 'PASS'})
+
+ idle_result = {
+ 'case': 'opnfv_yardstick_tc002',
+ 'criteria': 'PASS'
+ }
+
+ for _ in range(1000):
+ time.sleep(0.01)
+ if not self.runner.output_queue.empty():
+ break
+ actual_result = self.runner.get_output()
+ self.assertEqual(idle_result, actual_result)
+
+ @mock.patch("yardstick.benchmark.runners.iteration.multiprocessing")
+ def test_get_result(self, *args):
+ self.runner.result_queue.put({'case': 'opnfv_yardstick_tc002'})
+ self.runner.result_queue.put({'criteria': 'PASS'})
+
+ idle_result = [
+ {'case': 'opnfv_yardstick_tc002'},
+ {'criteria': 'PASS'}
+ ]
+
+ for _ in range(1000):
+ time.sleep(0.01)
+ if not self.runner.result_queue.empty():
+ break
+ actual_result = self.runner.get_result()
+ self.assertEqual(idle_result, actual_result)
+
+ def test__run_benchmark(self):
+ runner = runner_base.Runner(mock.Mock())
+
+ with self.assertRaises(NotImplementedError):
+ runner._run_benchmark(mock.Mock(), mock.Mock(), mock.Mock(), mock.Mock())
diff --git a/yardstick/tests/unit/benchmark/runner/test_duration.py b/yardstick/tests/unit/benchmark/runner/test_duration.py
new file mode 100644
index 000000000..fa47e96bf
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_duration.py
@@ -0,0 +1,315 @@
+##############################################################################
+# Copyright (c) 2018 Nokia 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 mock
+import unittest
+import multiprocessing
+import os
+import time
+
+from yardstick.benchmark.runners import duration
+from yardstick.common import exceptions as y_exc
+
+
+class DurationRunnerTest(unittest.TestCase):
+ class MyMethod(object):
+ SLA_VALIDATION_ERROR_SIDE_EFFECT = 1
+ BROAD_EXCEPTION_SIDE_EFFECT = 2
+
+ def __init__(self, side_effect=0):
+ self.count = 101
+ self.side_effect = side_effect
+
+ def __call__(self, data):
+ self.count += 1
+ data['my_key'] = self.count
+ if self.side_effect == self.SLA_VALIDATION_ERROR_SIDE_EFFECT:
+ raise y_exc.SLAValidationError(case_name='My Case',
+ error_msg='my error message')
+ elif self.side_effect == self.BROAD_EXCEPTION_SIDE_EFFECT:
+ raise y_exc.YardstickException
+ return self.count
+
+ def setUp(self):
+ self.scenario_cfg = {
+ 'runner': {'interval': 0, "duration": 0},
+ 'type': 'some_type'
+ }
+
+ self.benchmark = mock.Mock()
+ self.benchmark_cls = mock.Mock(return_value=self.benchmark)
+
+ def _assert_defaults__worker_run_setup_and_teardown(self):
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_called_once()
+
+ def _assert_defaults__worker_run_one_iteration(self):
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.my_method.assert_called_once_with({})
+ self.benchmark.post_run_wait_time.assert_called_once_with(0)
+
+ @mock.patch.object(os, 'getpid')
+ @mock.patch.object(multiprocessing, 'Process')
+ def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+ mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ runner = duration.DurationRunner({})
+ benchmark_cls = mock.Mock()
+ runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+ {})
+ mock_multiprocessing_process.assert_called_once_with(
+ name='Duration-some_type-101',
+ target=duration._worker_process,
+ args=(runner.result_queue, benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, runner.aborted, runner.output_queue))
+
+ @mock.patch.object(os, 'getpid')
+ def test__worker_process_runner_id(self, mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.assertEqual(self.scenario_cfg['runner']['runner_id'], 101)
+
+ def test__worker_process_called_with_cfg(self):
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
+
+ def test__worker_process_called_with_cfg_loop(self):
+ self.scenario_cfg['runner']['duration'] = 0.01
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.call_count, 0)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
+
+ def test__worker_process_called_without_cfg(self):
+ scenario_cfg = {'runner': {}}
+ aborted = multiprocessing.Event()
+ aborted.set()
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ scenario_cfg, {}, aborted, mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(1)
+ self.benchmark.my_method.assert_called_once_with({})
+ self.benchmark.post_run_wait_time.assert_called_once_with(1)
+ self.benchmark.teardown.assert_called_once()
+
+ def test__worker_process_output_queue(self):
+ self.benchmark.my_method = mock.Mock(return_value='my_result')
+
+ output_queue = multiprocessing.Queue()
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
+ self.assertEquals(output_queue.get(), 'my_result')
+
+ def test__worker_process_output_queue_multiple_iterations(self):
+ self.scenario_cfg['runner']['duration'] = 0.01
+ self.benchmark.my_method = self.MyMethod()
+
+ output_queue = multiprocessing.Queue()
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), output_queue)
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.count, 1)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
+
+ count = 101
+ while not output_queue.empty():
+ count += 1
+ self.assertEquals(output_queue.get(), count)
+
+ def test__worker_process_queue(self):
+ self.benchmark.my_method = self.MyMethod()
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ duration._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.post_run_wait_time.assert_called_once_with(0)
+
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': 102})
+ self.assertEqual(result['sequence'], 1)
+
+ def test__worker_process_queue_multiple_iterations(self):
+ self.scenario_cfg['runner']['duration'] = 0.5
+ self.benchmark.my_method = self.MyMethod()
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ duration._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.assertGreater(self.benchmark.pre_run_wait_time.call_count, 0)
+ self.assertGreater(self.benchmark.my_method.count, 1)
+ self.assertGreater(self.benchmark.post_run_wait_time.call_count, 0)
+
+ count = 0
+ while not queue.empty():
+ count += 1
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': count + 101})
+ self.assertEqual(result['sequence'], count)
+
+ def test__worker_process_except_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
+
+ def test__worker_process_except_sla_validation_error_sla_cfg_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_default(self):
+ self.scenario_cfg['sla'] = {}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ duration._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.my_method.assert_called_once_with({})
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ duration._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.my_method.assert_called_once_with({})
+
+ def test__worker_process_queue_on_sla_validation_error_monitor(self):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ duration._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.post_run_wait_time.assert_called_once_with(0)
+
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertEqual(result['errors'], ('My Case SLA validation failed. '
+ 'Error: my error message',))
+ self.assertEqual(result['data'], {'my_key': 102})
+ self.assertEqual(result['sequence'], 1)
+
+ def test__worker_process_broad_exception(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ duration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
+
+ def test__worker_process_queue_on_broad_exception(self):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+
+ queue = multiprocessing.Queue()
+ timestamp = time.time()
+ duration._worker_process(queue, self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ time.sleep(0.1)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.post_run_wait_time.assert_called_once_with(0)
+
+ result = queue.get()
+ self.assertGreater(result['timestamp'], timestamp)
+ self.assertNotEqual(result['errors'], '')
+ self.assertEqual(result['data'], {'my_key': 102})
+ self.assertEqual(result['sequence'], 1)
+
+ def test__worker_process_benchmark_teardown_on_broad_exception(self):
+ self.benchmark.teardown = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ with self.assertRaises(SystemExit) as raised:
+ duration._worker_process(mock.Mock(), self.benchmark_cls,
+ 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+ self.assertEqual(raised.exception.code, 1)
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self._assert_defaults__worker_run_one_iteration()
diff --git a/yardstick/tests/unit/benchmark/runner/test_iteration.py b/yardstick/tests/unit/benchmark/runner/test_iteration.py
new file mode 100644
index 000000000..783b236f5
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_iteration.py
@@ -0,0 +1,45 @@
+##############################################################################
+# 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
+##############################################################################
+
+import mock
+import unittest
+import multiprocessing
+from yardstick.benchmark.runners import iteration
+from yardstick.common import exceptions as y_exc
+
+
+class IterationRunnerTest(unittest.TestCase):
+ def setUp(self):
+ self.scenario_cfg = {
+ 'runner': {'interval': 0, "duration": 0},
+ 'type': 'some_type'
+ }
+
+ self.benchmark = mock.Mock()
+ self.benchmark_cls = mock.Mock(return_value=self.benchmark)
+
+ def _assert_defaults__worker_run_setup_and_teardown(self):
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+
+ def _assert_defaults__worker_run_one_iteration(self):
+ self.benchmark.pre_run_wait_time.assert_called_once_with(0)
+ self.benchmark.my_method.assert_called_once_with({})
+
+ def test__worker_process_broad_exception(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+
+ with self.assertRaises(Exception):
+ iteration._worker_process(mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_one_iteration()
+ self._assert_defaults__worker_run_setup_and_teardown()
diff --git a/yardstick/tests/unit/benchmark/runner/test_proxduration.py b/yardstick/tests/unit/benchmark/runner/test_proxduration.py
new file mode 100644
index 000000000..056195fd3
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_proxduration.py
@@ -0,0 +1,286 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+import unittest
+import multiprocessing
+import os
+
+from yardstick.benchmark.runners import proxduration
+from yardstick.common import constants
+from yardstick.common import exceptions as y_exc
+
+
+class ProxDurationRunnerTest(unittest.TestCase):
+
+ class MyMethod(object):
+ SLA_VALIDATION_ERROR_SIDE_EFFECT = 1
+ BROAD_EXCEPTION_SIDE_EFFECT = 2
+
+ def __init__(self, side_effect=0):
+ self.count = 101
+ self.side_effect = side_effect
+
+ def __call__(self, data):
+ self.count += 1
+ data['my_key'] = self.count
+ if self.side_effect == self.SLA_VALIDATION_ERROR_SIDE_EFFECT:
+ raise y_exc.SLAValidationError(case_name='My Case',
+ error_msg='my error message')
+ elif self.side_effect == self.BROAD_EXCEPTION_SIDE_EFFECT:
+ raise y_exc.YardstickException
+ return self.count
+
+ def setUp(self):
+ self.scenario_cfg = {
+ 'runner': {'interval': 0, "duration": 0},
+ 'type': 'some_type'
+ }
+
+ self.benchmark = mock.Mock()
+ self.benchmark_cls = mock.Mock(return_value=self.benchmark)
+
+ def _assert_defaults__worker_run_setup_and_teardown(self):
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_called_once()
+
+ @mock.patch.object(os, 'getpid')
+ @mock.patch.object(multiprocessing, 'Process')
+ def test__run_benchmark_called_with(self, mock_multiprocessing_process,
+ mock_os_getpid):
+ mock_os_getpid.return_value = 101
+
+ runner = proxduration.ProxDurationRunner({})
+ benchmark_cls = mock.Mock()
+ runner._run_benchmark(benchmark_cls, 'my_method', self.scenario_cfg,
+ {})
+ mock_multiprocessing_process.assert_called_once_with(
+ name='ProxDuration-some_type-101',
+ target=proxduration._worker_process,
+ args=(runner.result_queue, benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, runner.aborted, runner.output_queue))
+
+ @mock.patch.object(os, 'getpid')
+ def test__worker_process_runner_id(self, mock_os_getpid):
+ mock_os_getpid.return_value = 101
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), mock.Mock())
+
+ self.assertEqual(101, self.scenario_cfg['runner']['runner_id'])
+
+ def test__worker_process_called_with_cfg(self):
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+
+ def test__worker_process_called_with_cfg_loop(self):
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ self.assertGreater(self.benchmark.my_method.call_count, 0)
+
+ def test__worker_process_called_without_cfg(self):
+ scenario_cfg = {'runner': {}}
+ aborted = multiprocessing.Event()
+ aborted.set()
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', scenario_cfg, {},
+ aborted, mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.teardown.assert_called_once()
+
+ def test__worker_process_output_queue(self):
+ self.benchmark.my_method = mock.Mock(return_value='my_result')
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ output_queue = mock.Mock()
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), output_queue)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ output_queue.put.assert_has_calls(
+ [mock.call('my_result', True, constants.QUEUE_PUT_TIMEOUT)])
+
+ def test__worker_process_output_queue_multiple_iterations(self):
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.benchmark.my_method = self.MyMethod()
+ output_queue = mock.Mock()
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), output_queue)
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ for idx in range(102, 101 + len(output_queue.method_calls)):
+ output_queue.put.assert_has_calls(
+ [mock.call(idx, True, constants.QUEUE_PUT_TIMEOUT)])
+
+ def test__worker_process_queue(self):
+ self.benchmark.my_method = self.MyMethod()
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ queue = mock.Mock()
+ proxduration._worker_process(
+ queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ benchmark_output = {'timestamp': mock.ANY,
+ 'sequence': 1,
+ 'data': {'my_key': 102},
+ 'errors': ''}
+ queue.put.assert_has_calls(
+ [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+ def test__worker_process_queue_multiple_iterations(self):
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.benchmark.my_method = self.MyMethod()
+ queue = mock.Mock()
+ proxduration._worker_process(
+ queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ for idx in range(102, 101 + len(queue.method_calls)):
+ benchmark_output = {'timestamp': mock.ANY,
+ 'sequence': idx - 101,
+ 'data': {'my_key': idx},
+ 'errors': ''}
+ queue.put.assert_has_calls(
+ [mock.call(benchmark_output, True,
+ constants.QUEUE_PUT_TIMEOUT)])
+
+ def test__worker_process_except_sla_validation_error_no_sla_cfg(self):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+
+ @mock.patch.object(proxduration.LOG, 'warning')
+ def test__worker_process_except_sla_validation_error_sla_cfg_monitor(
+ self, *args):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method', self.scenario_cfg,
+ {}, multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_default(self):
+ self.scenario_cfg['sla'] = {}
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+ with self.assertRaises(y_exc.SLAValidationError):
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.my_method.assert_called_once_with({})
+
+ def test__worker_process_raise_sla_validation_error_sla_cfg_assert(self):
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.scenario_cfg['sla'] = {'action': 'assert'}
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+ self.benchmark_cls.assert_called_once_with(self.scenario_cfg, {})
+ self.benchmark.setup.assert_called_once()
+ self.benchmark.my_method.assert_called_once_with({})
+
+ @mock.patch.object(proxduration.LOG, 'warning')
+ def test__worker_process_queue_on_sla_validation_error_monitor(
+ self, *args):
+ self.scenario_cfg['sla'] = {'action': 'monitor'}
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.SLA_VALIDATION_ERROR_SIDE_EFFECT)
+ queue = mock.Mock()
+ proxduration._worker_process(
+ queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+ benchmark_output = {'timestamp': mock.ANY,
+ 'sequence': 1,
+ 'data': {'my_key': 102},
+ 'errors': ('My Case SLA validation failed. '
+ 'Error: my error message', )}
+ queue.put.assert_has_calls(
+ [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+ @mock.patch.object(proxduration.LOG, 'exception')
+ def test__worker_process_broad_exception(self, *args):
+ self.benchmark.my_method = mock.Mock(
+ side_effect=y_exc.YardstickException)
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+
+ self._assert_defaults__worker_run_setup_and_teardown()
+
+ @mock.patch.object(proxduration.LOG, 'exception')
+ def test__worker_process_queue_on_broad_exception(self, *args):
+ self.benchmark.my_method = self.MyMethod(
+ side_effect=self.MyMethod.BROAD_EXCEPTION_SIDE_EFFECT)
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+ queue = mock.Mock()
+ proxduration._worker_process(
+ queue, self.benchmark_cls, 'my_method', self.scenario_cfg, {},
+ multiprocessing.Event(), mock.Mock())
+
+ benchmark_output = {'timestamp': mock.ANY,
+ 'sequence': 1,
+ 'data': {'my_key': 102},
+ 'errors': mock.ANY}
+ queue.put.assert_has_calls(
+ [mock.call(benchmark_output, True, constants.QUEUE_PUT_TIMEOUT)])
+
+ @mock.patch.object(proxduration.LOG, 'exception')
+ def test__worker_process_benchmark_teardown_on_broad_exception(
+ self, *args):
+ self.benchmark.teardown = mock.Mock(
+ side_effect=y_exc.YardstickException)
+ self.scenario_cfg["runner"] = {"sampled": True, "duration": 0.1}
+
+ with self.assertRaises(SystemExit) as raised:
+ proxduration._worker_process(
+ mock.Mock(), self.benchmark_cls, 'my_method',
+ self.scenario_cfg, {}, multiprocessing.Event(), mock.Mock())
+ self.assertEqual(1, raised.exception.code)
+ self._assert_defaults__worker_run_setup_and_teardown()
diff --git a/yardstick/tests/unit/benchmark/runner/test_search.py b/yardstick/tests/unit/benchmark/runner/test_search.py
new file mode 100644
index 000000000..d5d1b8ded
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/runner/test_search.py
@@ -0,0 +1,192 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import time
+
+import mock
+import unittest
+
+from yardstick.benchmark.runners.search import SearchRunner
+from yardstick.benchmark.runners.search import SearchRunnerHelper
+from yardstick.common import exceptions as y_exc
+
+
+class TestSearchRunnerHelper(unittest.TestCase):
+
+ def test___call__(self):
+ scenario_cfg = {
+ 'runner': {},
+ }
+
+ benchmark = mock.Mock()
+ method = getattr(benchmark(), 'my_method')
+ helper = SearchRunnerHelper(
+ benchmark, 'my_method', scenario_cfg, {}, mock.Mock())
+
+ with helper.get_benchmark_instance():
+ helper()
+
+ method.assert_called_once()
+
+ def test___call___error(self):
+ scenario_cfg = {
+ 'runner': {},
+ }
+
+ helper = SearchRunnerHelper(
+ mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
+
+ with self.assertRaises(RuntimeError):
+ helper()
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(time, 'time')
+ def test_is_not_done(self, mock_time, *args):
+ scenario_cfg = {
+ 'runner': {},
+ }
+
+ mock_time.side_effect = range(1000)
+
+ helper = SearchRunnerHelper(
+ mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
+
+ index = -1
+ for index in helper.is_not_done():
+ if index >= 10:
+ break
+
+ self.assertGreaterEqual(index, 10)
+
+ @mock.patch.object(time, 'sleep')
+ def test_is_not_done_immediate_stop(self, *args):
+ scenario_cfg = {
+ 'runner': {
+ 'run_step': '',
+ },
+ }
+
+ helper = SearchRunnerHelper(
+ mock.Mock(), 'my_method', scenario_cfg, {}, mock.Mock())
+
+ index = -1
+ for index in helper.is_not_done():
+ if index >= 10:
+ break
+
+ self.assertEqual(index, -1)
+
+
+class TestSearchRunner(unittest.TestCase):
+
+ def test__worker_run_once(self):
+ def update(*args):
+ args[-1].update(data)
+
+ data = {
+ 'key1': {
+ 'inner1': 'value1',
+ 'done': 0,
+ },
+ 'key2': {
+ 'done': None,
+ },
+ }
+
+ runner = SearchRunner({})
+ runner.worker_helper = mock.Mock(side_effect=update)
+
+ self.assertFalse(runner._worker_run_once('sequence 1'))
+
+ def test__worker_run_once_done(self):
+ def update(*args):
+ args[-1].update(data)
+
+ data = {
+ 'key1': {
+ 'inner1': 'value1',
+ 'done': 0,
+ },
+ 'key2': {
+ 'done': None,
+ },
+ 'key3': {
+ 'done': True,
+ },
+ 'key4': [],
+ 'key5': 'value5',
+ }
+
+ runner = SearchRunner({})
+ runner.worker_helper = mock.Mock(side_effect=update)
+
+ self.assertTrue(runner._worker_run_once('sequence 1'))
+
+ def test__worker_run_once_assertion_error_assert(self):
+ runner = SearchRunner({})
+ runner.sla_action = 'assert'
+ runner.worker_helper = mock.Mock(side_effect=y_exc.SLAValidationError)
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ runner._worker_run_once('sequence 1')
+
+ def test__worker_run_once_assertion_error_monitor(self):
+ runner = SearchRunner({})
+ runner.sla_action = 'monitor'
+ runner.worker_helper = mock.Mock(side_effect=y_exc.SLAValidationError)
+
+ self.assertFalse(runner._worker_run_once('sequence 1'))
+
+ def test__worker_run_once_non_assertion_error_none(self):
+ runner = SearchRunner({})
+ runner.worker_helper = mock.Mock(side_effect=RuntimeError)
+
+ self.assertTrue(runner._worker_run_once('sequence 1'))
+
+ def test__worker_run_once_non_assertion_error(self):
+ runner = SearchRunner({})
+ runner.sla_action = 'monitor'
+ runner.worker_helper = mock.Mock(side_effect=RuntimeError)
+
+ self.assertFalse(runner._worker_run_once('sequence 1'))
+
+ def test__worker_run(self):
+ scenario_cfg = {
+ 'runner': {'interval': 0, 'timeout': 1},
+ }
+
+ runner = SearchRunner({})
+ runner._worker_run_once = mock.Mock(side_effect=[0, 0, 1])
+
+ runner._worker_run(mock.Mock(), 'my_method', scenario_cfg, {})
+
+ def test__worker_run_immediate_stop(self):
+ scenario_cfg = {
+ 'runner': {
+ 'run_step': '',
+ },
+ }
+
+ runner = SearchRunner({})
+ runner._worker_run(mock.Mock(), 'my_method', scenario_cfg, {})
+
+ @mock.patch('yardstick.benchmark.runners.search.multiprocessing')
+ def test__run_benchmark(self, mock_multi_process):
+ scenario_cfg = {
+ 'runner': {},
+ }
+
+ runner = SearchRunner({})
+ runner._run_benchmark(mock.Mock(), 'my_method', scenario_cfg, {})
+ mock_multi_process.Process.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/__init__.py b/yardstick/tests/unit/benchmark/scenarios/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/__init__.py b/yardstick/tests/unit/benchmark/scenarios/availability/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py
new file mode 100644
index 000000000..35455a49c
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_baremetal.py
@@ -0,0 +1,93 @@
+##############################################################################
+# Copyright (c) 2015 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.attacker import \
+ attacker_baremetal
+
+
+class ExecuteShellTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_subprocess = mock.patch.object(attacker_baremetal,
+ 'subprocess')
+ self.mock_subprocess = self._mock_subprocess.start()
+
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_subprocess.stop()
+
+ def test__execute_shell_command_successful(self):
+ self.mock_subprocess.check_output.return_value = (0, 'unittest')
+ exitcode, _ = attacker_baremetal._execute_shell_command("env")
+ self.assertEqual(exitcode, 0)
+
+ @mock.patch.object(attacker_baremetal, 'LOG')
+ def test__execute_shell_command_fail_cmd_exception(self, mock_log):
+ self.mock_subprocess.check_output.side_effect = RuntimeError
+ exitcode, _ = attacker_baremetal._execute_shell_command("env")
+ self.assertEqual(exitcode, -1)
+ mock_log.error.assert_called_once()
+
+
+class AttackerBaremetalTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_ssh = mock.patch.object(attacker_baremetal, 'ssh')
+ self.mock_ssh = self._mock_ssh.start()
+ self._mock_subprocess = mock.patch.object(attacker_baremetal,
+ 'subprocess')
+ self.mock_subprocess = self._mock_subprocess.start()
+ self.addCleanup(self._stop_mocks)
+
+ self.mock_ssh.SSH.from_node().execute.return_value = (
+ 0, "running", '')
+
+ host = {
+ "ipmi_ip": "10.20.0.5",
+ "ipmi_user": "root",
+ "ipmi_password": "123456",
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.attacker_cfg = {
+ 'fault_type': 'bear-metal-down',
+ 'host': 'node1',
+ }
+
+ self.ins = attacker_baremetal.BaremetalAttacker(self.attacker_cfg,
+ self.context)
+
+ def _stop_mocks(self):
+ self._mock_ssh.stop()
+ self._mock_subprocess.stop()
+
+ def test__attacker_baremetal_all_successful(self):
+ self.ins.setup()
+ self.ins.inject_fault()
+ self.ins.recover()
+
+ def test__attacker_baremetal_check_failure(self):
+ self.mock_ssh.SSH.from_node().execute.return_value = (
+ 0, "error check", '')
+ self.ins.setup()
+
+ def test__attacker_baremetal_recover_successful(self):
+ self.attacker_cfg["jump_host"] = 'node1'
+ self.context["node1"]["password"] = "123456"
+ ins = attacker_baremetal.BaremetalAttacker(self.attacker_cfg,
+ self.context)
+
+ ins.setup()
+ ins.recover()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py
new file mode 100644
index 000000000..c1b3c0d72
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_general.py
@@ -0,0 +1,56 @@
+##############################################################################
+# Copyright (c) 2016 Juan Qiu and others
+# juan_ qiu@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.attacker
+# .attacker_general
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.attacker import baseattacker
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.attacker.'
+ 'attacker_general.ssh')
+class GeneralAttackerServiceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.attacker_cfg = {
+ 'fault_type': 'general-attacker',
+ 'action_parameter': {'process_name': 'nova_api'},
+ 'rollback_parameter': {'process_name': 'nova_api'},
+ 'key': 'stop-service',
+ 'attack_key': 'stop-service',
+ 'host': 'node1',
+ }
+
+ def test__attacker_service_all_successful(self, mock_ssh):
+
+ cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg)
+ ins = cls(self.attacker_cfg, self.context)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "running", '')
+ ins.setup()
+ ins.inject_fault()
+ ins.recover()
+
+ def test__attacker_service_check_failuer(self, mock_ssh):
+
+ cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg)
+ ins = cls(self.attacker_cfg, self.context)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "error check", '')
+ ins.setup()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py
new file mode 100644
index 000000000..2e9f1c6bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_attacker_process.py
@@ -0,0 +1,53 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.availability.attacker.attacker_process
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.attacker import baseattacker
+
+
+@mock.patch(
+ 'yardstick.benchmark.scenarios.availability.attacker.attacker_process.ssh')
+class AttackerServiceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.attacker_cfg = {
+ 'fault_type': 'kill-process',
+ 'process_name': 'nova-api',
+ 'host': 'node1',
+ }
+
+ def test__attacker_service_all_successful(self, mock_ssh):
+
+ cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg)
+ ins = cls(self.attacker_cfg, self.context)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "10", '')
+ ins.setup()
+ ins.inject_fault()
+ ins.recover()
+
+ def test__attacker_service_check_failuer(self, mock_ssh):
+
+ cls = baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg)
+ ins = cls(self.attacker_cfg, self.context)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, None, '')
+ ins.setup()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_baseattacker.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseattacker.py
new file mode 100644
index 000000000..74f86983b
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseattacker.py
@@ -0,0 +1,36 @@
+##############################################################################
+# 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
+##############################################################################
+
+import unittest
+
+from yardstick.benchmark.scenarios.availability.attacker import baseattacker
+
+
+class BaseAttackerTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.attacker_cfg = {
+ 'fault_type': 'test-attacker',
+ 'action_parameter': {'process_name': 'nova_api'},
+ 'rollback_parameter': {'process_name': 'nova_api'},
+ 'key': 'stop-service',
+ 'attack_key': 'stop-service',
+ 'host': 'node1',
+ }
+ self.base_attacker = baseattacker.BaseAttacker({}, {})
+
+ def test__init__(self):
+ self.assertEqual(self.base_attacker.data, {})
+ self.assertFalse(self.base_attacker.mandatory)
+ self.assertEqual(self.base_attacker.intermediate_variables, {})
+ self.assertFalse(self.base_attacker.mandatory)
+
+ def test_get_attacker_cls(self):
+ with self.assertRaises(RuntimeError):
+ baseattacker.BaseAttacker.get_attacker_cls(self.attacker_cfg)
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
new file mode 100644
index 000000000..8d042c406
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_basemonitor.py
@@ -0,0 +1,119 @@
+##############################################################################
+# Copyright (c) 2015 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 time
+
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.monitor import basemonitor
+
+
+class MonitorMgrTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.monitor_configs = [
+ {
+ "monitor_type": "openstack-cmd",
+ "command_name": "openstack router list",
+ "monitor_time": 10,
+ "monitor_number": 3,
+ "sla": {
+ "max_outage_time": 5
+ }
+ },
+ {
+ "monitor_type": "process",
+ "process_name": "neutron-server",
+ "host": "node1",
+ "monitor_time": 20,
+ "monitor_number": 3,
+ "sla": {
+ "max_recover_time": 20
+ }
+ }
+ ]
+ self.MonitorMgr = basemonitor.MonitorMgr([])
+ self.MonitorMgr.init_monitors(self.monitor_configs, None)
+ self.monitor_list = self.MonitorMgr._monitor_list
+ for mo in self.monitor_list:
+ mo._result = {"outage_time": 10}
+
+ @mock.patch.object(basemonitor, 'BaseMonitor')
+ def test__MonitorMgr_setup_successful(self, *args):
+ instance = basemonitor.MonitorMgr({"nova-api": 10})
+ instance.init_monitors(self.monitor_configs, None)
+ instance.start_monitors()
+ instance.wait_monitors()
+
+ # TODO(elfoley): Check the return value
+ ret = instance.verify_SLA() # pylint: disable=unused-variable
+
+ @mock.patch.object(basemonitor, 'BaseMonitor')
+ def test_MonitorMgr_getitem(self, *args):
+ monitorMgr = basemonitor.MonitorMgr({"nova-api": 10})
+ monitorMgr.init_monitors(self.monitor_configs, None)
+
+ @mock.patch.object(basemonitor, 'BaseMonitor')
+ def test_store_result(self, *args):
+ expect = {'process_neutron-server_outage_time': 10,
+ 'openstack-router-list_outage_time': 10}
+ result = {}
+ self.MonitorMgr.store_result(result)
+ self.assertDictEqual(result, expect)
+
+
+class BaseMonitorTestCase(unittest.TestCase):
+
+ class MonitorSimple(basemonitor.BaseMonitor):
+ __monitor_type__ = "MonitorForTest"
+
+ def setup(self):
+ self.monitor_result = False
+
+ def monitor_func(self):
+ return self.monitor_result
+
+ def setUp(self):
+ self.monitor_cfg = {
+ 'monitor_type': 'MonitorForTest',
+ 'command_name': 'nova image-list',
+ 'monitor_time': 0.01,
+ 'sla': {'max_outage_time': 5}
+ }
+
+ def _close_queue(self, instace):
+ time.sleep(0.1)
+ instace._queue.close()
+
+ def test__basemonitor_start_wait_successful(self):
+ ins = basemonitor.BaseMonitor(self.monitor_cfg, None, {"nova-api": 10})
+ self.addCleanup(self._close_queue, ins)
+ ins.start_monitor()
+ ins.wait_monitor()
+
+ def test__basemonitor_all_successful(self):
+ ins = self.MonitorSimple(self.monitor_cfg, None, {"nova-api": 10})
+ self.addCleanup(self._close_queue, ins)
+ ins.setup()
+ ins.run()
+ ins.verify_SLA()
+
+ @mock.patch.object(basemonitor, 'multiprocessing')
+ def test__basemonitor_func_false(self, mock_multiprocess):
+ ins = self.MonitorSimple(self.monitor_cfg, None, {"nova-api": 10})
+ self.addCleanup(self._close_queue, ins)
+ ins.setup()
+ mock_multiprocess.Event().is_set.return_value = False
+ ins.run()
+ ins.verify_SLA()
+
+ def test__basemonitor_getmonitorcls_successfule(self):
+ with self.assertRaises(RuntimeError):
+ basemonitor.BaseMonitor.get_monitor_cls(self.monitor_cfg)
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_baseoperation.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseoperation.py
new file mode 100644
index 000000000..b7c9f62ff
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseoperation.py
@@ -0,0 +1,79 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.operation import baseoperation
+
+
+class OperationMgrTestCase(unittest.TestCase):
+
+ def setUp(self):
+ config = {
+ 'operation_type': 'general-operation',
+ 'key': 'service-status'
+ }
+
+ self.operation_configs = []
+ self.operation_configs.append(config)
+
+ @mock.patch.object(baseoperation, 'BaseOperation')
+ def test_all_successful(self, *args):
+ mgr_ins = baseoperation.OperationMgr()
+ mgr_ins.init_operations(self.operation_configs, None)
+ _ = mgr_ins["service-status"]
+ mgr_ins.rollback()
+
+ @mock.patch.object(baseoperation, 'BaseOperation')
+ def test_getitem_fail(self, *args):
+ mgr_ins = baseoperation.OperationMgr()
+ mgr_ins.init_operations(self.operation_configs, None)
+ with self.assertRaises(KeyError):
+ _ = mgr_ins["operation-not-exist"]
+
+
+class TestOperation(baseoperation.BaseOperation):
+ __operation__type__ = "test-operation"
+
+ def setup(self):
+ pass
+
+ def run(self):
+ pass
+
+ def rollback(self):
+ pass
+
+
+class BaseOperationTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.config = {
+ 'operation_type': 'general-operation',
+ 'key': 'service-status'
+ }
+ self.base_ins = baseoperation.BaseOperation(self.config, None)
+
+ def test_all_successful(self):
+ self.base_ins.setup()
+ self.base_ins.run()
+ self.base_ins.rollback()
+
+ def test_get_script_fullpath(self):
+ self.base_ins.get_script_fullpath("ha_tools/test.bash")
+
+ # TODO(elfoley): Fix test to check on expected outputs
+ # pylint: disable=unused-variable
+ def test_get_operation_cls_successful(self):
+ operation_ins = self.base_ins.get_operation_cls("test-operation")
+
+ def test_get_operation_cls_fail(self):
+ with self.assertRaises(RuntimeError):
+ self.base_ins.get_operation_cls("operation-not-exist")
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py
new file mode 100644
index 000000000..d4df02819
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_baseresultchecker.py
@@ -0,0 +1,89 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.result_checker import \
+ baseresultchecker
+
+
+class ResultCheckerMgrTestCase(unittest.TestCase):
+
+ def setUp(self):
+ config = {
+ 'checker_type': 'general-result-checker',
+ 'key': 'process-checker'
+ }
+
+ self.checker_configs = []
+ self.checker_configs.append(config)
+
+ self.mgr_ins = baseresultchecker.ResultCheckerMgr()
+
+ self._mock_basechecker = mock.patch.object(baseresultchecker,
+ 'BaseResultChecker')
+ self.mock_basechecker = self._mock_basechecker.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_basechecker.stop()
+
+ def test_ResultCheckerMgr_setup_successful(self):
+ self.mgr_ins.verify()
+
+ def test_getitem_succeessful(self):
+ self.mgr_ins.init_ResultChecker(self.checker_configs, None)
+ _ = self.mgr_ins["process-checker"]
+
+ def test_getitem_fail(self):
+ self.mgr_ins.init_ResultChecker(self.checker_configs, None)
+ with self.assertRaises(KeyError):
+ _ = self.mgr_ins["checker-not-exist"]
+
+
+class BaseResultCheckerTestCase(unittest.TestCase):
+
+ class ResultCheckeSimple(baseresultchecker.BaseResultChecker):
+ __result_checker__type__ = "ResultCheckeForTest"
+
+ def setup(self):
+ self.success = False
+
+ def verify(self):
+ return self.success
+
+ def setUp(self):
+ self.checker_cfg = {
+ 'checker_type': 'general-result-checker',
+ 'key': 'process-checker'
+ }
+ self.ins = baseresultchecker.BaseResultChecker(self.checker_cfg, None)
+
+ def test_baseresultchecker_setup_verify_successful(self):
+ self.ins.setup()
+ self.ins.verify()
+
+ def test_baseresultchecker_verfiy_pass(self):
+ self.ins.setup()
+ self.ins.actualResult = True
+ self.ins.expectedResult = True
+ self.ins.verify()
+
+ def test_get_script_fullpath(self):
+ self.ins.get_script_fullpath("test.bash")
+
+ def test_get_resultchecker_cls_successful(self):
+ baseresultchecker.BaseResultChecker.get_resultchecker_cls(
+ "ResultCheckeForTest")
+
+ def test_get_resultchecker_cls_fail(self):
+ with self.assertRaises(RuntimeError):
+ baseresultchecker.BaseResultChecker.get_resultchecker_cls(
+ "ResultCheckeNotExist")
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py
new file mode 100644
index 000000000..e49544e1c
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_director.py
@@ -0,0 +1,106 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.director
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.director import Director
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.director.basemonitor')
+@mock.patch('yardstick.benchmark.scenarios.availability.director.baseattacker')
+@mock.patch(
+ 'yardstick.benchmark.scenarios.availability.director.baseoperation')
+@mock.patch(
+ 'yardstick.benchmark.scenarios.availability.director.baseresultchecker')
+class DirectorTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.scenario_cfg = {
+ 'type': "general_scenario",
+ 'options': {
+ 'attackers': [{
+ 'fault_type': "general-attacker",
+ 'key': "kill-process"}],
+ 'monitors': [{
+ 'monitor_type': "general-monitor",
+ 'key': "service-status"}],
+ 'operations': [{
+ 'operation_type': 'general-operation',
+ 'key': 'service-status'}],
+ 'resultCheckers': [{
+ 'checker_type': 'general-result-checker',
+ 'key': 'process-checker', }],
+ 'steps': [
+ {
+ 'actionKey': "service-status",
+ 'actionType': "operation",
+ 'index': 1},
+ {
+ 'actionKey': "kill-process",
+ 'actionType': "attacker",
+ 'index': 2},
+ {
+ 'actionKey': "process-checker",
+ 'actionType': "resultchecker",
+ 'index': 3},
+ {
+ 'actionKey': "service-status",
+ 'actionType': "monitor",
+ 'index': 4},
+ ]
+ }
+ }
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.ctx = {"nodes": {"node1": host}}
+
+ def test_director_all_successful(self, mock_checer, mock_opertion,
+ mock_attacker, mock_monitor):
+ ins = Director(self.scenario_cfg, self.ctx)
+ opertion_action = ins.createActionPlayer("operation", "service-status")
+ attacker_action = ins.createActionPlayer("attacker", "kill-process")
+ checker_action = ins.createActionPlayer("resultchecker",
+ "process-checker")
+ monitor_action = ins.createActionPlayer("monitor", "service-status")
+
+ opertion_rollback = ins.createActionRollbacker("operation",
+ "service-status")
+ attacker_rollback = ins.createActionRollbacker("attacker",
+ "kill-process")
+ ins.executionSteps.append(opertion_rollback)
+ ins.executionSteps.append(attacker_rollback)
+
+ opertion_action.action()
+ attacker_action.action()
+ checker_action.action()
+ monitor_action.action()
+
+ attacker_rollback.rollback()
+ opertion_rollback.rollback()
+
+ ins.stopMonitors()
+ ins.verify()
+ ins.knockoff()
+
+ def test_director_get_wrong_item(self, mock_checer, mock_opertion,
+ mock_attacker, mock_monitor):
+ ins = Director(self.scenario_cfg, self.ctx)
+ ins.createActionPlayer("wrong_type", "wrong_key")
+ ins.createActionRollbacker("wrong_type", "wrong_key")
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_command.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_command.py
new file mode 100644
index 000000000..1aebcc85b
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_command.py
@@ -0,0 +1,95 @@
+##############################################################################
+# Copyright (c) 2015 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.monitor import monitor_command
+
+
+class ExecuteShellTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_subprocess = mock.patch.object(monitor_command, 'subprocess')
+ self.mock_subprocess = self._mock_subprocess.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_subprocess.stop()
+
+ def test__fun_execute_shell_command_successful(self):
+ cmd = "env"
+ self.mock_subprocess.check_output.return_value = (0, 'unittest')
+ exitcode, _t = monitor_command._execute_shell_command(cmd)
+ self.assertEqual(exitcode, 0)
+
+ @mock.patch.object(monitor_command, 'LOG')
+ def test__fun_execute_shell_command_fail_cmd_exception(self, mock_log):
+ cmd = "env"
+ self.mock_subprocess.check_output.side_effect = RuntimeError
+ exitcode, _ = monitor_command._execute_shell_command(cmd)
+ self.assertEqual(exitcode, -1)
+ mock_log.error.assert_called_once()
+
+
+class MonitorOpenstackCmdTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.config = {
+ 'monitor_type': 'openstack-api',
+ 'command_name': 'nova image-list',
+ 'monitor_time': 1,
+ 'sla': {'max_outage_time': 5}
+ }
+ self._mock_subprocess = mock.patch.object(monitor_command, 'subprocess')
+ self.mock_subprocess = self._mock_subprocess.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_subprocess.stop()
+
+ def test__monitor_command_monitor_func_successful(self):
+
+ instance = monitor_command.MonitorOpenstackCmd(self.config, None, {"nova-api": 10})
+ instance.setup()
+ self.mock_subprocess.check_output.return_value = (0, 'unittest')
+ ret = instance.monitor_func()
+ self.assertTrue(ret)
+ instance._result = {"outage_time": 0}
+ instance.verify_SLA()
+
+ @mock.patch.object(monitor_command, 'LOG')
+ def test__monitor_command_monitor_func_failure(self, mock_log):
+ self.mock_subprocess.check_output.return_value = (1, 'unittest')
+ instance = monitor_command.MonitorOpenstackCmd(self.config, None, {"nova-api": 10})
+ instance.setup()
+ self.mock_subprocess.check_output.side_effect = RuntimeError
+ ret = instance.monitor_func()
+ self.assertFalse(ret)
+ mock_log.error.assert_called_once()
+ instance._result = {"outage_time": 10}
+ instance.verify_SLA()
+
+ @mock.patch.object(monitor_command, 'ssh')
+ def test__monitor_command_ssh_monitor_successful(self, mock_ssh):
+
+ self.mock_subprocess.check_output.return_value = (0, 'unittest')
+ self.config["host"] = "node1"
+ instance = monitor_command.MonitorOpenstackCmd(
+ self.config, self.context, {"nova-api": 10})
+ instance.setup()
+ mock_ssh.SSH.from_node().execute.return_value = (0, "0", '')
+ ret = instance.monitor_func()
+ self.assertTrue(ret)
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py
new file mode 100644
index 000000000..5907c8b6a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_general.py
@@ -0,0 +1,82 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.monitor
+# .monitor_general
+
+from __future__ import absolute_import
+import mock
+import unittest
+from yardstick.benchmark.scenarios.availability.monitor import monitor_general
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.monitor.'
+ 'monitor_general.ssh')
+@mock.patch('yardstick.benchmark.scenarios.availability.monitor.'
+ 'monitor_general.open')
+class GeneralMonitorServiceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.monitor_cfg = {
+ 'monitor_type': 'general-monitor',
+ 'key': 'service-status',
+ 'monitor_key': 'service-status',
+ 'host': 'node1',
+ 'monitor_time': 3,
+ 'parameter': {'serviceName': 'haproxy'},
+ 'sla': {'max_outage_time': 1}
+ }
+ self.monitor_cfg_noparam = {
+ 'monitor_type': 'general-monitor',
+ 'key': 'service-status',
+ 'monitor_key': 'service-status',
+ 'host': 'node1',
+ 'monitor_time': 3,
+ 'sla': {'max_outage_time': 1}
+ }
+
+ def test__monitor_general_all_successful(self, mock_open, mock_ssh):
+ ins = monitor_general.GeneralMonitor(self.monitor_cfg, self.context, {"nova-api": 10})
+
+ ins.setup()
+ mock_ssh.SSH.from_node().execute.return_value = (0, "running", '')
+ ins.monitor_func()
+ ins._result = {'outage_time': 0}
+ ins.verify_SLA()
+
+ def test__monitor_general_all_successful_noparam(self, mock_open,
+ mock_ssh):
+ ins = monitor_general.GeneralMonitor(
+ self.monitor_cfg_noparam, self.context, {"nova-api": 10})
+
+ ins.setup()
+ mock_ssh.SSH.from_node().execute.return_value = (0, "running", '')
+ ins.monitor_func()
+ ins._result = {'outage_time': 0}
+ ins.verify_SLA()
+
+ def test__monitor_general_failure(self, mock_open, mock_ssh):
+ ins = monitor_general.GeneralMonitor(
+ self.monitor_cfg_noparam, self.context, {"nova-api": 10})
+
+ ins.setup()
+ mock_ssh.SSH.from_node().execute.return_value = (1, "error", 'error')
+ ins.monitor_func()
+ ins._result = {'outage_time': 2}
+ ins.verify_SLA()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py
new file mode 100644
index 000000000..dc3a4b99a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_multi.py
@@ -0,0 +1,82 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.monitor
+# .monitor_multi
+
+from __future__ import absolute_import
+import mock
+import unittest
+from yardstick.benchmark.scenarios.availability.monitor import monitor_multi
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.monitor.'
+ 'monitor_general.ssh')
+@mock.patch('yardstick.benchmark.scenarios.availability.monitor.'
+ 'monitor_general.open')
+class MultiMonitorServiceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.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'},
+ 'sla': {'max_outage_time': 1}
+ }
+
+ def test__monitor_multi_all_successful(self, mock_open, mock_ssh):
+ ins = monitor_multi.MultiMonitor(
+ self.monitor_cfg, self.context, {"nova-api": 10})
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "running", '')
+
+ ins.start_monitor()
+ ins.wait_monitor()
+ ins.verify_SLA()
+
+ def test__monitor_multi_all_fail(self, mock_open, mock_ssh):
+ ins = monitor_multi.MultiMonitor(
+ self.monitor_cfg, self.context, {"nova-api": 10})
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "running", '')
+
+ 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
new file mode 100644
index 000000000..8c73bf221
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_monitor_process.py
@@ -0,0 +1,73 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.availability.monitor.monitor_process
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability.monitor import monitor_process
+
+
+@mock.patch(
+ 'yardstick.benchmark.scenarios.availability.monitor.monitor_process.ssh')
+class MonitorProcessTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.monitor_cfg = {
+ 'monitor_type': 'process',
+ 'process_name': 'nova-api',
+ 'host': "node1",
+ 'monitor_time': 1,
+ 'sla': {'max_recover_time': 5}
+ }
+
+ def test__monitor_process_all_successful(self, mock_ssh):
+
+ ins = monitor_process.MonitorProcess(self.monitor_cfg, self.context, {"nova-api": 10})
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, "1", '')
+ ins.setup()
+ ins.monitor_func()
+ ins._result = {"outage_time": 0}
+ ins.verify_SLA()
+
+ def test__monitor_process_down_failuer(self, mock_ssh):
+
+ ins = monitor_process.MonitorProcess(self.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}
+ 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())
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py
new file mode 100644
index 000000000..2b09c0385
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_operation_general.py
@@ -0,0 +1,74 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.operation
+# .operation_general
+
+from __future__ import absolute_import
+import mock
+import unittest
+from yardstick.benchmark.scenarios.availability.operation import \
+ operation_general
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.operation.'
+ 'operation_general.ssh')
+@mock.patch('yardstick.benchmark.scenarios.availability.operation.'
+ 'operation_general.open')
+class GeneralOperaionTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.operation_cfg = {
+ 'operation_type': 'general-operation',
+ 'action_parameter': {'ins_cup': 2},
+ 'rollback_parameter': {'ins_id': 'id123456'},
+ 'key': 'nova-create-instance',
+ 'operation_key': 'nova-create-instance',
+ 'host': 'node1',
+ }
+ self.operation_cfg_noparam = {
+ 'operation_type': 'general-operation',
+ 'key': 'nova-create-instance',
+ 'operation_key': 'nova-create-instance',
+ 'host': 'node1',
+ }
+
+ def test__operation_successful(self, mock_open, mock_ssh):
+ ins = operation_general.GeneralOperaion(self.operation_cfg,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "success", '')
+ ins.setup()
+ ins.run()
+ ins.rollback()
+
+ def test__operation_successful_noparam(self, mock_open, mock_ssh):
+ ins = operation_general.GeneralOperaion(self.operation_cfg_noparam,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "success", '')
+ ins.setup()
+ ins.run()
+ ins.rollback()
+
+ def test__operation_fail(self, mock_open, mock_ssh):
+ ins = operation_general.GeneralOperaion(self.operation_cfg,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (1, "failed", '')
+ ins.setup()
+ ins.run()
+ ins.rollback()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py
new file mode 100644
index 000000000..324a5bda2
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_result_checker_general.py
@@ -0,0 +1,118 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.result_checker
+# .result_checker_general
+
+from __future__ import absolute_import
+import mock
+import unittest
+import copy
+
+from yardstick.benchmark.scenarios.availability.result_checker import \
+ result_checker_general
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.availability.result_checker.'
+ 'result_checker_general.ssh')
+@mock.patch('yardstick.benchmark.scenarios.availability.result_checker.'
+ 'result_checker_general.open')
+class GeneralResultCheckerTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.context = {"node1": host}
+ self.checker_cfg = {
+ 'parameter': {'processname': 'process'},
+ 'checker_type': 'general-result-checker',
+ 'condition': 'eq',
+ 'expectedValue': 1,
+ 'key': 'process-checker',
+ 'checker_key': 'process-checker',
+ 'host': 'node1'
+ }
+
+ def test__result_checker_eq(self, mock_open, mock_ssh):
+ ins = result_checker_general.GeneralResultChecker(self.checker_cfg,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "1", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_gt(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'gt'
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "2", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_gt_eq(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'gt_eq'
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "1", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_lt(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'lt'
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "0", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_lt_eq(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'lt_eq'
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "1", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_in(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'in'
+ config['expectedValue'] = "value"
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "value return", '')
+ ins.setup()
+ self.assertTrue(ins.verify())
+
+ def test__result_checker_wrong(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config['condition'] = 'wrong'
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (0, "1", '')
+ ins.setup()
+ self.assertFalse(ins.verify())
+
+ def test__result_checker_fail(self, mock_open, mock_ssh):
+ config = copy.deepcopy(self.checker_cfg)
+ config.pop('parameter')
+ ins = result_checker_general.GeneralResultChecker(config,
+ self.context)
+ mock_ssh.SSH.from_node().execute.return_value = (1, "fail", '')
+ ins.setup()
+ ins.verify()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_scenario_general.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_scenario_general.py
new file mode 100644
index 000000000..dbf3d83b2
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_scenario_general.py
@@ -0,0 +1,76 @@
+##############################################################################
+# Copyright (c) 2016 Huan Li and others
+# lihuansse@tongji.edu.cn
+# 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability import scenario_general
+from yardstick.common import exceptions as y_exc
+
+
+class ScenarioGeneralTestCase(unittest.TestCase):
+
+ @mock.patch.object(scenario_general, 'Director')
+ def setUp(self, *args):
+ self.scenario_cfg = {
+ 'type': "general_scenario",
+ 'options': {
+ 'attackers': [{
+ 'fault_type': "general-attacker",
+ 'key': "kill-process"}],
+ 'monitors': [{
+ 'monitor_type': "general-monitor",
+ 'key': "service-status"}],
+ 'steps': [
+ {
+ 'actionKey': "kill-process",
+ 'actionType': "attacker",
+ 'index': 1},
+ {
+ 'actionKey': "service-status",
+ 'actionType': "monitor",
+ 'index': 2}]
+ }
+ }
+ self.instance = scenario_general.ScenarioGeneral(self.scenario_cfg,
+ None)
+ self.instance.setup()
+ self.instance.director.verify.return_value = True
+
+ def test_scenario_general_all_successful(self):
+ ret = {}
+ self.instance.run(ret)
+ self.instance.teardown()
+ self.assertEqual(ret['sla_pass'], 1)
+
+ @mock.patch.object(scenario_general.LOG, 'exception')
+ def test_scenario_general_exception(self, *args):
+ self.instance.director.createActionPlayer.side_effect = (
+ KeyError('Wrong'))
+ self.instance.director.data = {}
+ ret = {}
+ self.instance.run(ret)
+ self.instance.teardown()
+ self.assertEqual(ret['sla_pass'], 1)
+
+ def test_scenario_general_case_fail(self):
+ self.instance.director.verify.return_value = False
+ self.instance.director.data = {}
+ ret = {}
+ self.assertRaises(y_exc.SLAValidationError, self.instance.run, ret)
+ self.instance.teardown()
+ self.assertEqual(ret['sla_pass'], 0)
+
+ def test_scenario_general_case_service_not_found_fail(self):
+ self.instance.director.verify.return_value = True
+ self.instance.director.data = {"general-attacker": 0}
+ ret = {}
+ self.assertRaises(y_exc.SLAValidationError, self.instance.run, ret)
+ self.instance.teardown()
+ self.assertEqual(ret['sla_pass'], 0)
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_serviceha.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_serviceha.py
new file mode 100644
index 000000000..d61fa67c7
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_serviceha.py
@@ -0,0 +1,131 @@
+##############################################################################
+# Copyright (c) 2015 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability import serviceha
+from yardstick.common import exceptions as y_exc
+
+
+class ServicehaTestCase(unittest.TestCase):
+
+ def setUp(self):
+ host = {
+ "ip": "10.20.0.5",
+ "user": "root",
+ "key_filename": "/root/.ssh/id_rsa"
+ }
+ self.ctx = {"nodes": {"node1": host}}
+ attacker_cfg = {
+ "fault_type": "kill-process",
+ "process_name": "nova-api",
+ "host": "node1"
+ }
+ attacker_cfgs = []
+ attacker_cfgs.append(attacker_cfg)
+ monitor_cfg = {
+ "monitor_cmd": "nova image-list",
+ "monitor_time": 0.1
+ }
+ monitor_cfgs = []
+ monitor_cfgs.append(monitor_cfg)
+
+ options = {
+ "attackers": attacker_cfgs,
+ "monitors": monitor_cfgs
+ }
+ sla = {"outage_time": 5}
+ self.args = {"options": options, "sla": sla}
+ self.test__serviceha = serviceha.ServiceHA(self.args, self.ctx)
+
+ def test___init__(self):
+
+ self.assertEqual(self.test__serviceha.data, {})
+ self.assertFalse(self.test__serviceha.setup_done)
+ self.assertFalse(self.test__serviceha.sla_pass)
+
+ # NOTE(elfoley): This should be split into test_setup and test_run
+ # NOTE(elfoley): This should explicitly test outcomes and states
+ @mock.patch.object(serviceha, 'baseattacker')
+ @mock.patch.object(serviceha, 'basemonitor')
+ def test__serviceha_setup_run_successful(self, mock_monitor, *args):
+ p = serviceha.ServiceHA(self.args, self.ctx)
+
+ p.setup()
+ self.assertTrue(p.setup_done)
+ mock_monitor.MonitorMgr().verify_SLA.return_value = True
+ ret = {}
+ p.run(ret)
+ p.teardown()
+
+ p.setup()
+ self.assertTrue(p.setup_done)
+
+ @mock.patch.object(serviceha, 'baseattacker')
+ @mock.patch.object(serviceha, 'basemonitor')
+ def test__serviceha_run_sla_error(self, mock_monitor, *args):
+ p = serviceha.ServiceHA(self.args, self.ctx)
+
+ p.setup()
+ self.assertEqual(p.setup_done, True)
+
+ mock_monitor.MonitorMgr().verify_SLA.return_value = False
+
+ ret = {}
+ self.assertRaises(y_exc.SLAValidationError, p.run, ret)
+ self.assertEqual(ret['sla_pass'], 0)
+
+ @mock.patch.object(serviceha, 'baseattacker')
+ @mock.patch.object(serviceha, 'basemonitor')
+ def test__serviceha_run_service_not_found_sla_error(self, mock_monitor,
+ *args):
+ p = serviceha.ServiceHA(self.args, self.ctx)
+
+ p.setup()
+ self.assertTrue(p.setup_done)
+ p.data["kill-process"] = 0
+
+ mock_monitor.MonitorMgr().verify_SLA.return_value = True
+
+ ret = {}
+ self.assertRaises(y_exc.SLAValidationError, p.run, ret)
+ self.assertEqual(ret['sla_pass'], 0)
+
+ @mock.patch.object(serviceha, 'baseattacker')
+ @mock.patch.object(serviceha, 'basemonitor')
+ def test__serviceha_no_teardown_when_sla_pass(self, mock_monitor,
+ *args):
+ p = serviceha.ServiceHA(self.args, self.ctx)
+ p.setup()
+ self.assertTrue(p.setup_done)
+ mock_monitor.MonitorMgr().verify_SLA.return_value = True
+ ret = {}
+ p.run(ret)
+ attacker = mock.Mock()
+ attacker.mandatory = False
+ p.attackers = [attacker]
+ p.teardown()
+ attacker.recover.assert_not_called()
+
+ @mock.patch.object(serviceha, 'baseattacker')
+ @mock.patch.object(serviceha, 'basemonitor')
+ def test__serviceha_teardown_when_mandatory(self, mock_monitor,
+ *args):
+ p = serviceha.ServiceHA(self.args, self.ctx)
+ p.setup()
+ self.assertTrue(p.setup_done)
+ mock_monitor.MonitorMgr().verify_SLA.return_value = True
+ ret = {}
+ p.run(ret)
+ attacker = mock.Mock()
+ attacker.mandatory = True
+ p.attackers = [attacker]
+ p.teardown()
+ attacker.recover.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py b/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py
new file mode 100644
index 000000000..4d97585d4
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/availability/test_util.py
@@ -0,0 +1,56 @@
+##############################################################################
+# Copyright (c) 2016 Kanglin Yin and others
+# 14_ykl@tongji.edu.cn
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.availability.utils
+
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.availability import util
+
+
+class ExecuteShellTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.param_config = {'serviceName': '@serviceName', 'value': 1}
+ self.intermediate_variables = {'@serviceName': 'nova-api'}
+ self.std_output = '| id | 1 |'
+ self.cmd_config = {'cmd': 'ls', 'param': '-a'}
+
+ self._mock_subprocess = mock.patch.object(util, 'subprocess')
+ self.mock_subprocess = self._mock_subprocess.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_subprocess.stop()
+
+ def test_util_build_command_shell(self):
+ result = util.build_shell_command(self.param_config, True,
+ self.intermediate_variables)
+ self.assertIn("nova-api", result)
+
+ def test_read_stdout_item(self):
+ result = util.read_stdout_item(self.std_output, 'id')
+ self.assertEqual('1', result)
+
+ def test_buildshellparams(self):
+ result = util.buildshellparams(self.cmd_config, True)
+ self.assertEqual('/bin/bash -s {0} {1}', result)
+
+ def test__fun_execute_shell_command_successful(self):
+ cmd = "env"
+ self.mock_subprocess.check_output.return_value = (0, 'unittest')
+ exitcode, _ = util.execute_shell_command(cmd)
+ self.assertEqual(exitcode, 0)
+
+ def test__fun_execute_shell_command_fail_cmd_exception(self):
+ cmd = "env"
+ self.mock_subprocess.check_output.side_effect = RuntimeError
+ exitcode, _ = util.execute_shell_command(cmd)
+ self.assertEqual(exitcode, -1)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/__init__.py b/yardstick/tests/unit/benchmark/scenarios/compute/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt b/yardstick/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt
new file mode 100644
index 000000000..e2c79a9b1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/cachestat_sample_output.txt
@@ -0,0 +1,5 @@
+Counting cache functions... Output every 1 seconds.
+ HITS MISSES DIRTIES RATIO BUFFERS_MB CACHE_MB
+ 6462 0 29 100.0% 1157 66782
+
+Ending tracing...
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output1.txt b/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output1.txt
new file mode 100644
index 000000000..723e64bcb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output1.txt
@@ -0,0 +1,9 @@
+Linux 3.13.0-68-generic (elxg482ls42) 11/30/2015 _x86_64_ (1 CPU)
+
+04:34:26 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
+04:34:26 PM all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
+04:34:26 PM 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
+
+Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
+Average: all 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
+Average: 0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 100.00
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output2.txt b/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output2.txt
new file mode 100644
index 000000000..c66520a27
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/cpuload_sample_output2.txt
@@ -0,0 +1,2 @@
+cpu 245813227 366650 17338727 1195600354 2652765 178 177114 0 80439531 0
+cpu0 32334587 35782 1659040 87008833 401178 60 73571 0 8030817 0
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt b/yardstick/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt
new file mode 100644
index 000000000..1793e2f10
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/memload_sample_output.txt
@@ -0,0 +1,3 @@
+ total used free shared buff/cache available
+Mem: 263753976 76737332 187016644 2844 853528 67252400
+Swap: 268029948 0 268029948
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py
new file mode 100644
index 000000000..6f66c30f9
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cachestat.py
@@ -0,0 +1,95 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.cachestat.CACHEstat
+
+from __future__ import absolute_import
+import mock
+import unittest
+import os
+
+from yardstick.benchmark.scenarios.compute import cachestat
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.cachestat.ssh')
+class CACHEstatTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_cachestat_successful_setup(self, mock_ssh):
+ c = cachestat.CACHEstat({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ c.setup()
+ self.assertIsNotNone(c.client)
+ self.assertTrue(c.setup_done)
+
+ def test_execute_command_success(self, mock_ssh):
+ c = cachestat.CACHEstat({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ expected_result = 'abcdefg'
+ mock_ssh.SSH.from_node().execute.return_value = (0, expected_result, '')
+ result = c._execute_command("foo")
+ self.assertEqual(result, expected_result)
+
+ def test_execute_command_failed(self, mock_ssh):
+ c = cachestat.CACHEstat({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (127, '', 'Failed executing \
+ command')
+ self.assertRaises(RuntimeError, c._execute_command,
+ "cat /proc/meminfo")
+
+ def test_get_cache_usage_successful(self, mock_ssh):
+ options = {
+ "interval": 1,
+ }
+ args = {"options": options}
+ c = cachestat.CACHEstat(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ output = self._read_file("cachestat_sample_output.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, output, '')
+ result = c._get_cache_usage()
+ expected_result = {"cachestat": {"cache0": {"HITS": "6462",
+ "DIRTIES": "29",
+ "RATIO": "100.0%",
+ "MISSES": "0",
+ "BUFFERS_MB": "1157",
+ "CACHE_MB": "66782"}},
+ "average": {"HITS": 6462, "DIRTIES": 29,
+ "RATIO": "100.0%",
+ "MISSES": 0, "BUFFERS_MB": 1157,
+ "CACHE_MB": 66782},
+ "max": {"HITS": 6462,
+ "DIRTIES": 29, "RATIO": 100.0, "MISSES": 0,
+ "BUFFERS_MB": 1157, "CACHE_MB": 66782}}
+
+ self.assertEqual(result, expected_result)
+
+ def _read_file(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py
new file mode 100644
index 000000000..4bef589f4
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_computecapacity.py
@@ -0,0 +1,64 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.compute.computecapacity.ComputeCapacity
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import computecapacity
+
+SAMPLE_OUTPUT = '{"Cpu_number": "2", "Core_number": "24",\
+ "Memory_size": "263753976 kB", "Thread_number": "48",\
+ "Cache_size": "30720 KB", "HT_Open": "0"}'
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.computecapacity.ssh')
+class ComputeCapacityTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'nodes': {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key",
+ 'password': "root"
+ },
+ }
+ }
+
+ self.result = {}
+
+ def test_capacity_successful_setup(self, mock_ssh):
+ c = computecapacity.ComputeCapacity({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ c.setup()
+ self.assertIsNotNone(c.client)
+ self.assertTrue(c.setup_done)
+
+ def test_capacity_successful(self, mock_ssh):
+ c = computecapacity.ComputeCapacity({}, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, SAMPLE_OUTPUT, '')
+ c.run(self.result)
+ expected_result = jsonutils.loads(SAMPLE_OUTPUT)
+ self.assertEqual(self.result, expected_result)
+
+ def test_capacity_unsuccessful_script_error(self, mock_ssh):
+ c = computecapacity.ComputeCapacity({}, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, c.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py
new file mode 100644
index 000000000..da6e6a22e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cpuload.py
@@ -0,0 +1,262 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.lmbench.Lmbench
+
+from __future__ import absolute_import
+import mock
+import unittest
+import os
+
+from yardstick.benchmark.scenarios.compute import cpuload
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.cpuload.ssh')
+class CPULoadTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_setup_mpstat_installed(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ l.setup()
+ self.assertIsNotNone(l.client)
+ self.assertTrue(l.setup_done)
+ self.assertTrue(l.has_mpstat)
+
+ def test_setup_mpstat_not_installed(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (127, '', '')
+
+ l.setup()
+ self.assertIsNotNone(l.client)
+ self.assertTrue(l.setup_done)
+ self.assertFalse(l.has_mpstat)
+
+ def test_execute_command_success(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ l.setup()
+
+ expected_result = 'abcdefg'
+ mock_ssh.SSH.from_node().execute.return_value = (0, expected_result, '')
+ result = l._execute_command("foo")
+ self.assertEqual(result, expected_result)
+
+ def test_execute_command_failed(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ l.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (127, '', 'abcdefg')
+ self.assertRaises(RuntimeError, l._execute_command,
+ "cat /proc/loadavg")
+
+ def test_get_loadavg(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ l.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = \
+ (0, '1.50 1.45 1.51 3/813 14322', '')
+ result = l._get_loadavg()
+ expected_result = \
+ {'loadavg': ['1.50', '1.45', '1.51', '3/813', '14322']}
+ self.assertEqual(result, expected_result)
+
+ def test_get_cpu_usage_mpstat(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ l.setup()
+
+ l.interval = 1
+ l.count = 1
+ mpstat_output = self._read_file("cpuload_sample_output1.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, mpstat_output, '')
+ result = l._get_cpu_usage_mpstat()
+
+ expected_result = \
+ {"mpstat_minimum":
+ {"cpu": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"},
+ "cpu0": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"}},
+ "mpstat_average":
+ {"cpu": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"},
+ "cpu0": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"}},
+ "mpstat_maximun":
+ {"cpu": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"},
+ "cpu0": {"%steal": "0.00", "%usr": "0.00", "%gnice": "0.00",
+ "%idle": "100.00", "%guest": "0.00",
+ "%iowait": "0.00", "%sys": "0.00", "%soft": "0.00",
+ "%irq": "0.00", "%nice": "0.00"}}}
+
+ self.assertDictEqual(result, expected_result)
+
+ def test_get_cpu_usage(self, mock_ssh):
+ options = {
+ "interval": 0,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ l.setup()
+
+ l.interval = 0
+ output = self._read_file("cpuload_sample_output2.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, output, '')
+ result = l._get_cpu_usage()
+
+ expected_result = \
+ {'mpstat':
+ {'cpu':
+ {'%steal': '0.00',
+ '%usr': '11.31',
+ '%gnice': '0.00',
+ '%idle': '81.78',
+ '%iowait': '0.18',
+ '%guest': '5.50',
+ '%sys': '1.19',
+ '%soft': '0.01',
+ '%irq': '0.00',
+ '%nice': '0.03'},
+ 'cpu0':
+ {'%steal': '0.00',
+ '%usr': '20.00',
+ '%gnice': '0.00',
+ '%idle': '71.60',
+ '%iowait': '0.33',
+ '%guest': '6.61',
+ '%sys': '1.37',
+ '%soft': '0.06',
+ '%irq': '0.00',
+ '%nice': '0.03'}}}
+
+ self.assertDictEqual(result, expected_result)
+
+ def test_run_proc_stat(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+
+ args = {'options': options}
+
+ l = cpuload.CPULoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+ l.setup()
+
+ l.interval = 0
+ stat_output = self._read_file("cpuload_sample_output2.txt")
+ mock_ssh.SSH.from_node().execute.side_effect = \
+ [(0, '1.50 1.45 1.51 3/813 14322', ''), (0, stat_output, '')]
+
+ l.run(self.result)
+ expected_result = {
+ 'loadavg': ['1.50', '1.45', '1.51', '3/813', '14322'],
+ 'mpstat':
+ {'cpu':
+ {'%steal': '0.00',
+ '%usr': '11.31',
+ '%gnice': '0.00',
+ '%idle': '81.78',
+ '%iowait': '0.18',
+ '%guest': '5.50',
+ '%sys': '1.19',
+ '%soft': '0.01',
+ '%irq': '0.00',
+ '%nice': '0.03'},
+ 'cpu0':
+ {'%steal': '0.00',
+ '%usr': '20.00',
+ '%gnice': '0.00',
+ '%idle': '71.60',
+ '%iowait': '0.33',
+ '%guest': '6.61',
+ '%sys': '1.37',
+ '%soft': '0.06',
+ '%irq': '0.00',
+ '%nice': '0.03'}}}
+
+ self.assertDictEqual(self.result, expected_result)
+
+ def _read_file(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
new file mode 100644
index 000000000..4fadde4dc
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_cyclictest.py
@@ -0,0 +1,167 @@
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
+#
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.cyclictest.Cyclictest
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import cyclictest
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.cyclictest.ssh')
+class CyclictestTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.scenario_cfg = {
+ "host": "kvm.LF",
+ "setup_options": {
+ "rpm_dir": "/opt/rpm",
+ "host_setup_seqs": [
+ "host-setup0.sh",
+ "host-setup1.sh",
+ "host-run-qemu.sh"
+ ],
+ "script_dir": "/opt/scripts",
+ "image_dir": "/opt/image",
+ "guest_setup_seqs": [
+ "guest-setup0.sh",
+ "guest-setup1.sh"
+ ]
+ },
+ "sla": {
+ "action": "monitor",
+ "max_min_latency": 50,
+ "max_avg_latency": 100,
+ "max_max_latency": 1000
+ },
+ "options": {
+ "priority": 99,
+ "threads": 1,
+ "loops": 1000,
+ "affinity": 1,
+ "interval": 1000,
+ "histogram": 90
+ }
+ }
+ self.context_cfg = {
+ "host": {
+ "ip": "10.229.43.154",
+ "key_filename": "/yardstick/resources/files/yardstick_key",
+ "role": "BareMetal",
+ "name": "kvm.LF",
+ "user": "root"
+ }
+ }
+
+ def test_cyclictest_successful_setup(self, mock_ssh):
+
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ c.setup()
+ self.assertIsNotNone(c.guest)
+ self.assertIsNotNone(c.host)
+ self.assertTrue(c.setup_done)
+
+ def test_cyclictest_successful_no_sla(self, mock_ssh):
+ result = {}
+ self.scenario_cfg.pop("sla", None)
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+ sample_output = '{"min": 100, "avg": 500, "max": 1000}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ c.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_cyclictest_successful_sla(self, mock_ssh):
+ result = {}
+ self.scenario_cfg.update({"sla": {
+ "action": "monitor",
+ "max_min_latency": 100,
+ "max_avg_latency": 500,
+ "max_max_latency": 1000
+ }
+ })
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+ sample_output = '{"min": 100, "avg": 500, "max": 1000}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ c.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_cyclictest_unsuccessful_sla_min_latency(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_min_latency": 10}})
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+ sample_output = '{"min": 100, "avg": 500, "max": 1000}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, c.run, result)
+
+ def test_cyclictest_unsuccessful_sla_avg_latency(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_avg_latency": 10}})
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+ sample_output = '{"min": 100, "avg": 500, "max": 1000}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, c.run, result)
+
+ def test_cyclictest_unsuccessful_sla_max_latency(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_max_latency": 10}})
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+ sample_output = '{"min": 100, "avg": 500, "max": 1000}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, c.run, result)
+
+ def test_cyclictest_unsuccessful_script_error(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_max_latency": 10}})
+ c = cyclictest.Cyclictest(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+
+ c.guest = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, c.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
new file mode 100644
index 000000000..ba63e5f9e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_lmbench.py
@@ -0,0 +1,192 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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 oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import lmbench
+from yardstick.common import exceptions as y_exc
+from yardstick import ssh
+
+
+class LmbenchTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh.stop()
+
+ def test_successful_setup(self):
+
+ l = lmbench.Lmbench({}, self.ctx)
+ self.mock_ssh.from_node().execute.return_value = (0, '', '')
+
+ l.setup()
+ self.assertIsNotNone(l.client)
+ self.assertTrue(l.setup_done)
+
+ def test_unsuccessful_unknown_type_run(self):
+
+ options = {
+ "test_type": "foo"
+ }
+ args = {'options': options}
+
+ l = lmbench.Lmbench(args, self.ctx)
+
+ self.assertRaises(RuntimeError, l.run, self.result)
+
+ def test_successful_latency_run_no_sla(self):
+
+ options = {
+ "test_type": "latency",
+ "stride": 64,
+ "stop_size": 16
+ }
+ args = {'options': options}
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '[{"latency": 4.944, "size": 0.00049}]'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ l.run(self.result)
+ expected_result = {"latencies0.latency": 4.944, "latencies0.size": 0.00049}
+ self.assertEqual(self.result, expected_result)
+
+ def test_successful_bandwidth_run_no_sla(self):
+
+ options = {
+ "test_type": "bandwidth",
+ "size": 500,
+ "benchmark": "rd",
+ "warmup": 0
+ }
+ args = {"options": options}
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 11025.5}'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ l.run(self.result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(self.result, expected_result)
+
+ def test_successful_latency_run_sla(self):
+
+ options = {
+ "test_type": "latency",
+ "stride": 64,
+ "stop_size": 16
+ }
+ args = {
+ "options": options,
+ "sla": {"max_latency": 35}
+ }
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '[{"latency": 4.944, "size": 0.00049}]'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ l.run(self.result)
+ expected_result = {"latencies0.latency": 4.944, "latencies0.size": 0.00049}
+ self.assertEqual(self.result, expected_result)
+
+ def test_successful_bandwidth_run_sla(self):
+
+ options = {
+ "test_type": "bandwidth",
+ "size": 500,
+ "benchmark": "rd",
+ "warmup": 0
+ }
+ args = {
+ "options": options,
+ "sla": {"min_bandwidth": 10000}
+ }
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 11025.5}'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ l.run(self.result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(self.result, expected_result)
+
+ def test_unsuccessful_latency_run_sla(self):
+
+ options = {
+ "test_type": "latency",
+ "stride": 64,
+ "stop_size": 16
+ }
+ args = {
+ "options": options,
+ "sla": {"max_latency": 35}
+ }
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '[{"latency": 37.5, "size": 0.00049}]'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
+
+ def test_unsuccessful_bandwidth_run_sla(self):
+
+ options = {
+ "test_type": "bandwidth",
+ "size": 500,
+ "benchmark": "rd",
+ "warmup": 0
+ }
+ args = {
+ "options": options,
+ "sla": {"min_bandwidth": 10000}
+ }
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = '{"size(MB)": 0.262144, "bandwidth(MBps)": 9925.5}'
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, l.run, self.result)
+
+ def test_successful_latency_for_cache_run_sla(self):
+
+ options = {
+ "test_type": "latency_for_cache",
+ "repetition": 1,
+ "warmup": 0
+ }
+ args = {
+ "options": options,
+ "sla": {"max_latency": 35}
+ }
+ l = lmbench.Lmbench(args, self.ctx)
+
+ sample_output = "{\"L1cache\": 1.6}"
+ self.mock_ssh.from_node().execute.return_value = (0, sample_output, '')
+ l.run(self.result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(self.result, expected_result)
+
+ def test_unsuccessful_script_error(self):
+
+ options = {"test_type": "bandwidth"}
+ args = {"options": options}
+ l = lmbench.Lmbench(args, self.ctx)
+
+ self.mock_ssh.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, l.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py
new file mode 100644
index 000000000..8213d4490
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_memload.py
@@ -0,0 +1,109 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.memload.MEMLoad
+
+from __future__ import absolute_import
+import mock
+import unittest
+import os
+
+from yardstick.benchmark.scenarios.compute import memload
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.memload.ssh')
+class MEMLoadTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_memload_successful_setup(self, mock_ssh):
+ m = memload.MEMLoad({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ m.setup()
+ self.assertIsNotNone(m.client)
+ self.assertTrue(m.setup_done)
+
+ def test_execute_command_success(self, mock_ssh):
+ m = memload.MEMLoad({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ m.setup()
+
+ expected_result = 'abcdefg'
+ mock_ssh.SSH.from_node().execute.return_value = (0, expected_result, '')
+ result = m._execute_command("foo")
+ self.assertEqual(result, expected_result)
+
+ def test_execute_command_failed(self, mock_ssh):
+ m = memload.MEMLoad({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ m.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (127, '', 'Failed executing \
+ command')
+ self.assertRaises(RuntimeError, m._execute_command,
+ "cat /proc/meminfo")
+
+ def test_get_mem_usage_successful(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+ args = {"options": options}
+ m = memload.MEMLoad(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ m.setup()
+
+ output = self._read_file("memload_sample_output.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, output, '')
+ result = m._get_mem_usage()
+ expected_result = {
+ "max": {
+ 'shared': 2844,
+ 'buff/cache': 853528,
+ 'total': 263753976,
+ 'free': 187016644,
+ 'used': 76737332
+ },
+ "average": {
+ 'shared': 2844,
+ 'buff/cache': 853528,
+ 'total': 263753976,
+ 'free': 187016644,
+ 'used': 76737332
+ },
+ "free": {
+ "memory0": {
+ "used": "76737332",
+ "buff/cache": "853528",
+ "free": "187016644",
+ "shared": "2844",
+ "total": "263753976",
+ "available": "67252400"
+ }
+ }
+ }
+
+ self.assertEqual(result, expected_result)
+
+ def _read_file(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py
new file mode 100644
index 000000000..875301729
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_plugintest.py
@@ -0,0 +1,60 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.plugintest.PluginTest
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import plugintest
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.plugintest.ssh')
+class PluginTestTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'nodes': {
+ 'host1': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key",
+ 'password': "root"
+ },
+ }
+ }
+
+ self.result = {}
+
+ def test_sample_successful_setup(self, mock_ssh):
+ s = plugintest.PluginTest({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ s.setup()
+ self.assertIsNotNone(s.client)
+ self.assertTrue(s.setup_done)
+
+ def test_sample_successful(self, mock_ssh):
+ s = plugintest.PluginTest({}, self.ctx)
+
+ sample_output = '{"Test Output": "Hello world!"}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ s.run(self.result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(self.result, expected_result)
+
+ def test_sample_unsuccessful_script_error(self, mock_ssh):
+ s = plugintest.PluginTest({}, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, s.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
new file mode 100644
index 000000000..02040ca01
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_qemumigrate.py
@@ -0,0 +1,158 @@
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
+#
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.qemu_migrate.QemuMigrate
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import qemu_migrate
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.qemu_migrate.ssh')
+class QemuMigrateTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.scenario_cfg = {
+ "host": "kvm.LF",
+ "setup_options": {
+ "rpm_dir": "/opt/rpm",
+ "script_dir": "/opt/scripts",
+ "image_dir": "/opt/image",
+ "host_setup_seqs": [
+ "host-setup0.sh",
+ "host-setup1.sh",
+ "setup-ovsdpdk.sh",
+ "host-install-qemu.sh",
+ "host-run-qemu4lm.sh"
+ ]
+ },
+ "sla": {
+ "action": "monitor",
+ "max_totaltime": 10,
+ "max_downtime": 0.10,
+ "max_setuptime": 0.50
+ },
+ "options": {
+ "smp": 99,
+ "migrate_to_port": 4444,
+ "incoming_ip": 0,
+ "qmp_src_path": "/tmp/qmp-sock-src",
+ "qmp_dst_path": "/tmp/qmp-sock-dst",
+ "max_down_time": "0.10"
+ }
+ }
+ self.context_cfg = {
+ "host": {
+ "ip": "10.229.43.154",
+ "key_filename": "/yardstick/resources/files/yardstick_key",
+ "role": "BareMetal",
+ "name": "kvm.LF",
+ "user": "root"
+ }
+ }
+
+ def test_qemu_migrate_successful_setup(self, mock_ssh):
+
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ q.setup()
+ self.assertIsNotNone(q.host)
+ self.assertTrue(q.setup_done)
+
+ def test_qemu_migrate_successful_no_sla(self, mock_ssh):
+ result = {}
+ self.scenario_cfg.pop("sla", None)
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+ sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ q.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_qemu_migrate_successful_sla(self, mock_ssh):
+ result = {}
+ self.scenario_cfg.update({"sla": {
+ "action": "monitor",
+ "max_totaltime": 15,
+ "max_downtime": 2,
+ "max_setuptime": 1
+ }
+ })
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+ sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ q.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_qemu_migrate_unsuccessful_sla_totaltime(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_totaltime": 10}})
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+ sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, q.run, result)
+
+ def test_qemu_migrate_unsuccessful_sla_downtime(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_downtime": 0.10}})
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+ sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, q.run, result)
+
+ def test_qemu_migrate_unsuccessful_sla_setuptime(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_setuptime": 0.50}})
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+ sample_output = '{"totaltime": 15, "downtime": 2, "setuptime": 1}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, q.run, result)
+
+ def test_qemu_migrate_unsuccessful_script_error(self, mock_ssh):
+
+ result = {}
+ self.scenario_cfg.update({"sla": {"max_totaltime": 10}})
+ q = qemu_migrate.QemuMigrate(self.scenario_cfg, self.context_cfg)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ q.setup()
+
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, q.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
new file mode 100644
index 000000000..9e055befe
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_ramspeed.py
@@ -0,0 +1,236 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.ramspeed.Ramspeed
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.common import utils
+from yardstick.benchmark.scenarios.compute import ramspeed
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.ramspeed.ssh')
+class RamspeedTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_ramspeed_successful_setup(self, mock_ssh):
+
+ r = ramspeed.Ramspeed({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ r.setup()
+ self.assertIsNotNone(r.client)
+ self.assertTrue(r.setup_done, True)
+
+ def test_ramspeed_successful__run_no_sla(self, mock_ssh):
+
+ options = {
+ "test_id": 1,
+ "load": 16,
+ "block_size": 32
+ }
+ args = {"options": options}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 1, "Bandwidth(MBps)": 19909.18}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 2, "Bandwidth(MBps)": 19873.89},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 4, "Bandwidth(MBps)":\
+ 19907.56}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 8,\
+ "Bandwidth(MBps)": 19906.94}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 16, "Bandwidth(MBps)": 19881.74}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 32, "Bandwidth(MBps)": 19395.65},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 64, "Bandwidth(MBps)":\
+ 17623.14}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 128,\
+ "Bandwidth(MBps)": 17677.36}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 256, "Bandwidth(MBps)": 16113.49}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 512, "Bandwidth(MBps)": 14659.19},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 1024, "Bandwidth(MBps)":\
+ 14680.75}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 2048,\
+ "Bandwidth(MBps)": 14756.45}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 4096, "Bandwidth(MBps)": 14604.44}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 8192, "Bandwidth(MBps)": 14159.86},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 16384,\
+ "Bandwidth(MBps)": 14128.94}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 32768, "Bandwidth(MBps)": 8340.85}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ r.run(self.result)
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ self.assertEqual(self.result, expected_result)
+
+ def test_ramspeed_successful_run_sla(self, mock_ssh):
+
+ options = {
+ "test_id": 1,
+ "load": 16,
+ "block_size": 32
+ }
+ args = {"options": options, "sla": {"min_bandwidth": 6000}}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 1, "Bandwidth(MBps)": 19909.18}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 2, "Bandwidth(MBps)": 19873.89},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 4, "Bandwidth(MBps)":\
+ 19907.56}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 8,\
+ "Bandwidth(MBps)": 19906.94}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 16, "Bandwidth(MBps)": 19881.74}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 32, "Bandwidth(MBps)": 19395.65},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 64, "Bandwidth(MBps)":\
+ 17623.14}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 128,\
+ "Bandwidth(MBps)": 17677.36}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 256, "Bandwidth(MBps)": 16113.49}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 512, "Bandwidth(MBps)": 14659.19},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 1024, "Bandwidth(MBps)":\
+ 14680.75}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 2048,\
+ "Bandwidth(MBps)": 14756.45}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 4096, "Bandwidth(MBps)": 14604.44}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 8192, "Bandwidth(MBps)": 14159.86},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 16384,\
+ "Bandwidth(MBps)": 14128.94}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 32768, "Bandwidth(MBps)": 8340.85}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ r.run(self.result)
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ self.assertEqual(self.result, expected_result)
+
+ def test_ramspeed_unsuccessful_run_sla(self, mock_ssh):
+ options = {
+ "test_id": 1,
+ "load": 8,
+ "block_size": 64
+ }
+ args = {"options": options, "sla": {"min_bandwidth": 100000}}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 1, "Bandwidth(MBps)": 5000.18}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 2, "Bandwidth(MBps)": 5000.89},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 4,\
+ "Bandwidth(MBps)": 5000.56}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 8, "Bandwidth(MBps)": 19906.94}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 16, "Bandwidth(MBps)": 19881.74},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 32,\
+ "Bandwidth(MBps)": 19395.65}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 64, "Bandwidth(MBps)": 17623.14}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 128, "Bandwidth(MBps)": 17677.36},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 256, "Bandwidth(MBps)":\
+ 16113.49}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 512,\
+ "Bandwidth(MBps)": 14659.19}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 1024, "Bandwidth(MBps)": 14680.75}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 2048, "Bandwidth(MBps)": 14756.45},\
+ {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 4096, "Bandwidth(MBps)":\
+ 14604.44}, {"Test_type": "INTEGER & WRITING", "Block_size(kb)": 8192,\
+ "Bandwidth(MBps)": 14159.86}, {"Test_type": "INTEGER & WRITING",\
+ "Block_size(kb)": 16384, "Bandwidth(MBps)": 14128.94}, {"Test_type":\
+ "INTEGER & WRITING", "Block_size(kb)": 32768, "Bandwidth(MBps)": 8340.85}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, r.run, self.result)
+
+ def test_ramspeed_unsuccessful_script_error(self, mock_ssh):
+ options = {
+ "test_id": 1,
+ "load": 16,
+ "block_size": 32
+ }
+ args = {"options": options}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, r.run, self.result)
+
+ def test_ramspeed_mem_successful_run_no_sla(self, mock_ssh):
+ options = {
+ "test_id": 3,
+ "load": 16,
+ "block_size": 32,
+ "iteration": 1
+ }
+ args = {"options": options}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER Copy:",\
+ "Bandwidth(MBps)": 8353.97}, {"Test_type": "INTEGER Scale:",\
+ "Bandwidth(MBps)": 9078.59}, {"Test_type": "INTEGER Add:",\
+ "Bandwidth(MBps)": 10057.48}, {"Test_type": "INTEGER Triad:",\
+ "Bandwidth(MBps)": 10116.27}, {"Test_type": "INTEGER AVERAGE:",\
+ "Bandwidth(MBps)": 9401.58}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ r.run(self.result)
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ self.assertEqual(self.result, expected_result)
+
+ def test_ramspeed_mem_successful_run_sla(self, mock_ssh):
+ options = {
+ "test_id": 3,
+ "load": 16,
+ "block_size": 32,
+ "iteration": 1
+ }
+ args = {"options": options, "sla": {"min_bandwidth": 6000}}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER Copy:",\
+ "Bandwidth(MBps)": 8353.97}, {"Test_type": "INTEGER Scale:",\
+ "Bandwidth(MBps)": 9078.59}, {"Test_type": "INTEGER Add:",\
+ "Bandwidth(MBps)": 10057.48}, {"Test_type": "INTEGER Triad:",\
+ "Bandwidth(MBps)": 10116.27}, {"Test_type": "INTEGER AVERAGE:",\
+ "Bandwidth(MBps)": 9401.58}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ r.run(self.result)
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ self.assertEqual(self.result, expected_result)
+
+ def test_ramspeed_mem_unsuccessful_run_sla(self, mock_ssh):
+ options = {
+ "test_id": 3,
+ "load": 16,
+ "block_size": 32,
+ "iteration": 1
+ }
+ args = {"options": options, "sla": {"min_bandwidth": 86000}}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ sample_output = '{"Result": [{"Test_type": "INTEGER Copy:",\
+ "Bandwidth(MBps)": 4000.97}, {"Test_type": "INTEGER Scale:",\
+ "Bandwidth(MBps)": 4400.59}, {"Test_type": "INTEGER Add:",\
+ "Bandwidth(MBps)": 4300.48}, {"Test_type": "INTEGER Triad:",\
+ "Bandwidth(MBps)": 1300.27}, {"Test_type": "INTEGER AVERAGE:",\
+ "Bandwidth(MBps)": 2401.58}]}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, r.run, self.result)
+
+ def test_ramspeed_unsuccessful_unknown_type_run(self, mock_ssh):
+ options = {
+ "test_id": 30,
+ "load": 16,
+ "block_size": 32
+ }
+ args = {'options': options}
+ r = ramspeed.Ramspeed(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'No such type_id: 30 for \
+ Ramspeed scenario')
+ self.assertRaises(RuntimeError, r.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py
new file mode 100644
index 000000000..643e1eae2
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu.py
@@ -0,0 +1,75 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.spec_cpu.SpecCPU
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+
+from yardstick.benchmark.scenarios.compute import spec_cpu
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.spec_cpu.ssh')
+class SpecCPUTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_spec_cpu_successful_setup(self, mock_ssh):
+
+ options = {
+ "SPECint_benchmark": "perlbench",
+ "output_format": "all",
+ "runspec_iterations": "1",
+ "runspec_tune": "base",
+ "runspec_size": "test"
+ }
+ args = {"options": options}
+ s = spec_cpu.SpecCPU(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ s.setup()
+ self.assertIsNotNone(s.client)
+ self.assertTrue(s.setup_done, True)
+
+ def test_spec_cpu_successful__run_no_sla(self, mock_ssh):
+
+ options = {
+ "SPECint_benchmark": "perlbench",
+ "runspec_tune": "all",
+ "output_format": "all"
+ }
+ args = {"options": options}
+ s = spec_cpu.SpecCPU(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ s.run(self.result)
+ expected_result = {}
+ self.assertEqual(self.result, expected_result)
+
+ def test_ramspeed_unsuccessful_script_error(self, mock_ssh):
+ options = {
+ "benchmark_subset": "int"
+ }
+ args = {"options": options}
+ s = spec_cpu.SpecCPU(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, s.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py
new file mode 100644
index 000000000..74ef576b6
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_spec_cpu_for_vm.py
@@ -0,0 +1,76 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.spec_cpu_for_vm.SpecCPUforVM
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+
+from yardstick.benchmark.scenarios.compute import spec_cpu_for_vm
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.spec_cpu_for_vm.ssh')
+class SpecCPUforVMTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_spec_cpu_successful_setup(self, mock_ssh):
+
+ options = {
+ "SPECint_benchmark": "perlbench",
+ "runspec_tune": "all",
+ "output_format": "all",
+ "runspec_iterations": "1",
+ "runspec_size": "test"
+ }
+ args = {"options": options}
+ s = spec_cpu_for_vm.SpecCPUforVM(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ s.setup()
+ self.assertIsNotNone(s.client)
+ self.assertTrue(s.setup_done, True)
+
+ def test_spec_cpu_successful__run_no_sla(self, mock_ssh):
+
+ options = {
+ "SPECint_benchmark": "perlbench",
+ "runspec_tune": "all",
+ "output_format": "all"
+ }
+ args = {"options": options}
+ s = spec_cpu_for_vm.SpecCPUforVM(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_ssh.SSH.from_node().get.return_value = (0, '', '')
+ s.run(self.result)
+ expected_result = {'SPEC_CPU_result': ''}
+ self.assertEqual(self.result, expected_result)
+
+ def test_spec_cpu_unsuccessful_script_error(self, mock_ssh):
+ options = {
+ "benchmark_subset": "int"
+ }
+ args = {"options": options}
+ s = spec_cpu_for_vm.SpecCPUforVM(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, s.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py b/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
new file mode 100644
index 000000000..e4a8d6e26
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/compute/test_unixbench.py
@@ -0,0 +1,163 @@
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
+#
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.compute.unixbench.Unixbench
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.compute import unixbench
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.compute.unixbench.ssh')
+class UnixbenchTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ "host": {
+ "ip": "192.168.50.28",
+ "user": "root",
+ "key_filename": "mykey.key"
+ }
+ }
+
+ def test_unixbench_successful_setup(self, mock_ssh):
+
+ u = unixbench.Unixbench({}, self.ctx)
+ u.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(u.client)
+ self.assertTrue(u.setup_done)
+
+ def test_unixbench_successful_no_sla(self, mock_ssh):
+
+ options = {
+ "test_type": 'dhry2reg',
+ "run_mode": 'verbose'
+ }
+ args = {
+ "options": options,
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+
+ sample_output = '{"Score":"4425.4"}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ u.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_unixbench_successful_in_quiet_mode(self, mock_ssh):
+
+ options = {
+ "test_type": 'dhry2reg',
+ "run_mode": 'quiet',
+ "copies": 1
+ }
+ args = {
+ "options": options,
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+
+ sample_output = '{"Score":"4425.4"}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ u.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_unixbench_successful_sla(self, mock_ssh):
+
+ options = {
+ "test_type": 'dhry2reg',
+ "run_mode": 'verbose'
+ }
+ sla = {
+ "single_score": '100',
+ "parallel_score": '500'
+ }
+ args = {
+ "options": options,
+ "sla": sla
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+
+ sample_output = '{"signle_score":"2251.7","parallel_score":"4395.9"}'
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ u.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ self.assertEqual(result, expected_result)
+
+ def test_unixbench_unsuccessful_sla_single_score(self, mock_ssh):
+
+ args = {
+ "options": {},
+ "sla": {"single_score": "500"}
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+ sample_output = '{"single_score":"200.7","parallel_score":"4395.9"}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, u.run, result)
+
+ def test_unixbench_unsuccessful_sla_parallel_score(self, mock_ssh):
+
+ args = {
+ "options": {},
+ "sla": {"parallel_score": "4000"}
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+ sample_output = '{"signle_score":"2251.7","parallel_score":"3395.9"}'
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, u.run, result)
+
+ def test_unixbench_unsuccessful_script_error(self, mock_ssh):
+
+ options = {
+ "test_type": 'dhry2reg',
+ "run_mode": 'verbose'
+ }
+ sla = {
+ "single_score": '100',
+ "parallel_score": '500'
+ }
+ args = {
+ "options": options,
+ "sla": sla
+ }
+ u = unixbench.Unixbench(args, self.ctx)
+ result = {}
+
+ u.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, u.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/dummy/__init__.py b/yardstick/tests/unit/benchmark/scenarios/dummy/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/dummy/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py b/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py
new file mode 100644
index 000000000..875302da8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/dummy/test_dummy.py
@@ -0,0 +1,32 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.dummy.dummy
+
+from __future__ import absolute_import
+import unittest
+
+from yardstick.benchmark.scenarios.dummy import dummy
+
+
+class DummyTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.test_context = dummy.Dummy(None, None)
+
+ self.assertIsNone(self.test_context.scenario_cfg)
+ self.assertIsNone(self.test_context.context_cfg)
+ self.assertFalse(self.test_context.setup_done)
+
+ def test_run(self):
+ result = {}
+ self.test_context.run(result)
+
+ self.assertEqual(result["hello"], "yardstick")
+ self.assertTrue(self.test_context.setup_done)
diff --git a/yardstick/tests/unit/benchmark/scenarios/energy/__init__.py b/yardstick/tests/unit/benchmark/scenarios/energy/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/energy/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_chassis_output.txt b/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_chassis_output.txt
new file mode 100644
index 000000000..9b3afd1fb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_chassis_output.txt
@@ -0,0 +1,14 @@
+{
+ "@odata.id": "/redfish/v1/Chassis",
+ "Name": "ChassisCollection",
+ "@odata.context": "/redfish/v1/$metadata#ChassisCollection.ChassisCollection",
+ "Members": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.type": "#ChassisCollection.ChassisCollection",
+ "@odata.etag": "\"af5a94479815eb5f87fe91ea08fde0ac\"",
+ "Members@odata.count": 1,
+ "Description": "A collection of Chassis resource instances."
+}
diff --git a/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_power_metrics.txt b/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_power_metrics.txt
new file mode 100644
index 000000000..343ed3667
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/energy/energy_sample_power_metrics.txt
@@ -0,0 +1,300 @@
+{
+ "PowerControl@odata.count": 1,
+ "@odata.id": "/redfish/v1/Chassis/1/Power",
+ "Redundancy@odata.count": 1,
+ "@odata.context": "/redfish/v1/$metadata#Power.Power",
+ "Voltages": [
+ {
+ "MaxReadingRange": 14.28,
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Systems/1"
+ },
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/Voltages/0",
+ "Status": {
+ "State": "Enabled"
+ },
+ "SensorNumber": 140,
+ "Name": "SysBrd 12V",
+ "PhysicalContext": "VoltageRegulator",
+ "LowerThresholdCritical": 10.81,
+ "RelatedItem@odata.count": 2,
+ "MemberId": "0",
+ "MinReadingRange": null,
+ "ReadingVolts": 12.15,
+ "UpperThresholdCritical": 13.22
+ },
+ {
+ "MaxReadingRange": 3.95,
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Systems/1"
+ },
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/Voltages/1",
+ "Status": {
+ "State": "Enabled"
+ },
+ "SensorNumber": 141,
+ "Name": "SysBrd 3.3V",
+ "PhysicalContext": "VoltageRegulator",
+ "LowerThresholdCritical": 2.98,
+ "RelatedItem@odata.count": 2,
+ "MemberId": "1",
+ "MinReadingRange": null,
+ "UpperThresholdCritical": 3.63,
+ "ReadingVolts": 3.36
+ },
+ {
+ "MaxReadingRange": 5.97,
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Systems/1"
+ },
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/Voltages/2",
+ "Status": {
+ "State": "Enabled"
+ },
+ "SensorNumber": 142,
+ "Name": "SysBrd 5V",
+ "PhysicalContext": "VoltageRegulator",
+ "LowerThresholdCritical": 4.49,
+ "RelatedItem@odata.count": 2,
+ "MemberId": "2",
+ "MinReadingRange": null,
+ "UpperThresholdCritical": 5.5,
+ "ReadingVolts": 5.03
+ },
+ {
+ "MaxReadingRange": 3.32,
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Systems/1"
+ },
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/Voltages/3",
+ "Status": {
+ "State": "Enabled"
+ },
+ "SensorNumber": 3,
+ "Name": "CMOS Battery",
+ "PhysicalContext": "VoltageRegulator",
+ "LowerThresholdCritical": 2.25,
+ "RelatedItem@odata.count": 2,
+ "MemberId": "3",
+ "MinReadingRange": null,
+ "LowerThresholdNonCritical": 2.39,
+ "ReadingVolts": 3.12
+ }
+ ],
+ "Voltages@odata.count": 4,
+ "Redundancy": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/Redundancy/0",
+ "Status": {
+ "State": "Enabled",
+ "Health": "OK"
+ },
+ "Name": "PSU Redundancy",
+ "MinNumNeeded": 2,
+ "Oem": {
+ "Lenovo": {
+ "NonRedundantAvailablePower": 1100,
+ "@odata.type": "#LenovoRedundancy.v1_0_0.LenovoRedundancyProperties",
+ "PowerRedundancySettings": {
+ "EstimatedUsage": "58.55%",
+ "MaxPowerLimitWatts": 1100,
+ "PowerFailureLimit": 0,
+ "PowerRedundancyPolicy": "RedundantWithThrottling"
+ }
+ }
+ },
+ "RedundancyEnabled": true,
+ "RedundancySet": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/PowerSupplies/0"
+ },
+ {
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/PowerSupplies/1"
+ }
+ ],
+ "RedundancySet@odata.count": 2,
+ "MaxNumSupported": 2,
+ "Mode": "N+m",
+ "MemberId": "0"
+ }
+ ],
+ "Description": "Power Consumption and Power Limiting",
+ "Name": "Power",
+ "PowerSupplies@odata.count": 2,
+ "Oem": {
+ "Lenovo": {
+ "@odata.type": "#LenovoPower.v1_0_0.Capabilities",
+ "LocalPowerControlEnabled": true,
+ "PowerOnPermissionEnabled": true,
+ "PowerRestorePolicy": "Restore",
+ "WakeOnLANEnabled": true
+ }
+ },
+ "@odata.type": "#Power.v1_5_1.Power",
+ "Id": "Power",
+ "@odata.etag": "\"ad85a1403e07a433386e9907d00565cc\"",
+ "PowerControl": [
+ {
+ "PowerAllocatedWatts": 1100,
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/PowerControl/0",
+ "Status": {
+ "HealthRollup": "Warning",
+ "State": "Enabled"
+ },
+ "PowerLimit": {
+ "LimitException": "NoAction",
+ "LimitInWatts": null
+ },
+ "Name": "Server Power Control",
+ "Oem": {
+ "Lenovo": {
+ "PowerUtilization": {
+ "MaxLimitInWatts": 1100,
+ "EnablePowerCapping": false,
+ "LimitMode": "AC",
+ "EnablePowerCapping@Redfish.Deprecated": "The property is deprecated. Please use LimitInWatts instead.",
+ "CapacityMinAC": 617,
+ "MinLimitInWatts": 0,
+ "GuaranteedInWatts": 617,
+ "CapacityMinDC": 578,
+ "CapacityMaxDC": 749,
+ "CapacityMaxAC": 802
+ },
+ "HistoryPowerMetric": {
+ "@odata.id": "/redfish/v1/Chassis/1/Power/PowerControl/0/Oem/Lenovo/HistoryPowerMetric"
+ },
+ "@odata.type": "#LenovoPower.v1_0_0.PowerControl"
+ }
+ },
+ "PowerAvailableWatts": 0,
+ "PowerMetrics": {
+ "IntervalInMin": 60,
+ "AverageConsumedWatts": 314.716675,
+ "MinConsumedWatts": 311,
+ "MaxConsumedWatts": 318
+ },
+ "RelatedItem@odata.count": 1,
+ "MemberId": "0",
+ "PowerRequestedWatts": 802,
+ "PowerConsumedWatts": 344,
+ "PowerCapacityWatts": 1100
+ }
+ ],
+ "PowerSupplies": [
+ {
+ "SerialNumber": "A4DB8BP11WJ",
+ "InputRanges": [
+ {
+ "InputType": null,
+ "OutputWattage": null,
+ "MinimumVoltage": null,
+ "MaximumVoltage": null
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/PowerSupplies/0",
+ "RelatedItem@odata.count": 1,
+ "MemberId": "0",
+ "PartNumber": "SP57A02023",
+ "FirmwareVersion": "4.52",
+ "Status": {
+ "State": "Enabled",
+ "Health": "Warning"
+ },
+ "LineInputVoltage": null,
+ "Name": "PSU1",
+ "PowerSupplyType": "Unknown",
+ "LastPowerOutputWatts": 316,
+ "Oem": {
+ "Lenovo": {
+ "Location": {
+ "InfoFormat": "Slot X",
+ "Info": "Slot 1"
+ },
+ "HistoryPowerSupplyMetric": {
+ "@odata.id": "/redfish/v1/Chassis/1/Power/PowerSupplies/0/Oem/Lenovo/HistoryPowerSupplyMetric"
+ },
+ "@odata.type": "#LenovoPower.v1_0_0.PowerSupply"
+ }
+ },
+ "PowerCapacityWatts": null,
+ "Manufacturer": "ACBE",
+ "LineInputVoltageType": "Unknown",
+ "Model": "LENOVO-SP57A02023",
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ]
+ },
+ {
+ "SerialNumber": "A4DB8BP12J7",
+ "InputRanges": [
+ {
+ "InputType": "AC",
+ "OutputWattage": 1100,
+ "MinimumVoltage": 200,
+ "MaximumVoltage": 240
+ }
+ ],
+ "@odata.id": "/redfish/v1/Chassis/1/Power#/PowerSupplies/1",
+ "RelatedItem@odata.count": 1,
+ "MemberId": "1",
+ "PartNumber": "SP57A02023",
+ "FirmwareVersion": "4.52",
+ "Status": {
+ "State": "Enabled",
+ "Health": "OK"
+ },
+ "LineInputVoltage": 220,
+ "Name": "PSU2",
+ "PowerSupplyType": "AC",
+ "LastPowerOutputWatts": 316,
+ "Oem": {
+ "Lenovo": {
+ "Location": {
+ "InfoFormat": "Slot X",
+ "Info": "Slot 2"
+ },
+ "HistoryPowerSupplyMetric": {
+ "@odata.id": "/redfish/v1/Chassis/1/Power/PowerSupplies/1/Oem/Lenovo/HistoryPowerSupplyMetric"
+ },
+ "@odata.type": "#LenovoPower.v1_0_0.PowerSupply"
+ }
+ },
+ "PowerCapacityWatts": 1100,
+ "Manufacturer": "ACBE",
+ "LineInputVoltageType": "ACMidLine",
+ "Model": "LENOVO-SP57A02023",
+ "RelatedItem": [
+ {
+ "@odata.id": "/redfish/v1/Chassis/1"
+ }
+ ]
+ }
+ ]
+}
diff --git a/yardstick/tests/unit/benchmark/scenarios/energy/test_energy.py b/yardstick/tests/unit/benchmark/scenarios/energy/test_energy.py
new file mode 100644
index 000000000..98daefeb7
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/energy/test_energy.py
@@ -0,0 +1,182 @@
+##############################################################################
+# Copyright (c) 2019 Lenovo Group Limited 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.energy.energy.Energy
+
+from __future__ import absolute_import
+import unittest
+import mock
+import os
+from yardstick.benchmark.scenarios.energy import energy
+
+
+class EnergyTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'target': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'password': 'passw0rd',
+ 'redfish_ip': '10.229.17.105',
+ 'redfish_user': 'USERID',
+ 'redfish_pwd': "PASSW0RD",
+ }
+ }
+ self.result = {}
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_setup_response_success(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ p.setup()
+ self.assertTrue(p.get_response)
+ self.assertTrue(p.setup_done)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_setup_response_failed(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 404
+ p.setup()
+ self.assertFalse(p.get_response)
+ self.assertTrue(p.setup_done)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_load_chassis_list_success(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ expect_result = self._read_file("energy_sample_chassis_output.txt")
+ expect_result = str(expect_result)
+ expect_result = expect_result.replace("'", '"')
+ mock_send_request.return_value.status_code = 200
+ mock_send_request.return_value.text = expect_result
+ self.result = p.load_chassis_list()
+ self.assertEqual(self.result, ["/redfish/v1/Chassis/1"])
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_load_chassis_response_fail(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 404
+ self.result = p.load_chassis_list()
+ self.assertEqual(self.result, [])
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_load_chassis_wrongtype_response(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ expect_result = {}
+ mock_send_request.return_value.text = expect_result
+ self.result = p.load_chassis_list()
+ self.assertEqual(self.result, [])
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_load_chassis_inproper_key(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ expect_result = '{"some_key": "some_value"}'
+ mock_send_request.return_value.text = expect_result
+ self.result = p.load_chassis_list()
+ self.assertEqual(self.result, [])
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_energy_getpower_success(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ expect_result = self._read_file("energy_sample_power_metrics.txt")
+ expect_result = str(expect_result)
+ expect_result = expect_result.replace("'", '"')
+ mock_send_request.return_value.status_code = 200
+ mock_send_request.return_value.text = expect_result
+ self.result = p.get_power("/redfish/v1/Chassis/1")
+ self.assertEqual(self.result, 344)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_energy_getpower_response_fail(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 404
+ self.result = p.get_power("/redfish/v1/Chassis/1")
+ self.assertEqual(self.result, -1)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_energy_getpower_wrongtype_response(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ expect_result = {}
+ mock_send_request.return_value.text = expect_result
+ self.result = p.get_power("/redfish/v1/Chassis/1")
+ self.assertEqual(self.result, -1)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_energy_getpower_inproper_key(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ expect_result = '{"some_key": "some_value"}'
+ mock_send_request.return_value.text = expect_result
+ self.result = p.get_power("/redfish/v1/Chassis/1")
+ self.assertEqual(self.result, -1)
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_run_success(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ chassis_list = mock.Mock(return_value=["/redfish/v1/Chassis/1"])
+ p.load_chassis_list = chassis_list
+ power = mock.Mock(return_value=344)
+ p.get_power = power
+ p.run(self.result)
+ self.assertEqual(self.result, {"power": 344})
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_run_no_response(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 404
+ chassis_list = mock.Mock(return_value=["/redfish/v1/Chassis/1"])
+ p.load_chassis_list = chassis_list
+ p.run(self.result)
+ self.assertEqual(self.result, {"power": -1})
+
+ @mock.patch('yardstick.benchmark.scenarios.'
+ 'energy.energy.Energy._send_request')
+ def test_run_wrong_chassis(self, mock_send_request):
+ args = {}
+ p = energy.Energy(args, self.ctx)
+ mock_send_request.return_value.status_code = 200
+ chassis_list = mock.Mock(return_value=[])
+ p.load_chassis_list = chassis_list
+ p.run(self.result)
+ self.assertEqual(self.result, {"power": -1})
+
+ def _read_file(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/__init__.py b/yardstick/tests/unit/benchmark/scenarios/lib/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
new file mode 100644
index 000000000..af4f0c8ab
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_add_memory_load.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.add_memory_load import AddMemoryLoad
+
+
+class AddMemoryLoadTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.ssh.SSH.from_node')
+ def test_add_memory_load_with_load(self, mock_from_node):
+ scenario_cfg = {
+ 'options': {
+ 'memory_load': 0.5
+ }
+ }
+ context_cfg = {
+ 'host': {}
+ }
+ mock_from_node().execute.return_value = (0, '0 2048 512', '')
+ obj = AddMemoryLoad(scenario_cfg, context_cfg)
+ obj.run({})
+ mock_from_node.assert_called()
+
+ @mock.patch('yardstick.ssh.SSH.from_node')
+ def test_add_memory_load_without_load(self, mock_from_node):
+ scenario_cfg = {
+ 'options': {
+ 'memory_load': 0
+ }
+ }
+ context_cfg = {
+ 'host': {}
+ }
+ obj = AddMemoryLoad(scenario_cfg, context_cfg)
+ obj.run({})
+ mock_from_node.assert_called_once()
+
+ @mock.patch('yardstick.ssh.SSH.from_node')
+ def test_add_memory_load_without_args(self, mock_from_node):
+ scenario_cfg = {
+ 'options': {
+ }
+ }
+ context_cfg = {
+ 'host': {}
+ }
+ obj = AddMemoryLoad(scenario_cfg, context_cfg)
+ obj.run({})
+ mock_from_node.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
new file mode 100644
index 000000000..bb7fa4536
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_attach_volume.py
@@ -0,0 +1,56 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import attach_volume
+
+
+class AttachVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_attach_volume_to_server = mock.patch.object(
+ openstack_utils, 'attach_volume_to_server')
+ self.mock_attach_volume_to_server = (
+ self._mock_attach_volume_to_server.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(attach_volume, 'LOG')
+ self.mock_log = self._mock_log.start()
+ _uuid = uuidutils.generate_uuid()
+ self.args = {'options': {'server_name_or_id': _uuid,
+ 'volume_name_or_id': _uuid}}
+ self.result = {}
+ self.addCleanup(self._stop_mock)
+ self.attachvol_obj = attach_volume.AttachVolume(self.args, mock.ANY)
+
+ def _stop_mock(self):
+ self._mock_attach_volume_to_server.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_attach_volume_to_server.return_value = True
+ self.assertIsNone(self.attachvol_obj.run(self.result))
+ self.assertEqual({'attach_volume': 1}, self.result)
+ self.mock_log.info.asset_called_once_with(
+ 'Attach volume to server successful!')
+
+ def test_run_fail(self):
+ self.mock_attach_volume_to_server.return_value = False
+ with self.assertRaises(exceptions.ScenarioAttachVolumeError):
+ self.attachvol_obj.run(self.result)
+ self.assertEqual({'attach_volume': 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ 'Attach volume to server failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py
new file mode 100644
index 000000000..a48353a4f
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_connectivity.py
@@ -0,0 +1,78 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.lib.check_connectivity.CheckConnectivity
+
+from __future__ import absolute_import
+
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.lib import check_connectivity
+
+
+class CheckConnectivityTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': 'mykey.key',
+ 'ssh_port': '22'
+ },
+ 'target': {
+ 'ipaddr': '172.16.0.138'
+ }
+ }
+
+ @mock.patch('yardstick.benchmark.scenarios.lib.check_connectivity.ssh')
+ def test_check_connectivity(self, mock_ssh):
+
+ args = {
+ 'options': {'src_ip_addr': '192.168.23.2',
+ 'dest_ip_addr': '192.168.23.10',
+ 'ssh_user': 'root',
+ 'ssh_passwd': 'root',
+ 'ssh_port': '22',
+ 'ssh_timeout': 600,
+ 'ping_parameter': "-s 2048"
+ },
+ 'sla': {'status': 'True',
+ 'action': 'assert'}
+ }
+
+ # TODO(elfoley): Properly check the outputs
+ result = {} # pylint: disable=unused-variable
+
+ obj = check_connectivity.CheckConnectivity(args, {})
+ obj.setup()
+ mock_ssh.SSH.execute.return_value = (0, '100', '')
+
+ @mock.patch('yardstick.benchmark.scenarios.lib.check_connectivity.ssh')
+ def test_check_connectivity_key(self, mock_ssh):
+
+ args = {
+ 'options': {'ssh_user': 'root',
+ 'ssh_key': '/root/.ssh/id_rsa',
+ 'ssh_port': '22',
+ 'ssh_timeout': 600,
+ 'ping_parameter': "-s 2048"
+ },
+ 'sla': {'status': 'True',
+ 'action': 'assert'}
+ }
+
+ # TODO(elfoley): Properly check the outputs
+ result = {} # pylint: disable=unused-variable
+
+ obj = check_connectivity.CheckConnectivity(args, self.ctx)
+ obj.setup()
+
+ mock_ssh.SSH.execute.return_value = (0, '100', '')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
new file mode 100644
index 000000000..270c9d3c9
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_numa_info.py
@@ -0,0 +1,76 @@
+##############################################################################
+# Copyright (c) 2017 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.lib.check_numa_info import CheckNumaInfo
+
+
+class CheckNumaInfoTestCase(unittest.TestCase):
+
+ @mock.patch.object(CheckNumaInfo, '_check_vm2_status')
+ def test_run(self, mock_check_vm2):
+ scenario_cfg = {'info1': {}, 'info2': {}}
+ obj = CheckNumaInfo(scenario_cfg, {})
+ obj.run({})
+ mock_check_vm2.assert_called_once()
+
+ def test_check_vm2_status_length_eq_1(self):
+ info1 = {
+ 'pinning': [0],
+ 'vcpupin': [{
+ 'cpuset': '1,2'
+ }]
+ }
+ info2 = {
+ 'pinning': [0],
+ 'vcpupin': [{
+ 'cpuset': '1,2'
+ }]
+ }
+ scenario_cfg = {'info1': info1, 'info2': info2}
+ obj = CheckNumaInfo(scenario_cfg, {})
+ status = obj._check_vm2_status(info1, info2)
+ self.assertTrue(status)
+
+ def test_check_vm2_status_length_gt_1(self):
+ info1 = {
+ 'pinning': [0, 1],
+ 'vcpupin': [{
+ 'cpuset': '1,2'
+ }]
+ }
+ info2 = {
+ 'pinning': [0, 1],
+ 'vcpupin': [{
+ 'cpuset': '1,2'
+ }]
+ }
+ scenario_cfg = {'info1': info1, 'info2': info2}
+ obj = CheckNumaInfo(scenario_cfg, {})
+ status = obj._check_vm2_status(info1, info2)
+ self.assertFalse(status)
+
+ def test_check_vm2_status_length_not_in_set(self):
+ info1 = {
+ 'pinning': [0],
+ 'vcpupin': [{
+ 'cpuset': '1,7'
+ }]
+ }
+ info2 = {
+ 'pinning': [0],
+ 'vcpupin': [{
+ 'cpuset': '1,7'
+ }]
+ }
+ scenario_cfg = {'info1': info1, 'info2': info2}
+ obj = CheckNumaInfo(scenario_cfg, {})
+ status = obj._check_vm2_status(info1, info2)
+ self.assertFalse(status)
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py
new file mode 100644
index 000000000..b0488bacd
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_check_value.py
@@ -0,0 +1,63 @@
+##############################################################################
+# Copyright (c) 2017 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
+
+from yardstick.benchmark.scenarios.lib import check_value
+from yardstick.common import exceptions as y_exc
+
+
+class CheckValueTestCase(unittest.TestCase):
+
+ def test_eq_pass(self):
+ scenario_cfg = {'options': {'operator': 'eq',
+ 'value1': 1,
+ 'value2': 1}}
+ obj = check_value.CheckValue(scenario_cfg, {})
+ result = obj.run({})
+
+ self.assertEqual({}, result)
+
+ def test_ne_pass(self):
+ scenario_cfg = {'options': {'operator': 'ne',
+ 'value1': 1,
+ 'value2': 2}}
+ obj = check_value.CheckValue(scenario_cfg, {})
+ result = obj.run({})
+
+ self.assertEqual({}, result)
+
+ def test_result(self):
+ scenario_cfg = {'options': {'operator': 'eq',
+ 'value1': 1,
+ 'value2': 1},
+ 'output': 'foo'}
+ obj = check_value.CheckValue(scenario_cfg, {})
+ result = obj.run({})
+
+ self.assertDictEqual(result, {'foo': 'PASS'})
+
+ def test_eq(self):
+ scenario_cfg = {'options': {'operator': 'eq',
+ 'value1': 1,
+ 'value2': 2}}
+ obj = check_value.CheckValue(scenario_cfg, {})
+
+ with self.assertRaises(y_exc.ValueCheckError):
+ result = obj.run({})
+ self.assertEqual({}, result)
+
+ def test_ne(self):
+ scenario_cfg = {'options': {'operator': 'ne',
+ 'value1': 1,
+ 'value2': 1}}
+ obj = check_value.CheckValue(scenario_cfg, {})
+
+ with self.assertRaises(y_exc.ValueCheckError):
+ result = obj.run({})
+ self.assertEqual({}, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
new file mode 100644
index 000000000..0b175fae8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_flavor.py
@@ -0,0 +1,29 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.create_flavor import CreateFlavor
+
+
+class CreateFlavorTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.create_flavor')
+ def test_create_flavor(self, mock_create_flavor):
+ options = {
+ 'flavor_name': 'yardstick_test_flavor',
+ 'vcpus': '2',
+ 'ram': '1024',
+ 'disk': '100',
+ 'is_public': 'True'
+ }
+ args = {"options": options}
+ obj = CreateFlavor(args, {})
+ obj.run({})
+ mock_create_flavor.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_floating_ip.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_floating_ip.py
new file mode 100644
index 000000000..894cc1c2a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_floating_ip.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib import create_floating_ip
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+
+
+class CreateFloatingIpTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_create_floating_ip = mock.patch.object(
+ openstack_utils, 'create_floating_ip')
+ self.mock_create_floating_ip = self._mock_create_floating_ip.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_floating_ip, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'network_name_or_id': 'yardstick_net'}}
+ self.result = {}
+
+ self.fip_obj = create_floating_ip.CreateFloatingIp(self.args, mock.ANY)
+ self.fip_obj.scenario_cfg = {'output': 'key1\nkey2'}
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_floating_ip.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_create_floating_ip.return_value = {'fip_id': 'value1',
+ 'fip_addr': 'value2'}
+ output = self.fip_obj.run(self.result)
+ self.assertEqual({'floating_ip_create': 1}, self.result)
+ self.assertEqual({'key1': 'value1', 'key2': 'value2'}, output)
+ self.mock_log.info.asset_called_once_with(
+ 'Creating floating ip successful!')
+
+ def test_run_no_fip(self):
+ self.mock_create_floating_ip.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateFloatingIPError):
+ self.fip_obj.run(self.result)
+ self.assertEqual({'floating_ip_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ 'Creating floating ip failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py
new file mode 100644
index 000000000..aebd1dfe8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_image.py
@@ -0,0 +1,55 @@
+##############################################################################
+# Copyright (c) 2017 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 mock
+from oslo_utils import uuidutils
+import unittest
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_image
+
+
+class CreateImageTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_create_image = mock.patch.object(
+ openstack_utils, 'create_image')
+ self.mock_create_image = (
+ self._mock_create_image.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_image, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'image_name': 'yardstick_image'}}
+ self.result = {}
+ self.cimage_obj = create_image.CreateImage(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_image.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.cimage_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_image.return_value = _uuid
+ output = self.cimage_obj.run(self.result)
+ self.assertEqual({'image_create': 1}, self.result)
+ self.assertEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with('Create image successful!')
+
+ def test_run_fail(self):
+ self.mock_create_image.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateImageError):
+ self.cimage_obj.run(self.result)
+ self.assertEqual({'image_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Create image failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py
new file mode 100644
index 000000000..a7b683f47
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_keypair.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_keypair
+
+
+class CreateKeypairTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_keypair = mock.patch.object(
+ openstack_utils, 'create_keypair')
+ self.mock_create_keypair = (
+ self._mock_create_keypair.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_keypair, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'key_name': 'yardstick_key'}}
+ self.result = {}
+
+ self.ckeypair_obj = create_keypair.CreateKeypair(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_keypair.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.ckeypair_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_keypair.return_value = {
+ 'name': 'key-name', 'type': 'ssh', 'id': _uuid}
+ output = self.ckeypair_obj.run(self.result)
+ self.assertDictEqual({'keypair_create': 1}, self.result)
+ self.assertDictEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with('Create keypair successful!')
+
+ def test_run_fail(self):
+ self.mock_create_keypair.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateKeypairError):
+ self.ckeypair_obj.run(self.result)
+ self.assertDictEqual({'keypair_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Create keypair failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
new file mode 100644
index 000000000..17a4ef2e1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_network.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_network
+
+
+class CreateNetworkTestCase(unittest.TestCase):
+
+ 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!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
new file mode 100644
index 000000000..bea02a630
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_port.py
@@ -0,0 +1,27 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.create_port import CreatePort
+
+
+class CreatePortTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
+ def test_create_port(self, mock_get_neutron_client):
+ options = {
+ 'openstack_paras': {
+ 'name': 'yardstick_port'
+ }
+ }
+ args = {"options": options}
+ obj = CreatePort(args, {})
+ obj.run({})
+ mock_get_neutron_client.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
new file mode 100644
index 000000000..8d6f119ab
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_router.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_router
+
+
+class CreateRouterTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_neutron_router = mock.patch.object(
+ openstack_utils, 'create_neutron_router')
+ self.mock_create_neutron_router = (
+ self._mock_create_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(create_router, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name': 'yardstick_net'}}
+ self.result = {}
+
+ self.crouter_obj = create_router.CreateRouter(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_neutron_router.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.crouter_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_neutron_router.return_value = _uuid
+ output = self.crouter_obj.run(self.result)
+ self.assertEqual({"router_create": 1}, self.result)
+ self.assertEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with('Create router successful!')
+
+ def test_run_fail(self):
+ self.mock_create_neutron_router.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateRouterError):
+ self.crouter_obj.run(self.result)
+ self.assertEqual({"router_create": 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Create router failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
new file mode 100644
index 000000000..0477a49d4
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_sec_group.py
@@ -0,0 +1,59 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_sec_group
+
+
+class CreateSecurityGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_security_group_full = mock.patch.object(
+ openstack_utils, 'create_security_group_full')
+ self.mock_create_security_group_full = (
+ self._mock_create_security_group_full.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_sec_group, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'sg_name': 'yardstick_sg'}}
+ self.result = {}
+
+ self.csecgp_obj = create_sec_group.CreateSecgroup(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_security_group_full.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.csecgp_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_security_group_full.return_value = _uuid
+ output = self.csecgp_obj.run(self.result)
+ self.assertEqual({'sg_create': 1}, self.result)
+ self.assertEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with(
+ 'Create security group successful!')
+
+ def test_run_fail(self):
+ self.mock_create_security_group_full.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateSecurityGroupError):
+ self.csecgp_obj.run(self.result)
+ self.assertEqual({'sg_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ 'Create security group failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
new file mode 100644
index 000000000..b58785112
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_server.py
@@ -0,0 +1,59 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_server
+
+
+class CreateServerTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_instance_and_wait_for_active = mock.patch.object(
+ openstack_utils, 'create_instance_and_wait_for_active')
+ self.mock_create_instance_and_wait_for_active = (
+ self._mock_create_instance_and_wait_for_active.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_server, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {
+ 'options': {'name': 'server-name', 'image': 'image-name',
+ 'flavor': 'flavor-name'}}
+ self.result = {}
+
+ self.addCleanup(self._stop_mock)
+ self.cserver_obj = create_server.CreateServer(self.args, mock.ANY)
+
+ def _stop_mock(self):
+ self._mock_create_instance_and_wait_for_active.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.cserver_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_instance_and_wait_for_active.return_value = (
+ {'name': 'server-name', 'flavor': 'flavor-name', 'id': _uuid})
+ output = self.cserver_obj.run(self.result)
+ self.assertEqual({'instance_create': 1}, self.result)
+ self.assertEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with('Create server successful!')
+
+ def test_run_fail(self):
+ self.mock_create_instance_and_wait_for_active.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateServerError):
+ self.cserver_obj.run(self.result)
+ self.assertEqual({'instance_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Create server failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
new file mode 100644
index 000000000..856e985c4
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_subnet.py
@@ -0,0 +1,58 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_subnet
+
+
+class CreateSubnetTestCase(unittest.TestCase):
+
+ 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!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
new file mode 100644
index 000000000..f91d2c3f4
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_create_volume.py
@@ -0,0 +1,58 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import create_volume
+
+
+class CreateVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_create_volume = mock.patch.object(
+ openstack_utils, 'create_volume')
+ self.mock_create_volume = (
+ self._mock_create_volume.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_volume, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'size_gb': 1}}
+ self.result = {}
+
+ self.cvolume_obj = create_volume.CreateVolume(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_create_volume.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.cvolume_obj.scenario_cfg = {'output': 'id'}
+ self.mock_create_volume.return_value = {'name': 'yardstick_volume',
+ 'id': _uuid,
+ 'status': 'available'}
+ output = self.cvolume_obj.run(self.result)
+ self.assertDictEqual({'volume_create': 1}, self.result)
+ self.assertDictEqual({'id': _uuid}, output)
+ self.mock_log.info.asset_called_once_with('Create volume successful!')
+
+ def test_run_fail(self):
+ self.mock_create_volume.return_value = None
+ with self.assertRaises(exceptions.ScenarioCreateVolumeError):
+ self.cvolume_obj.run(self.result)
+ self.assertDictEqual({'volume_create': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Create volume failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
new file mode 100644
index 000000000..24dbf8a16
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_flavor.py
@@ -0,0 +1,27 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.delete_flavor import DeleteFlavor
+
+
+class DeleteFlavorTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.delete_flavor')
+ @mock.patch('yardstick.common.openstack_utils.get_nova_client')
+ def test_delete_flavor(self, mock_get_nova_client, mock_delete_flavor):
+ options = {
+ 'flavor_name': 'yardstick_test_flavor'
+ }
+ args = {"options": options}
+ obj = DeleteFlavor(args, {})
+ obj.run({})
+ mock_get_nova_client.assert_called_once()
+ mock_delete_flavor.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
new file mode 100644
index 000000000..45a39eba2
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_floating_ip.py
@@ -0,0 +1,55 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_floating_ip
+
+
+class DeleteFloatingIpTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_floating_ip = mock.patch.object(
+ openstack_utils, 'delete_floating_ip')
+ self.mock_delete_floating_ip = self._mock_delete_floating_ip.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_floating_ip, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'floating_ip_id': uuidutils.generate_uuid()}}
+ self.result = {}
+
+ self.del_obj = delete_floating_ip.DeleteFloatingIp(
+ self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_floating_ip.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_floating_ip.return_value = True
+ self.assertIsNone(self.del_obj.run(self.result))
+ self.assertEqual({"delete_floating_ip": 1}, self.result)
+ self.mock_log.info.assert_called_once_with(
+ "Delete floating ip successful!")
+
+ def test_run_fail(self):
+ self.mock_delete_floating_ip.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteFloatingIPError):
+ self.del_obj.run(self.result)
+ self.assertEqual({"delete_floating_ip": 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ "Delete floating ip failed!")
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
new file mode 100644
index 000000000..8a1d6d695
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_image.py
@@ -0,0 +1,52 @@
+##############################################################################
+# Copyright (c) 2017 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.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_image
+
+
+class DeleteImageTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_image = mock.patch.object(
+ openstack_utils, 'delete_image')
+ self.mock_delete_image = (
+ self._mock_delete_image.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_image, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name_or_id': 'yardstick_image'}}
+ self.result = {}
+
+ self.delimg_obj = delete_image.DeleteImage(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_image.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_image.return_value = True
+ self.assertIsNone(self.delimg_obj.run(self.result))
+ self.assertEqual({'delete_image': 1}, self.result)
+ self.mock_log.info.assert_called_once_with('Delete image successful!')
+
+ def test_run_fail(self):
+ self.mock_delete_image.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteImageError):
+ self.delimg_obj.run(self.result)
+ self.assertEqual({'delete_image': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Delete image failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
new file mode 100644
index 000000000..c7940251e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_keypair.py
@@ -0,0 +1,51 @@
+##############################################################################
+# Copyright (c) 2017 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.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_keypair
+
+
+class DeleteKeypairTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_keypair = mock.patch.object(
+ openstack_utils, 'delete_keypair')
+ self.mock_delete_keypair = self._mock_delete_keypair.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_keypair, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'key_name': 'yardstick_key'}}
+ self.result = {}
+ self.delkey_obj = delete_keypair.DeleteKeypair(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_keypair.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_keypair.return_value = True
+ self.assertIsNone(self.delkey_obj.run(self.result))
+ self.assertEqual({'delete_keypair': 1}, self.result)
+ self.mock_log.info.assert_called_once_with(
+ 'Delete keypair successful!')
+
+ def test_run_fail(self):
+ self.mock_delete_keypair.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteKeypairError):
+ self.delkey_obj.run(self.result)
+ self.assertEqual({'delete_keypair': 0}, self.result)
+ self.mock_log.error.assert_called_once_with("Delete keypair failed!")
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py
new file mode 100644
index 000000000..b6dbf4791
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_network.py
@@ -0,0 +1,54 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_network
+
+
+class DeleteNetworkTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_neutron_net = mock.patch.object(
+ openstack_utils, "delete_neutron_net")
+ self.mock_delete_neutron_net = self._mock_delete_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(delete_network, "LOG")
+ self.mock_log = self._mock_log.start()
+ self.args = {"options": {"network_name_or_id": (
+ uuidutils.generate_uuid())}}
+ self.result = {}
+ self.del_obj = delete_network.DeleteNetwork(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_neutron_net.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_neutron_net.return_value = True
+ self.assertIsNone(self.del_obj.run(self.result))
+ self.assertEqual({"delete_network": 1}, self.result)
+ self.mock_log.info.assert_called_once_with(
+ "Delete network successful!")
+
+ def test_run_fail(self):
+ self.mock_delete_neutron_net.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteNetworkError):
+ self.del_obj.run(self.result)
+ self.assertEqual({"delete_network": 0}, self.result)
+ self.mock_log.error.assert_called_once_with("Delete network failed!")
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
new file mode 100644
index 000000000..9fd318580
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_port.py
@@ -0,0 +1,25 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.delete_port import DeletePort
+
+
+class DeletePortTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
+ def test_delete_port(self, mock_get_neutron_client):
+ options = {
+ 'port_id': '123-123-123'
+ }
+ args = {"options": options}
+ obj = DeletePort(args, {})
+ obj.run({})
+ mock_get_neutron_client.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
new file mode 100644
index 000000000..b76100f19
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router.py
@@ -0,0 +1,54 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_router
+
+
+class DeleteRouterTestCase(unittest.TestCase):
+
+ 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!")
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
new file mode 100644
index 000000000..0c9cf7c17
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_gateway.py
@@ -0,0 +1,27 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.delete_router_gateway import DeleteRouterGateway
+
+
+class DeleteRouterGatewayTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.get_neutron_client')
+ @mock.patch('yardstick.common.openstack_utils.remove_gateway_router')
+ def test_delete_router_gateway(self, mock_get_neutron_client, mock_remove_gateway_router):
+ options = {
+ 'router_id': '123-123-123'
+ }
+ args = {"options": options}
+ obj = DeleteRouterGateway(args, {})
+ obj.run({})
+ mock_get_neutron_client.assert_called_once()
+ mock_remove_gateway_router.assert_called_once()
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
new file mode 100644
index 000000000..823cb951a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_router_interface.py
@@ -0,0 +1,56 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.benchmark.scenarios.lib import delete_router_interface
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+
+
+class DeleteRouterInterfaceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_remove_router_interface = mock.patch.object(
+ openstack_utils, 'remove_router_interface')
+ self.mock_remove_router_interface = (
+ self._mock_remove_router_interface.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_interface, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'router': uuidutils.generate_uuid()}}
+ self.result = {}
+ self.delrout_obj = delete_router_interface.DeleteRouterInterface(
+ self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_remove_router_interface.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_remove_router_interface.return_value = True
+ self.assertIsNone(self.delrout_obj.run(self.result))
+ self.assertEqual({"delete_router_interface": 1}, self.result)
+ self.mock_log.info.assert_called_once_with(
+ "Delete router interface successful!")
+
+ def test_run_fail(self):
+ self.mock_remove_router_interface.return_value = False
+ with self.assertRaises(exceptions.ScenarioRemoveRouterIntError):
+ self.delrout_obj.run(self.result)
+ self.assertEqual({"delete_router_interface": 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ "Delete router interface failed!")
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
new file mode 100644
index 000000000..55fe53df8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_server.py
@@ -0,0 +1,54 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_server
+
+
+class DeleteServerTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_instance = mock.patch.object(
+ openstack_utils, 'delete_instance')
+ self.mock_delete_instance = (
+ self._mock_delete_instance.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_server, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name_or_id': uuidutils.generate_uuid()
+ }}
+ self.result = {}
+
+ self.delserver_obj = delete_server.DeleteServer(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_instance.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_instance.return_value = True
+ self.assertIsNone(self.delserver_obj.run(self.result))
+ self.assertEqual({'delete_server': 1}, self.result)
+ self.mock_log.info.assert_called_once_with('Delete server successful!')
+
+ def test_run_fail(self):
+ self.mock_delete_instance.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteServerError):
+ self.delserver_obj.run(self.result)
+ self.assertEqual({'delete_server': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Delete server failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
new file mode 100644
index 000000000..0db16f396
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_delete_volume.py
@@ -0,0 +1,52 @@
+##############################################################################
+# Copyright (c) 2017 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.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import delete_volume
+
+
+class DeleteVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_delete_volume = mock.patch.object(
+ openstack_utils, 'delete_volume')
+ self.mock_delete_volume = (
+ self._mock_delete_volume.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_volume, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name_or_id': 'yardstick_volume'}}
+ self.result = {}
+
+ self.delvol_obj = delete_volume.DeleteVolume(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_delete_volume.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_delete_volume.return_value = True
+ self.assertIsNone(self.delvol_obj.run(self.result))
+ self.assertEqual({'delete_volume': 1}, self.result)
+ self.mock_log.info.assert_called_once_with('Delete volume successful!')
+
+ def test_run_fail(self):
+ self.mock_delete_volume.return_value = False
+ with self.assertRaises(exceptions.ScenarioDeleteVolumeError):
+ self.delvol_obj.run(self.result)
+ self.assertEqual({'delete_volume': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Delete volume failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
new file mode 100644
index 000000000..2bc57f495
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_detach_volume.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import detach_volume
+
+
+class DetachVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_detach_volume = mock.patch.object(
+ openstack_utils, 'detach_volume')
+ self.mock_detach_volume = (
+ self._mock_detach_volume.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(detach_volume, 'LOG')
+ self.mock_log = self._mock_log.start()
+ _uuid = uuidutils.generate_uuid()
+ self.args = {'options': {'server_name_or_id': _uuid,
+ 'volume_name_or_id': _uuid}}
+ self.result = {}
+
+ self.detachvol_obj = detach_volume.DetachVolume(self.args, mock.ANY)
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_detach_volume.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ self.mock_detach_volume.return_value = True
+ self.assertIsNone(self.detachvol_obj.run(self.result))
+ self.assertEqual({'detach_volume': 1}, self.result)
+ self.mock_log.info.assert_called_once_with(
+ 'Detach volume from server successful!')
+
+ def test_run_fail(self):
+ self.mock_detach_volume.return_value = False
+ with self.assertRaises(exceptions.ScenarioDetachVolumeError):
+ self.detachvol_obj.run(self.result)
+ self.assertEqual({'detach_volume': 0}, self.result)
+ self.mock_log.error.assert_called_once_with(
+ 'Detach volume from server failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
new file mode 100644
index 000000000..1c1364348
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_flavor.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import get_flavor
+
+
+class GetFlavorTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_get_flavor = mock.patch.object(
+ openstack_utils, 'get_flavor')
+ self.mock_get_flavor = self._mock_get_flavor.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(get_flavor, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name_or_id': 'yardstick_flavor'}}
+ self.result = {}
+
+ self.getflavor_obj = get_flavor.GetFlavor(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_get_flavor.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.getflavor_obj.scenario_cfg = {'output': 'flavor'}
+ self.mock_get_flavor.return_value = (
+ {'name': 'flavor-name', 'id': _uuid})
+ output = self.getflavor_obj.run(self.result)
+ self.assertDictEqual({'get_flavor': 1}, self.result)
+ self.assertDictEqual({'flavor': {'name': 'flavor-name', 'id': _uuid}},
+ output)
+ self.mock_log.info.asset_called_once_with('Get flavor successful!')
+
+ def test_run_fail(self):
+ self.mock_get_flavor.return_value = None
+ with self.assertRaises(exceptions.ScenarioGetFlavorError):
+ self.getflavor_obj.run(self.result)
+ self.assertDictEqual({'get_flavor': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Get flavor failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
new file mode 100644
index 000000000..879b2b988
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_migrate_target_host.py
@@ -0,0 +1,43 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.get_migrate_target_host import GetMigrateTargetHost
+
+BASE = 'yardstick.benchmark.scenarios.lib.get_migrate_target_host'
+
+
+class GetMigrateTargetHostTestCase(unittest.TestCase):
+
+ @mock.patch('{}.openstack_utils.get_nova_client'.format(BASE))
+ @mock.patch('{}.GetMigrateTargetHost._get_migrate_host'.format(BASE))
+ @mock.patch('{}.GetMigrateTargetHost._get_current_host_name'.format(BASE))
+ def test_get_migrate_target_host(self,
+ mock_get_current_host_name,
+ mock_get_migrate_host,
+ mock_get_nova_client):
+ obj = GetMigrateTargetHost({}, {})
+ obj.run({})
+ 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):
+ class A(object):
+ def __init__(self, service):
+ self.service = service
+ self.host = 'host4'
+
+ mock_get_nova_client().hosts.list_all.return_value = [A('compute')]
+ obj = GetMigrateTargetHost({}, {})
+ host = obj._get_migrate_host('host5')
+ mock_get_nova_client.assert_called()
+ self.assertEqual(host, 'host4')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
new file mode 100644
index 000000000..bea978b8a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_numa_info.py
@@ -0,0 +1,103 @@
+##############################################################################
+# Copyright (c) 2017 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.benchmark.scenarios.lib.get_numa_info import GetNumaInfo
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+BASE = 'yardstick.benchmark.scenarios.lib.get_numa_info'
+
+
+class GetNumaInfoTestCase(unittest.TestCase):
+
+ @mock.patch('{}.GetNumaInfo._check_numa_node'.format(BASE))
+ @mock.patch('{}.GetNumaInfo._get_current_host_name'.format(BASE))
+ @mock.patch('yardstick.benchmark.scenarios.lib.get_numa_info.yaml_load')
+ @mock.patch('yardstick.common.task_template.TaskTemplate.render')
+ def test_get_numa_info(self,
+ mock_render,
+ mock_safe_load,
+ mock_get_current_host_name,
+ mock_check_numa_node):
+ scenario_cfg = {
+ 'options': {
+ 'server': {
+ 'id': '1'
+ },
+ 'file': 'yardstick/ssh.py'
+ },
+ 'output': 'numa_info'
+ }
+ mock_safe_load.return_value = {
+ 'nodes': []
+ }
+ obj = GetNumaInfo(scenario_cfg, {})
+ obj.run({})
+ 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))
+ @mock.patch('yardstick.benchmark.scenarios.lib.get_numa_info.yaml_load')
+ @mock.patch('yardstick.common.task_template.TaskTemplate.render')
+ def test_check_numa_node(self,
+ mock_render,
+ mock_safe_load,
+ mock_get_current_host_name,
+ mock_from_node):
+ scenario_cfg = {
+ 'options': {
+ 'server': {
+ 'id': '1'
+ },
+ 'file': 'yardstick/ssh.py'
+ },
+ 'output': 'numa_info'
+ }
+ mock_safe_load.return_value = {
+ 'nodes': []
+ }
+ data = """
+ <data>
+ </data>
+ """
+ mock_from_node().execute.return_value = (0, data, '')
+ obj = GetNumaInfo(scenario_cfg, {})
+ result = obj._check_numa_node('1', 'host4')
+ self.assertEqual(result, {'pinning': [], 'vcpupin': []})
+
+ @mock.patch('{}.change_obj_to_dict'.format(BASE))
+ @mock.patch('{}.get_nova_client'.format(BASE))
+ @mock.patch('yardstick.benchmark.scenarios.lib.get_numa_info.yaml_load')
+ @mock.patch('yardstick.common.task_template.TaskTemplate.render')
+ def test_get_current_host_name(self,
+ mock_render,
+ mock_safe_load,
+ mock_get_nova_client,
+ mock_change_obj_to_dict):
+ scenario_cfg = {
+ 'options': {
+ 'server': {
+ 'id': '1'
+ },
+ 'file': 'yardstick/ssh.py'
+ },
+ 'output': 'numa_info'
+ }
+ mock_get_nova_client().servers.get.return_value = ''
+ mock_change_obj_to_dict.return_value = {'OS-EXT-SRV-ATTR:host': 'host5'}
+
+ obj = GetNumaInfo(scenario_cfg, {})
+ result = obj._get_current_host_name('1')
+ self.assertEqual(result, 'host5')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
new file mode 100644
index 000000000..5b5329cb0
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server.py
@@ -0,0 +1,57 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+from oslo_utils import uuidutils
+import unittest
+import mock
+
+from yardstick.common import openstack_utils
+from yardstick.common import exceptions
+from yardstick.benchmark.scenarios.lib import get_server
+
+
+class GetServerTestCase(unittest.TestCase):
+
+ def setUp(self):
+
+ self._mock_get_server = mock.patch.object(
+ openstack_utils, 'get_server')
+ self.mock_get_server = self._mock_get_server.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(get_server, 'LOG')
+ self.mock_log = self._mock_log.start()
+ self.args = {'options': {'name_or_id': 'yardstick_key'}}
+ self.result = {}
+
+ self.getserver_obj = get_server.GetServer(self.args, mock.ANY)
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_get_server.stop()
+ self._mock_get_shade_client.stop()
+ self._mock_log.stop()
+
+ def test_run(self):
+ _uuid = uuidutils.generate_uuid()
+ self.getserver_obj.scenario_cfg = {'output': 'server'}
+ self.mock_get_server.return_value = (
+ {'name': 'server-name', 'id': _uuid})
+ output = self.getserver_obj.run(self.result)
+ self.assertDictEqual({'get_server': 1}, self.result)
+ self.assertDictEqual({'server': {'name': 'server-name', 'id': _uuid}},
+ output)
+ self.mock_log.info.asset_called_once_with('Get Server successful!')
+
+ def test_run_fail(self):
+ self.mock_get_server.return_value = None
+ with self.assertRaises(exceptions.ScenarioGetServerError):
+ self.getserver_obj.run(self.result)
+ self.assertDictEqual({'get_server': 0}, self.result)
+ self.mock_log.error.assert_called_once_with('Get Server failed!')
diff --git a/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py
new file mode 100644
index 000000000..04fca16aa
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/lib/test_get_server_ip.py
@@ -0,0 +1,33 @@
+##############################################################################
+# Copyright (c) 2017 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
+
+from yardstick.benchmark.scenarios.lib.get_server_ip import GetServerIp
+
+
+class GetServerIpTestCase(unittest.TestCase):
+ def test_get_server_ip(self):
+ scenario_cfg = {
+ 'options': {
+ 'server': {
+ 'addresses': {
+ 'net1': [
+ {
+ 'OS-EXT-IPS:type': 'floating',
+ 'addr': '127.0.0.1'
+ }
+ ]
+ }
+ }
+ },
+ 'output': 'ip'
+ }
+ obj = GetServerIp(scenario_cfg, {})
+ result = obj.run({})
+ self.assertEqual(result, {'ip': '127.0.0.1'})
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/__init__.py b/yardstick/tests/unit/benchmark/scenarios/networking/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/imix_voice.yaml b/yardstick/tests/unit/benchmark/scenarios/networking/imix_voice.yaml
new file mode 100644
index 000000000..b8f8e5358
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/imix_voice.yaml
@@ -0,0 +1,41 @@
+# 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.
+
+#imix definition for voice traffic
+#
+# it is a typical case for testing the synthetic VNF performance.
+#
+#percentage of the packets can be less than 100%
+#the traffic in downstream and upstream direction could be different
+
+schema: "nsb:imix:0.1"
+
+imix:
+ private:
+ imix_small: 100 #ipv4 case - 72B should be 0 ipv6 case - 84B
+ imix_128B: 0
+ imix_256B: 0
+ imix_373B: 0
+ imix_570B: 0
+ imix_1400B: 0
+ imix_1500B: 0
+
+ public:
+ imix_small: 100 #ipv4 case - 72B ipv6 - 84B
+ imix_128B: 0
+ imix_256B: 0
+ imix_373B: 0
+ imix_570B: 0
+ imix_1400B: 0
+ imix_1500B: 0
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output.json b/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output.json
new file mode 100644
index 000000000..b56009ba1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output.json
@@ -0,0 +1 @@
+{"start": {"connecting_to": {"host": "172.16.0.252", "port": 5201}, "timestamp": {"timesecs": 1436254758, "time": "Tue, 07 Jul 2015 07:39:18 GMT"}, "test_start": {"protocol": "TCP", "num_streams": 1, "omit": 0, "bytes": 0, "blksize": 131072, "duration": 10, "blocks": 0, "reverse": 0}, "system_info": "Linux client 3.13.0-55-generic #94-Ubuntu SMP Thu Jun 18 00:27:10 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux\n", "version": "iperf 3.0.7", "connected": [{"local_host": "10.0.1.2", "local_port": 37633, "remote_host": "172.16.0.252", "socket": 4, "remote_port": 5201}], "cookie": "client.1436254758.606879.1fb328dc230", "tcp_mss_default": 1448}, "intervals": [{"sum": {"end": 1.00068, "seconds": 1.00068, "bytes": 16996624, "bits_per_second": 135881000.0, "start": 0, "retransmits": 0, "omitted": false}, "streams": [{"end": 1.00068, "socket": 4, "seconds": 1.00068, "bytes": 16996624, "bits_per_second": 135881000.0, "start": 0, "retransmits": 0, "omitted": false, "snd_cwnd": 451776}]}, {"sum": {"end": 2.00048, "seconds": 0.999804, "bytes": 20010192, "bits_per_second": 160113000.0, "start": 1.00068, "retransmits": 0, "omitted": false}, "streams": [{"end": 2.00048, "socket": 4, "seconds": 0.999804, "bytes": 20010192, "bits_per_second": 160113000.0, "start": 1.00068, "retransmits": 0, "omitted": false, "snd_cwnd": 713864}]}, {"sum": {"end": 3.00083, "seconds": 1.00035, "bytes": 18330464, "bits_per_second": 146592000.0, "start": 2.00048, "retransmits": 0, "omitted": false}, "streams": [{"end": 3.00083, "socket": 4, "seconds": 1.00035, "bytes": 18330464, "bits_per_second": 146592000.0, "start": 2.00048, "retransmits": 0, "omitted": false, "snd_cwnd": 768888}]}, {"sum": {"end": 4.00707, "seconds": 1.00624, "bytes": 19658376, "bits_per_second": 156292000.0, "start": 3.00083, "retransmits": 0, "omitted": false}, "streams": [{"end": 4.00707, "socket": 4, "seconds": 1.00624, "bytes": 19658376, "bits_per_second": 156292000.0, "start": 3.00083, "retransmits": 0, "omitted": false, "snd_cwnd": 812328}]}, {"sum": {"end": 5.00104, "seconds": 0.993972, "bytes": 15709072, "bits_per_second": 126435000.0, "start": 4.00707, "retransmits": 0, "omitted": false}, "streams": [{"end": 5.00104, "socket": 4, "seconds": 0.993972, "bytes": 15709072, "bits_per_second": 126435000.0, "start": 4.00707, "retransmits": 0, "omitted": false, "snd_cwnd": 849976}]}, {"sum": {"end": 6.00049, "seconds": 0.999443, "bytes": 19616288, "bits_per_second": 157018000.0, "start": 5.00104, "retransmits": 53, "omitted": false}, "streams": [{"end": 6.00049, "socket": 4, "seconds": 0.999443, "bytes": 19616288, "bits_per_second": 157018000.0, "start": 5.00104, "retransmits": 53, "omitted": false, "snd_cwnd": 641464}]}, {"sum": {"end": 7.00085, "seconds": 1.00036, "bytes": 22250480, "bits_per_second": 177939000.0, "start": 6.00049, "retransmits": 0, "omitted": false}, "streams": [{"end": 7.00085, "socket": 4, "seconds": 1.00036, "bytes": 22250480, "bits_per_second": 177939000.0, "start": 6.00049, "retransmits": 0, "omitted": false, "snd_cwnd": 706624}]}, {"sum": {"end": 8.00476, "seconds": 1.00391, "bytes": 22282240, "bits_per_second": 177564000.0, "start": 7.00085, "retransmits": 0, "omitted": false}, "streams": [{"end": 8.00476, "socket": 4, "seconds": 1.00391, "bytes": 22282240, "bits_per_second": 177564000.0, "start": 7.00085, "retransmits": 0, "omitted": false, "snd_cwnd": 761648}]}, {"sum": {"end": 9.0016, "seconds": 0.996847, "bytes": 19657680, "bits_per_second": 157759000.0, "start": 8.00476, "retransmits": 28, "omitted": false}, "streams": [{"end": 9.0016, "socket": 4, "seconds": 0.996847, "bytes": 19657680, "bits_per_second": 157759000.0, "start": 8.00476, "retransmits": 28, "omitted": false, "snd_cwnd": 570512}]}, {"sum": {"end": 10.0112, "seconds": 1.00955, "bytes": 20932520, "bits_per_second": 165876000.0, "start": 9.0016, "retransmits": 0, "omitted": false}, "streams": [{"end": 10.0112, "socket": 4, "seconds": 1.00955, "bytes": 20932520, "bits_per_second": 165876000.0, "start": 9.0016, "retransmits": 0, "omitted": false, "snd_cwnd": 615400}]}], "end": {"sum_received": {"seconds": 10.0112, "start": 0, "end": 10.0112, "bytes": 193366712, "bits_per_second": 154521000.0}, "streams": [{"sender": {"end": 10.0112, "socket": 4, "seconds": 10.0112, "bytes": 195443936, "bits_per_second": 156181000.0, "start": 0, "retransmits": 81}, "receiver": {"end": 10.0112, "socket": 4, "seconds": 10.0112, "bytes": 193366712, "bits_per_second": 154521000.0, "start": 0}}], "sum_sent": {"end": 10.0112, "seconds": 10.0112, "bytes": 195443936, "bits_per_second": 156181000.0, "start": 0, "retransmits": 81}, "cpu_utilization_percent": {"remote_user": 1.10295, "remote_system": 40.0403, "host_user": 2.41785, "remote_total": 41.1438, "host_system": 5.09548, "host_total": 7.51411}}} \ No newline at end of file
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output_udp.json b/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output_udp.json
new file mode 100644
index 000000000..8173c8f64
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/iperf3_sample_output_udp.json
@@ -0,0 +1 @@
+{"start":{"connected":[{"socket":4, "local_host":"10.0.1.2", "local_port":46384, "remote_host":"172.16.9.195", "remote_port":5201}], "version":"iperf 3.0.7", "system_info":"Linux zeus 3.13.0-61-generic #100-Ubuntu SMP Wed Jul 29 11:21:34 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux\n", "timestamp":{"time":"Tue, 29 Sep 2015 01:48:23 GMT", "timesecs":1443491303}, "connecting_to":{"host":"172.16.9.195", "port":5201}, "cookie":"zeus.1443491303.539703.3479129b58a5b", "test_start":{"protocol":"UDP", "num_streams":1, "blksize":8192, "omit":0, "duration":10, "bytes":0, "blocks":0, "reverse":0}}, "intervals":[{"streams":[{"socket":4, "start":0, "end":1.00022, "seconds":1.00022, "bytes":2252800, "bits_per_second":1.80184e+07, "packets":275, "omitted":false}], "sum":{"start":0, "end":1.00022, "seconds":1.00022, "bytes":2252800, "bits_per_second":1.80184e+07, "packets":275, "omitted":false}}, {"streams":[{"socket":4, "start":1.00022, "end":2.00022, "seconds":0.999993, "bytes":2498560, "bits_per_second":1.99886e+07, "packets":305, "omitted":false}], "sum":{"start":1.00022, "end":2.00022, "seconds":0.999993, "bytes":2498560, "bits_per_second":1.99886e+07, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":2.00022, "end":3.00022, "seconds":1, "bytes":2506752, "bits_per_second":2.0054e+07, "packets":306, "omitted":false}], "sum":{"start":2.00022, "end":3.00022, "seconds":1, "bytes":2506752, "bits_per_second":2.0054e+07, "packets":306, "omitted":false}}, {"streams":[{"socket":4, "start":3.00022, "end":4.00022, "seconds":1, "bytes":2498560, "bits_per_second":19988480, "packets":305, "omitted":false}], "sum":{"start":3.00022, "end":4.00022, "seconds":1, "bytes":2498560, "bits_per_second":19988480, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":4.00022, "end":5.0002, "seconds":0.999977, "bytes":2498560, "bits_per_second":1.99889e+07, "packets":305, "omitted":false}], "sum":{"start":4.00022, "end":5.0002, "seconds":0.999977, "bytes":2498560, "bits_per_second":1.99889e+07, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":5.0002, "end":6.00024, "seconds":1.00004, "bytes":2498560, "bits_per_second":1.99877e+07, "packets":305, "omitted":false}], "sum":{"start":5.0002, "end":6.00024, "seconds":1.00004, "bytes":2498560, "bits_per_second":1.99877e+07, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":6.00024, "end":7.00023, "seconds":0.999998, "bytes":2498560, "bits_per_second":1.99885e+07, "packets":305, "omitted":false}], "sum":{"start":6.00024, "end":7.00023, "seconds":0.999998, "bytes":2498560, "bits_per_second":1.99885e+07, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":7.00023, "end":8.00023, "seconds":0.999999, "bytes":2506752, "bits_per_second":2.0054e+07, "packets":306, "omitted":false}], "sum":{"start":7.00023, "end":8.00023, "seconds":0.999999, "bytes":2506752, "bits_per_second":2.0054e+07, "packets":306, "omitted":false}}, {"streams":[{"socket":4, "start":8.00023, "end":9.00018, "seconds":0.999945, "bytes":2498560, "bits_per_second":1.99896e+07, "packets":305, "omitted":false}], "sum":{"start":8.00023, "end":9.00018, "seconds":0.999945, "bytes":2498560, "bits_per_second":1.99896e+07, "packets":305, "omitted":false}}, {"streams":[{"socket":4, "start":9.00018, "end":10.0002, "seconds":1.00004, "bytes":2498560, "bits_per_second":1.99876e+07, "packets":305, "omitted":false}], "sum":{"start":9.00018, "end":10.0002, "seconds":1.00004, "bytes":2498560, "bits_per_second":1.99876e+07, "packets":305, "omitted":false}}], "end":{"streams":[{"udp":{"socket":4, "start":0, "end":10.0002, "seconds":10.0002, "bytes":24756224, "bits_per_second":1.98045e+07, "jitter_ms":0.0113579, "lost_packets":0, "packets":3022, "lost_percent":0}}], "sum":{"start":0, "end":10.0002, "seconds":10.0002, "bytes":24756224, "bits_per_second":1.98045e+07, "jitter_ms":0.0113579, "lost_packets":0, "packets":3022, "lost_percent":0}, "cpu_utilization_percent":{"host_total":0.647561, "host_user":0.146468, "host_system":0.501083, "remote_total":0.31751, "remote_user":0, "remote_system":0.31751}}}
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_1flow_Packets_vpe.yaml b/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_1flow_Packets_vpe.yaml
new file mode 100644
index 000000000..f3046f463
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_1flow_Packets_vpe.yaml
@@ -0,0 +1,18 @@
+# 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.
+
+flow:
+ srcip4_range: '152.16.0.20'
+ dstip4_range: '152.40.0.20'
+ count: 1
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_throughput_vpe.yaml b/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_throughput_vpe.yaml
new file mode 100644
index 000000000..2123e4705
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/ipv4_throughput_vpe.yaml
@@ -0,0 +1,101 @@
+# 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.
+
+# flow definition for ACL tests - 1K flows - ipv4 only
+#
+# the number of flows defines the widest range of parameters
+# for example if srcip_range=1.0.0.1-1.0.0.255 and dst_ip_range=10.0.0.1-10.0.1.255
+# and it should define only 16 flows
+#
+#there is assumption that packets generated will have a random sequences of following addresses pairs
+# in the packets
+# 1. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+# 2. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+# ...
+# 512. src=1.x.x.x(x.x.x =random from 1..255) dst=10.x.x.x (random from 1..512)
+#
+# not all combination should be filled
+# Any other field with random range will be added to flow definition
+#
+# the example.yaml provides all possibilities for traffic generation
+#
+# the profile defines a public and private side to make limited traffic correlation
+# between private and public side same way as it is made by IXIA solution.
+#
+schema: "isb:traffic_profile:0.1"
+
+# This file is a template, it will be filled with values from tc.yaml before passing to the traffic generator
+
+name: rfc2544
+description: Traffic profile to run RFC2544 latency
+traffic_profile:
+ traffic_type : RFC2544Profile # defines traffic behavior - constant or look for highest possible throughput
+ frame_rate : 100 # pc of linerate
+ # that specifies a range (e.g. ipv4 address, port)
+
+
+private:
+ ipv4:
+ outer_l2:
+ framesize:
+ 64B: "{{ get(imix, 'imix.uplink.imix_small', '0') }}"
+ 128B: "{{ get(imix, 'imix.uplink.imix_128B', '0') }}"
+ 256B: "{{ get(imix, 'imix.uplink.imix_256B', '0') }}"
+ 373b: "{{ get(imix, 'imix.uplink.imix_373B', '0') }}"
+ 570B: "{{get(imix, 'imix.uplink.imix_570B', '0') }}"
+ 1400B: "{{get(imix, 'imix.uplink.imix_1400B', '0') }}"
+ 1518B: "{{get(imix, 'imix.uplink.imix_1500B', '0') }}"
+
+ QinQ:
+ S-VLAN:
+ id: 128
+ priority: 0
+ cfi: 0
+ C-VLAN:
+ id: 512
+ priority: 0
+ cfi: 0
+
+ outer_l3v4:
+ proto: "tcp"
+ srcip4: "{{get(flow, 'flow.srcip4_range', '192.168.0.0-192.168.255.255') }}"
+ dstip4: "{{get(flow, 'flow.dstip4_range', '192.16.0.0-192.16.0.31') }}"
+ ttl: 32
+ dscp: 32
+
+ outer_l4:
+ srcport: "{{get(flow, 'flow.srcport_range', '0') }}"
+ dstport: "{{get(flow, 'flow.dstport_range', '0') }}"
+public:
+ ipv4:
+ outer_l2:
+ framesize:
+ 64B: "{{ get(imix, 'imix.uplink.imix_small', '0') }}"
+ 128B: "{{ get(imix, 'imix.uplink.imix_128B', '0') }}"
+ 256B: "{{ get(imix, 'imix.uplink.imix_256B', '0') }}"
+ 373b: "{{ get(imix, 'imix.uplink.imix_373B', '0') }}"
+ 570B: "{{get(imix, 'imix.uplink.imix_570B', '0') }}"
+ 1400B: "{{get(imix, 'imix.uplink.imix_1400B', '0') }}"
+ 1518B: "{{get(imix, 'imix.uplink.imix_1500B', '0') }}"
+
+ outer_l3v4:
+ proto: "tcp"
+ srcip4: "{{get(flow, 'flow.dstip4_range', '192.16.0.0-192.16.0.31') }}"
+ dstip4: "{{get(flow, 'flow.srcip4_range', '192.168.0.0-192.168.255.255') }}"
+ ttl: 32
+ dscp: 32
+
+ outer_l4:
+ srcport: "{{get(flow, 'flow.dstport_range', '0') }}"
+ dstport: "{{get(flow, 'flow.srcport_range', '0') }}"
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/netperf_sample_output.json b/yardstick/tests/unit/benchmark/scenarios/networking/netperf_sample_output.json
new file mode 100755
index 000000000..bba76cfa5
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/netperf_sample_output.json
@@ -0,0 +1 @@
+{"mean_latency":"9.49","troughput":"823.77","troughput_unit":"10^6bits/s"} \ No newline at end of file
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output1.txt b/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output1.txt
new file mode 100644
index 000000000..f90457cb3
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output1.txt
@@ -0,0 +1,9 @@
+Linux 3.19.0-25-generic (huawei-pod4) 07/19/2016 _x86_64_ (1 CPU)
+
+02:01:50 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
+02:01:51 PM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+02:01:51 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+
+Average: IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
+Average: eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+Average: lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output2.txt b/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output2.txt
new file mode 100644
index 000000000..417613ec1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/netutilization_sample_output2.txt
@@ -0,0 +1,13 @@
+Linux 3.19.0-25-generic (huawei-pod4) 07/19/2016 _x86_64_ (1 CPU)
+
+02:01:50 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
+02:01:51 PM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+02:01:51 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+
+02:01:52 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
+02:01:53 PM eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+02:01:53 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+
+Average: IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
+Average: eth0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
+Average: lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
new file mode 100644
index 000000000..5f342df7d
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_iperf3.py
@@ -0,0 +1,190 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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 os
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.common import utils
+from yardstick.benchmark.scenarios.networking import iperf3
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch.object(iperf3, 'ssh')
+class IperfTestCase(unittest.TestCase):
+ output_name_tcp = 'iperf3_sample_output.json'
+ output_name_udp = 'iperf3_sample_output_udp.json'
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': 'mykey.key'
+ },
+ 'target': {
+ 'ip': '172.16.0.138',
+ 'user': 'root',
+ 'key_filename': 'mykey.key',
+ 'ipaddr': '172.16.0.138',
+ }
+ }
+ self._mock_log_info = mock.patch.object(iperf3.LOG, 'info')
+ self.mock_log_info = self._mock_log_info.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_log_info.stop()
+
+ def test_iperf_successful_setup(self, mock_ssh):
+ p = iperf3.Iperf({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p.setup()
+ self.assertIsNotNone(p.target)
+ self.assertIsNotNone(p.host)
+ mock_ssh.SSH.from_node().execute.assert_called_with("iperf3 -s -D")
+
+ def test_iperf_unsuccessful_setup(self, mock_ssh):
+ p = iperf3.Iperf({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.setup)
+
+ def test_iperf_successful_teardown(self, mock_ssh):
+ p = iperf3.Iperf({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+ p.target = mock_ssh.SSH.from_node()
+
+ p.teardown()
+ 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):
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_tcp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_iperf_successful_sla(self, mock_ssh):
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'bytes_per_second': 15000000}
+ }
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_tcp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_iperf_unsuccessful_sla(self, mock_ssh):
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'bytes_per_second': 25000000}
+ }
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_tcp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_iperf_successful_sla_jitter(self, mock_ssh):
+ options = {"protocol": "udp", "bandwidth": "20m"}
+ args = {
+ 'options': options,
+ 'sla': {'jitter': 10}
+ }
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_udp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_iperf_unsuccessful_sla_jitter(self, mock_ssh):
+ options = {"protocol": "udp", "bandwidth": "20m"}
+ args = {
+ 'options': options,
+ 'sla': {'jitter': 0.0001}
+ }
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_udp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_iperf_successful_tcp_protocal(self, mock_ssh):
+ options = {"protocol": "tcp", "nodelay": "yes"}
+ args = {
+ 'options': options,
+ 'sla': {'bytes_per_second': 15000000}
+ }
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.output_name_tcp)
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = utils.flatten_dict_key(jsonutils.loads(sample_output))
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_iperf_unsuccessful_script_error(self, mock_ssh):
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = iperf3.Iperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ @staticmethod
+ def _read_sample_output(filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py
new file mode 100644
index 000000000..620155c7e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_moongen_testpmd.py
@@ -0,0 +1,353 @@
+#!/usr/bin/env python
+
+# Copyright 2017 Nokia
+#
+# 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.
+
+# Unittest for yardstick.benchmark.scenarios.networking.MoongenTestPMD
+
+from __future__ import absolute_import
+try:
+ from unittest import mock
+except ImportError:
+ import mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import moongen_testpmd
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.moongen_testpmd.subprocess')
+class MoongenTestPMDTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ "host": {
+ "ip": "10.229.47.137",
+ "user": "ubuntu",
+ "password": "ubuntu",
+ },
+ }
+ self.TestPMDargs = {
+ 'task_id': "1234-5678",
+ 'options': {
+ 'multistream': 1,
+ 'frame_size': 1024,
+ 'testpmd_queue': 2,
+ 'trafficgen_port1': 'ens5',
+ 'trafficgen_port2': 'ens6',
+ 'moongen_host_user': 'root',
+ 'moongen_host_passwd': 'root',
+ 'moongen_host_ip': '10.5.201.151',
+ 'moongen_dir': '/home/lua-trafficgen',
+ 'moongen_runBidirec': 'true',
+ 'Package_Loss': 0,
+ 'SearchRuntime': 60,
+ 'moongen_port1_mac': '88:cf:98:2f:4d:ed',
+ 'moongen_port2_mac': '88:cf:98:2f:4d:ee',
+ 'forward_type': 'testpmd',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_mpps',
+ 'throughput_rx_mpps': 0.5,
+ 'action': 'monitor',
+ }
+ }
+ self.L2fwdargs = {
+ 'task_id': "1234-5678",
+ 'options': {
+ 'multistream': 1,
+ 'frame_size': 1024,
+ 'testpmd_queue': 2,
+ 'trafficgen_port1': 'ens5',
+ 'trafficgen_port2': 'ens6',
+ 'moongen_host_user': 'root',
+ 'moongen_host_passwd': 'root',
+ 'moongen_host_ip': '10.5.201.151',
+ 'moongen_dir': '/home/lua-trafficgen',
+ 'moongen_runBidirec': 'true',
+ 'Package_Loss': 0,
+ 'SearchRuntime': 60,
+ 'moongen_port1_mac': '88:cf:98:2f:4d:ed',
+ 'moongen_port2_mac': '88:cf:98:2f:4d:ee',
+ 'forward_type': 'l2fwd',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_mpps',
+ 'throughput_rx_mpps': 0.5,
+ 'action': 'monitor',
+ }
+ }
+
+ self._mock_ssh = mock.patch(
+ 'yardstick.benchmark.scenarios.networking.moongen_testpmd.ssh')
+ self.mock_ssh = self._mock_ssh.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_ssh.stop()
+
+ def test_MoongenTestPMD_setup(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_MoongenTestPMD_teardown(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.teardown()
+ self.assertFalse(p.setup_done)
+
+ def test_MoongenTestPMD_l2fwd_is_forward_setup_no(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ result = p._is_forward_setup()
+ self.assertFalse(result)
+
+ def test_MoongenTestPMD_l2fwd_is_forward_setup_yes(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ result = p._is_forward_setup()
+ self.assertTrue(result)
+
+ def test_MoongenTestPMD_testpmd_is_forward_setup_no(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ result = p._is_forward_setup()
+ self.assertFalse(result)
+
+ def test_MoongenTestPMD_testpmd_is_forward_setup_yes(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ result = p._is_forward_setup()
+ self.assertTrue(result)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_testpmd_forward_setup_first(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+
+ p.forward_setup()
+ self.assertFalse(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_testpmd_dpdk_setup_next(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.forward_setup()
+ self.assertTrue(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_l2fwd_forward_setup_first(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p.forward_setup()
+ self.assertFalse(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ @mock.patch('time.sleep')
+ def test_MoongenTestPMD_l2fwd_dpdk_setup_next(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.L2fwdargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, 'dummy', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ p.forward_setup()
+ self.assertTrue(p._is_forward_setup())
+ self.assertTrue(p.forward_setup_done)
+
+ def test_moongen_testpmd_generate_config_file(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ mock_subprocess.call().execute.return_value = None
+
+ p.generate_config_file(frame_size=1, multistream=1,
+ runBidirec="True", tg_port1_vlan=1,
+ tg_port2_vlan=2, SearchRuntime=1,
+ Package_Loss=0)
+ self.assertTrue(p.CONFIG_FILE)
+
+ def test_moongen_testpmd_result_to_data_match(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ mock_subprocess.call().execute.return_value = None
+ result = ("[REPORT]Device 1->0: Tx frames: 420161490 Rx Frames: 420161490"
+ " frame loss: 0, 0.000000% Rx Mpps: 7.002708\n[REPORT] "
+ "total: Tx frames: 840321216 Rx Frames: 840321216 frame loss: "
+ "0, 0.000000% Tx Mpps: 14.005388 Rx Mpps: 14.005388\n'")
+ p.result_to_data(result=result)
+ self.assertTrue(p.TO_DATA)
+
+ def test_moongen_testpmd_result_to_data_not_match(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ mock_subprocess.call().execute.return_value = None
+ result = ("")
+ p.result_to_data(result=result)
+ self.assertTrue(p.TO_DATA)
+
+ @mock.patch('time.sleep')
+ def test_moongen_testpmd_run_ok(self, _, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+ p.setup_done = True
+ p.forward_setup_done = True
+ p.setup()
+
+ # run() specific mocks
+ p.server = self.mock_ssh.SSH.from_node()
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ result = ("[REPORT]Device 1->0: Tx frames: 420161490 Rx Frames: 420161490"
+ " frame loss: 0, 0.000000% Rx Mpps: 7.002708\n[REPORT] "
+ "total: Tx frames: 840321216 Rx Frames: 840321216 frame loss: "
+ "0, 0.000000% Tx Mpps: 14.005388 Rx Mpps: 14.005388\n'")
+ self.mock_ssh.SSH.from_node().execute.return_value = (
+ 0, result, '')
+
+ test_result = {}
+ p.run(test_result)
+
+ self.assertEqual(test_result['rx_mpps'], 14.005388)
+
+ def test_moongen_testpmd_run_falied_vsperf_execution(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # run() specific mocks
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ self.mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ result = {}
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def test_moongen_testpmd_run_falied_csv_report(self, mock_subprocess):
+ p = moongen_testpmd.MoongenTestPMD(self.TestPMDargs, self.ctx)
+
+ # setup() specific mocks
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ mock_subprocess.call().execute.return_value = None
+
+ p.setup()
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ # run() specific mocks
+ mock_subprocess.call().execute.return_value = None
+ mock_subprocess.call().execute.return_value = None
+ self.mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ result = {}
+ self.assertRaises(RuntimeError, p.run, result)
+
+def main():
+ unittest.main()
+
+
+if __name__ == '__main__':
+ main()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
new file mode 100755
index 000000000..a7abcd98a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf.py
@@ -0,0 +1,122 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.networking.netperf.Netperf
+
+from __future__ import absolute_import
+
+import os
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.networking import netperf
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.netperf.ssh')
+class NetperfTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': 'mykey.key'
+ },
+ 'target': {
+ 'ip': '172.16.0.138',
+ 'user': 'cirros',
+ 'key_filename': 'mykey.key',
+ 'ipaddr': '172.16.0.138'
+ }
+ }
+
+ def test_netperf_successful_setup(self, mock_ssh):
+
+ p = netperf.Netperf({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p.setup()
+ self.assertIsNotNone(p.server)
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_netperf_successful_no_sla(self, mock_ssh):
+
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = netperf.Netperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = jsonutils.loads(sample_output)
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_netperf_successful_sla(self, mock_ssh):
+
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'mean_latency': 100}
+ }
+ result = {}
+
+ p = netperf.Netperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = jsonutils.loads(sample_output)
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_netperf_unsuccessful_sla(self, mock_ssh):
+
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'mean_latency': 5}
+ }
+ result = {}
+
+ p = netperf.Netperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_netperf_unsuccessful_script_error(self, mock_ssh):
+
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = netperf.Netperf(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def _read_sample_output(self):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, 'netperf_sample_output.json')
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
new file mode 100755
index 000000000..a577dba59
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netperf_node.py
@@ -0,0 +1,122 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.networking.netperf_node.NetperfNode
+
+from __future__ import absolute_import
+
+import os
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.networking import netperf_node
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.netperf_node.ssh')
+class NetperfNodeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '192.168.10.10',
+ 'user': 'root',
+ 'password': 'root'
+ },
+ 'target': {
+ 'ip': '192.168.10.11',
+ 'user': 'root',
+ 'password': 'root'
+ }
+ }
+
+ def test_netperf_node_successful_setup(self, mock_ssh):
+
+ p = netperf_node.NetperfNode({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p.setup()
+ self.assertIsNotNone(p.server)
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_netperf_node_successful_no_sla(self, mock_ssh):
+
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = netperf_node.NetperfNode(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = jsonutils.loads(sample_output)
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_netperf_node_successful_sla(self, mock_ssh):
+
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'mean_latency': 100}
+ }
+ result = {}
+
+ p = netperf_node.NetperfNode(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ expected_result = jsonutils.loads(sample_output)
+ p.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_netperf_node_unsuccessful_sla(self, mock_ssh):
+
+ options = {}
+ args = {
+ 'options': options,
+ 'sla': {'mean_latency': 5}
+ }
+ result = {}
+
+ p = netperf_node.NetperfNode(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output()
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_netperf_node_unsuccessful_script_error(self, mock_ssh):
+
+ options = {}
+ args = {'options': options}
+ result = {}
+
+ p = netperf_node.NetperfNode(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.host = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def _read_sample_output(self):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, 'netperf_sample_output.json')
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py
new file mode 100644
index 000000000..4cdfde6b1
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_netutilization.py
@@ -0,0 +1,225 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd and other.
+#
+# 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.networking.netutilization.NetUtilization
+
+from __future__ import absolute_import
+import mock
+import unittest
+import os
+
+from yardstick.benchmark.scenarios.networking import netutilization
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.netutilization.ssh')
+class NetUtilizationTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ def test_setup_success(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+ args = {'options': options}
+
+ n = netutilization.NetUtilization(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ n.setup()
+ self.assertIsNotNone(n.client)
+ self.assertTrue(n.setup_done)
+
+ def test_execute_command_success(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+ args = {'options': options}
+
+ n = netutilization.NetUtilization(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ n.setup()
+
+ expected_result = 'abcdefg'
+ mock_ssh.SSH.from_node().execute.return_value = (0, expected_result, '')
+ result = n._execute_command("foo")
+ self.assertEqual(result, expected_result)
+
+ def test_execute_command_failed(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+ args = {'options': options}
+
+ n = netutilization.NetUtilization(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ n.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (127, '', 'abcdefg')
+ self.assertRaises(RuntimeError, n._execute_command,
+ "failed")
+
+ def test_get_network_utilization_success(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 1
+ }
+ args = {'options': options}
+
+ n = netutilization.NetUtilization(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ n.setup()
+
+ mpstat_output = self._read_file("netutilization_sample_output1.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, mpstat_output, '')
+ result = n._get_network_utilization()
+
+ expected_result = \
+ {"network_utilization_maximun": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}},
+ "network_utilization_average": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}},
+ "network_utilization_minimum": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}}}
+
+ self.assertDictEqual(result, expected_result)
+
+ def test_get_network_utilization_2_success(self, mock_ssh):
+ options = {
+ "interval": 1,
+ "count": 2
+ }
+ args = {'options': options}
+
+ n = netutilization.NetUtilization(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ n.setup()
+
+ mpstat_output = self._read_file("netutilization_sample_output2.txt")
+ mock_ssh.SSH.from_node().execute.return_value = (0, mpstat_output, '')
+ result = n._get_network_utilization()
+
+ expected_result = \
+ {"network_utilization_maximun": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}},
+ "network_utilization_average": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}},
+ "network_utilization_minimum": {
+ "lo": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"},
+ "eth0": {"rxcmp/s": "0.00",
+ "%ifutil": "0.00",
+ "txcmp/s": "0.00",
+ "txkB/s": "0.00",
+ "rxkB/s": "0.00",
+ "rxpck/s": "0.00",
+ "txpck/s": "0.00",
+ "rxmcst/s": "0.00"}}}
+
+ self.assertDictEqual(result, expected_result)
+
+ def _read_file(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, filename)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py
new file mode 100644
index 000000000..36e8c8a77
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_networkcapacity.py
@@ -0,0 +1,59 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.networking.networkcapacity.NetworkCapacity
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.networking import networkcapacity
+
+SAMPLE_OUTPUT = \
+ '{"Number of connections":"308","Number of frames received": "166503"}'
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.networkcapacity.ssh')
+class NetworkCapacityTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'password': "root"
+ },
+ }
+
+ self.result = {}
+
+ def test_capacity_successful_setup(self, mock_ssh):
+ c = networkcapacity.NetworkCapacity({}, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+ self.assertIsNotNone(c.client)
+ self.assertTrue(c.setup_done)
+
+ def test_capacity_successful(self, mock_ssh):
+ c = networkcapacity.NetworkCapacity({}, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, SAMPLE_OUTPUT, '')
+ c.run(self.result)
+ expected_result = jsonutils.loads(SAMPLE_OUTPUT)
+ self.assertEqual(self.result, expected_result)
+
+ def test_capacity_unsuccessful_script_error(self, mock_ssh):
+ c = networkcapacity.NetworkCapacity({}, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, c.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py
new file mode 100644
index 000000000..b02d58437
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_nstat.py
@@ -0,0 +1,105 @@
+##############################################################################
+# Copyright (c) 2017 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 mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import nstat
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.nstat.ssh')
+class NstatTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ "host": {
+ "ip": "192.168.50.28",
+ "user": "root",
+ "key_filename": "mykey.key"
+ }
+ }
+
+ def test_nstat_successful_setup(self, mock_ssh):
+
+ n = nstat.Nstat({}, self.ctx)
+ n.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(n.client)
+ self.assertTrue(n.setup_done)
+
+ def test_nstat_successful_no_sla(self, mock_ssh):
+
+ options = {
+ "duration": 0
+ }
+ args = {
+ "options": options,
+ }
+ n = nstat.Nstat(args, self.ctx)
+ result = {}
+
+ sample_output = '#kernel\nIpInReceives 1837 0.0\nIpInHdrErrors 0 0.0\nIpInAddrErrors 2 0.0\nIcmpInMsgs 319 0.0\nIcmpInErrors 0 0.0\nTcpInSegs 36 0.0\nTcpInErrs 0 0.0\nUdpInDatagrams 1318 0.0\nUdpInErrors 0 0.0\n' # pylint: disable=line-too-long
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ n.run(result)
+ expected_result = {"TcpInErrs": 0, "UdpInDatagrams": 1318,
+ "Tcp_segment_error_rate": 0.0, "IpInAddrErrors": 2,
+ "IpInHdrErrors": 0, "IcmpInErrors": 0, "IpErrors": 2,
+ "TcpInSegs": 36, "IpInReceives": 1837, "IcmpInMsgs": 319,
+ "IP_datagram_error_rate": 0.001, "Udp_datagram_error_rate": 0.0,
+ "Icmp_message_error_rate": 0.0, "UdpInErrors": 0}
+ self.assertEqual(result, expected_result)
+
+ def test_nstat_successful_sla(self, mock_ssh):
+
+ options = {
+ "duration": 0
+ }
+ sla = {
+ "IP_datagram_error_rate": 0.1
+ }
+ args = {
+ "options": options,
+ "sla": sla
+ }
+ n = nstat.Nstat(args, self.ctx)
+ result = {}
+
+ sample_output = '#kernel\nIpInReceives 1837 0.0\nIpInHdrErrors 0 0.0\nIpInAddrErrors 2 0.0\nIcmpInMsgs 319 0.0\nIcmpInErrors 0 0.0\nTcpInSegs 36 0.0\nTcpInErrs 0 0.0\nUdpInDatagrams 1318 0.0\nUdpInErrors 0 0.0\n' # pylint: disable=line-too-long
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ n.run(result)
+ expected_result = {"TcpInErrs": 0, "UdpInDatagrams": 1318,
+ "Tcp_segment_error_rate": 0.0, "IpInAddrErrors": 2,
+ "IpInHdrErrors": 0, "IcmpInErrors": 0, "IpErrors": 2,
+ "TcpInSegs": 36, "IpInReceives": 1837, "IcmpInMsgs": 319,
+ "IP_datagram_error_rate": 0.001, "Udp_datagram_error_rate": 0.0,
+ "Icmp_message_error_rate": 0.0, "UdpInErrors": 0}
+ self.assertEqual(result, expected_result)
+
+ def test_nstat_unsuccessful_cmd_error(self, mock_ssh):
+
+ options = {
+ "duration": 0
+ }
+ sla = {
+ "IP_datagram_error_rate": 0.1
+ }
+ args = {
+ "options": options,
+ "sla": sla
+ }
+ n = nstat.Nstat(args, self.ctx)
+ result = {}
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, n.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
new file mode 100644
index 000000000..944202658
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping.py
@@ -0,0 +1,107 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.networking.ping.Ping
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import ping
+from yardstick.common import exceptions as y_exc
+
+
+class PingTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key"
+ },
+ "target": {
+ "ipaddr": "10.229.17.105",
+ }
+ }
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
+ def test_ping_successful_no_sla(self, mock_ssh):
+
+ args = {
+ 'options': {'packetsize': 200},
+ 'target': 'ares.demo'
+ }
+ result = {}
+
+ p = ping.Ping(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '100', '')
+ p.run(result)
+ self.assertEqual(result, {'rtt.ares': 100.0})
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
+ def test_ping_successful_sla(self, mock_ssh):
+
+ args = {
+ 'options': {'packetsize': 200},
+ 'sla': {'max_rtt': 150},
+ 'target': 'ares.demo'
+ }
+ result = {}
+
+ p = ping.Ping(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '100', '')
+ p.run(result)
+ self.assertEqual(result, {'rtt.ares': 100.0})
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
+ def test_ping_unsuccessful_sla(self, mock_ssh):
+
+ args = {
+ 'options': {'packetsize': 200},
+ 'sla': {'max_rtt': 50},
+ 'target': 'ares.demo'
+ }
+ result = {}
+
+ p = ping.Ping(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '100', '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
+ def test_ping_unsuccessful_script_error(self, mock_ssh):
+
+ args = {
+ 'options': {'packetsize': 200},
+ 'sla': {'max_rtt': 50},
+ 'target': 'ares.demo'
+ }
+ result = {}
+
+ p = ping.Ping(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping.ssh')
+ def test_ping_unsuccessful_no_sla(self, mock_ssh):
+
+ args = {
+ 'options': {'packetsize': 200},
+ 'target': 'ares.demo'
+ }
+ result = {}
+
+ p = ping.Ping(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
new file mode 100644
index 000000000..ad5217a14
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_ping6.py
@@ -0,0 +1,117 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.networking.ping.Ping
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import ping6
+from yardstick.common import exceptions as y_exc
+
+
+class PingTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'nodes': {
+ 'host1': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'role': "Controller",
+ 'key_filename': "mykey.key",
+ 'password': "root"
+ },
+ 'host2': {
+ "ip": "172.16.0.138",
+ "key_filename": "/root/.ssh/id_rsa",
+ "role": "Compute",
+ "name": "node3.IPV6",
+ "user": "root"
+ },
+ }
+ }
+
+ def test_get_controller_node(self):
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+ 'sla': {'max_rtt': 50}
+ }
+ p = ping6.Ping6(args, self.ctx)
+ controller_node = p._get_controller_node(['host1', 'host2'])
+ self.assertEqual(controller_node, 'host1')
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
+ def test_ping_successful_setup(self, mock_ssh):
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+ 'sla': {'max_rtt': 50}
+ }
+ p = ping6.Ping6(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '0', '')
+ p.setup()
+
+ self.assertTrue(p.setup_done)
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
+ def test_ping_successful_no_sla(self, mock_ssh):
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+
+ }
+ result = {}
+
+ p = ping6.Ping6(args, self.ctx)
+ p.client = mock_ssh.SSH.from_node()
+ mock_ssh.SSH.from_node().execute.side_effect = [(0, 'host1', ''), (0, 100, '')]
+ p.run(result)
+ self.assertEqual(result, {'rtt': 100.0})
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
+ def test_ping_successful_sla(self, mock_ssh):
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+ 'sla': {'max_rtt': 150}
+ }
+ result = {}
+
+ p = ping6.Ping6(args, self.ctx)
+ p.client = mock_ssh.SSH.from_node()
+ mock_ssh.SSH.from_node().execute.side_effect = [(0, 'host1', ''), (0, 100, '')]
+ p.run(result)
+ self.assertEqual(result, {'rtt': 100.0})
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
+ def test_ping_unsuccessful_sla(self, mock_ssh):
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+ 'sla': {'max_rtt': 50}
+ }
+ result = {}
+
+ p = ping6.Ping6(args, self.ctx)
+ p.client = mock_ssh.SSH.from_node()
+ mock_ssh.SSH.from_node().execute.side_effect = [(0, 'host1', ''), (0, 100, '')]
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.ping6.ssh')
+ def test_ping_unsuccessful_script_error(self, mock_ssh):
+
+ args = {
+ 'options': {'host': 'host1', 'packetsize': 200, 'ping_count': 5},
+ 'sla': {'max_rtt': 150}
+ }
+ result = {}
+
+ p = ping6.Ping6(args, self.ctx)
+ p.client = mock_ssh.SSH.from_node()
+ mock_ssh.SSH.from_node().execute.side_effect = [
+ (0, 'host1', ''), (1, '', 'FOOBAR')]
+ self.assertRaises(RuntimeError, p.run, result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
new file mode 100644
index 000000000..5761e2403
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen.py
@@ -0,0 +1,453 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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 mock
+import unittest
+import logging
+
+from oslo_serialization import jsonutils
+
+from yardstick import ssh
+from yardstick.benchmark.scenarios.networking import pktgen
+from yardstick.common import exceptions as y_exc
+
+
+logging.disable(logging.CRITICAL)
+
+
+class PktgenTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.context_cfg = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': 'mykey.key'
+ },
+ 'target': {
+ 'ip': '172.16.0.138',
+ 'user': 'root',
+ 'key_filename': 'mykey.key',
+ 'ipaddr': '172.16.0.138'
+ }
+ }
+ self.scenario_cfg = {
+ 'options': {'packetsize': 60}
+ }
+
+ self._mock_SSH = mock.patch.object(ssh, 'SSH')
+ self.mock_SSH = self._mock_SSH.start()
+
+ self.mock_SSH.from_node().execute.return_value = (0, '', '')
+ self.mock_SSH.from_node().run.return_value = 0
+
+ self.addCleanup(self._stop_mock)
+
+ self.scenario = pktgen.Pktgen(self.scenario_cfg, self.context_cfg)
+ self.scenario.setup()
+
+ def _stop_mock(self):
+ self._mock_SSH.stop()
+
+ def test_setup_successful(self):
+ self.assertIsNotNone(self.scenario.server)
+ self.assertIsNotNone(self.scenario.client)
+ self.assertTrue(self.scenario.setup_done)
+
+ def test_iptables_setup_successful(self):
+ self.scenario.number_of_ports = 10
+ self.scenario._iptables_setup()
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "sudo iptables -F; "
+ "sudo iptables -A INPUT -p udp --dport 1000:%s -j DROP"
+ % 1010, timeout=60)
+
+ def test_iptables_setup_unsuccessful(self):
+ self.scenario.number_of_ports = 10
+ self.mock_SSH.from_node().run.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._iptables_setup()
+
+ def test_iptables_get_result_successful(self):
+ self.scenario.number_of_ports = 10
+ self.mock_SSH.from_node().execute.return_value = (0, '150000', '')
+
+ result = self.scenario._iptables_get_result()
+
+ self.assertEqual(result, 150000)
+ self.mock_SSH.from_node().execute.assert_called_with(
+ "sudo iptables -L INPUT -vnx |"
+ "awk '/dpts:1000:%s/ {{printf \"%%s\", $1}}'"
+ % 1010, raise_on_error=True)
+
+ def test_iptables_get_result_unsuccessful(self):
+ self.scenario.number_of_ports = 10
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._iptables_get_result()
+
+ def test_run_successful_no_sla(self):
+ self.scenario._iptables_get_result = mock.Mock(return_value=149300)
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149776,
+ "packetsize": 60,
+ "flows": 110,
+ "ppm": 3179})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ self.scenario.run(result)
+
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_run_successful_sla(self):
+ self.scenario_cfg['sla'] = {'max_ppm': 10000}
+ scenario = pktgen.Pktgen(self.scenario_cfg, self.context_cfg)
+ scenario.setup()
+ scenario._iptables_get_result = mock.Mock(return_value=149300)
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149776,
+ "packetsize": 60,
+ "flows": 110,
+ "ppm": 3179})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ scenario.run(result)
+
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_run_unsuccessful_sla(self):
+ self.scenario_cfg['sla'] = {'max_ppm': 1000}
+ scenario = pktgen.Pktgen(self.scenario_cfg, self.context_cfg)
+ scenario.setup()
+ scenario._iptables_get_result = mock.Mock(return_value=149300)
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149776,
+ "packetsize": 60,
+ "flows": 110})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ scenario.run({})
+
+ def test_run_ssh_error_not_caught(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario.run({})
+
+ def test_get_vnic_driver_name(self):
+ self.mock_SSH.from_node().execute.return_value = (0, 'ixgbevf', '')
+ vnic_driver_name = self.scenario._get_vnic_driver_name()
+
+ self.assertEqual(vnic_driver_name, 'ixgbevf')
+
+ def test_get_vnic_driver_name_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._get_vnic_driver_name()
+
+ def test_get_sriov_queue_number(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '2', '')
+
+ self.scenario.queue_number = self.scenario._get_sriov_queue_number()
+ self.assertEqual(self.scenario.queue_number, 2)
+
+ def test_get_sriov_queue_number_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._get_sriov_queue_number()
+
+ def test_get_available_queue_number(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '4', '')
+
+ self.assertEqual(self.scenario._get_available_queue_number(), 4)
+ self.mock_SSH.from_node().execute.assert_called_with(
+ "sudo ethtool -l eth0 | grep Combined | head -1 |"
+ "awk '{printf $2}'", raise_on_error=True)
+
+ def test_get_available_queue_number_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._get_available_queue_number()
+
+ def test_get_usable_queue_number(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '1', '')
+
+ self.assertEqual(self.scenario._get_usable_queue_number(), 1)
+ self.mock_SSH.from_node().execute.assert_called_with(
+ "sudo ethtool -l eth0 | grep Combined | tail -1 |"
+ "awk '{printf $2}'", raise_on_error=True)
+
+ def test_get_usable_queue_number_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._get_usable_queue_number()
+
+ def test_enable_ovs_multiqueue(self):
+ self.scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ self.scenario._get_available_queue_number = mock.Mock(return_value=4)
+ self.scenario.queue_number = self.scenario._enable_ovs_multiqueue()
+
+ self.assertEqual(self.scenario.queue_number, 4)
+ self.mock_SSH.from_node().run.assert_has_calls(
+ (mock.call("sudo ethtool -L eth0 combined 4"),
+ mock.call("sudo ethtool -L eth0 combined 4")))
+
+ def test_enable_ovs_multiqueue_1q(self):
+ self.scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ self.scenario._get_available_queue_number = mock.Mock(return_value=1)
+ self.scenario.queue_number = self.scenario._enable_ovs_multiqueue()
+
+ self.assertEqual(self.scenario.queue_number, 1)
+ self.mock_SSH.from_node().run.assert_not_called()
+
+ def test_enable_ovs_multiqueue_unsuccessful(self):
+ self.mock_SSH.from_node().run.side_effect = y_exc.SSHError
+ self.scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ self.scenario._get_available_queue_number = mock.Mock(return_value=4)
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._enable_ovs_multiqueue()
+
+ def test_setup_irqmapping_ovs(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '10', '')
+ self.scenario._setup_irqmapping_ovs(4)
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "echo 8 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_setup_irqmapping_ovs_1q(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '10', '')
+ self.scenario._setup_irqmapping_ovs(1)
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "echo 1 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_setup_irqmapping_ovs_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._setup_irqmapping_ovs(4)
+
+ def test_setup_irqmapping_ovs_1q_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._setup_irqmapping_ovs(1)
+
+ def test_setup_irqmapping_sriov(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '10', '')
+ self.scenario._setup_irqmapping_sriov(2)
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "echo 2 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_setup_irqmapping_sriov_1q(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '10', '')
+ self.scenario._setup_irqmapping_sriov(1)
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "echo 1 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_setup_irqmapping_sriov_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._setup_irqmapping_sriov(2)
+
+ def test_setup_irqmapping_sriov_1q_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._setup_irqmapping_sriov(1)
+
+ def test_is_irqbalance_disabled(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '', '')
+
+ self.assertFalse(self.scenario._is_irqbalance_disabled())
+ self.mock_SSH.from_node().execute.assert_called_with(
+ "grep ENABLED /etc/default/irqbalance", raise_on_error=True)
+
+ def test_is_irqbalance_disabled_unsuccessful(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._is_irqbalance_disabled()
+
+ def test_disable_irqbalance(self):
+ self.scenario._disable_irqbalance()
+
+ self.mock_SSH.from_node().run.assert_called_with(
+ "sudo service irqbalance disable")
+
+ def test_disable_irqbalance_unsuccessful(self):
+ self.mock_SSH.from_node().run.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario._disable_irqbalance()
+
+ def test_multiqueue_setup_ovs(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '4', '')
+ self.scenario._is_irqbalance_disabled = mock.Mock(return_value=False)
+ self.scenario._get_vnic_driver_name = mock.Mock(
+ return_value="virtio_net")
+ self.scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ self.scenario._get_available_queue_number = mock.Mock(return_value=4)
+
+ self.scenario.multiqueue_setup()
+
+ self.assertEqual(self.scenario.queue_number, 4)
+ self.assertTrue(self.scenario.multiqueue_setup_done)
+
+ def test_multiqueue_setup_ovs_1q(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '1', '')
+ self.scenario._is_irqbalance_disabled = mock.Mock(return_value=False)
+ self.scenario._get_vnic_driver_name = mock.Mock(
+ return_value="virtio_net")
+ self.scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ self.scenario._get_available_queue_number = mock.Mock(return_value=1)
+
+ self.scenario.multiqueue_setup()
+
+ self.assertEqual(self.scenario.queue_number, 1)
+ self.assertTrue(self.scenario.multiqueue_setup_done)
+
+ def test_multiqueue_setup_sriov(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '2', '')
+ self.scenario._is_irqbalance_disabled = mock.Mock(return_value=False)
+ self.scenario._get_vnic_driver_name = mock.Mock(return_value="ixgbevf")
+
+ self.scenario.multiqueue_setup()
+
+ self.assertEqual(self.scenario.queue_number, 2)
+ self.assertTrue(self.scenario.multiqueue_setup_done)
+
+ def test_multiqueue_setup_sriov_1q(self):
+ self.mock_SSH.from_node().execute.return_value = (0, '1', '')
+ self.scenario._is_irqbalance_disabled = mock.Mock(return_value=False)
+ self.scenario._get_vnic_driver_name = mock.Mock(return_value="ixgbevf")
+
+ self.scenario.multiqueue_setup()
+
+ self.assertEqual(self.scenario.queue_number, 1)
+ self.assertTrue(self.scenario.multiqueue_setup_done)
+
+ def test_run_with_setup_done(self):
+ scenario_cfg = {
+ 'options': {
+ 'packetsize': 60,
+ 'number_of_ports': 10,
+ 'duration': 20,
+ 'multiqueue': True},
+ 'sla': {
+ 'max_ppm': 1}
+ }
+ scenario = pktgen.Pktgen(scenario_cfg, self.context_cfg)
+ scenario.server = self.mock_SSH.from_node()
+ scenario.client = self.mock_SSH.from_node()
+ scenario.setup_done = True
+ scenario.multiqueue_setup_done = True
+ scenario._iptables_get_result = mock.Mock(return_value=149300)
+
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149300,
+ "flows": 110,
+ "ppm": 0})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ scenario.run(result)
+
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_run_with_ovs_multiqueque(self):
+ scenario_cfg = {
+ 'options': {
+ 'packetsize': 60,
+ 'number_of_ports': 10,
+ 'duration': 20,
+ 'multiqueue': True},
+ 'sla': {'max_ppm': 1}
+ }
+ scenario = pktgen.Pktgen(scenario_cfg, self.context_cfg)
+ scenario.setup()
+ scenario._get_vnic_driver_name = mock.Mock(return_value="virtio_net")
+ scenario._get_usable_queue_number = mock.Mock(return_value=1)
+ scenario._get_available_queue_number = mock.Mock(return_value=4)
+ scenario._enable_ovs_multiqueue = mock.Mock(return_value=4)
+ scenario._setup_irqmapping_ovs = mock.Mock()
+ scenario._iptables_get_result = mock.Mock(return_value=149300)
+
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149300,
+ "flows": 110,
+ "ppm": 0})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ scenario.run(result)
+
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_run_with_sriov_multiqueque(self):
+ scenario_cfg = {
+ 'options': {
+ 'packetsize': 60,
+ 'number_of_ports': 10,
+ 'duration': 20,
+ 'multiqueue': True},
+ 'sla': {'max_ppm': 1}
+ }
+ scenario = pktgen.Pktgen(scenario_cfg, self.context_cfg)
+ scenario.setup()
+ scenario._get_vnic_driver_name = mock.Mock(return_value="ixgbevf")
+ scenario._get_sriov_queue_number = mock.Mock(return_value=2)
+ scenario._setup_irqmapping_sriov = mock.Mock()
+ scenario._iptables_get_result = mock.Mock(return_value=149300)
+
+ sample_output = jsonutils.dumps({"packets_per_second": 9753,
+ "errors": 0,
+ "packets_sent": 149300,
+ "flows": 110,
+ "ppm": 0})
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ scenario.run(result)
+
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
new file mode 100644
index 000000000..70cd8ad40
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk.py
@@ -0,0 +1,136 @@
+##############################################################################
+# Copyright (c) 2015 ZTE 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 mock
+import unittest
+import time
+import logging
+
+import yardstick.common.utils as utils
+from yardstick import ssh
+from yardstick.benchmark.scenarios.networking import pktgen_dpdk
+from yardstick.common import exceptions as y_exc
+
+
+logging.disable(logging.CRITICAL)
+
+
+class PktgenDPDKLatencyTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.context_cfg = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': 'mykey.key'
+ },
+ 'target': {
+ 'ip': '172.16.0.138',
+ 'user': 'root',
+ 'key_filename': 'mykey.key',
+ 'ipaddr': '172.16.0.138'
+ }
+ }
+ self.scenario_cfg = {
+ 'options': {'packetsize': 60}
+ }
+
+ self._mock_SSH = mock.patch.object(ssh, 'SSH')
+ self.mock_SSH = self._mock_SSH.start()
+
+ self._mock_time_sleep = mock.patch.object(time, 'sleep')
+ self.mock_time_sleep = self._mock_time_sleep.start()
+
+ self._mock_utils_get_port_ip = mock.patch.object(utils, 'get_port_ip')
+ self.mock_utils_get_port_ip = self._mock_utils_get_port_ip.start()
+
+ self._mock_utils_get_port_mac = mock.patch.object(utils,
+ 'get_port_mac')
+ self.mock_utils_get_port_mac = self._mock_utils_get_port_mac.start()
+
+ self.mock_SSH.from_node().execute.return_value = (0, '', '')
+
+ self.addCleanup(self._stop_mock)
+
+ self.scenario = pktgen_dpdk.PktgenDPDKLatency(self.scenario_cfg,
+ self.context_cfg)
+ self.scenario.server = self.mock_SSH.from_node()
+ self.scenario.client = self.mock_SSH.from_node()
+
+ def _stop_mock(self):
+ self._mock_SSH.stop()
+ self._mock_time_sleep.stop()
+ self._mock_utils_get_port_ip.stop()
+ self._mock_utils_get_port_mac.stop()
+
+ def test_setup(self):
+ scenario = pktgen_dpdk.PktgenDPDKLatency(self.scenario_cfg,
+ self.context_cfg)
+ scenario.setup()
+
+ self.assertIsNotNone(scenario.server)
+ self.assertIsNotNone(scenario.client)
+ self.assertTrue(scenario.setup_done)
+
+ def test_run_get_port_ip_command(self):
+ self.scenario.run({})
+
+ self.mock_utils_get_port_ip.assert_has_calls(
+ [mock.call(self.scenario.server, 'ens4'),
+ mock.call(self.scenario.server, 'ens5')])
+
+ def test_get_port_mac_command(self):
+ self.scenario.run({})
+
+ self.mock_utils_get_port_mac.assert_has_calls(
+ [mock.call(self.scenario.server, 'ens5'),
+ mock.call(self.scenario.server, 'ens4'),
+ mock.call(self.scenario.server, 'ens5')])
+
+ def test_run_no_sla(self):
+ sample_output = '100\n110\n112\n130\n149\n150\n90\n150\n200\n162\n'
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ self.scenario.run(result)
+ # with python 3 we get float, might be due python division changes
+ # AssertionError: {'avg_latency': 132.33333333333334} != {
+ # 'avg_latency': 132}
+ delta = result['avg_latency'] - 132
+ self.assertLessEqual(delta, 1)
+
+ def test_run_sla(self):
+ self.scenario_cfg['sla'] = {'max_latency': 100}
+ scenario = pktgen_dpdk.PktgenDPDKLatency(self.scenario_cfg,
+ self.context_cfg)
+
+ sample_output = '100\n100\n100\n100\n100\n100\n100\n100\n100\n100\n'
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ result = {}
+ scenario.run(result)
+
+ self.assertEqual(result, {"avg_latency": 100})
+
+ def test_run_sla_error(self):
+ self.scenario_cfg['sla'] = {'max_latency': 100}
+ scenario = pktgen_dpdk.PktgenDPDKLatency(self.scenario_cfg,
+ self.context_cfg)
+
+ sample_output = '100\n110\n112\n130\n149\n150\n90\n150\n200\n162\n'
+ self.mock_SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ with self.assertRaises(y_exc.SLAValidationError):
+ scenario.run({})
+
+ def test_run_last_command_raise_on_error(self):
+ self.mock_SSH.from_node().execute.side_effect = y_exc.SSHError
+
+ with self.assertRaises(y_exc.SSHError):
+ self.scenario.run({})
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
new file mode 100644
index 000000000..39392e4bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_pktgen_dpdk_throughput.py
@@ -0,0 +1,194 @@
+##############################################################################
+# Copyright (c) 2017 Nokia 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.networking.pktgen.PktgenDPDK
+
+from __future__ import absolute_import
+import unittest
+
+from oslo_serialization import jsonutils
+import mock
+
+from yardstick.benchmark.scenarios.networking import pktgen_dpdk_throughput
+from yardstick.common import exceptions as y_exc
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+@mock.patch('yardstick.benchmark.scenarios.networking.pktgen_dpdk_throughput.ssh')
+class PktgenDPDKTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': 'mykey.key'
+ },
+ 'target': {
+ 'ip': '172.16.0.138',
+ 'user': 'root',
+ 'key_filename': 'mykey.key',
+ }
+ }
+
+ self._mock_time = mock.patch(
+ 'yardstick.benchmark.scenarios.networking.pktgen_dpdk_throughput.time')
+ self.mock_time = self._mock_time.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_time.stop()
+
+ def test_pktgen_dpdk_throughput_successful_setup(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+ p.setup()
+
+ mock_ssh.SSH().execute.return_value = (0, '', '')
+ self.assertIsNotNone(p.server)
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_pktgen_dpdk_throughput_successful_no_sla(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10},
+ }
+
+ result = {}
+
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_dpdk_result = mock.Mock()
+ mock_dpdk_result.return_value = 149300
+ p._dpdk_get_result = mock_dpdk_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149776, "flows": 110}'
+ mock_ssh.SSH().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_pktgen_dpdk_throughput_successful_sla(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10},
+ 'sla': {'max_ppm': 10000}
+ }
+ result = {}
+
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_dpdk_result = mock.Mock()
+ mock_dpdk_result.return_value = 149300
+ p._dpdk_get_result = mock_dpdk_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149776, "flows": 110}'
+ mock_ssh.SSH().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+ expected_result = jsonutils.loads(sample_output)
+ expected_result["packets_received"] = 149300
+ expected_result["packetsize"] = 60
+ self.assertEqual(result, expected_result)
+
+ def test_pktgen_dpdk_throughput_unsuccessful_sla(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10},
+ 'sla': {'max_ppm': 1000}
+ }
+ result = {}
+
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_dpdk_result = mock.Mock()
+ mock_dpdk_result.return_value = 149300
+ p._dpdk_get_result = mock_dpdk_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149776, "flows": 110}'
+ mock_ssh.SSH().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_pktgen_dpdk_throughput_unsuccessful_script_error(
+ self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10},
+ 'sla': {'max_ppm': 1000}
+ }
+ result = {}
+
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_ssh.SSH().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def test_pktgen_dpdk_throughput_is_dpdk_setup(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+ p.server = mock_ssh.SSH()
+
+ mock_ssh.SSH().execute.return_value = (0, '', '')
+
+ p._is_dpdk_setup("server")
+
+ mock_ssh.SSH().execute.assert_called_with(
+ "ip a | grep eth1 2>/dev/null")
+
+ def test_pktgen_dpdk_throughput_dpdk_setup(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_ssh.SSH().execute.return_value = (0, '', '')
+
+ p.dpdk_setup()
+
+ self.assertTrue(p.dpdk_setup_done)
+
+ def test_pktgen_dpdk_throughput_dpdk_get_result(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen_dpdk_throughput.PktgenDPDK(args, self.ctx)
+ p.server = mock_ssh.SSH()
+ p.client = mock_ssh.SSH()
+
+ mock_ssh.SSH().execute.return_value = (0, '10000', '')
+
+ p._dpdk_get_result()
+
+ mock_ssh.SSH().execute.assert_called_with(
+ "sudo /dpdk/destdir/bin/dpdk-procinfo -- --stats-reset > /dev/null 2>&1")
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py
new file mode 100644
index 000000000..a5e5e39dc
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_sfc.py
@@ -0,0 +1,68 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.networking.sfc
+
+from __future__ import absolute_import
+import mock
+import unittest
+
+from yardstick.benchmark.scenarios.networking import sfc
+
+
+class SfcTestCase(unittest.TestCase):
+
+ def setUp(self):
+ scenario_cfg = {}
+ context_cfg = {
+ # Used in Sfc.setup()
+ 'target': {
+ 'user': 'root',
+ 'password': 'opnfv',
+ 'ip': '127.0.0.1',
+ },
+
+ # Used in Sfc.run()
+ 'host': {
+ 'user': 'root',
+ 'password': 'opnfv',
+ 'ip': None,
+ }
+ }
+
+ self.sfc = sfc.Sfc(scenario_cfg=scenario_cfg, context_cfg=context_cfg)
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.ssh')
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.sfc_openstack')
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.subprocess')
+ def test_run_for_success(self, mock_subprocess, mock_openstack, mock_ssh):
+ # Mock a successfull SSH in Sfc.setup() and Sfc.run()
+ mock_ssh.SSH.from_node().execute.return_value = (0, '100', '')
+ mock_openstack.get_an_IP.return_value = "127.0.0.1"
+ mock_subprocess.call.return_value = 'mocked!'
+
+ result = {}
+ self.sfc.setup()
+ self.sfc.run(result)
+ self.sfc.teardown()
+
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.ssh')
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.sfc_openstack')
+ @mock.patch('yardstick.benchmark.scenarios.networking.sfc.subprocess')
+ def test2_run_for_success(self, mock_subprocess, mock_openstack, mock_ssh):
+ # Mock a successfull SSH in Sfc.setup() and Sfc.run()
+ mock_ssh.SSH.from_node().execute.return_value = (
+ 0, 'vxlan_tool.py', 'succeeded timed out')
+ mock_openstack.get_an_IP.return_value = "127.0.0.1"
+ mock_subprocess.call.return_value = 'mocked!'
+
+ result = {}
+ self.sfc.setup()
+ self.sfc.run(result)
+ self.sfc.teardown()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
new file mode 100644
index 000000000..cf9a26a76
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vnf_generic.py
@@ -0,0 +1,873 @@
+# Copyright (c) 2016-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.
+
+from copy import deepcopy
+import os
+import sys
+
+import mock
+import unittest
+
+from yardstick import tests
+from yardstick.common import exceptions
+from yardstick.common import utils
+from yardstick.network_services.collector.subscriber import Collector
+from yardstick.network_services.traffic_profile import base
+from yardstick.network_services.vnf_generic import vnfdgen
+from yardstick.network_services.vnf_generic.vnf.base import GenericTrafficGen
+from yardstick.network_services.vnf_generic.vnf.base import GenericVNF
+
+
+stl_patch = mock.patch.dict(sys.modules, tests.STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.benchmark.scenarios.networking import vnf_generic
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+
+
+COMPLETE_TREX_VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ {
+ 'benchmark': {
+ 'kpi': [
+ 'rx_throughput_fps',
+ 'tx_throughput_fps',
+ 'tx_throughput_mbps',
+ 'rx_throughput_mbps',
+ 'tx_throughput_pc_linerate',
+ 'rx_throughput_pc_linerate',
+ 'min_latency',
+ 'max_latency',
+ 'avg_latency',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'name': 'xe0',
+ 'type': 'VPORT',
+ },
+ {
+ 'name': 'xe1',
+ 'type': 'VPORT',
+ },
+ ],
+ 'description': 'TRex stateless traffic generator for RFC2544',
+ 'id': 'TrexTrafficGen',
+ 'mgmt-interface': {
+ 'ip': '1.1.1.1',
+ 'password': 'berta',
+ 'user': 'berta',
+ 'vdu-id': 'trexgen-baremetal',
+ },
+ 'name': 'trexgen',
+ 'short-name': 'trexgen',
+ 'class-name': 'TrexTrafficGen',
+ 'vdu': [
+ {
+ 'description': 'TRex stateless traffic generator for RFC2544',
+ 'external-interface': [
+ {
+ 'name': 'xe0',
+ 'virtual-interface': {
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '1.1.1.1',
+ 'dst_mac': '00:01:02:03:04:05',
+ 'local_ip': '1.1.1.2',
+ 'local_mac': '00:01:02:03:05:05',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': "255.255.255.0",
+ 'driver': 'i40',
+ 'vpci': '0000:00:10.2',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ },
+ {
+ 'name': 'xe1',
+ 'virtual-interface': {
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '2.1.1.1',
+ 'dst_mac': '00:01:02:03:04:06',
+ 'local_ip': '2.1.1.2',
+ 'local_mac': '00:01:02:03:05:06',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': "255.255.255.0",
+ 'driver': 'i40',
+ 'vpci': '0000:00:10.1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ },
+ ],
+ 'id': 'trexgen-baremetal',
+ 'name': 'trexgen-baremetal',
+ },
+ ],
+ },
+ ],
+ },
+}
+
+IP_ADDR_SHOW = """
+28: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
+group default qlen 1000
+ link/ether 90:e2:ba:a7:6a:c8 brd ff:ff:ff:ff:ff:ff
+ inet 1.1.1.1/8 brd 1.255.255.255 scope global eth1
+ inet6 fe80::92e2:baff:fea7:6ac8/64 scope link
+ valid_lft forever preferred_lft forever
+29: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP \
+group default qlen 1000
+ link/ether 90:e2:ba:a7:6a:c9 brd ff:ff:ff:ff:ff:ff
+ inet 2.1.1.1/8 brd 2.255.255.255 scope global eth5
+ inet6 fe80::92e2:baff:fea7:6ac9/64 scope link tentative
+ valid_lft forever preferred_lft forever
+"""
+
+SYS_CLASS_NET = """
+lrwxrwxrwx 1 root root 0 sie 10 14:16 eth1 -> \
+../../devices/pci0000:80/0000:80:02.2/0000:84:00.1/net/eth1
+lrwxrwxrwx 1 root root 0 sie 3 10:37 eth2 -> \
+../../devices/pci0000:00/0000:00:01.1/0000:84:00.2/net/eth5
+"""
+
+TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+}
+
+
+class TestNetworkServiceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.tg__0 = {
+ 'name': 'trafficgen_1.yardstick',
+ 'ip': '10.10.10.11',
+ 'role': 'TrafficGen',
+ 'user': 'root',
+ 'password': 'r00t',
+ 'interfaces': {
+ 'xe0': {
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:07:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02',
+ 'driver': 'i40e',
+ 'vpci': '0000:07:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ }
+
+ self.vnf__0 = {
+ 'name': 'vnf.yardstick',
+ 'ip': '10.10.10.12',
+ 'host': '10.223.197.164',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'password': 'r00t',
+ 'interfaces': {
+ 'xe0': {
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'local_mac': '00:00:00:00:00:03',
+ 'driver': 'i40e',
+ 'vpci': '0000:07:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'local_mac': '00:00:00:00:00:04',
+ 'driver': 'i40e',
+ 'vpci': '0000:07:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ }
+
+ self.context_cfg = {
+ 'nodes': {
+ 'tg__0': self.tg__0,
+ 'vnf__0': self.vnf__0,
+ },
+ 'networks': {
+ GenericVNF.UPLINK: {
+ 'vld_id': GenericVNF.UPLINK,
+ },
+ GenericVNF.DOWNLINK: {
+ 'vld_id': GenericVNF.DOWNLINK,
+ },
+ },
+ }
+
+ self.vld0 = {
+ 'vnfd-connection-point-ref': [
+ {
+ 'vnfd-connection-point-ref': 'xe0',
+ 'member-vnf-index-ref': '1',
+ 'vnfd-id-ref': 'trexgen'
+ },
+ {
+ 'vnfd-connection-point-ref': 'xe0',
+ 'member-vnf-index-ref': '2',
+ 'vnfd-id-ref': 'trexgen'
+ }
+ ],
+ 'type': 'ELAN',
+ 'id': GenericVNF.UPLINK,
+ 'name': 'tg__0 to vnf__0 link 1'
+ }
+
+ self.vld1 = {
+ 'vnfd-connection-point-ref': [
+ {
+ 'vnfd-connection-point-ref': 'xe1',
+ 'member-vnf-index-ref': '1',
+ 'vnfd-id-ref': 'trexgen'
+ },
+ {
+ 'vnfd-connection-point-ref': 'xe1',
+ 'member-vnf-index-ref': '2',
+ 'vnfd-id-ref': 'trexgen'
+ }
+ ],
+ 'type': 'ELAN',
+ 'id': GenericVNF.DOWNLINK,
+ 'name': 'vnf__0 to tg__0 link 2'
+ }
+
+ self.topology = {
+ 'id': 'trex-tg-topology',
+ 'short-name': 'trex-tg-topology',
+ 'name': 'trex-tg-topology',
+ 'description': 'trex-tg-topology',
+ 'constituent-vnfd': [
+ {
+ 'member-vnf-index': '1',
+ 'VNF model': 'tg_trex_tpl.yaml',
+ 'vnfd-id-ref': 'tg__0',
+ },
+ {
+ 'member-vnf-index': '2',
+ 'VNF model': 'tg_trex_tpl.yaml',
+ 'vnfd-id-ref': 'vnf__0',
+ },
+ ],
+ 'vld': [self.vld0, self.vld1],
+ }
+
+ self.scenario_cfg = {
+ 'task_path': "",
+ "topology": self._get_file_abspath("vpe_vnf_topology.yaml"),
+ 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+ 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+ 'traffic_profile': 'ipv4_throughput_vpe.yaml',
+ 'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
+ 'type': 'ISB',
+ 'tc_options': {
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ },
+ 'options': {
+ 'simulated_users': {'uplink': [1, 2]},
+ 'page_object': {'uplink': [1, 2]},
+ 'framesize': {'64B': 100}
+ },
+ 'runner': {
+ 'object': 'NetworkServiceTestCase',
+ 'interval': 35,
+ 'output_filename': 'yardstick.out',
+ 'runner_id': 74476,
+ 'duration': 400,
+ 'type': 'Duration',
+ },
+ 'traffic_options': {
+ 'flow': 'ipv4_1flow_Packets_vpe.yaml',
+ 'imix': 'imix_voice.yaml'
+ },
+ 'nodes': {
+ 'tg__2': 'trafficgen_2.yardstick',
+ 'tg__0': 'trafficgen_1.yardstick',
+ 'vnf__0': 'vnf.yardstick',
+ },
+ }
+
+ self.s = vnf_generic.NetworkServiceTestCase(self.scenario_cfg,
+ self.context_cfg)
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test___init__(self):
+ self.assertIsNotNone(self.topology)
+
+ def test__get_ip_flow_range_string(self):
+ result = '152.16.100.2-152.16.100.254'
+ self.assertEqual(result, self.s._get_ip_flow_range(
+ '152.16.100.2-152.16.100.254'))
+
+ def test__get_ip_flow_range_no_nodes(self):
+ self.assertEqual('0.0.0.0', self.s._get_ip_flow_range({}))
+
+ def test__get_ip_flow_range_no_node_data(self):
+ node_data = {'tg__0': 'xe0'}
+ self.s.context_cfg['nodes']['tg__0'] = {}
+ result = self.s._get_ip_flow_range(node_data)
+ self.assertEqual('0.0.0.2-0.0.0.254', result)
+
+ def test__et_ip_flow_range_ipv4(self):
+ node_data = {'tg__0': 'xe0'}
+ self.s.context_cfg['nodes']['tg__0'] = {
+ 'interfaces': {
+ 'xe0': {'local_ip': '192.168.1.15',
+ 'netmask': '255.255.255.128'}
+ }
+ }
+ result = self.s._get_ip_flow_range(node_data)
+ self.assertEqual('192.168.1.2-192.168.1.126', result)
+
+ def test__get_ip_flow_range_ipv4_mask_30(self):
+ node_data = {'tg__0': 'xe0'}
+ self.s.context_cfg['nodes']['tg__0'] = {
+ 'interfaces': {
+ 'xe0': {'local_ip': '192.168.1.15', 'netmask': 30}
+ }
+ }
+ result = self.s._get_ip_flow_range(node_data)
+ self.assertEqual('192.168.1.15', result)
+
+ def test__get_ip_flow_range_ipv6(self):
+ node_data = {'tg__0': 'xe0'}
+ self.s.context_cfg['nodes']['tg__0'] = {
+ 'interfaces': {
+ 'xe0': {'local_ip': '2001::11', 'netmask': 64}
+ }
+ }
+ result = self.s._get_ip_flow_range(node_data)
+ self.assertEqual('2001::2-2001::ffff:ffff:ffff:fffe', result)
+
+ def test___get_traffic_flow(self):
+ self.scenario_cfg["traffic_options"]["flow"] = \
+ self._get_file_abspath("ipv4_1flow_Packets_vpe.yaml")
+ self.scenario_cfg['options'] = {
+ 'flow': {
+ 'src_ip': [
+ {
+ 'tg__0': 'xe0',
+ },
+ ],
+ 'dst_ip': [
+ {
+ 'tg__0': 'xe1',
+ },
+ ],
+ 'public_ip': ['1.1.1.1'],
+ },
+ }
+ expected_flow = {'flow': {'dst_ip_0': '152.16.40.2-152.16.40.254',
+ 'public_ip_0': '1.1.1.1',
+ 'src_ip_0': '152.16.100.2-152.16.100.254'}}
+ self.assertEqual(expected_flow, self.s._get_traffic_flow())
+
+ def test___get_traffic_flow_error(self):
+ self.scenario_cfg["traffic_options"]["flow"] = \
+ "ipv4_1flow_Packets_vpe.yaml1"
+ self.assertEqual({'flow': {}}, self.s._get_traffic_flow())
+
+ def test_get_vnf_imp(self):
+ vnfd = COMPLETE_TREX_VNFD['vnfd:vnfd-catalog']['vnfd'][0]['class-name']
+ with mock.patch.dict(sys.modules, tests.STL_MOCKS):
+ self.assertIsNotNone(self.s.get_vnf_impl(vnfd))
+
+ with self.assertRaises(exceptions.IncorrectConfig) as raised:
+ self.s.get_vnf_impl('NonExistentClass')
+
+ exc_str = str(raised.exception)
+ print(exc_str)
+ self.assertIn('No implementation', exc_str)
+ self.assertIn('found in', exc_str)
+
+ def test_load_vnf_models_invalid(self):
+ self.context_cfg["nodes"]['tg__0']['VNF model'] = \
+ self._get_file_abspath("tg_trex_tpl.yaml")
+ self.context_cfg["nodes"]['vnf__0']['VNF model'] = \
+ self._get_file_abspath("tg_trex_tpl.yaml")
+
+ vnf = mock.Mock(autospec=GenericVNF)
+ self.s.get_vnf_impl = mock.Mock(return_value=vnf)
+
+ self.assertIsNotNone(
+ self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
+
+ def test_load_vnf_models_no_model(self):
+ vnf = mock.Mock(autospec=GenericVNF)
+ self.s.get_vnf_impl = mock.Mock(return_value=vnf)
+
+ self.assertIsNotNone(
+ self.s.load_vnf_models(self.scenario_cfg, self.context_cfg))
+
+ def test_map_topology_to_infrastructure(self):
+ self.s.map_topology_to_infrastructure()
+
+ nodes = self.context_cfg["nodes"]
+ self.assertEqual('../../vnf_descriptors/tg_rfc2544_tpl.yaml',
+ nodes['tg__0']['VNF model'])
+ self.assertEqual('../../vnf_descriptors/vpe_vnf.yaml',
+ nodes['vnf__0']['VNF model'])
+
+ def test_map_topology_to_infrastructure_insufficient_nodes(self):
+ cfg = deepcopy(self.context_cfg)
+ del cfg['nodes']['vnf__0']
+
+ cfg_patch = mock.patch.object(self.s, 'context_cfg', cfg)
+ with cfg_patch:
+ with self.assertRaises(exceptions.IncorrectConfig):
+ self.s.map_topology_to_infrastructure()
+
+ def test_map_topology_to_infrastructure_config_invalid(self):
+ ssh_mock = mock.Mock()
+ ssh_mock.execute.return_value = 0, SYS_CLASS_NET + IP_ADDR_SHOW, ""
+
+ cfg = deepcopy(self.s.context_cfg)
+
+ # delete all, we don't know which will come first
+ del cfg['nodes']['vnf__0']['interfaces']['xe0']['local_mac']
+ del cfg['nodes']['vnf__0']['interfaces']['xe1']['local_mac']
+ del cfg['nodes']['tg__0']['interfaces']['xe0']['local_mac']
+ del cfg['nodes']['tg__0']['interfaces']['xe1']['local_mac']
+
+ config_patch = mock.patch.object(self.s, 'context_cfg', cfg)
+ with config_patch:
+ with self.assertRaises(exceptions.IncorrectConfig):
+ self.s.map_topology_to_infrastructure()
+
+ def test__resolve_topology_invalid_config(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ # purge an important key from the data structure
+ for interface in self.tg__0['interfaces'].values():
+ del interface['local_mac']
+
+ with self.assertRaises(exceptions.IncorrectConfig) as raised:
+ self.s._resolve_topology()
+
+ self.assertIn('not found', str(raised.exception))
+
+ # restore local_mac
+ for index, interface in enumerate(self.tg__0['interfaces'].values()):
+ interface['local_mac'] = '00:00:00:00:00:{:2x}'.format(index)
+
+ # make a connection point ref with 3 points
+ self.s.topology["vld"][0]['vnfd-connection-point-ref'].append(
+ self.s.topology["vld"][0]['vnfd-connection-point-ref'][0])
+
+ with self.assertRaises(exceptions.IncorrectConfig) as raised:
+ self.s._resolve_topology()
+
+ self.assertIn('wrong endpoint count', str(raised.exception))
+
+ # make a connection point ref with 1 point
+ self.s.topology["vld"][0]['vnfd-connection-point-ref'] = \
+ self.s.topology["vld"][0]['vnfd-connection-point-ref'][:1]
+
+ with self.assertRaises(exceptions.IncorrectConfig) as raised:
+ self.s._resolve_topology()
+
+ self.assertIn('wrong endpoint count', str(raised.exception))
+
+ def test_run(self):
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.name = "tgen__1"
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ result = {}
+ self.s.run(result)
+ self.assertDictEqual(result, {tgen.name: verified_dict})
+
+ def test_setup(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.terminate = mock.Mock(return_value=True)
+ tgen.name = "tgen__1"
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ vnf.terminate = mock.Mock(return_value=True)
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
+ self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
+ self.s._fill_traffic_profile = \
+ mock.Mock(return_value=TRAFFIC_PROFILE)
+ self.assertIsNone(self.s.setup())
+
+ def test_setup_exception(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.terminate = mock.Mock(return_value=True)
+ tgen.name = "tgen__1"
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ vnf.instantiate.side_effect = RuntimeError(
+ "error during instantiate")
+ vnf.terminate = mock.Mock(return_value=True)
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
+ self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
+ self.s._fill_traffic_profile = \
+ mock.Mock(return_value=TRAFFIC_PROFILE)
+ with self.assertRaises(RuntimeError):
+ self.s.setup()
+
+ def test__get_traffic_profile(self):
+ self.scenario_cfg["traffic_profile"] = \
+ self._get_file_abspath("ipv4_throughput_vpe.yaml")
+ self.assertIsNotNone(self.s._get_traffic_profile())
+
+ def test__get_traffic_profile_exception(self):
+ with mock.patch.dict(self.scenario_cfg, {'traffic_profile': ''}):
+ with self.assertRaises(IOError):
+ self.s._get_traffic_profile()
+
+ def test__key_list_to_dict(self):
+ result = self.s._key_list_to_dict("uplink", {"uplink": [1, 2]})
+ self.assertEqual({"uplink_0": 1, "uplink_1": 2}, result)
+
+ def test__get_simulated_users(self):
+ result = self.s._get_simulated_users()
+ self.assertEqual({'simulated_users': {'uplink_0': 1, 'uplink_1': 2}},
+ result)
+
+ def test__get_page_object(self):
+ result = self.s._get_page_object()
+ self.assertEqual({'page_object': {'uplink_0': 1, 'uplink_1': 2}},
+ result)
+
+ def test___get_traffic_imix_exception(self):
+ with mock.patch.dict(self.scenario_cfg["traffic_options"], {'imix': ''}):
+ self.assertEqual({'imix': {'64B': 100}},
+ self.s._get_traffic_imix())
+
+ def test__get_ip_priority(self):
+ with mock.patch.dict(self.scenario_cfg["options"],
+ {'priority': {'raw': '0x01'}}):
+ self.assertEqual({'raw': '0x01'}, self.s._get_ip_priority())
+
+ def test__get_ip_priority_exception(self):
+ self.assertEqual({}, self.s._get_ip_priority())
+
+ @mock.patch.object(base.TrafficProfile, 'get')
+ @mock.patch.object(vnfdgen, 'generate_vnfd')
+ def test__fill_traffic_profile(self, mock_generate, mock_tprofile_get):
+ fake_tprofile = mock.Mock()
+ fake_vnfd = mock.MagicMock()
+ with mock.patch.object(self.s, '_get_traffic_profile',
+ return_value=fake_tprofile) as mock_get_tp:
+ mock_generate.return_value = fake_vnfd
+ self.s._fill_traffic_profile()
+ mock_get_tp.assert_called_once()
+ mock_generate.assert_called_once_with(
+ fake_tprofile,
+ {'downlink': {},
+ 'extra_args': {'arg1': 'value1', 'arg2': 'value2'},
+ 'flow': {'flow': {}},
+ 'imix': {'imix': {'64B': 100}},
+ 'priority': {},
+ 'uplink': {},
+ 'duration': 30,
+ 'simulated_users': {
+ 'simulated_users': {'uplink_0': 1, 'uplink_1': 2}},
+ 'page_object': {
+ 'page_object': {'uplink_0': 1, 'uplink_1': 2}},}
+ )
+ mock_tprofile_get.assert_called_once_with(fake_vnfd)
+
+ @mock.patch.object(base.TrafficProfile, 'get')
+ @mock.patch.object(vnfdgen, 'generate_vnfd')
+ def test__fill_traffic_profile2(self, mock_generate, mock_tprofile_get):
+ fake_tprofile = mock.Mock()
+ fake_vnfd = {}
+ with mock.patch.object(self.s, '_get_traffic_profile',
+ return_value=fake_tprofile) as mock_get_tp:
+ mock_generate.return_value = fake_vnfd
+
+ self.s.scenario_cfg["options"] = {"traffic_config": {"duration": 99899}}
+ self.s._fill_traffic_profile()
+ mock_get_tp.assert_called_once()
+ self.assertIn("traffic_profile", fake_vnfd)
+ self.assertIn("duration", fake_vnfd["traffic_profile"])
+ self.assertEqual(99899, fake_vnfd["traffic_profile"]["duration"])
+
+ @mock.patch.object(utils, 'open_relative_file')
+ def test__get_topology(self, mock_open_path):
+ self.s.scenario_cfg['topology'] = 'fake_topology'
+ self.s.scenario_cfg['task_path'] = 'fake_path'
+ mock_open_path.side_effect = mock.mock_open(read_data='fake_data')
+ self.assertEqual('fake_data', self.s._get_topology())
+ mock_open_path.assert_called_once_with('fake_topology', 'fake_path')
+
+ @mock.patch.object(vnfdgen, 'generate_vnfd')
+ def test__render_topology(self, mock_generate):
+ fake_topology = 'fake_topology'
+ mock_generate.return_value = {'nsd:nsd-catalog': {'nsd': ['fake_nsd']}}
+ with mock.patch.object(self.s, '_get_topology',
+ return_value=fake_topology) as mock_get_topology:
+ self.s._render_topology()
+ mock_get_topology.assert_called_once()
+
+ mock_generate.assert_called_once_with(
+ fake_topology,
+ {'extra_args': {'arg1': 'value1', 'arg2': 'value2'}}
+ )
+ self.assertEqual(self.s.topology, 'fake_nsd')
+
+ def test_teardown(self):
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.terminate = mock.Mock(return_value=True)
+ vnf.name = str(vnf)
+ self.s.vnfs = [vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.stop = \
+ mock.Mock(return_value=True)
+ self.assertIsNone(self.s.teardown())
+
+ def test_teardown_exception(self):
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.terminate = mock.Mock(
+ side_effect=RuntimeError("error duing terminate"))
+ vnf.name = str(vnf)
+ self.s.vnfs = [vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.stop = \
+ mock.Mock(return_value=True)
+ with self.assertRaises(RuntimeError):
+ self.s.teardown()
+
+
+class TestNetworkServiceRFC2544TestCase(TestNetworkServiceTestCase):
+
+ def setUp(self):
+ super(TestNetworkServiceRFC2544TestCase, self).setUp()
+ self.s = vnf_generic.NetworkServiceRFC2544(self.scenario_cfg,
+ self.context_cfg)
+
+ def test_run(self):
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.name = "tgen__1"
+ tgen.wait_on_trafic.return_value = 'COMPLETE'
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s._fill_traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = mock.Mock(
+ return_value={tgen.name: verified_dict})
+ result = mock.Mock()
+ self.s.run(result)
+ self.s._fill_traffic_profile.assert_called_once()
+ result.push.assert_called_once()
+
+ def test_setup(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.terminate = mock.Mock(return_value=True)
+ tgen.name = "tgen__1"
+ tgen.run_traffic.return_value = 'tg_id'
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ vnf.terminate = mock.Mock(return_value=True)
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
+ self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
+ self.s.setup()
+
+ def test_setup_exception(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.terminate = mock.Mock(return_value=True)
+ tgen.name = "tgen__1"
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ vnf.instantiate.side_effect = RuntimeError(
+ "error during instantiate")
+ vnf.terminate = mock.Mock(return_value=True)
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
+ self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
+ self.s._fill_traffic_profile = \
+ mock.Mock(return_value=TRAFFIC_PROFILE)
+ with self.assertRaises(RuntimeError):
+ self.s.setup()
+
+class TestNetworkServiceRFC3511TestCase(TestNetworkServiceTestCase):
+
+ def setUp(self):
+ super(TestNetworkServiceRFC3511TestCase, self).setUp()
+ self.s = vnf_generic.NetworkServiceRFC3511(self.scenario_cfg,
+ self.context_cfg)
+
+ def test_run(self):
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.name = "tgen__1"
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s._fill_traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = mock.Mock()
+ result = mock.Mock()
+ self.s.run(result)
+ self.s._fill_traffic_profile.assert_called_once()
+ result.push.assert_called_once()
+
+ def test_setup(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, SYS_CLASS_NET + IP_ADDR_SHOW, ""))
+ ssh.from_node.return_value = ssh_mock
+
+ tgen = mock.Mock(autospec=GenericTrafficGen)
+ tgen.traffic_finished = True
+ verified_dict = {"verified": True}
+ tgen.verify_traffic = lambda x: verified_dict
+ tgen.terminate = mock.Mock(return_value=True)
+ tgen.name = "tgen__1"
+ tgen.run_traffic.return_value = 'tg_id'
+ vnf = mock.Mock(autospec=GenericVNF)
+ vnf.runs_traffic = False
+ vnf.terminate = mock.Mock(return_value=True)
+ self.s.vnfs = [tgen, vnf]
+ self.s.traffic_profile = mock.Mock()
+ self.s.collector = mock.Mock(autospec=Collector)
+ self.s.collector.get_kpi = \
+ mock.Mock(return_value={tgen.name: verified_dict})
+ self.s.map_topology_to_infrastructure = mock.Mock(return_value=0)
+ self.s.load_vnf_models = mock.Mock(return_value=self.s.vnfs)
+ self.s.setup()
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
new file mode 100644
index 000000000..a1c27f5fb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf.py
@@ -0,0 +1,196 @@
+# Copyright 2016 Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+import unittest
+import subprocess
+import yardstick.ssh as ssh
+
+from yardstick.benchmark.scenarios.networking import vsperf
+from yardstick import exceptions as y_exc
+
+
+class VsperfTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.context_cfg = {
+ "host": {
+ "ip": "10.229.47.137",
+ "user": "ubuntu",
+ "password": "ubuntu",
+ },
+ }
+ self.scenario_cfg = {
+ 'options': {
+ 'testname': 'p2p_rfc2544_continuous',
+ 'traffic_type': 'continuous',
+ 'frame_size': '64',
+ 'bidirectional': 'True',
+ 'iload': 100,
+ 'trafficgen_port1': 'eth1',
+ 'trafficgen_port2': 'eth3',
+ 'external_bridge': 'br-ex',
+ 'conf_file': 'vsperf-yardstick.conf',
+ 'setup_script': 'setup_yardstick.sh',
+ 'test_params': 'TRAFFICGEN_DURATION=30;',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_fps',
+ 'throughput_rx_fps': 500000,
+ 'action': 'monitor',
+ }
+ }
+
+ self._mock_SSH = mock.patch.object(ssh, 'SSH')
+ self.mock_SSH = self._mock_SSH.start()
+ self.mock_SSH.from_node().execute.return_value = (
+ 0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
+
+ self._mock_subprocess_call = mock.patch.object(subprocess, 'call')
+ self.mock_subprocess_call = self._mock_subprocess_call.start()
+ self.mock_subprocess_call.return_value = None
+
+ self.addCleanup(self._stop_mock)
+
+ self.scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+
+ def _stop_mock(self):
+ self._mock_SSH.stop()
+ self._mock_subprocess_call.stop()
+
+ def test_setup(self):
+ self.scenario.setup()
+ self.assertIsNotNone(self.scenario.client)
+ self.assertTrue(self.scenario.setup_done)
+
+ def test_setup_tg_port_not_set(self):
+ del self.scenario_cfg['options']['trafficgen_port1']
+ del self.scenario_cfg['options']['trafficgen_port2']
+ scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+ scenario.setup()
+
+ self.mock_subprocess_call.assert_called_once_with(
+ 'setup_yardstick.sh setup', shell=True)
+ self.assertIsNone(scenario.tg_port1)
+ self.assertIsNone(scenario.tg_port2)
+ self.assertIsNotNone(scenario.client)
+ self.assertTrue(scenario.setup_done)
+
+ def test_setup_no_setup_script(self):
+ del self.scenario_cfg['options']['setup_script']
+ scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+ scenario.setup()
+
+ self.mock_subprocess_call.assert_has_calls(
+ (mock.call('sudo bash -c "ovs-vsctl add-port br-ex eth1"',
+ shell=True),
+ mock.call('sudo bash -c "ovs-vsctl add-port br-ex eth3"',
+ shell=True)))
+ self.assertEqual(2, self.mock_subprocess_call.call_count)
+ self.assertIsNone(scenario.setup_script)
+ self.assertIsNotNone(scenario.client)
+ self.assertTrue(scenario.setup_done)
+
+ def test_run_ok(self):
+ self.scenario.setup()
+
+ result = {}
+ self.scenario.run(result)
+
+ self.assertEqual(result['throughput_rx_fps'], '14797660.000')
+
+ def test_run_ok_setup_not_done(self):
+ result = {}
+ self.scenario.run(result)
+
+ self.assertTrue(self.scenario.setup_done)
+ self.assertEqual(result['throughput_rx_fps'], '14797660.000')
+
+ def test_run_ssh_command_call_counts(self):
+ self.scenario.run({})
+
+ self.assertEqual(self.mock_SSH.from_node().execute.call_count, 2)
+ self.mock_SSH.from_node().run.assert_called_once()
+
+ def test_run_sla_fail(self):
+ self.mock_SSH.from_node().execute.return_value = (
+ 0, 'throughput_rx_fps\r\n123456.000\r\n', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertTrue('VSPERF_throughput_rx_fps(123456.000000) < '
+ 'SLA_throughput_rx_fps(500000.000000)'
+ in str(raised.exception))
+
+ def test_run_sla_fail_metric_not_collected(self):
+ self.mock_SSH.from_node().execute.return_value = (
+ 0, 'nonexisting_metric\r\n14797660.000\r\n', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertTrue('throughput_rx_fps was not collected by VSPERF'
+ in str(raised.exception))
+
+ def test_run_faulty_result_csv(self):
+ self.mock_SSH.from_node().execute.return_value = (
+ 0, 'faulty output not csv', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertTrue('throughput_rx_fps was not collected by VSPERF'
+ in str(raised.exception))
+
+ def test_run_sla_fail_metric_not_defined_in_sla(self):
+ del self.scenario_cfg['sla']['throughput_rx_fps']
+ scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+ scenario.setup()
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ scenario.run({})
+ self.assertTrue('throughput_rx_fps is not defined in SLA'
+ in str(raised.exception))
+
+ def test_teardown(self):
+ self.scenario.setup()
+ self.assertIsNotNone(self.scenario.client)
+ self.assertTrue(self.scenario.setup_done)
+
+ self.scenario.teardown()
+ self.assertFalse(self.scenario.setup_done)
+
+ def test_teardown_tg_port_not_set(self):
+ del self.scenario_cfg['options']['trafficgen_port1']
+ del self.scenario_cfg['options']['trafficgen_port2']
+ scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+ scenario.teardown()
+
+ self.mock_subprocess_call.assert_called_once_with(
+ 'setup_yardstick.sh teardown', shell=True)
+ self.assertFalse(scenario.setup_done)
+
+ def test_teardown_no_setup_script(self):
+ del self.scenario_cfg['options']['setup_script']
+ scenario = vsperf.Vsperf(self.scenario_cfg, self.context_cfg)
+ scenario.teardown()
+
+ self.mock_subprocess_call.assert_has_calls(
+ (mock.call('sudo bash -c "ovs-vsctl del-port br-ex eth1"',
+ shell=True),
+ mock.call('sudo bash -c "ovs-vsctl del-port br-ex eth3"',
+ shell=True)))
+ self.assertEqual(2, self.mock_subprocess_call.call_count)
+ self.assertFalse(scenario.setup_done)
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
new file mode 100644
index 000000000..8bbe6911e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/test_vsperf_dpdk.py
@@ -0,0 +1,181 @@
+# Copyright 2017 Nokia
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import subprocess
+import time
+
+import mock
+import unittest
+
+from yardstick import exceptions as y_exc
+from yardstick.benchmark.scenarios.networking import vsperf_dpdk
+from yardstick.common import exceptions as y_exc
+from yardstick import ssh
+
+
+class VsperfDPDKTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ "host": {
+ "ip": "10.229.47.137",
+ "user": "ubuntu",
+ "password": "ubuntu",
+ },
+ }
+ self.args = {
+ 'task_id': "1234-5678",
+ 'options': {
+ 'testname': 'pvp_tput',
+ 'traffic_type': 'rfc2544_throughput',
+ 'frame_size': '64',
+ 'test_params': 'TRAFFICGEN_DURATION=30;',
+ 'trafficgen_port1': 'ens4',
+ 'trafficgen_port2': 'ens5',
+ 'conf_file': 'vsperf-yardstick.conf',
+ 'setup_script': 'setup_yardstick.sh',
+ 'moongen_helper_file': '~/moongen.py',
+ 'moongen_host_ip': '10.5.201.151',
+ 'moongen_port1_mac': '8c:dc:d4:ae:7c:5c',
+ 'moongen_port2_mac': '8c:dc:d4:ae:7c:5d',
+ 'trafficgen_port1_nw': 'test2',
+ 'trafficgen_port2_nw': 'test3',
+ },
+ 'sla': {
+ 'metrics': 'throughput_rx_fps',
+ 'throughput_rx_fps': 500000,
+ 'action': 'monitor',
+ }
+ }
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+ self._mock_subprocess_call = mock.patch.object(subprocess, 'call')
+ self.mock_subprocess_call = self._mock_subprocess_call.start()
+ mock_call_obj = mock.Mock()
+ mock_call_obj.execute.return_value = None
+ self.mock_subprocess_call.return_value = mock_call_obj
+
+ self._mock_log_info = mock.patch.object(vsperf_dpdk.LOG, 'info')
+ self.mock_log_info = self._mock_log_info.start()
+
+ self.addCleanup(self._cleanup)
+
+ self.scenario = vsperf_dpdk.VsperfDPDK(self.args, self.ctx)
+ self.scenario.setup()
+
+ def _cleanup(self):
+ self._mock_ssh.stop()
+ self._mock_subprocess_call.stop()
+ self._mock_log_info.stop()
+
+ def test_setup(self):
+ self.assertIsNotNone(self.scenario.client)
+ self.assertTrue(self.scenario.setup_done)
+
+ def test_teardown(self):
+ self.scenario.teardown()
+ self.assertFalse(self.scenario.setup_done)
+
+ def test_is_dpdk_setup_no(self):
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.from_node().execute.return_value = (0, 'dummy', '')
+
+ self.assertFalse(self.scenario._is_dpdk_setup())
+
+ def test_is_dpdk_setup_yes(self):
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.from_node().execute.return_value = (0, '', '')
+
+ self.assertTrue(self.scenario._is_dpdk_setup())
+
+ @mock.patch.object(time, 'sleep')
+ def test_dpdk_setup_first(self, *args):
+ # is_dpdk_setup() specific mocks
+ self.mock_ssh.from_node().execute.return_value = (0, 'dummy', '')
+
+ self.scenario.dpdk_setup()
+ self.assertFalse(self.scenario._is_dpdk_setup())
+ self.assertTrue(self.scenario.dpdk_setup_done)
+
+ @mock.patch.object(time, 'sleep')
+ def test_dpdk_setup_next(self, *args):
+ self.mock_ssh.from_node().execute.return_value = (0, '', '')
+
+ self.scenario.dpdk_setup()
+ self.assertTrue(self.scenario._is_dpdk_setup())
+ self.assertTrue(self.scenario.dpdk_setup_done)
+
+ @mock.patch.object(subprocess, 'check_output')
+ def test_run_ok(self, *args):
+ # run() specific mocks
+ self.mock_ssh.from_node().execute.return_value = (
+ 0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
+
+ result = {}
+ self.scenario.run(result)
+ self.assertEqual(result['throughput_rx_fps'], '14797660.000')
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(subprocess, 'check_output')
+ def test_vsperf_run_sla_fail(self, *args):
+ self.mock_ssh.from_node().execute.return_value = (
+ 0, 'throughput_rx_fps\r\n123456.000\r\n', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertIn('VSPERF_throughput_rx_fps(123456.000000) < '
+ 'SLA_throughput_rx_fps(500000.000000)',
+ str(raised.exception))
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(subprocess, 'check_output')
+ def test_vsperf_run_sla_fail_metric_not_collected(self, *args):
+ self.mock_ssh.from_node().execute.return_value = (
+ 0, 'nonexisting_metric\r\n123456.000\r\n', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertIn('throughput_rx_fps was not collected by VSPERF',
+ str(raised.exception))
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(subprocess, 'check_output')
+ def test_vsperf_run_sla_fail_metric_not_collected_faulty_csv(self, *args):
+ self.scenario.setup()
+
+ self.mock_ssh.from_node().execute.return_value = (
+ 0, 'faulty output not csv', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertIn('throughput_rx_fps was not collected by VSPERF',
+ str(raised.exception))
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(subprocess, 'check_output')
+ def test_vsperf_run_sla_fail_sla_not_defined(self, *args):
+ del self.scenario.scenario_cfg['sla']['throughput_rx_fps']
+ self.scenario.setup()
+
+ self.mock_ssh.from_node().execute.return_value = (
+ 0, 'throughput_rx_fps\r\n14797660.000\r\n', '')
+
+ with self.assertRaises(y_exc.SLAValidationError) as raised:
+ self.scenario.run({})
+
+ self.assertIn('throughput_rx_fps is not defined in SLA',
+ str(raised.exception))
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/tg_trex_tpl.yaml b/yardstick/tests/unit/benchmark/scenarios/networking/tg_trex_tpl.yaml
new file mode 100644
index 000000000..b1641836b
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/tg_trex_tpl.yaml
@@ -0,0 +1,75 @@
+# 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.
+
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: TrexTrafficGen # NSPerf class mapping
+ name: trexgen
+ short-name: trexgen
+ description: TRex stateless traffic generator for tests
+ vm-flavor:
+ vcpu-count: '4'
+ memory-mb: '4096'
+ mgmt-interface:
+ vdu-id: trexgen-baremetal
+ user: '{{user}}' # Value filled by vnfdgen
+ password: '{{password}}' # Value filled by vnfdgen
+ ip: '{{ip}}' # Value filled by vnfdgen
+ connection-point:
+ - name: xe0
+ type: VPORT
+ - name: xe1
+ type: VPORT
+ vdu:
+ - id: trexgen-baremetal
+ name: trexgen-baremetal
+ description: TRex stateless traffic generator for tests
+ external-interface:
+ - name: xe0
+ virtual-interface:
+ type: PCI-PASSTHROUGH
+ # Substitution variables MUST be quoted. Otherwise Python can misinterpet them.
+ vpci: '{{ interfaces.xe0.vpci }}' # Value filled by vnfdgen
+ local_ip: '{{ interfaces.xe0.local_ip }}' # Value filled by vnfdgen
+ driver: '{{ interfaces.xe0.driver}}' # Value filled by vnfdgen
+ dst_ip: '{{ interfaces.xe0.dst_ip }}' # Value filled by vnfdgen
+ local_mac: '{{ interfaces.xe0.local_mac }}' # Value filled by vnfdgen
+ dst_mac: '{{ interfaces.xe0.dst_mac }}' # Value filled by vnfdgen
+ vld_id: '{{ interfaces.xe0.vld_id }}' # Value filled by vnfdgen
+ bandwidth: 10 Gbps
+ vnfd-connection-point-ref: xe0
+ - name: xe1
+ virtual-interface:
+ type: PCI-PASSTHROUGH
+ vpci: '{{ interfaces.xe1.vpci }}' # Value filled by vnfdgen
+ local_ip: '{{ interfaces.xe1.local_ip }}' # Value filled by vnfdgen
+ driver: '{{ interfaces.xe1.driver}}' # Value filled by vnfdgen
+ dst_ip: '{{ interfaces.xe1.dst_ip }}' # Value filled by vnfdgen
+ local_mac: '{{ interfaces.xe1.local_mac }}' # Value filled by vnfdgen
+ dst_mac: '{{ interfaces.xe1.dst_mac }}' # Value filled by vnfdgen
+ vld_id: '{{ interfaces.xe1.vld_id }}' # Value filled by vnfdgen
+ bandwidth: 10 Gbps
+ vnfd-connection-point-ref: xe1
+
+ benchmark:
+ kpi:
+ - rx_throughput_fps
+ - tx_throughput_fps
+ - tx_throughput_mbps
+ - rx_throughput_mbps
+ - tx_throughput_pc_linerate
+ - rx_throughput_pc_linerate
+ - min_latency
+ - max_latency
+ - avg_latency
diff --git a/yardstick/tests/unit/benchmark/scenarios/networking/vpe_vnf_topology.yaml b/yardstick/tests/unit/benchmark/scenarios/networking/vpe_vnf_topology.yaml
new file mode 100644
index 000000000..aaf84bb5e
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/networking/vpe_vnf_topology.yaml
@@ -0,0 +1,50 @@
+# Copyright (c) 2016-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.
+
+nsd:nsd-catalog:
+ nsd:
+ - id: VPE
+ name: VPE
+ short-name: VPE
+ description: scenario with VPE,L3fwd and VNF
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__0
+ VNF model: ../../vnf_descriptors/tg_rfc2544_tpl.yaml #tg_trex_tpl.yaml #TREX
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__0
+ VNF model: ../../vnf_descriptors/vpe_vnf.yaml #VPE VNF
+
+ vld:
+ - id: uplink
+ name: tg__0 to vnf__0 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__0
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__0
+
+ - id: downlink
+ name: vnf__0 to tg__0 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__0
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__0
diff --git a/yardstick/tests/unit/benchmark/scenarios/parser/__init__.py b/yardstick/tests/unit/benchmark/scenarios/parser/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/parser/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py b/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py
new file mode 100644
index 000000000..9fd5cce38
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/parser/test_parser.py
@@ -0,0 +1,70 @@
+##############################################################################
+# Copyright (c) 2015 Huawei Technologies Co.,Ltd and other.
+#
+# 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 subprocess
+
+import unittest
+import mock
+
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.parser import parser
+
+
+class ParserTestCase(unittest.TestCase):
+
+ def setUp(self):
+ args = {
+ 'options': {'yangfile': '/root/yardstick/samples/yang.yaml',
+ 'toscafile': '/root/yardstick/samples/tosca.yaml'},
+ }
+ self.scenario = parser.Parser(scenario_cfg=args, context_cfg={})
+
+ self._mock_popen = mock.patch.object(subprocess, 'Popen')
+ self.mock_popen = self._mock_popen.start()
+ self._mock_call = mock.patch.object(subprocess, 'call')
+ self.mock_call = self._mock_call.start()
+
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_popen.stop()
+ self._mock_call.stop()
+
+ def test_setup_successful(self):
+
+ self.mock_call.return_value = 0
+ self.scenario.setup()
+ self.assertTrue(self.scenario.setup_done)
+
+ def test_run_successful(self):
+
+ result = {}
+
+ self.mock_popen().returncode = 0
+
+ expected_result = jsonutils.loads('{"yangtotosca": "success"}')
+
+ self.scenario.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_run_fail(self):
+ result = {}
+
+ self.mock_popen().returncode = 1
+ expected_result = jsonutils.loads('{"yangtotosca": "fail"}')
+
+ self.scenario.run(result)
+ self.assertEqual(result, expected_result)
+
+ def test_teardown_successful(self):
+
+ self.mock_call.return_value = 0
+ self.scenario.teardown()
+ self.assertTrue(self.scenario.teardown_done)
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/__init__.py b/yardstick/tests/unit/benchmark/scenarios/storage/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/__init__.py
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/fio_read_sample_output.json b/yardstick/tests/unit/benchmark/scenarios/storage/fio_read_sample_output.json
new file mode 100644
index 000000000..e9f642aba
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/fio_read_sample_output.json
@@ -0,0 +1 @@
+{"fioversion": "fio-2.1.3","jobs": [{"jobname": "yardstick-fio","groupid": 0,"error": 0,"read": {"io_bytes": 2166860,"bw": 36113,"iops": 9028,"runtime": 60001,"slat": {"min": 7,"max": 1807,"mean": 10.49,"stddev": 3.00},"clat": {"min": 1,"max": 16902,"mean": 97.84,"stddev": 78.16,"percentile": {"1.000000": 84,"5.000000": 86,"10.000000": 87,"20.000000": 88,"30.000000": 89,"40.000000": 90,"50.000000": 91,"60.000000": 93,"70.000000": 98,"80.000000": 103,"90.000000": 111,"95.000000": 127,"99.000000": 161,"99.500000": 177,"99.900000": 215,"99.950000": 266,"99.990000": 4128,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 86,"max": 16912,"mean": 108.70,"stddev": 78.29},"bw_min": 0,"bw_max": 38128,"bw_agg": 35816.54,"bw_mean": 35816.54,"bw_dev": 3579.16},"write": {"io_bytes": 0,"bw": 0,"iops": 0,"runtime": 0,"slat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"clat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00,"percentile": {"1.000000": 0,"5.000000": 0,"10.000000": 0,"20.000000": 0,"30.000000": 0,"40.000000": 0,"50.000000": 0,"60.000000": 0,"70.000000": 0,"80.000000": 0,"90.000000": 0,"95.000000": 0,"99.000000": 0,"99.500000": 0,"99.900000": 0,"99.950000": 0,"99.990000": 0,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"bw_min": 0,"bw_max": 0,"bw_agg": 0.00,"bw_mean": 0.00,"bw_dev": 0.00},"trim": {"io_bytes": 0,"bw": 0,"iops": 0,"runtime": 0,"slat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"clat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00,"percentile": {"1.000000": 0,"5.000000": 0,"10.000000": 0,"20.000000": 0,"30.000000": 0,"40.000000": 0,"50.000000": 0,"60.000000": 0,"70.000000": 0,"80.000000": 0,"90.000000": 0,"95.000000": 0,"99.000000": 0,"99.500000": 0,"99.900000": 0,"99.950000": 0,"99.990000": 0,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"bw_min": 0,"bw_max": 0,"bw_agg": 0.00,"bw_mean": 0.00,"bw_dev": 0.00},"usr_cpu": 4.86,"sys_cpu": 19.38,"ctx": 632024,"majf": 0,"minf": 30,"iodepth_level": {"1": 116.58,"2": 0.00,"4": 0.00,"8": 0.00,"16": 0.00,"32": 0.00,">=64": 0.00},"latency_us": {"2": 0.01,"4": 0.01,"10": 0.00,"20": 0.00,"50": 0.01,"100": 72.60,"250": 27.34,"500": 0.04,"750": 0.01,"1000": 0.01},"latency_ms": {"2": 0.01,"4": 0.01,"10": 0.01,"20": 0.01,"50": 0.00,"100": 0.00,"250": 0.00,"500": 0.00,"750": 0.00,"1000": 0.00,"2000": 0.00,">=2000": 0.00}}],"disk_util": [{"name": "vda","read_ios": 631084,"write_ios": 212,"read_merges": 0,"write_merges": 232,"read_ticks": 57300,"write_ticks": 324,"in_queue": 57400,"util": 81.55}]}
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/fio_rw_sample_output.json b/yardstick/tests/unit/benchmark/scenarios/storage/fio_rw_sample_output.json
new file mode 100644
index 000000000..4c7501818
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/fio_rw_sample_output.json
@@ -0,0 +1 @@
+{"jobs": [{"trim": {"io_bytes": 0, "slat": {"max": 0, "mean": 0.0, "stddev": 0.0, "min": 0}, "bw_max": 0, "bw_mean": 0.0, "iops": 0, "bw": 0, "lat": {"max": 0, "mean": 0.0, "stddev": 0.0, "min": 0}, "bw_agg": 0.0, "clat": {"max": 0, "mean": 0.0, "percentile": {"70.000000": 0, "5.000000": 0, "50.000000": 0, "99.990000": 0, "30.000000": 0, "10.000000": 0, "99.000000": 0, "0.00": 0, "90.000000": 0, "95.000000": 0, "60.000000": 0, "40.000000": 0, "20.000000": 0, "99.900000": 0, "99.950000": 0, "1.000000": 0, "99.500000": 0, "80.000000": 0}, "stddev": 0.0, "min": 0}, "runtime": 0, "bw_min": 0, "bw_dev": 0.0}, "latency_us": {"10": 0.01, "750": 0.03, "20": 0.0, "50": 0.02, "2": 0.01, "4": 0.01, "100": 0.75, "250": 88.37, "500": 10.72, "1000": 0.01}, "latency_ms": {"10": 0.01, "750": 0.0, "20": 0.01, ">=2000": 0.0, "50": 0.01, "2000": 0.0, "2": 0.07, "4": 0.01, "100": 0.0, "250": 0.01, "500": 0.0, "1000": 0.01}, "read": {"io_bytes": 839056, "slat": {"max": 1990, "mean": 18.14, "stddev": 15.4, "min": 0}, "bw_max": 10328, "bw_mean": 8721.27, "iops": 20972, "bw": 83888, "lat": {"max": 776676, "mean": 236.8, "stddev": 4668.12, "min": 45}, "bw_agg": 8721.27, "clat": {"max": 776663, "mean": 217.79, "percentile": {"70.000000": 199, "5.000000": 119, "50.000000": 175, "99.990000": 15168, "30.000000": 155, "10.000000": 131, "99.000000": 342, "0.00": 0, "90.000000": 247, "95.000000": 278, "60.000000": 185, "40.000000": 165, "20.000000": 145, "99.900000": 820, "99.950000": 1272, "1.000000": 96, "99.500000": 370, "80.000000": 217}, "stddev": 4667.79, "min": 0}, "runtime": 10002, "bw_min": 4, "bw_dev": 2178.08}, "majf": 0, "ctx": 490590, "minf": 87, "jobname": "yardstick-fio", "write": {"io_bytes": 841992, "slat": {"max": 2594, "mean": 19.78, "stddev": 16.25, "min": 0}, "bw_max": 10472, "bw_mean": 8464.0, "iops": 21045, "bw": 84182, "lat": {"max": 776709, "mean": 233.55, "stddev": 3115.46, "min": 64}, "bw_agg": 8464.0, "clat": {"max": 776685, "mean": 212.87, "percentile": {"70.000000": 211, "5.000000": 135, "50.000000": 187, "99.990000": 3536, "30.000000": 169, "10.000000": 145, "99.000000": 358, "0.00": 0, "90.000000": 258, "95.000000": 290, "60.000000": 197, "40.000000": 177, "20.000000": 159, "99.900000": 756, "99.950000": 1288, "1.000000": 114, "99.500000": 382, "80.000000": 229}, "stddev": 3115.23, "min": 0}, "runtime": 10002, "bw_min": 4, "bw_dev": 2584.23}, "iodepth_level": {"16": 0.0, "32": 0.0, "1": 111.92, "2": 0.0, "4": 0.0, ">=64": 0.0, "8": 0.0}, "usr_cp": 2.87, "error": 0, "sys_cp": 12.37, "groupid": 0}], "fio version": "fio-2.1.3", "disk_util": [{"aggr_write_ticks": 42020, "read_merges": 0, "name": "dm-0", "write_ios": 233547, "aggr_write_ios": 235129, "aggr_read_ticks": 42576, "read_ios": 233492, "util": 97.22, "read_ticks": 42096, "aggr_write_merge": 0, "write_merges": 0, "aggr_in_queue": 84524, "aggr_read_ios": 235224, "aggr_util": 96.96, "aggr_read_merges": 0, "in_queue": 83732, "write_ticks": 41468}, {"read_merges": 0, "name": "vda", "write_ios": 235129, "read_ios": 235224, "util": 96.96, "read_ticks": 42576, "write_merges": 0, "in_queue": 84524, "write_ticks": 42020}]}
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/fio_write_sample_output.json b/yardstick/tests/unit/benchmark/scenarios/storage/fio_write_sample_output.json
new file mode 100644
index 000000000..7c760e8bc
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/fio_write_sample_output.json
@@ -0,0 +1 @@
+{"fioversion": "fio-2.1.3","jobs": [{"jobname": "yardstick-fio","groupid": 0,"error": 0,"read": {"io_bytes": 0,"bw": 0,"iops": 0,"runtime": 0,"slat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"clat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00,"percentile": {"1.000000": 0,"5.000000": 0,"10.000000": 0,"20.000000": 0,"30.000000": 0,"40.000000": 0,"50.000000": 0,"60.000000": 0,"70.000000": 0,"80.000000": 0,"90.000000": 0,"95.000000": 0,"99.000000": 0,"99.500000": 0,"99.900000": 0,"99.950000": 0,"99.990000": 0,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"bw_min": 0,"bw_max": 0,"bw_agg": 0.00,"bw_mean": 0.00,"bw_dev": 0.00},"write": {"io_bytes": 2106508,"bw": 35107,"iops": 8776,"runtime": 60001,"slat": {"min": 8,"max": 5166,"mean": 11.83,"stddev": 7.05},"clat": {"min": 1,"max": 23472,"mean": 99.54,"stddev": 44.23,"percentile": {"1.000000": 85,"5.000000": 87,"10.000000": 88,"20.000000": 89,"30.000000": 90,"40.000000": 91,"50.000000": 93,"60.000000": 99,"70.000000": 104,"80.000000": 107,"90.000000": 113,"95.000000": 127,"99.000000": 161,"99.500000": 179,"99.900000": 231,"99.950000": 286,"99.990000": 628,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 87,"max": 23486,"mean": 111.74,"stddev": 45.61},"bw_min": 0,"bw_max": 37288,"bw_agg": 34839.53,"bw_mean": 34839.53,"bw_dev": 3387.37},"trim": {"io_bytes": 0,"bw": 0,"iops": 0,"runtime": 0,"slat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"clat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00,"percentile": {"1.000000": 0,"5.000000": 0,"10.000000": 0,"20.000000": 0,"30.000000": 0,"40.000000": 0,"50.000000": 0,"60.000000": 0,"70.000000": 0,"80.000000": 0,"90.000000": 0,"95.000000": 0,"99.000000": 0,"99.500000": 0,"99.900000": 0,"99.950000": 0,"99.990000": 0,"0.00": 0,"0.00": 0,"0.00": 0}},"lat": {"min": 0,"max": 0,"mean": 0.00,"stddev": 0.00},"bw_min": 0,"bw_max": 0,"bw_agg": 0.00,"bw_mean": 0.00,"bw_dev": 0.00},"usr_cpu": 5.25,"sys_cpu": 19.72,"ctx": 616160,"majf": 0,"minf": 27,"iodepth_level": {"1": 116.90,"2": 0.00,"4": 0.00,"8": 0.00,"16": 0.00,"32": 0.00,">=64": 0.00},"latency_us": {"2": 0.01,"4": 0.01,"10": 0.00,"20": 0.00,"50": 0.01,"100": 60.74,"250": 39.18,"500": 0.06,"750": 0.01,"1000": 0.01},"latency_ms": {"2": 0.01,"4": 0.01,"10": 0.01,"20": 0.00,"50": 0.01,"100": 0.00,"250": 0.00,"500": 0.00,"750": 0.00,"1000": 0.00,"2000": 0.00,">=2000": 0.00}}],"disk_util": [{"name": "vda","read_ios": 0,"write_ios": 615418,"read_merges": 0,"write_merges": 231,"read_ticks": 0,"write_ticks": 58284,"in_queue": 58024,"util": 82.45}]}
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py
new file mode 100644
index 000000000..d78506584
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_bonnie.py
@@ -0,0 +1,63 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+
+from yardstick.benchmark.scenarios.storage import bonnie
+
+
+class BonnieTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'root',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ @mock.patch('yardstick.benchmark.scenarios.storage.bonnie.ssh')
+ def test_bonnie_successful_setup(self, mock_ssh):
+
+ options = {
+ "file_size": "1024",
+ "ram_size": "512",
+ "test_dir": "/tmp",
+ "concurrency": "1",
+ "test_user": "root"
+ }
+ args = {"options": options}
+ b = bonnie.Bonnie(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ b.setup()
+ self.assertIsNotNone(b.client)
+ self.assertTrue(b.setup_done, True)
+
+ @mock.patch('yardstick.benchmark.scenarios.storage.bonnie.ssh')
+ def test_bonnie_unsuccessful_script_error(self, mock_ssh):
+ options = {
+ "file_size": "1024",
+ "ram_size": "512",
+ "test_dir": "/tmp",
+ "concurrency": "1",
+ "test_user": "root"
+ }
+ args = {"options": options}
+ b = bonnie.Bonnie(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, b.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
new file mode 100644
index 000000000..6e69ddc6d
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_fio.py
@@ -0,0 +1,280 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.storage.fio.Fio
+
+from __future__ import absolute_import
+
+import os
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.storage import fio
+from yardstick.common import exceptions as y_exc
+
+
+@mock.patch('yardstick.benchmark.scenarios.storage.fio.ssh')
+class FioTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': 'mykey.key'
+ }
+ }
+ self.sample_output = {
+ 'read': 'fio_read_sample_output.json',
+ 'write': 'fio_write_sample_output.json',
+ 'rw': 'fio_rw_sample_output.json'
+ }
+
+ def test_fio_successful_setup(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ p.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_fio_job_file_successful_setup(self, mock_ssh):
+
+ options = {
+ 'job_file': 'job_file.ini',
+ 'directory': '/FIO_Test'
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '/dev/vdb', '')
+ p.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_fio_job_file_no_disk__setup(self, mock_ssh):
+
+ options = {
+ 'job_file': 'job_file.ini',
+ 'directory': '/FIO_Test'
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ p.setup()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ self.assertIsNotNone(p.client)
+ self.assertTrue(p.setup_done)
+
+ def test_fio_successful_no_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['rw'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+
+ expected_result = '{"read_bw": 83888, "read_iops": 20972,' \
+ '"read_lat": 236.8, "write_bw": 84182, "write_iops": 21045,'\
+ '"write_lat": 233.55}'
+ expected_result = jsonutils.loads(expected_result)
+ self.assertEqual(result, expected_result)
+
+ def test_fio_successful_read_no_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': "read",
+ 'ramp_time': 10
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['read'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+
+ expected_result = '{"read_bw": 36113, "read_iops": 9028,' \
+ '"read_lat": 108.7}'
+ expected_result = jsonutils.loads(expected_result)
+ self.assertEqual(result, expected_result)
+
+ def test_fio_successful_write_no_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'write',
+ 'ramp_time': 10
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['write'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+
+ expected_result = '{"write_bw": 35107, "write_iops": 8776,'\
+ '"write_lat": 111.74}'
+ expected_result = jsonutils.loads(expected_result)
+ self.assertEqual(result, expected_result)
+
+ def test_fio_successful_lat_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {
+ 'options': options,
+ 'sla': {'write_lat': 300.1}
+ }
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['rw'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+
+ expected_result = '{"read_bw": 83888, "read_iops": 20972,' \
+ '"read_lat": 236.8, "write_bw": 84182, "write_iops": 21045,'\
+ '"write_lat": 233.55}'
+ expected_result = jsonutils.loads(expected_result)
+ self.assertEqual(result, expected_result)
+
+ def test_fio_unsuccessful_lat_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {
+ 'options': options,
+ 'sla': {'write_lat': 200.1}
+ }
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['rw'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_fio_successful_bw_iops_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {
+ 'options': options,
+ 'sla': {'read_iops': 20000}
+ }
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['rw'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+
+ p.run(result)
+
+ expected_result = '{"read_bw": 83888, "read_iops": 20972,' \
+ '"read_lat": 236.8, "write_bw": 84182, "write_iops": 21045,'\
+ '"write_lat": 233.55}'
+ expected_result = jsonutils.loads(expected_result)
+ self.assertEqual(result, expected_result)
+
+ def test_fio_unsuccessful_bw_iops_sla(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {
+ 'options': options,
+ 'sla': {'read_iops': 30000}
+ }
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ sample_output = self._read_sample_output(self.sample_output['rw'])
+ mock_ssh.SSH.from_node().execute.return_value = (0, sample_output, '')
+ self.assertRaises(y_exc.SLAValidationError, p.run, result)
+
+ def test_fio_unsuccessful_script_error(self, mock_ssh):
+
+ options = {
+ 'filename': '/home/ubuntu/data.raw',
+ 'bs': '4k',
+ 'rw': 'rw',
+ 'ramp_time': 10
+ }
+ args = {'options': options}
+ p = fio.Fio(args, self.ctx)
+ result = {}
+
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, p.run, result)
+
+ def _read_sample_output(self, file_name):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ output = os.path.join(curr_path, file_name)
+ with open(output) as f:
+ sample_output = f.read()
+ return sample_output
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py
new file mode 100644
index 000000000..c1c731b0a
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_storagecapacity.py
@@ -0,0 +1,99 @@
+##############################################################################
+# 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
+##############################################################################
+
+# Unittest for
+# yardstick.benchmark.scenarios.storage.storagecapacity.StorageCapacity
+
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.benchmark.scenarios.storage import storagecapacity
+
+DISK_SIZE_SAMPLE_OUTPUT = \
+ '{"Numberf of devides": "2", "Total disk size in bytes": "1024000000"}'
+BLOCK_SIZE_SAMPLE_OUTPUT = '{"/dev/sda": 1024, "/dev/sdb": 4096}'
+DISK_UTIL_RAW_OUTPUT = "vda 10.00\nvda 0.00"
+DISK_UTIL_SAMPLE_OUTPUT = \
+ '{"vda": {"avg_util": 5.0, "max_util": 10.0, "min_util": 0.0}}'
+
+
+@mock.patch('yardstick.benchmark.scenarios.storage.storagecapacity.ssh')
+class StorageCapacityTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.scn = {
+ "options": {
+ 'test_type': 'disk_size'
+ }
+ }
+ self.ctx = {
+ "host": {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'password': "root"
+ }
+ }
+ self.result = {}
+
+ def test_capacity_successful_setup(self, mock_ssh):
+ c = storagecapacity.StorageCapacity(self.scn, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+ c.setup()
+ self.assertIsNotNone(c.client)
+ self.assertTrue(c.setup_done)
+
+ def test_capacity_disk_size_successful(self, mock_ssh):
+ c = storagecapacity.StorageCapacity(self.scn, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, DISK_SIZE_SAMPLE_OUTPUT, '')
+ c.run(self.result)
+ expected_result = jsonutils.loads(
+ DISK_SIZE_SAMPLE_OUTPUT)
+ self.assertEqual(self.result, expected_result)
+
+ def test_capacity_block_size_successful(self, mock_ssh):
+ args = {
+ "options": {
+ 'test_type': 'block_size'
+ }
+ }
+ c = storagecapacity.StorageCapacity(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, BLOCK_SIZE_SAMPLE_OUTPUT, '')
+ c.run(self.result)
+ expected_result = jsonutils.loads(
+ BLOCK_SIZE_SAMPLE_OUTPUT)
+ self.assertEqual(self.result, expected_result)
+
+ def test_capacity_disk_utilization_successful(self, mock_ssh):
+ args = {
+ "options": {
+ 'test_type': 'disk_utilization',
+ 'interval': 1,
+ 'count': 2
+ }
+ }
+ c = storagecapacity.StorageCapacity(args, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, DISK_UTIL_RAW_OUTPUT, '')
+ c.run(self.result)
+ expected_result = jsonutils.loads(
+ DISK_UTIL_SAMPLE_OUTPUT)
+ self.assertEqual(self.result, expected_result)
+
+ def test_capacity_unsuccessful_script_error(self, mock_ssh):
+ c = storagecapacity.StorageCapacity(self.scn, self.ctx)
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
+ self.assertRaises(RuntimeError, c.run, self.result)
diff --git a/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py b/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py
new file mode 100644
index 000000000..2ba53cb93
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/storage/test_storperf.py
@@ -0,0 +1,513 @@
+##############################################################################
+# Copyright (c) 2016 Huawei Technologies Co.,Ltd.
+#
+# 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
+##############################################################################
+
+# Unittest for yardstick.benchmark.scenarios.storage.storperf.StorPerf
+
+from __future__ import absolute_import
+
+import json
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+import requests
+
+from yardstick.benchmark.scenarios.storage import storperf
+
+
+# pylint: disable=unused-argument
+# disable this for now because I keep forgetting mock patch arg ordering
+def mocked_requests_config_post(*args, **kwargs):
+ class MockResponseConfigPost(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseConfigPost(
+ '{"stack_id": "dac27db1-3502-4300-b301-91c64e6a1622",'
+ '"stack_created": false}',
+ 200)
+
+
+def mocked_requests_config_post_fail(*args, **kwargs):
+ class MockResponseConfigPost(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseConfigPost(
+ '{"message": "ERROR: Parameter \'public_network\' is invalid: ' +
+ 'Error validating value \'foo\': Unable to find network with ' +
+ 'name or id \'foo\'"}',
+ 400)
+
+
+def mocked_requests_config_get(*args, **kwargs):
+ class MockResponseConfigGet(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseConfigGet(
+ '{"stack_id": "dac27db1-3502-4300-b301-91c64e6a1622",'
+ '"stack_created": true}',
+ 200)
+
+
+def mocked_requests_config_get_not_created(*args, **kwargs):
+ class MockResponseConfigGet(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseConfigGet(
+ '{"stack_id": "",'
+ '"stack_created": false}',
+ 200)
+
+
+def mocked_requests_config_get_no_payload(*args, **kwargs):
+ class MockResponseConfigGet(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseConfigGet(
+ '{}',
+ 200)
+
+
+def mocked_requests_initialize_post_fail(*args, **kwargs):
+ class MockResponseJobPost(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseJobPost(
+ '{"message": "ERROR: Stack StorPerfAgentGroup does not exist"}',
+ 400)
+
+
+def mocked_requests_job_get(*args, **kwargs):
+ class MockResponseJobGet(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseJobGet(
+ '{"Status": "Completed",\
+ "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}',
+ 200)
+
+
+def mocked_requests_job_post(*args, **kwargs):
+ class MockResponseJobPost(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseJobPost('{"job_id": \
+ "d46bfb8c-36f4-4a40-813b-c4b4a437f728"}', 200)
+
+
+def mocked_requests_job_post_fail(*args, **kwargs):
+ class MockResponseJobPost(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseJobPost(
+ '{"message": "ERROR: Stack StorPerfAgentGroup does not exist"}',
+ 400)
+
+
+def mocked_requests_job_delete(*args, **kwargs):
+ class MockResponseJobDelete(object):
+
+ def __init__(self, json_data, status_code):
+ self.content = json_data
+ self.status_code = status_code
+
+ return MockResponseJobDelete('{}', 200)
+
+
+def mocked_requests_delete(*args, **kwargs):
+ class MockResponseDelete(object):
+
+ def __init__(self, json_data, status_code):
+ self.json_data = json_data
+ self.status_code = status_code
+
+ return MockResponseDelete('{}', 200)
+
+
+def mocked_requests_delete_failed(*args, **kwargs):
+ class MockResponseDeleteFailed(object):
+
+ def __init__(self, json_data, status_code):
+ self.json_data = json_data
+ self.status_code = status_code
+
+ return MockResponseDeleteFailed('{"message": "Teardown failed"}', 400)
+
+
+class StorPerfTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ctx = {
+ 'host': {
+ 'ip': '172.16.0.137',
+ 'user': 'cirros',
+ 'key_filename': "mykey.key"
+ }
+ }
+
+ self.result = {}
+
+ @mock.patch.object(requests, 'post')
+ @mock.patch.object(requests, 'get')
+ def test_setup(self, mock_get, mock_post):
+ mock_post.side_effect = [mocked_requests_config_post(),
+ mocked_requests_job_post()]
+ mock_get.side_effect = [mocked_requests_config_get(),
+ mocked_requests_job_get()]
+
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workload": "rs",
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 0,
+ "timeout": 60
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ s.setup()
+
+ self.assertTrue(s.setup_done)
+
+ @mock.patch.object(requests, 'get')
+ def test_query_setup_state_unsuccessful(self, mock_get):
+ mock_get.side_effect = mocked_requests_config_get_not_created
+ args = {
+ "options": {}
+ }
+ s = storperf.StorPerf(args, self.ctx)
+ result = s._query_setup_state()
+ self.assertFalse(result)
+
+ @mock.patch.object(requests, 'get')
+ def test_query_setup_state_no_payload(self, mock_get):
+ mock_get.side_effect = mocked_requests_config_get_no_payload
+ args = {
+ "options": {}
+ }
+ s = storperf.StorPerf(args, self.ctx)
+ result = s._query_setup_state()
+ self.assertFalse(result)
+
+ @mock.patch.object(requests, 'post')
+ @mock.patch.object(requests, 'get')
+ def test_setup_config_post_failed(self, mock_get, mock_post):
+ mock_post.side_effect = mocked_requests_config_post_fail
+
+ args = {
+ "options": {
+ "public_network": "foo"
+ }
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ self.assertRaises(RuntimeError, s.setup)
+
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ def test_run_v1_successful(self, mock_post, mock_get):
+ mock_post.side_effect = mocked_requests_job_post
+ mock_get.side_effect = mocked_requests_job_get
+
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workload": "rs",
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 0,
+ "timeout": 60
+ }
+ expected_post = {
+ 'metadata': {
+ 'build_tag': 'latest',
+ 'test_case': 'opnfv_yardstick_tc074'
+ },
+ 'deadline': 60,
+ 'block_sizes': 4096,
+ 'queue_depths': 4,
+ "workload": "rs",
+ 'agent_count': 8
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+ s.setup_done = True
+
+ sample_output = '{"Status": "Completed",\
+ "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}'
+
+ expected_result = jsonutils.loads(sample_output)
+
+ s.run(self.result)
+
+ mock_post.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v1.0/jobs',
+ json=jsonutils.loads(json.dumps(expected_post)))
+
+ self.assertEqual(self.result, expected_result)
+
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ def test_run_v2_successful(self, mock_post, mock_get):
+ mock_post.side_effect = mocked_requests_job_post
+ mock_get.side_effect = mocked_requests_job_get
+
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workloads": {
+ "read_sequential": {
+ "rw": "rs"
+ }
+ },
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 0,
+ "timeout": 60
+ }
+ expected_post = {
+ 'metadata': {
+ 'build_tag': 'latest',
+ 'test_case': 'opnfv_yardstick_tc074'
+ },
+ 'deadline': 60,
+ 'block_sizes': 4096,
+ 'queue_depths': 4,
+ 'workloads': {
+ 'read_sequential': {
+ 'rw': 'rs'
+ }
+ },
+ 'agent_count': 8
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+ s.setup_done = True
+
+ sample_output = '{"Status": "Completed",\
+ "_ssd_preconditioning.queue-depth.8.block-size.16384.duration": 6}'
+
+ expected_result = jsonutils.loads(sample_output)
+
+ s.run(self.result)
+ mock_post.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v2.0/jobs',
+ json=expected_post)
+
+ self.assertEqual(self.result, expected_result)
+
+ @mock.patch('time.sleep')
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ def test_run_failed(self, mock_post, mock_get, _):
+ mock_post.side_effect = mocked_requests_job_post_fail
+ mock_get.side_effect = mocked_requests_job_get
+
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workloads": {
+ "read_sequential": {
+ "rw": "rs"
+ }
+ },
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 0,
+ "timeout": 60
+ }
+ expected_post = {
+ 'metadata': {
+ 'build_tag': 'latest',
+ 'test_case': 'opnfv_yardstick_tc074'
+ },
+ 'deadline': 60,
+ 'block_sizes': 4096,
+ 'queue_depths': 4,
+ 'workloads': {
+ 'read_sequential': {
+ 'rw': 'rs'
+ }
+ },
+ 'agent_count': 8
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+ s.setup_done = True
+
+ self.assertRaises(RuntimeError, s.run, self.ctx)
+ mock_post.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v2.0/jobs',
+ json=expected_post)
+
+ @mock.patch('time.sleep')
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ @mock.patch.object(storperf.StorPerf, 'setup')
+ def test_run_calls_setup(self, mock_setup, mock_post, mock_get, _):
+ mock_post.side_effect = mocked_requests_job_post
+ mock_get.side_effect = mocked_requests_job_get
+
+ args = {
+ "options": {
+ 'timeout': 60,
+ }
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ s.run(self.result)
+
+ mock_setup.assert_called_once()
+
+ @mock.patch('time.sleep')
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ def test_initialize_disks(self, mock_post, mock_get, _):
+ mock_post.side_effect = mocked_requests_job_post
+ mock_get.side_effect = mocked_requests_job_get
+
+ args = {
+ "options": {
+ "StorPerf_ip": "192.168.23.2"
+ }
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ s.initialize_disks()
+
+ mock_post.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v1.0/initializations',
+ json={})
+
+ @mock.patch('time.sleep')
+ @mock.patch.object(requests, 'get')
+ @mock.patch.object(requests, 'post')
+ def test_initialize_disks_post_failed(self, mock_post, mock_get, _):
+ mock_post.side_effect = mocked_requests_initialize_post_fail
+ mock_get.side_effect = mocked_requests_job_get
+
+ args = {
+ "options": {
+ "StorPerf_ip": "192.168.23.2"
+ }
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ self.assertRaises(RuntimeError, s.initialize_disks)
+ mock_post.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v1.0/initializations',
+ json={})
+
+ @mock.patch.object(requests, 'delete')
+ def test_teardown(self, mock_delete):
+ mock_delete.side_effect = mocked_requests_job_delete
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workload": "rs",
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 10,
+ "timeout": 60
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ s.teardown()
+
+ self.assertFalse(s.setup_done)
+ mock_delete.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v1.0/configurations')
+
+ @mock.patch.object(requests, 'delete')
+ def test_teardown_request_delete_failed(self, mock_delete):
+ mock_delete.side_effect = mocked_requests_delete_failed
+ options = {
+ "agent_count": 8,
+ "public_network": 'ext-net',
+ "volume_size": 10,
+ "block_sizes": 4096,
+ "queue_depths": 4,
+ "workload": "rs",
+ "StorPerf_ip": "192.168.23.2",
+ "query_interval": 10,
+ "timeout": 60
+ }
+
+ args = {
+ "options": options
+ }
+
+ s = storperf.StorPerf(args, self.ctx)
+
+ self.assertRaises(RuntimeError, s.teardown)
+ mock_delete.assert_called_once_with(
+ 'http://192.168.23.2:5000/api/v1.0/configurations')
diff --git a/yardstick/tests/unit/benchmark/scenarios/test_base.py b/yardstick/tests/unit/benchmark/scenarios/test_base.py
new file mode 100644
index 000000000..284a71cc8
--- /dev/null
+++ b/yardstick/tests/unit/benchmark/scenarios/test_base.py
@@ -0,0 +1,135 @@
+# Copyright 2017: Intel Ltd.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import time
+
+import mock
+
+from yardstick.benchmark.scenarios import base
+from yardstick.tests.unit import base as ut_base
+
+
+class _TestScenario(base.Scenario):
+ __scenario_type__ = 'Test Scenario'
+
+ def run(self):
+ pass
+
+
+class ScenarioTestCase(ut_base.BaseUnitTestCase):
+
+ def test_get_scenario_type(self):
+ scenario_type = 'dummy scenario'
+
+ class DummyScenario(base.Scenario):
+ __scenario_type__ = scenario_type
+
+ self.assertEqual(scenario_type, DummyScenario.get_scenario_type())
+
+ def test_get_scenario_type_not_defined(self):
+ class DummyScenario(base.Scenario):
+ pass
+
+ self.assertEqual(str(None), DummyScenario.get_scenario_type())
+
+ def test_get_description(self):
+ docstring = """First line
+ Second line
+ Third line
+ """
+
+ class DummyScenario(base.Scenario):
+ __doc__ = docstring
+
+ self.assertEqual(docstring.splitlines()[0],
+ DummyScenario.get_description())
+
+ def test_get_description_empty(self):
+ class DummyScenario(base.Scenario):
+ pass
+
+ self.assertEqual(str(None), DummyScenario.get_description())
+
+ def test_get_types(self):
+ scenario_names = set(
+ scenario.__scenario_type__ for scenario in
+ base.Scenario.get_types() if hasattr(scenario,
+ '__scenario_type__'))
+ existing_scenario_class_names = {
+ 'Iperf3', 'CACHEstat', 'SpecCPU2006', 'Dummy', 'NSPerf', 'Parser'}
+ self.assertTrue(existing_scenario_class_names.issubset(scenario_names))
+
+ def test_get_cls_existing_scenario(self):
+ scenario_name = 'NSPerf'
+ scenario = base.Scenario.get_cls(scenario_name)
+ self.assertEqual(scenario_name, scenario.__scenario_type__)
+
+ def test_get_cls_non_existing_scenario(self):
+ wrong_scenario_name = 'Non-existing-scenario'
+ with self.assertRaises(RuntimeError) as exc:
+ base.Scenario.get_cls(wrong_scenario_name)
+ self.assertEqual('No such scenario type %s' % wrong_scenario_name,
+ str(exc.exception))
+
+ def test_get_existing_scenario(self):
+ scenario_name = 'NSPerf'
+ scenario_module = ('yardstick.benchmark.scenarios.networking.'
+ 'vnf_generic.NetworkServiceTestCase')
+ self.assertEqual(scenario_module, base.Scenario.get(scenario_name))
+
+ def test_get_non_existing_scenario(self):
+ wrong_scenario_name = 'Non-existing-scenario'
+ with self.assertRaises(RuntimeError) as exc:
+ base.Scenario.get(wrong_scenario_name)
+ self.assertEqual('No such scenario type %s' % wrong_scenario_name,
+ str(exc.exception))
+
+ def test_scenario_abstract_class(self):
+ # pylint: disable=abstract-class-instantiated
+ with self.assertRaises(TypeError):
+ base.Scenario()
+
+ @mock.patch.object(time, 'sleep')
+ def test_pre_run_wait_time(self, mock_sleep):
+ """Ensure default behaviour (backwards compatibility): no wait time"""
+ test_scenario = _TestScenario()
+ test_scenario.pre_run_wait_time(mock.ANY)
+ mock_sleep.assert_not_called()
+
+ @mock.patch.object(time, 'sleep')
+ def test_post_run_wait_time(self, mock_sleep):
+ """Ensure default behaviour (backwards compatibility): wait time"""
+ test_scenario = _TestScenario()
+ test_scenario.post_run_wait_time(100)
+ mock_sleep.assert_called_once_with(100)
+
+
+class IterScenarioClassesTestCase(ut_base.BaseUnitTestCase):
+
+ def test_no_scenario_type_defined(self):
+ some_existing_scenario_class_names = [
+ 'Iperf3', 'CACHEstat', 'SpecCPU2006', 'Dummy', 'NSPerf', 'Parser']
+ scenario_types = [scenario.__scenario_type__ for scenario
+ in base._iter_scenario_classes()]
+ for class_name in some_existing_scenario_class_names:
+ self.assertIn(class_name, scenario_types)
+
+ def test_scenario_type_defined(self):
+ some_existing_scenario_class_names = [
+ 'Iperf3', 'CACHEstat', 'SpecCPU2006', 'Dummy', 'NSPerf', 'Parser']
+ for class_name in some_existing_scenario_class_names:
+ scenario_class = next(base._iter_scenario_classes(
+ scenario_type=class_name))
+ self.assertEqual(class_name, scenario_class.__scenario_type__)
diff --git a/yardstick/tests/unit/common/__init__.py b/yardstick/tests/unit/common/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/common/__init__.py
diff --git a/yardstick/tests/unit/common/banned_modules/__init__.py b/yardstick/tests/unit/common/banned_modules/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/__init__.py
diff --git a/yardstick/tests/unit/common/banned_modules/banned_module.py b/yardstick/tests/unit/common/banned_modules/banned_module.py
new file mode 100644
index 000000000..f57f939d2
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/banned_module.py
@@ -0,0 +1,17 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+class BannedClass(object):
+ pass
diff --git a/yardstick/tests/unit/common/banned_modules/importing_module.py b/yardstick/tests/unit/common/banned_modules/importing_module.py
new file mode 100644
index 000000000..fc2542f0c
--- /dev/null
+++ b/yardstick/tests/unit/common/banned_modules/importing_module.py
@@ -0,0 +1,21 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from yardstick.common import import_tools
+from yardstick.tests.unit.common.banned_modules import banned_module
+
+
+@import_tools.decorator_banned_modules
+class ImportingClass(banned_module.BannedClass):
+ pass
diff --git a/yardstick/tests/unit/common/config_sample.yaml b/yardstick/tests/unit/common/config_sample.yaml
new file mode 100644
index 000000000..09218cc79
--- /dev/null
+++ b/yardstick/tests/unit/common/config_sample.yaml
@@ -0,0 +1,10 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+releng:
+ dir: /home/opnfv/repos/releng
diff --git a/yardstick/tests/unit/common/messaging/__init__.py b/yardstick/tests/unit/common/messaging/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/__init__.py
diff --git a/yardstick/tests/unit/common/messaging/test_consumer.py b/yardstick/tests/unit/common/messaging/test_consumer.py
new file mode 100644
index 000000000..612dcaecd
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_consumer.py
@@ -0,0 +1,54 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from oslo_config import cfg
+import oslo_messaging
+
+from yardstick.common import messaging
+from yardstick.common.messaging import consumer
+from yardstick.tests.unit import base as ut_base
+
+
+class TestEndPoint(object):
+ def action_1(self):
+ pass
+
+
+class _MessagingConsumer(consumer.MessagingConsumer):
+ pass
+
+
+class MessagingConsumerTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ with mock.patch.object(oslo_messaging, 'get_rpc_server') as \
+ mock_get_rpc_server, \
+ mock.patch.object(oslo_messaging, 'get_rpc_transport') as \
+ mock_get_rpc_transport, \
+ mock.patch.object(oslo_messaging, 'Target') as \
+ mock_Target:
+ mock_get_rpc_transport.return_value = 'test_rpc_transport'
+ mock_Target.return_value = 'test_Target'
+
+ _MessagingConsumer('test_topic', 'test_pid', [TestEndPoint],
+ fanout=True)
+ mock_get_rpc_transport.assert_called_once_with(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ mock_Target.assert_called_once_with(
+ topic='test_topic', fanout=True, server=messaging.SERVER)
+ mock_get_rpc_server.assert_called_once_with(
+ 'test_rpc_transport', 'test_Target', [TestEndPoint],
+ executor=messaging.RPC_SERVER_EXECUTOR,
+ access_policy=oslo_messaging.DefaultRPCAccessPolicy)
diff --git a/yardstick/tests/unit/common/messaging/test_payloads.py b/yardstick/tests/unit/common/messaging/test_payloads.py
new file mode 100644
index 000000000..37b1f1926
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_payloads.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from yardstick.common import exceptions
+from yardstick.common.messaging import payloads
+from yardstick.tests.unit import base as ut_base
+
+
+class _DummyPayload(payloads.Payload):
+ REQUIRED_FIELDS = {'version', 'key1', 'key2'}
+
+
+class PayloadTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ payload = _DummyPayload(version=1, key1='value1', key2='value2')
+ self.assertEqual(1, payload.version)
+ self.assertEqual('value1', payload.key1)
+ self.assertEqual('value2', payload.key2)
+ self.assertEqual(3, len(payload._fields))
+
+ def test__init_missing_required_fields(self):
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ _DummyPayload(key1='value1', key2='value2')
+
+ def test_obj_to_dict(self):
+ payload = _DummyPayload(version=1, key1='value1', key2='value2')
+ payload_dict = payload.obj_to_dict()
+ self.assertEqual({'version': 1, 'key1': 'value1', 'key2': 'value2'},
+ payload_dict)
+
+ def test_dict_to_obj(self):
+ _dict = {'version': 2, 'key1': 'value100', 'key2': 'value200'}
+ payload = _DummyPayload.dict_to_obj(_dict)
+ self.assertEqual(set(_dict.keys()), payload._fields)
+
+
+class TrafficGeneratorPayloadTestCase(ut_base.BaseUnitTestCase):
+
+ def test_init(self):
+ tg_payload = payloads.TrafficGeneratorPayload(
+ version=1, iteration=10, kpi={'key1': 'value1'})
+ self.assertEqual(1, tg_payload.version)
+ self.assertEqual(10, tg_payload.iteration)
+ self.assertEqual({'key1': 'value1'}, tg_payload.kpi)
+ self.assertEqual(3, len(tg_payload._fields))
+
+ def test__init_missing_required_fields(self):
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.TrafficGeneratorPayload(version=1, iteration=10)
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.TrafficGeneratorPayload(iteration=10, kpi={})
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.TrafficGeneratorPayload(iteration=10)
+
+
+class RunnerPayloadTestCase(ut_base.BaseUnitTestCase):
+
+ def test_init(self):
+ runner_payload = payloads.RunnerPayload(version=5,
+ data={'key1': 'value1'})
+ self.assertEqual(5, runner_payload.version)
+ self.assertEqual({'key1': 'value1'}, runner_payload.data)
+
+ def test__init_missing_required_fields(self):
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.RunnerPayload(version=1)
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.RunnerPayload(data=None)
+ with self.assertRaises(exceptions.PayloadMissingAttributes):
+ payloads.RunnerPayload()
diff --git a/yardstick/tests/unit/common/messaging/test_producer.py b/yardstick/tests/unit/common/messaging/test_producer.py
new file mode 100644
index 000000000..22286e5c3
--- /dev/null
+++ b/yardstick/tests/unit/common/messaging/test_producer.py
@@ -0,0 +1,53 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from oslo_config import cfg
+import oslo_messaging
+
+from yardstick.common import messaging
+from yardstick.common.messaging import producer
+from yardstick.tests.unit import base as ut_base
+
+
+class _MessagingProducer(producer.MessagingProducer):
+ pass
+
+
+class MessagingProducerTestCase(ut_base.BaseUnitTestCase):
+
+ def test__init(self):
+ with mock.patch.object(oslo_messaging, 'RPCClient') as \
+ mock_RPCClient, \
+ mock.patch.object(oslo_messaging, 'get_rpc_transport') as \
+ mock_get_rpc_transport, \
+ mock.patch.object(oslo_messaging, 'Target') as \
+ mock_Target:
+ mock_get_rpc_transport.return_value = 'test_rpc_transport'
+ mock_Target.return_value = 'test_Target'
+
+ _MessagingProducer('test_topic', 'test_pid', fanout=True)
+ mock_get_rpc_transport.assert_called_once_with(
+ cfg.CONF, url=messaging.TRANSPORT_URL)
+ mock_Target.assert_called_once_with(
+ topic='test_topic', fanout=True, server=messaging.SERVER)
+ mock_RPCClient.assert_called_once_with('test_rpc_transport',
+ 'test_Target')
+
+ def test_id(self):
+ with mock.patch.object(oslo_messaging, 'RPCClient'), \
+ mock.patch.object(oslo_messaging, 'get_rpc_transport'), \
+ mock.patch.object(oslo_messaging, 'Target'):
+ msg_producer = _MessagingProducer('topic', 'id_to_check')
+ self.assertEqual('id_to_check', msg_producer.id)
diff --git a/yardstick/tests/unit/common/test_ansible_common.py b/yardstick/tests/unit/common/test_ansible_common.py
new file mode 100644
index 000000000..bf82f6288
--- /dev/null
+++ b/yardstick/tests/unit/common/test_ansible_common.py
@@ -0,0 +1,241 @@
+# 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.
+
+import collections
+import shutil
+import subprocess
+import tempfile
+
+import mock
+from six import moves
+from six.moves import configparser
+
+from yardstick.common import ansible_common
+from yardstick.tests.unit import base as ut_base
+
+
+class OverwriteDictTestCase(ut_base.BaseUnitTestCase):
+
+ def test_overwrite_dict_cfg(self):
+ c = configparser.ConfigParser(allow_no_value=True)
+ d = {
+ "section_a": "empty_value",
+ "section_b": {"key_c": "Val_d", "key_d": "VAL_D"},
+ "section_c": ["key_c", "key_d"],
+ }
+ ansible_common.overwrite_dict_to_cfg(c, d)
+ # Python3 and Python2 convert empty values into None or ''
+ # we don't really care but we need to compare correctly for unittest
+ self.assertTrue(c.has_option("section_a", "empty_value"))
+ self.assertEqual(sorted(c.items("section_b")),
+ [('key_c', 'Val_d'), ('key_d', 'VAL_D')])
+ self.assertTrue(c.has_option("section_c", "key_c"))
+ self.assertTrue(c.has_option("section_c", "key_d"))
+
+
+class FilenameGeneratorTestCase(ut_base.BaseUnitTestCase):
+
+ @mock.patch.object(tempfile, 'NamedTemporaryFile')
+ def test__handle_existing_file(self, _):
+ ansible_common.FileNameGenerator._handle_existing_file('/dev/null')
+
+ def test_get_generator_from_file(self):
+ ansible_common.FileNameGenerator.get_generator_from_filename(
+ '/dev/null', '', '', '')
+
+ def test_get_generator_from_file_middle(self):
+ ansible_common.FileNameGenerator.get_generator_from_filename(
+ '/dev/null', '', '', 'null')
+
+ def test_get_generator_from_file_prefix(self):
+ ansible_common.FileNameGenerator.get_generator_from_filename(
+ '/dev/null', '', 'null', 'middle')
+
+
+class AnsibleNodeTestCase(ut_base.BaseUnitTestCase):
+
+ def test_ansible_node_len(self):
+ self.assertEqual(0, len(ansible_common.AnsibleNode()))
+
+ def test_ansible_node_repr(self):
+ self.assertEqual('AnsibleNode<{}>', repr(ansible_common.AnsibleNode()))
+
+ def test_ansible_node_iter(self):
+ node = ansible_common.AnsibleNode(data={'a': 1, 'b': 2, 'c': 3})
+ for key in node:
+ self.assertIn(key, ('a', 'b', 'c'))
+
+ def test_is_role(self):
+ node = ansible_common.AnsibleNode()
+ self.assertFalse(node.is_role('', default='foo'))
+
+ def test_ansible_node_get_tuple(self):
+ node = ansible_common.AnsibleNode({'name': 'name'})
+ self.assertEqual(node.get_tuple(), ('name', node))
+
+ def test_gen_inventory_line(self):
+ a = ansible_common.AnsibleNode(collections.defaultdict(str))
+ self.assertEqual(a.gen_inventory_line(), "")
+
+ def test_ansible_node_delitem(self):
+ node = ansible_common.AnsibleNode({'name': 'name'})
+ self.assertEqual(1, len(node))
+ del node['name']
+ self.assertEqual(0, len(node))
+
+ def test_ansible_node_getattr(self):
+ node = ansible_common.AnsibleNode({'name': 'name'})
+ self.assertIsNone(getattr(node, 'nosuch', None))
+
+
+class AnsibleNodeDictTestCase(ut_base.BaseUnitTestCase):
+
+ def test_ansible_node_dict_len(self):
+ n = ansible_common.AnsibleNode
+ a = ansible_common.AnsibleNodeDict(n, {})
+ self.assertEqual(0, len(a))
+
+ def test_ansible_node_dict_repr(self):
+ n = ansible_common.AnsibleNode
+ a = ansible_common.AnsibleNodeDict(n, {})
+ self.assertEqual('{}', repr(a))
+
+ def test_ansible_node_dict_get(self):
+ n = ansible_common.AnsibleNode
+ a = ansible_common.AnsibleNodeDict(n, {})
+ self.assertIsNone(a.get(""))
+
+ def test_gen_inventory_lines_for_all_of_type(self):
+ n = ansible_common.AnsibleNode
+ a = ansible_common.AnsibleNodeDict(n, {})
+ self.assertEqual(a.gen_inventory_lines_for_all_of_type(""), [])
+
+ def test_gen_inventory_lines(self):
+ n = ansible_common.AnsibleNode
+ a = ansible_common.AnsibleNodeDict(n, [{
+ "name": "name", "user": "user", "password": "PASS",
+ "role": "role",
+ }])
+ self.assertEqual(a.gen_all_inventory_lines(),
+ ["name ansible_ssh_pass=PASS ansible_user=user"])
+
+
+class AnsibleCommonTestCase(ut_base.BaseUnitTestCase):
+
+ @staticmethod
+ def _delete_tmpdir(dir):
+ shutil.rmtree(dir)
+
+ def test_get_timeouts(self):
+ self.assertAlmostEqual(
+ ansible_common.AnsibleCommon.get_timeout(-100), 1200.0)
+
+ def test_reset(self):
+ a = ansible_common.AnsibleCommon({})
+ a.reset()
+
+ def test_do_install_no_dir(self):
+ a = ansible_common.AnsibleCommon({})
+ self.assertRaises(OSError, a.do_install, '', '')
+
+ def test_gen_inventory_dict(self):
+ nodes = [{
+ "name": "name", "user": "user", "password": "PASS",
+ "role": "role",
+ }]
+ a = ansible_common.AnsibleCommon(nodes)
+ a.gen_inventory_ini_dict()
+ self.assertEqual(a.inventory_dict, {
+ 'nodes': ['name ansible_ssh_pass=PASS ansible_user=user'],
+ 'role': ['name']
+ })
+
+ def test_deploy_dir(self):
+ a = ansible_common.AnsibleCommon({})
+ self.assertRaises(ValueError, getattr, a, "deploy_dir")
+
+ def test_deploy_dir_set(self):
+ a = ansible_common.AnsibleCommon({})
+ a.deploy_dir = ""
+
+ def test_deploy_dir_set_get(self):
+ a = ansible_common.AnsibleCommon({})
+ a.deploy_dir = "d"
+ self.assertEqual(a.deploy_dir, "d")
+
+ @mock.patch.object(moves.builtins, 'open')
+ def test__gen_ansible_playbook_file_list(self, *args):
+ d = tempfile.mkdtemp()
+ self.addCleanup(self._delete_tmpdir, d)
+ a = ansible_common.AnsibleCommon({})
+ a._gen_ansible_playbook_file(["a"], d)
+
+ @mock.patch.object(tempfile, 'NamedTemporaryFile')
+ @mock.patch.object(moves.builtins, 'open')
+ def test__gen_ansible_inventory_file(self, *args):
+ nodes = [{
+ "name": "name", "user": "user", "password": "PASS",
+ "role": "role",
+ }]
+ d = tempfile.mkdtemp()
+ self.addCleanup(self._delete_tmpdir, d)
+ a = ansible_common.AnsibleCommon(nodes)
+ a.gen_inventory_ini_dict()
+ inv_context = a._gen_ansible_inventory_file(d)
+ with inv_context:
+ c = moves.StringIO()
+ inv_context.write_func(c)
+ self.assertIn("ansible_ssh_pass=PASS", c.getvalue())
+
+ @mock.patch.object(tempfile, 'NamedTemporaryFile')
+ @mock.patch.object(moves.builtins, 'open')
+ def test__gen_ansible_playbook_file_list_multiple(self, *args):
+ d = tempfile.mkdtemp()
+ self.addCleanup(self._delete_tmpdir, d)
+ a = ansible_common.AnsibleCommon({})
+ a._gen_ansible_playbook_file(["a", "b"], d)
+
+ @mock.patch.object(tempfile, 'NamedTemporaryFile')
+ @mock.patch.object(subprocess, 'Popen')
+ @mock.patch.object(moves.builtins, 'open')
+ def test_do_install_tmp_dir(self, _, mock_popen, *args):
+ mock_popen.return_value.communicate.return_value = "", ""
+ mock_popen.return_value.wait.return_value = 0
+ d = tempfile.mkdtemp()
+ self.addCleanup(self._delete_tmpdir, d)
+ a = ansible_common.AnsibleCommon({})
+ a.do_install('', d)
+
+ @mock.patch.object(tempfile, 'NamedTemporaryFile')
+ @mock.patch.object(moves.builtins, 'open')
+ @mock.patch.object(subprocess, 'Popen')
+ def test_execute_ansible_check(self, mock_popen, *args):
+ mock_popen.return_value.communicate.return_value = "", ""
+ mock_popen.return_value.wait.return_value = 0
+ d = tempfile.mkdtemp()
+ self.addCleanup(self._delete_tmpdir, d)
+ a = ansible_common.AnsibleCommon({})
+ a.execute_ansible('', d, ansible_check=True, verbose=True)
+
+ def test_get_sut_info(self):
+ d = tempfile.mkdtemp()
+ a = ansible_common.AnsibleCommon({})
+ self.addCleanup(self._delete_tmpdir, d)
+ with mock.patch.object(a, '_exec_get_sut_info_cmd'):
+ a.get_sut_info(d)
+
+ def test_get_sut_info_not_exist(self):
+ a = ansible_common.AnsibleCommon({})
+ with self.assertRaises(OSError):
+ a.get_sut_info('/hello/world')
diff --git a/yardstick/tests/unit/common/test_exceptions.py b/yardstick/tests/unit/common/test_exceptions.py
new file mode 100644
index 000000000..884015536
--- /dev/null
+++ b/yardstick/tests/unit/common/test_exceptions.py
@@ -0,0 +1,28 @@
+# Copyright 2018 Intel Corporation.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from yardstick.common import exceptions
+from yardstick.tests.unit import base as ut_base
+
+
+class ErrorClassTestCase(ut_base.BaseUnitTestCase):
+
+ def test_init(self):
+ with self.assertRaises(RuntimeError):
+ exceptions.ErrorClass()
+
+ def test_getattr(self):
+ error_instance = exceptions.ErrorClass(test='')
+ with self.assertRaises(AttributeError):
+ error_instance.get_name()
diff --git a/yardstick/tests/unit/common/test_httpClient.py b/yardstick/tests/unit/common/test_httpClient.py
new file mode 100644
index 000000000..12a8be3a0
--- /dev/null
+++ b/yardstick/tests/unit/common/test_httpClient.py
@@ -0,0 +1,35 @@
+##############################################################################
+# 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
+##############################################################################
+from __future__ import absolute_import
+
+import unittest
+
+import mock
+from oslo_serialization import jsonutils
+
+from yardstick.common import httpClient
+
+
+class HttpClientTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.httpClient.requests')
+ def test_post(self, mock_requests):
+ url = 'http://localhost:5000/hello'
+ data = {'hello': 'world'}
+ headers = {'Content-Type': 'application/json'}
+ httpClient.HttpClient().post(url, data)
+ mock_requests.post.assert_called_with(
+ url, data=jsonutils.dump_as_bytes(data),
+ headers=headers)
+
+ @mock.patch('yardstick.common.httpClient.requests')
+ def test_get(self, mock_requests):
+ url = 'http://localhost:5000/hello'
+ httpClient.HttpClient().get(url)
+ mock_requests.get.assert_called_with(url)
diff --git a/yardstick/tests/unit/common/test_import_tools.py b/yardstick/tests/unit/common/test_import_tools.py
new file mode 100644
index 000000000..c8fe5fde0
--- /dev/null
+++ b/yardstick/tests/unit/common/test_import_tools.py
@@ -0,0 +1,46 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+from yardstick.common import exceptions as y_exc
+from yardstick.common import import_tools
+
+
+@import_tools.decorator_banned_modules
+class DummyClass(object):
+ pass
+
+
+class DecoratorBannedModule(unittest.TestCase):
+
+ MODULE = 'yardstick.tests.unit.common.banned_modules.banned_module'
+
+ def test_passt(self):
+ self.assertIsNotNone(DummyClass())
+
+ def test_banned_module(self):
+ import_tools.BANNED_MODULES[self.MODULE] = 'Banned module!!'
+ from yardstick.tests.unit.common.banned_modules import importing_module
+ self.addCleanup(self._remove_module)
+
+ with self.assertRaises(y_exc.YardstickBannedModuleImported) as exc:
+ importing_module.ImportingClass()
+
+ msg = ('Module "%s" cannnot be imported. Reason: "Banned module!!"'
+ % self.MODULE)
+ self.assertEqual(msg, str(exc.exception))
+
+ def _remove_module(self):
+ del import_tools.BANNED_MODULES[self.MODULE]
diff --git a/yardstick/tests/unit/common/test_kubernetes_utils.py b/yardstick/tests/unit/common/test_kubernetes_utils.py
new file mode 100644
index 000000000..ba6b5f388
--- /dev/null
+++ b/yardstick/tests/unit/common/test_kubernetes_utils.py
@@ -0,0 +1,447 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from kubernetes import client
+from kubernetes.client import rest
+from kubernetes import config
+
+from yardstick.common import constants
+from yardstick.common import exceptions
+from yardstick.common import kubernetes_utils
+from yardstick.tests.unit import base
+
+
+class GetExtensionsV1betaApiTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(client, 'ApiextensionsV1beta1Api', return_value='api')
+ @mock.patch.object(config, 'load_kube_config')
+ def test_execute_correct(self, mock_load_kube_config, mock_api):
+ self.assertEqual('api', kubernetes_utils.get_extensions_v1beta_api())
+ mock_load_kube_config.assert_called_once_with(
+ config_file=constants.K8S_CONF_FILE)
+ mock_api.assert_called_once()
+
+ @mock.patch.object(config, 'load_kube_config')
+ def test_execute_exception(self, mock_load_kube_config):
+ mock_load_kube_config.side_effect = IOError
+ with self.assertRaises(exceptions.KubernetesConfigFileNotFound):
+ kubernetes_utils.get_extensions_v1beta_api()
+
+
+class GetCustomObjectsApiTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(client, 'CustomObjectsApi', return_value='api')
+ @mock.patch.object(config, 'load_kube_config')
+ def test_execute_correct(self, mock_load_kube_config, mock_api):
+ self.assertEqual('api', kubernetes_utils.get_custom_objects_api())
+ mock_load_kube_config.assert_called_once_with(
+ config_file=constants.K8S_CONF_FILE)
+ mock_api.assert_called_once()
+
+ @mock.patch.object(config, 'load_kube_config')
+ def test_execute_exception(self, mock_load_kube_config):
+ mock_load_kube_config.side_effect = IOError
+ with self.assertRaises(exceptions.KubernetesConfigFileNotFound):
+ kubernetes_utils.get_custom_objects_api()
+
+
+class CreateCustomResourceDefinitionTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(client, 'V1beta1CustomResourceDefinition',
+ return_value='crd_obj')
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_correct(self, mock_get_api, mock_crd):
+ mock_create_crd = mock.Mock()
+ mock_get_api.return_value = mock_create_crd
+ body = {'spec': 'fake_spec', 'metadata': 'fake_metadata'}
+
+ kubernetes_utils.create_custom_resource_definition(body)
+ mock_get_api.assert_called_once()
+ mock_crd.assert_called_once_with(spec='fake_spec',
+ metadata='fake_metadata')
+ mock_create_crd.create_custom_resource_definition.\
+ assert_called_once_with('crd_obj')
+
+ @mock.patch.object(client, 'V1beta1CustomResourceDefinition',
+ return_value='crd_obj')
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_exception(self, mock_get_api, mock_crd):
+ mock_create_crd = mock.Mock()
+ mock_create_crd.create_custom_resource_definition.\
+ side_effect = rest.ApiException
+ mock_get_api.return_value = mock_create_crd
+ body = {'spec': 'fake_spec', 'metadata': 'fake_metadata'}
+
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.create_custom_resource_definition(body)
+ mock_get_api.assert_called_once()
+ mock_crd.assert_called_once_with(spec='fake_spec',
+ metadata='fake_metadata')
+ mock_create_crd.create_custom_resource_definition.\
+ assert_called_once_with('crd_obj')
+
+
+class DeleteCustomResourceDefinitionTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(client, 'V1DeleteOptions', return_value='del_obj')
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_correct(self, mock_get_api, mock_delobj):
+ mock_delete_crd = mock.Mock()
+ mock_get_api.return_value = mock_delete_crd
+
+ kubernetes_utils.delete_custom_resource_definition('name')
+ mock_get_api.assert_called_once()
+ mock_delobj.assert_called_once()
+ mock_delete_crd.delete_custom_resource_definition.\
+ assert_called_once_with('name', 'del_obj')
+
+ @mock.patch.object(client, 'V1DeleteOptions', return_value='del_obj')
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_exception(self, mock_get_api, mock_delobj):
+ mock_delete_crd = mock.Mock()
+ mock_delete_crd.delete_custom_resource_definition.\
+ side_effect = rest.ApiException
+ mock_get_api.return_value = mock_delete_crd
+
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_custom_resource_definition('name')
+ mock_delobj.assert_called_once()
+ mock_delete_crd.delete_custom_resource_definition.\
+ assert_called_once_with('name', 'del_obj')
+
+ @mock.patch.object(client, 'V1DeleteOptions', return_value='del_obj')
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ def test_execute_skip_exception(self, mock_log, mock_get_api, mock_delobj):
+ mock_delete_crd = mock.Mock()
+ mock_delete_crd.delete_custom_resource_definition.side_effect = rest.ApiException(
+ status=404)
+
+ mock_get_api.return_value = mock_delete_crd
+ kubernetes_utils.delete_custom_resource_definition('name', skip_codes=[404])
+
+ mock_delobj.assert_called_once()
+ mock_delete_crd.delete_custom_resource_definition.assert_called_once_with(
+ 'name', 'del_obj')
+
+ mock_log.info.assert_called_once()
+
+
+class GetCustomResourceDefinitionTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_value(self, mock_get_api):
+ crd_obj = mock.Mock()
+ crd_obj.spec.names.kind = 'some_kind'
+ crd_list = mock.Mock()
+ crd_list.items = [crd_obj]
+ mock_api = mock.Mock()
+ mock_api.list_custom_resource_definition.return_value = crd_list
+ mock_get_api.return_value = mock_api
+ self.assertEqual(
+ crd_obj,
+ kubernetes_utils.get_custom_resource_definition('some_kind'))
+
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_none(self, mock_get_api):
+ crd_obj = mock.Mock()
+ crd_obj.spec.names.kind = 'some_kind'
+ crd_list = mock.Mock()
+ crd_list.items = [crd_obj]
+ mock_api = mock.Mock()
+ mock_api.list_custom_resource_definition.return_value = crd_list
+ mock_get_api.return_value = mock_api
+ self.assertIsNone(
+ kubernetes_utils.get_custom_resource_definition('other_kind'))
+
+ @mock.patch.object(kubernetes_utils, 'get_extensions_v1beta_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.list_custom_resource_definition.\
+ side_effect = rest.ApiException
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.get_custom_resource_definition('kind')
+
+
+class GetNetworkTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ def test_execute_correct(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ group = 'group.com'
+ version = mock.Mock()
+ plural = 'networks'
+ name = 'net_one'
+
+ kubernetes_utils.get_network(
+ constants.SCOPE_CLUSTER, group, version, plural, name)
+ mock_api.get_cluster_custom_object.assert_called_once_with(
+ group, version, plural, name)
+
+ mock_api.reset_mock()
+ kubernetes_utils.get_network(
+ constants.SCOPE_NAMESPACED, group, version, plural, name)
+ mock_api.get_namespaced_custom_object.assert_called_once_with(
+ group, version, 'default', plural, name)
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.get_cluster_custom_object.side_effect = rest.ApiException(404)
+ mock_api.get_namespaced_custom_object.side_effect = rest.ApiException(404)
+ mock_get_api.return_value = mock_api
+ group = 'group.com'
+ version = mock.Mock()
+ plural = 'networks'
+ name = 'net_one'
+
+ network_obj = kubernetes_utils.get_network(
+ constants.SCOPE_CLUSTER, group, version, plural, name)
+ self.assertIsNone(network_obj)
+
+ mock_api.reset_mock()
+ network_obj = kubernetes_utils.get_network(
+ constants.SCOPE_NAMESPACED, group, version, plural, name)
+ self.assertIsNone(network_obj)
+
+
+class CreateNetworkTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ @mock.patch.object(kubernetes_utils, 'get_network')
+ def test_execute_correct(self, mock_get_net, mock_get_api):
+ mock_get_net.return_value = None
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ group = 'group.com'
+ version = mock.Mock()
+ plural = 'networks'
+ body = mock.Mock()
+ name = 'net_one'
+
+ kubernetes_utils.create_network(
+ constants.SCOPE_CLUSTER, group, version, plural, body, name)
+ mock_api.create_cluster_custom_object.assert_called_once_with(
+ group, version, plural, body)
+
+ mock_api.reset_mock()
+ kubernetes_utils.create_network(
+ constants.SCOPE_NAMESPACED, group, version, plural, body, name)
+ mock_api.create_namespaced_custom_object.assert_called_once_with(
+ group, version, 'default', plural, body)
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ @mock.patch.object(kubernetes_utils, 'get_network')
+ def test_network_already_created(self, mock_get_net, mock_get_api):
+ mock_get_net.return_value = mock.Mock
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ group = 'group.com'
+ version = mock.Mock()
+ plural = 'networks'
+ body = mock.Mock()
+ name = 'net_one'
+
+ mock_api.reset_mock()
+ kubernetes_utils.create_network(
+ constants.SCOPE_CLUSTER, group, version, plural, body, name)
+ mock_api.create_cluster_custom_object.assert_not_called()
+
+ mock_api.reset_mock()
+ kubernetes_utils.create_network(
+ constants.SCOPE_NAMESPACED, group, version, plural, body, name)
+ mock_api.create_namespaced_custom_object.assert_not_called()
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ @mock.patch.object(kubernetes_utils, 'get_network')
+ def test_execute_exception(self, mock_get_net, mock_get_api):
+ mock_get_net.return_value = None
+ mock_api = mock.Mock()
+ mock_api.create_cluster_custom_object.side_effect = rest.ApiException
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.create_network(
+ constants.SCOPE_CLUSTER, mock.ANY, mock.ANY, mock.ANY,
+ mock.ANY, mock.ANY)
+
+
+class DeleteNetworkTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ def test_execute_correct(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ group = 'group.com'
+ version = mock.Mock()
+ plural = 'networks'
+ name = 'network'
+
+ kubernetes_utils.delete_network(
+ constants.SCOPE_CLUSTER, group, version, plural, name)
+ mock_api.delete_cluster_custom_object.assert_called_once_with(
+ group, version, plural, name, {})
+
+ mock_api.reset_mock()
+ kubernetes_utils.delete_network(
+ constants.SCOPE_NAMESPACED, group, version, plural, name)
+ mock_api.delete_namespaced_custom_object.assert_called_once_with(
+ group, version, 'default', plural, name, {})
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_cluster_custom_object.side_effect = rest.ApiException
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_network(
+ constants.SCOPE_CLUSTER, mock.ANY, mock.ANY, mock.ANY,
+ mock.ANY)
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_objects_api')
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ def test_execute_skip_exception(self, mock_log, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_cluster_custom_object.side_effect = rest.ApiException(status=404)
+
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_network(
+ constants.SCOPE_CLUSTER, mock.ANY, mock.ANY, mock.ANY,
+ mock.ANY, skip_codes=[404])
+
+ mock_log.info.assert_called_once()
+
+
+class DeletePodTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_correct(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+
+ kubernetes_utils.delete_pod("name", body=None)
+ mock_api.delete_namespaced_pod.assert_called_once_with(
+ "name", 'default', None)
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_pod.side_effect = rest.ApiException(status=200)
+
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_pod(mock.ANY, skip_codes=[404])
+
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_skip_exception(self, mock_get_api, *args):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_pod.side_effect = rest.ApiException(status=404)
+
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_pod(mock.ANY, skip_codes=[404])
+
+
+class DeleteServiceTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(client, "V1DeleteOptions")
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_correct(self, mock_get_api, mock_options):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ mock_options.return_value = None
+ kubernetes_utils.delete_service("name", "default", None)
+ mock_api.delete_namespaced_service.assert_called_once_with(
+ "name", 'default', None)
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_service.side_effect = rest.ApiException(status=200)
+
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_service(mock.ANY, skip_codes=[404])
+
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_skip_exception(self, mock_get_api, *args):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_service.side_effect = rest.ApiException(status=404)
+
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_service(mock.ANY, skip_codes=[404])
+
+
+class DeleteReplicationControllerTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_correct(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_replication_controller(
+ "name", "default", body=None)
+
+ mock_api.delete_namespaced_replication_controller.assert_called_once_with(
+ "name", "default", None)
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_replication_controller.side_effect = (
+ rest.ApiException(status=200)
+ )
+
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_replication_controller(mock.ANY, skip_codes=[404])
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ def test_execute_skip_exception(self, mock_log, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_replication_controller.side_effect = (
+ rest.ApiException(status=404)
+ )
+
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_replication_controller(mock.ANY, skip_codes=[404])
+
+ mock_log.info.assert_called_once()
+
+
+class DeleteConfigMapTestCase(base.BaseUnitTestCase):
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_correct(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_config_map("name", body=None)
+ mock_api.delete_namespaced_config_map.assert_called_once_with(
+ "name", "default", None
+ )
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ def test_execute_exception(self, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_config_map.side_effect = rest.ApiException(status=200)
+
+ mock_get_api.return_value = mock_api
+ with self.assertRaises(exceptions.KubernetesApiException):
+ kubernetes_utils.delete_config_map(mock.ANY, skip_codes=[404])
+
+ @mock.patch.object(kubernetes_utils, 'get_core_api')
+ @mock.patch.object(kubernetes_utils, 'LOG')
+ def test_execute_skip_exception(self, mock_log, mock_get_api):
+ mock_api = mock.Mock()
+ mock_api.delete_namespaced_config_map.side_effect = rest.ApiException(status=404)
+
+ mock_get_api.return_value = mock_api
+ kubernetes_utils.delete_config_map(mock.ANY, skip_codes=[404])
+ mock_log.info.assert_called_once()
diff --git a/yardstick/tests/unit/common/test_openstack_utils.py b/yardstick/tests/unit/common/test_openstack_utils.py
new file mode 100644
index 000000000..f6a0bdcc1
--- /dev/null
+++ b/yardstick/tests/unit/common/test_openstack_utils.py
@@ -0,0 +1,730 @@
+##############################################################################
+# 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 os
+
+import mock
+from oslo_utils import uuidutils
+import shade
+from shade import exc
+import unittest
+
+from yardstick.common import constants
+from yardstick.common import openstack_utils
+
+
+class GetCredentialsTestCase(unittest.TestCase):
+
+ @mock.patch('yardstick.common.openstack_utils.os')
+ def test_get_credentials(self, _):
+ with mock.patch.dict('os.environ', {'OS_IDENTITY_API_VERSION': '2'},
+ clear=True):
+ openstack_utils.get_credentials()
+
+
+class GetHeatApiVersionTestCase(unittest.TestCase):
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_get_heat_api_version_check_result(self, *args):
+ API = 'HEAT_API_VERSION'
+ expected_result = '2'
+
+ with mock.patch.dict(os.environ, {API: '2'}, clear=True):
+ api_version = openstack_utils.get_heat_api_version()
+ self.assertEqual(api_version, expected_result)
+
+
+class GetShadeClientTestCase(unittest.TestCase):
+
+ @mock.patch.object(shade, 'openstack_cloud', return_value='os_client')
+ def test_get_shade_client(self, mock_openstack_cloud):
+ os_cloud_config = {'param1': True, 'param2': 'value2'}
+ self.assertEqual('os_client',
+ openstack_utils.get_shade_client(**os_cloud_config))
+ os_cloud_config.update(constants.OS_CLOUD_DEFAULT_CONFIG)
+ mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
+ mock_openstack_cloud.reset_mock()
+ os_cloud_config = {'verify': True, 'param2': 'value2'}
+ self.assertEqual('os_client',
+ openstack_utils.get_shade_client(**os_cloud_config))
+ mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
+ @mock.patch.object(shade, 'openstack_cloud', return_value='os_client')
+ def test_get_shade_client_no_parameters(self, mock_openstack_cloud):
+ self.assertEqual('os_client', openstack_utils.get_shade_client())
+ mock_openstack_cloud.assert_called_once_with(
+ **constants.OS_CLOUD_DEFAULT_CONFIG)
+
+ @mock.patch.object(shade, 'operator_cloud', return_value='os_client')
+ def test_get_shade_operator_client(self, mock_operator_cloud):
+ self.assertEqual('os_client', openstack_utils.get_shade_operator_client())
+ mock_operator_cloud.assert_called_once_with(
+ **constants.OS_CLOUD_DEFAULT_CONFIG)
+
+
+class DeleteNeutronNetTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+
+ def test_delete_neutron_net(self):
+ self.mock_shade_client.delete_network.return_value = True
+ output = openstack_utils.delete_neutron_net(self.mock_shade_client,
+ 'network_name_or_id')
+ self.assertTrue(output)
+
+ def test_delete_neutron_net_fail(self):
+ self.mock_shade_client.delete_network.return_value = False
+ output = openstack_utils.delete_neutron_net(self.mock_shade_client,
+ 'network_name_or_id')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_neutron_net_exception(self, mock_logger):
+ self.mock_shade_client.delete_network.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_neutron_net(self.mock_shade_client,
+ 'network_name_or_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)
+
+
+class CreateNeutronRouterTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.create_subnet = mock.Mock()
+
+ def test_create_neutron_router(self):
+ _uuid = uuidutils.generate_uuid()
+ self.mock_shade_client.create_router.return_value = {'id': _uuid}
+ output = openstack_utils.create_neutron_router(
+ self.mock_shade_client)
+ self.assertEqual(_uuid, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_neutron_subnet_exception(self, mock_logger):
+ self.mock_shade_client.create_router.side_effect = (
+ exc.OpenStackCloudException('error message'))
+
+ output = openstack_utils.create_neutron_router(
+ self.mock_shade_client)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class RemoveRouterInterfaceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.router = 'router'
+ self.mock_shade_client.remove_router_interface = mock.Mock()
+
+ def test_remove_router_interface(self):
+ self.mock_shade_client.remove_router_interface.return_value = True
+ output = openstack_utils.remove_router_interface(
+ self.mock_shade_client, self.router)
+ self.assertTrue(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_remove_router_interface_exception(self, mock_logger):
+ self.mock_shade_client.remove_router_interface.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.remove_router_interface(
+ self.mock_shade_client, self.router)
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class CreateFloatingIpTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.network_name_or_id = 'name'
+ self.mock_shade_client.create_floating_ip = mock.Mock()
+
+ def test_create_floating_ip(self):
+ self.mock_shade_client.create_floating_ip.return_value = \
+ {'floating_ip_address': 'value1', 'id': 'value2'}
+ output = openstack_utils.create_floating_ip(self.mock_shade_client,
+ self.network_name_or_id)
+ self.assertEqual({'fip_addr': 'value1', 'fip_id': 'value2'}, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_floating_ip_exception(self, mock_logger):
+ self.mock_shade_client.create_floating_ip.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_floating_ip(
+ self.mock_shade_client, self.network_name_or_id)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class DeleteFloatingIpTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.floating_ip_id = 'floating_ip_id'
+ self.mock_shade_client.delete_floating_ip = mock.Mock()
+
+ def test_delete_floating_ip(self):
+ self.mock_shade_client.delete_floating_ip.return_value = True
+ output = openstack_utils.delete_floating_ip(self.mock_shade_client,
+ 'floating_ip_id')
+ self.assertTrue(output)
+
+ def test_delete_floating_ip_fail(self):
+ self.mock_shade_client.delete_floating_ip.return_value = False
+ output = openstack_utils.delete_floating_ip(self.mock_shade_client,
+ 'floating_ip_id')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_floating_ip_exception(self, mock_logger):
+ self.mock_shade_client.delete_floating_ip.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_floating_ip(self.mock_shade_client,
+ 'floating_ip_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class CreateSecurityGroupRuleTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.secgroup_name_or_id = 'sg_name_id'
+ self.mock_shade_client.create_security_group_rule = mock.Mock()
+ self._mock_log = mock.patch.object(openstack_utils, 'log')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_log.stop()
+
+ def test_create_security_group_rule(self):
+ self.mock_shade_client.create_security_group_rule.return_value = (
+ {'security_group_rule'})
+ output = openstack_utils.create_security_group_rule(
+ self.mock_shade_client, self.secgroup_name_or_id)
+ self.assertTrue(output)
+
+ def test_create_security_group_rule_exception(self):
+ self.mock_shade_client.create_security_group_rule.side_effect = (
+ exc.OpenStackCloudException('error message'))
+
+ output = openstack_utils.create_security_group_rule(
+ self.mock_shade_client, self.secgroup_name_or_id)
+ self.mock_log.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class ListImageTestCase(unittest.TestCase):
+
+ def test_list_images(self):
+ mock_shade_client = mock.MagicMock()
+ mock_shade_client.list_images.return_value = []
+ openstack_utils.list_images(mock_shade_client)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_list_images_exception(self, mock_logger):
+ mock_shade_client = mock.MagicMock()
+ mock_shade_client.list_images = mock.MagicMock()
+ mock_shade_client.list_images.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ images = openstack_utils.list_images(mock_shade_client)
+ mock_logger.error.assert_called_once()
+ self.assertFalse(images)
+
+
+class SecurityGroupTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.sg_name = 'sg_name'
+ self.sg_description = 'sg_description'
+ self._uuid = uuidutils.generate_uuid()
+ self._mock_log = mock.patch.object(openstack_utils, 'log')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_log.stop()
+
+ def test_create_security_group_full_existing_security_group(self):
+ self.mock_shade_client.get_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ self.mock_shade_client.get_security_group.assert_called_once()
+ self.assertEqual(self._uuid, output)
+
+ def test_create_security_group_full_non_existing_security_group(self):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ self.mock_log.error.assert_called_once()
+ self.assertIsNone(output)
+
+ @mock.patch.object(openstack_utils, 'create_security_group_rule')
+ def test_create_security_group_full_create_rule_fail(
+ self, mock_create_security_group_rule):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ mock_create_security_group_rule.return_value = False
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ mock_create_security_group_rule.assert_called()
+ self.mock_shade_client.delete_security_group(self.sg_name)
+ self.mock_log.error.assert_called_once()
+ self.assertIsNone(output)
+
+ @mock.patch.object(openstack_utils, 'create_security_group_rule')
+ def test_create_security_group_full(
+ self, mock_create_security_group_rule):
+ self.mock_shade_client.get_security_group.return_value = None
+ self.mock_shade_client.create_security_group.return_value = (
+ {'name': 'name', 'id': self._uuid})
+ mock_create_security_group_rule.return_value = True
+ output = openstack_utils.create_security_group_full(
+ self.mock_shade_client, self.sg_name, self.sg_description)
+ mock_create_security_group_rule.assert_called()
+ self.mock_shade_client.delete_security_group(self.sg_name)
+ self.assertEqual(self._uuid, output)
+
+
+class CreateInstanceTestCase(unittest.TestCase):
+
+ def test_create_instance_and_wait_for_active(self):
+ self.mock_shade_client = mock.Mock()
+ name = 'server_name'
+ image = 'image_name'
+ flavor = 'flavor_name'
+ self.mock_shade_client.create_server.return_value = (
+ {'name': name, 'image': image, 'flavor': flavor})
+ output = openstack_utils.create_instance_and_wait_for_active(
+ self.mock_shade_client, name, image, flavor)
+ self.assertEqual(
+ {'name': name, 'image': image, 'flavor': flavor}, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_instance_and_wait_for_active_fail(self, mock_logger):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.create_server.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_instance_and_wait_for_active(
+ self.mock_shade_client, 'server_name', 'image_name', 'flavor_name')
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class DeleteInstanceTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+
+ def test_delete_instance(self):
+ self.mock_shade_client.delete_server.return_value = True
+ output = openstack_utils.delete_instance(self.mock_shade_client,
+ 'instance_name_id')
+ self.assertTrue(output)
+
+ def test_delete_instance_fail(self):
+ self.mock_shade_client.delete_server.return_value = False
+ output = openstack_utils.delete_instance(self.mock_shade_client,
+ 'instance_name_id')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_instance_exception(self, mock_logger):
+ self.mock_shade_client.delete_server.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_instance(self.mock_shade_client,
+ 'instance_name_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class CreateKeypairTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.name = 'key_name'
+
+ def test_create_keypair(self):
+ self.mock_shade_client.create_keypair.return_value = (
+ {'name': 'key-name', 'type': 'ssh'})
+ output = openstack_utils.create_keypair(
+ self.mock_shade_client, self.name)
+ self.assertEqual(
+ {'name': 'key-name', 'type': 'ssh'},
+ output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_keypair_fail(self, mock_logger):
+ self.mock_shade_client.create_keypair.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_keypair(
+ self.mock_shade_client, self.name)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class DeleteKeypairTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+
+ def test_delete_keypair(self):
+ self.mock_shade_client.delete_keypair.return_value = True
+ output = openstack_utils.delete_keypair(self.mock_shade_client,
+ 'key_name')
+ self.assertTrue(output)
+
+ def test_delete_keypair_fail(self):
+ self.mock_shade_client.delete_keypair.return_value = False
+ output = openstack_utils.delete_keypair(self.mock_shade_client,
+ 'key_name')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_keypair_exception(self, mock_logger):
+ self.mock_shade_client.delete_keypair.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_keypair(self.mock_shade_client,
+ 'key_name')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class AttachVolumeToServerTestCase(unittest.TestCase):
+
+ def test_attach_volume_to_server(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.get_server.return_value = {'server_dict'}
+ self.mock_shade_client.get_volume.return_value = {'volume_dict'}
+ self.mock_shade_client.attach_volume.return_value = True
+ output = openstack_utils.attach_volume_to_server(
+ self.mock_shade_client, 'server_name_or_id', 'volume_name_or_id')
+ self.assertTrue(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_attach_volume_to_server_fail(self, mock_logger):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.attach_volume.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.attach_volume_to_server(
+ self.mock_shade_client, 'server_name_or_id', 'volume_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class GetServerTestCase(unittest.TestCase):
+
+ def test_get_server(self):
+ self.mock_shade_client = mock.Mock()
+ _uuid = uuidutils.generate_uuid()
+ self.mock_shade_client.get_server.return_value = {
+ 'name': 'server_name', 'id': _uuid}
+ output = openstack_utils.get_server(self.mock_shade_client,
+ 'server_name_or_id')
+ self.assertEqual({'name': 'server_name', 'id': _uuid}, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_get_server_exception(self, mock_logger):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.get_server.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.get_server(self.mock_shade_client,
+ 'server_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class GetFlavorTestCase(unittest.TestCase):
+
+ def test_get_flavor(self):
+ self.mock_shade_client = mock.Mock()
+ _uuid = uuidutils.generate_uuid()
+ self.mock_shade_client.get_flavor.return_value = {
+ 'name': 'flavor_name', 'id': _uuid}
+ output = openstack_utils.get_flavor(self.mock_shade_client,
+ 'flavor_name_or_id')
+ self.assertEqual({'name': 'flavor_name', 'id': _uuid}, output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_get_flavor_exception(self, mock_logger):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.get_flavor.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.get_flavor(self.mock_shade_client,
+ 'flavor_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class GetVolumeIDTestCase(unittest.TestCase):
+
+ def test_get_volume_id(self):
+ self.mock_shade_client = mock.Mock()
+ _uuid = uuidutils.generate_uuid()
+ self.mock_shade_client.get_volume_id.return_value = _uuid
+ output = openstack_utils.get_volume_id(self.mock_shade_client,
+ 'volume_name')
+ self.assertEqual(_uuid, output)
+
+ def test_get_volume_id_None(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.get_volume_id.return_value = None
+ output = openstack_utils.get_volume_id(self.mock_shade_client,
+ 'volume_name')
+ self.assertIsNone(output)
+
+
+class GetVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.get_volume = mock.Mock()
+
+ def test_get_volume(self):
+ self.mock_shade_client.get_volume.return_value = {'volume'}
+ output = openstack_utils.get_volume(self.mock_shade_client,
+ 'volume_name_or_id')
+ self.assertEqual({'volume'}, output)
+
+ def test_get_volume_None(self):
+ self.mock_shade_client.get_volume.return_value = None
+ output = openstack_utils.get_volume(self.mock_shade_client,
+ 'volume_name_or_id')
+ self.assertIsNone(output)
+
+
+class CreateVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self.size = 1
+
+ def test_create_volume(self):
+ self.mock_shade_client.create_volume.return_value = (
+ {'name': 'volume-name', 'size': self.size})
+ output = openstack_utils.create_volume(
+ self.mock_shade_client, self.size)
+ self.assertEqual(
+ {'name': 'volume-name', 'size': self.size},
+ output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_create_volume_fail(self, mock_logger):
+ self.mock_shade_client.create_volume.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.create_volume(self.mock_shade_client,
+ self.size)
+ mock_logger.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class DeleteVolumeTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+
+ def test_delete_volume(self):
+ self.mock_shade_client.delete_volume.return_value = True
+ output = openstack_utils.delete_volume(self.mock_shade_client,
+ 'volume_name_or_id')
+ self.assertTrue(output)
+
+ def test_delete_volume_fail(self):
+ self.mock_shade_client.delete_volume.return_value = False
+ output = openstack_utils.delete_volume(self.mock_shade_client,
+ 'volume_name_or_id')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_volume_exception(self, mock_logger):
+ self.mock_shade_client.delete_volume.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_volume(self.mock_shade_client,
+ 'volume_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class DetachVolumeTestCase(unittest.TestCase):
+
+ @mock.patch.object(openstack_utils, 'get_server')
+ def test_detach_volume(self, mock_get_server):
+ self.mock_shade_client = mock.Mock()
+ mock_get_server.return_value = {'server_dict'}
+ self.mock_shade_client.get_volume.return_value = {'volume_dict'}
+ output = openstack_utils.detach_volume(self.mock_shade_client,
+ 'server_name_or_id',
+ 'volume_name_or_id')
+ self.assertTrue(output)
+
+ @mock.patch.object(openstack_utils, 'get_server')
+ @mock.patch.object(openstack_utils, 'log')
+ def test_detach_volume_exception(self, mock_logger, mock_get_server):
+ self.mock_shade_client = mock.Mock()
+ mock_get_server.return_value = {'server_dict'}
+ self.mock_shade_client.get_volume.return_value = {'volume_dict'}
+ self.mock_shade_client.detach_volume.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.detach_volume(self.mock_shade_client,
+ 'server_name_or_id',
+ 'volume_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
+
+
+class CreateImageTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_shade_client = mock.Mock()
+ self._uuid = uuidutils.generate_uuid()
+ self.name = 'image_name'
+ self._mock_log = mock.patch.object(openstack_utils, 'log')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_log.stop()
+
+ def test_create_image_already_exit(self):
+ self.mock_shade_client.get_image_id.return_value = self._uuid
+ output = openstack_utils.create_image(self.mock_shade_client, self.name)
+ self.mock_log.info.assert_called_once()
+ self.assertEqual(self._uuid, output)
+
+ def test_create_image(self):
+ self.mock_shade_client.get_image_id.return_value = None
+ self.mock_shade_client.create_image.return_value = {'id': self._uuid}
+ output = openstack_utils.create_image(self.mock_shade_client, self.name)
+ self.assertEqual(self._uuid, output)
+
+ def test_create_image_exception(self):
+ self.mock_shade_client.get_image_id.return_value = None
+ self.mock_shade_client.create_image.side_effect = (
+ exc.OpenStackCloudException('error message'))
+
+ output = openstack_utils.create_image(self.mock_shade_client,
+ self.name)
+ self.mock_log.error.assert_called_once()
+ self.assertIsNone(output)
+
+
+class DeleteImageTestCase(unittest.TestCase):
+
+ def test_delete_image(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.delete_image.return_value = True
+ output = openstack_utils.delete_image(self.mock_shade_client,
+ 'image_name_or_id')
+ self.assertTrue(output)
+
+ def test_delete_image_fail(self):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.delete_image.return_value = False
+ output = openstack_utils.delete_image(self.mock_shade_client,
+ 'image_name_or_id')
+ self.assertFalse(output)
+
+ @mock.patch.object(openstack_utils, 'log')
+ def test_delete_image_exception(self, mock_logger):
+ self.mock_shade_client = mock.Mock()
+ self.mock_shade_client.delete_image.side_effect = (
+ exc.OpenStackCloudException('error message'))
+ output = openstack_utils.delete_image(self.mock_shade_client,
+ 'image_name_or_id')
+ mock_logger.error.assert_called_once()
+ self.assertFalse(output)
diff --git a/yardstick/tests/unit/common/test_packages.py b/yardstick/tests/unit/common/test_packages.py
new file mode 100644
index 000000000..09d76fe44
--- /dev/null
+++ b/yardstick/tests/unit/common/test_packages.py
@@ -0,0 +1,88 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from pip._internal import exceptions as pip_exceptions
+from pip._internal.operations import freeze
+import unittest
+
+from yardstick.common import packages
+
+
+class PipExecuteActionTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_pip_main = mock.patch.object(packages, '_pip_main')
+ self.mock_pip_main = self._mock_pip_main.start()
+ self.mock_pip_main.return_value = 0
+ self._mock_freeze = mock.patch.object(freeze, 'freeze')
+ self.mock_freeze = self._mock_freeze.start()
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_pip_main.stop()
+ self._mock_freeze.stop()
+
+ def test_pip_execute_action(self):
+ self.assertEqual(0, packages._pip_execute_action('test_package'))
+
+ def test_remove(self):
+ self.assertEqual(0, packages._pip_execute_action('test_package',
+ action='uninstall'))
+
+ def test_install(self):
+ self.assertEqual(0, packages._pip_execute_action(
+ 'test_package', action='install', target='temp_dir'))
+
+ def test_pip_execute_action_error(self):
+ self.mock_pip_main.return_value = 1
+ self.assertEqual(1, packages._pip_execute_action('test_package'))
+
+ def test_pip_execute_action_exception(self):
+ self.mock_pip_main.side_effect = pip_exceptions.PipError
+ self.assertEqual(1, packages._pip_execute_action('test_package'))
+
+ def test_pip_list(self):
+ pkg_input = [
+ 'XStatic-Rickshaw==1.5.0.0',
+ 'xvfbwrapper==0.2.9',
+ '-e git+https://git.opnfv.org/yardstick@50773a24afc02c9652b662ecca'
+ '2fc5621ea6097a#egg=yardstick',
+ 'zope.interface==4.4.3'
+ ]
+ pkg_dict = {
+ 'XStatic-Rickshaw': '1.5.0.0',
+ 'xvfbwrapper': '0.2.9',
+ 'yardstick': '50773a24afc02c9652b662ecca2fc5621ea6097a',
+ 'zope.interface': '4.4.3'
+ }
+ self.mock_freeze.return_value = pkg_input
+
+ pkg_output = packages.pip_list()
+ for pkg_name, pkg_version in pkg_output.items():
+ self.assertEqual(pkg_dict.get(pkg_name), pkg_version)
+
+ def test_pip_list_single_package(self):
+ pkg_input = [
+ 'XStatic-Rickshaw==1.5.0.0',
+ 'xvfbwrapper==0.2.9',
+ '-e git+https://git.opnfv.org/yardstick@50773a24afc02c9652b662ecca'
+ '2fc5621ea6097a#egg=yardstick',
+ 'zope.interface==4.4.3'
+ ]
+ self.mock_freeze.return_value = pkg_input
+
+ pkg_output = packages.pip_list(pkg_name='xvfbwrapper')
+ self.assertEqual(1, len(pkg_output))
+ self.assertEqual(pkg_output.get('xvfbwrapper'), '0.2.9')
diff --git a/yardstick/tests/unit/common/test_process.py b/yardstick/tests/unit/common/test_process.py
new file mode 100644
index 000000000..e0933c6ac
--- /dev/null
+++ b/yardstick/tests/unit/common/test_process.py
@@ -0,0 +1,152 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+import unittest
+
+from oslo_utils import encodeutils
+
+from yardstick.common import exceptions
+from yardstick.common import process
+
+
+class ProcessTestcase(unittest.TestCase):
+ def test_check_if_procces_failed_None(self):
+ p = mock.MagicMock(**{"exitcode": None, "name": "debug"})
+ process.check_if_process_failed(p)
+
+ def test_check_if_procces_failed_0(self):
+ p = mock.MagicMock(**{"exitcode": 0, "name": "debug"})
+ process.check_if_process_failed(p)
+
+ def test_check_if_procces_failed_1(self):
+ p = mock.MagicMock(**{"exitcode": 1, "name": "debug"})
+ with self.assertRaises(RuntimeError):
+ process.check_if_process_failed(p)
+
+
+@mock.patch("yardstick.common.process.multiprocessing")
+class TerminateChildrenTestcase(unittest.TestCase):
+ def test_some_children(self, mock_multiprocessing):
+ p1 = mock.MagicMock()
+ p2 = mock.MagicMock()
+ mock_multiprocessing.active_children.return_value = [p1, p2]
+ process.terminate_children()
+
+ def test_no_children(self, mock_multiprocessing):
+ mock_multiprocessing.active_children.return_value = []
+ process.terminate_children()
+
+
+class ExecuteTestCase(unittest.TestCase):
+
+ RET_CODE_OK = 0
+ RET_CODE_WRONG = 1
+
+ def setUp(self):
+ self._mock_create_process = mock.patch.object(process,
+ 'create_process')
+ self.mock_create_process = self._mock_create_process.start()
+ self.obj = mock.Mock()
+ self.cmd = mock.Mock()
+ self.obj.communicate = mock.Mock()
+ self.stdout = 'std out'
+ self.stderr = 'std err'
+ self.obj.communicate.return_value = (self.stdout, self.stderr)
+ self.mock_create_process.return_value = (self.obj, self.cmd)
+ self.input_cmd = 'input cmd'
+ self.additional_env = mock.Mock()
+
+ def test_execute_with_input(self):
+ process_input = 'process input'
+ self.obj.returncode = self.RET_CODE_OK
+ out = process.execute(self.input_cmd, process_input=process_input,
+ additional_env=self.additional_env)
+ self.obj.communicate.assert_called_once_with(
+ encodeutils.to_utf8(process_input))
+ self.mock_create_process.assert_called_once_with(
+ self.input_cmd, run_as_root=False,
+ additional_env=self.additional_env)
+ self.assertEqual(self.stdout, out)
+
+ def test_execute_no_input(self):
+ self.obj.returncode = self.RET_CODE_OK
+ out = process.execute(self.input_cmd,
+ additional_env=self.additional_env)
+ self.obj.communicate.assert_called_once_with(None)
+ self.mock_create_process.assert_called_once_with(
+ self.input_cmd, run_as_root=False,
+ additional_env=self.additional_env)
+ self.assertEqual(self.stdout, out)
+
+ @mock.patch.object(process, 'LOG')
+ def test_execute_exception(self, *args):
+ self.obj.returncode = self.RET_CODE_WRONG
+ with self.assertRaises(exceptions.ProcessExecutionError):
+ process.execute(self.input_cmd, additional_env=self.additional_env)
+ self.obj.communicate.assert_called_once_with(None)
+
+ def test_execute_with_extra_code(self):
+ self.obj.returncode = self.RET_CODE_WRONG
+ out = process.execute(self.input_cmd,
+ additional_env=self.additional_env,
+ extra_ok_codes=[self.RET_CODE_WRONG])
+ self.obj.communicate.assert_called_once_with(None)
+ self.mock_create_process.assert_called_once_with(
+ self.input_cmd, run_as_root=False,
+ additional_env=self.additional_env)
+ self.assertEqual(self.stdout, out)
+
+ @mock.patch.object(process, 'LOG')
+ def test_execute_exception_no_check(self, *args):
+ self.obj.returncode = self.RET_CODE_WRONG
+ out = process.execute(self.input_cmd,
+ additional_env=self.additional_env,
+ check_exit_code=False)
+ self.obj.communicate.assert_called_once_with(None)
+ self.mock_create_process.assert_called_once_with(
+ self.input_cmd, run_as_root=False,
+ additional_env=self.additional_env)
+ self.assertEqual(self.stdout, out)
+
+
+class CreateProcessTestCase(unittest.TestCase):
+
+ @mock.patch.object(process, 'subprocess_popen')
+ def test_process_string_command(self, mock_subprocess_popen):
+ cmd = 'command'
+ obj = mock.Mock()
+ mock_subprocess_popen.return_value = obj
+ out1, out2 = process.create_process(cmd)
+ self.assertEqual(obj, out1)
+ self.assertEqual([cmd], out2)
+
+ @mock.patch.object(process, 'subprocess_popen')
+ def test_process_list_command(self, mock_subprocess_popen):
+ cmd = ['command']
+ obj = mock.Mock()
+ mock_subprocess_popen.return_value = obj
+ out1, out2 = process.create_process(cmd)
+ self.assertEqual(obj, out1)
+ self.assertEqual(cmd, out2)
+
+ @mock.patch.object(process, 'subprocess_popen')
+ def test_process_with_env(self, mock_subprocess_popen):
+ cmd = ['command']
+ obj = mock.Mock()
+ additional_env = {'var1': 'value1'}
+ mock_subprocess_popen.return_value = obj
+ out1, out2 = process.create_process(cmd, additional_env=additional_env)
+ self.assertEqual(obj, out1)
+ self.assertEqual(['env', 'var1=value1'] + cmd, out2)
diff --git a/yardstick/tests/unit/common/test_template_format.py b/yardstick/tests/unit/common/test_template_format.py
new file mode 100644
index 000000000..6e4827e16
--- /dev/null
+++ b/yardstick/tests/unit/common/test_template_format.py
@@ -0,0 +1,52 @@
+# 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.
+
+# yardstick: this file is copied from python-heatclient and slightly modified
+
+from __future__ import absolute_import
+import mock
+import unittest
+import yaml
+
+from yardstick.common import template_format
+
+
+class TemplateFormatTestCase(unittest.TestCase):
+
+ def test_parse_scanner(self):
+
+ with mock.patch.object(yaml, 'load') as yaml_loader:
+ yaml_loader.side_effect = yaml.scanner.ScannerError()
+ self.assertRaises(ValueError, template_format.parse, 'FOOBAR')
+
+ def test_parse_parser(self):
+
+ with mock.patch.object(yaml, 'load') as yaml_loader:
+ yaml_loader.side_effect = yaml.parser.ParserError()
+ self.assertRaises(ValueError, template_format.parse, 'FOOBAR')
+
+ def test_parse_reader(self):
+
+ with mock.patch.object(yaml, 'load') as yaml_loader:
+ yaml_loader.side_effect = \
+ yaml.reader.ReaderError('', '', '', '', '')
+ self.assertRaises(ValueError, template_format.parse, 'FOOBAR')
+
+ def test_parse_no_version_format(self):
+
+ yaml = ''
+ self.assertRaises(ValueError, template_format.parse, yaml)
+ yaml2 = "Parameters: {}\n" \
+ "Mappings: {}\n" \
+ "Resources: {}\n" \
+ "Outputs: {}"
+ self.assertRaises(ValueError, template_format.parse, yaml2)
diff --git a/yardstick/tests/unit/common/test_utils.py b/yardstick/tests/unit/common/test_utils.py
new file mode 100644
index 000000000..8fed5ecf1
--- /dev/null
+++ b/yardstick/tests/unit/common/test_utils.py
@@ -0,0 +1,1463 @@
+##############################################################################
+# Copyright (c) 2015 Ericsson AB 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
+##############################################################################
+
+from copy import deepcopy
+import errno
+import importlib
+import ipaddress
+from itertools import product, chain
+import os
+import socket
+import time
+import threading
+
+import mock
+import six
+from six.moves import configparser
+import unittest
+
+import yardstick
+from yardstick import ssh
+from yardstick.common import constants
+from yardstick.common import utils
+from yardstick.common import exceptions
+from yardstick.tests.unit import base as ut_base
+
+
+class IterSubclassesTestCase(ut_base.BaseUnitTestCase):
+ # Disclaimer: this class is a modified copy from
+ # rally/tests/unit/common/plugin/test_discover.py
+ # Copyright 2015: Mirantis Inc.
+
+ def test_itersubclasses(self):
+ class A(object):
+ pass
+
+ class B(A):
+ pass
+
+ class C(A):
+ pass
+
+ class D(C):
+ pass
+
+ self.assertEqual([B, C, D], list(utils.itersubclasses(A)))
+
+
+class ImportModulesFromPackageTestCase(ut_base.BaseUnitTestCase):
+
+ @mock.patch('yardstick.common.utils.os.walk')
+ def test_import_modules_from_package_no_mod(self, mock_walk):
+ yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__))
+ mock_walk.return_value = ([
+ (os.path.join(yardstick_root, 'foo'), ['bar'], ['__init__.py']),
+ (os.path.join(yardstick_root, 'foo', 'bar'), [], ['baz.txt', 'qux.rst'])
+ ])
+
+ utils.import_modules_from_package('foo.bar')
+
+ @mock.patch('yardstick.common.utils.os.walk')
+ @mock.patch.object(importlib, 'import_module')
+ def test_import_modules_from_package(self, mock_import_module, mock_walk):
+
+ yardstick_root = os.path.dirname(os.path.dirname(yardstick.__file__))
+ mock_walk.return_value = ([
+ (os.path.join(yardstick_root, 'foo', os.pardir, 'bar'), [], ['baz.py'])
+ ])
+
+ utils.import_modules_from_package('foo.bar')
+ mock_import_module.assert_called_once_with('bar.baz')
+
+
+class GetParaFromYaml(ut_base.BaseUnitTestCase):
+
+ @mock.patch('yardstick.common.utils.os.environ.get')
+ def test_get_param_para_not_found(self, get_env):
+ file_path = 'config_sample.yaml'
+ get_env.return_value = self._get_file_abspath(file_path)
+ args = 'releng.file'
+ default = 'hello'
+ self.assertTrue(constants.get_param(args, default), default)
+
+ @mock.patch('yardstick.common.utils.os.environ.get')
+ def test_get_param_para_exists(self, get_env):
+ file_path = 'config_sample.yaml'
+ get_env.return_value = self._get_file_abspath(file_path)
+ args = 'releng.dir'
+ para = '/home/opnfv/repos/releng'
+ self.assertEqual(para, constants.get_param(args))
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+
+class CommonUtilTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self.data = {
+ "benchmark": {
+ "data": {
+ "mpstat": {
+ "cpu0": {
+ "%sys": "0.00",
+ "%idle": "99.00"
+ },
+ "loadavg": [
+ "1.09",
+ "0.29"
+ ]
+ },
+ "rtt": "1.03"
+ }
+ }
+ }
+
+ def test__dict_key_flatten(self):
+ line = 'mpstat.loadavg1=0.29,rtt=1.03,mpstat.loadavg0=1.09,' \
+ 'mpstat.cpu0.%idle=99.00,mpstat.cpu0.%sys=0.00'
+ # need to sort for assert to work
+ line = ",".join(sorted(line.split(',')))
+ flattened_data = utils.flatten_dict_key(
+ self.data['benchmark']['data'])
+ result = ",".join(
+ ("=".join(item) for item in sorted(flattened_data.items())))
+ self.assertEqual(result, line)
+
+ def test_get_key_with_default_negative(self):
+ with self.assertRaises(KeyError):
+ utils.get_key_with_default({}, 'key1')
+
+ @mock.patch('yardstick.common.utils.open', create=True)
+ def test_(self, mock_open):
+ mock_open.side_effect = IOError
+
+ with self.assertRaises(IOError):
+ utils.find_relative_file('my/path', 'task/path')
+
+ self.assertEqual(mock_open.call_count, 2)
+
+ @mock.patch('yardstick.common.utils.open', create=True)
+ def test_open_relative_path(self, mock_open):
+ mock_open_result = mock_open()
+ mock_open_call_count = 1 # initial call to get result
+
+ self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
+
+ mock_open_call_count += 1 # one more call expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertNotIn('bar', mock_open.call_args_list[-1][0][0])
+
+ def open_effect(*args, **kwargs):
+ if kwargs.get('name', args[0]) == os.path.join('bar', 'foo'):
+ return mock_open_result
+ raise IOError(errno.ENOENT, 'not found')
+
+ mock_open.side_effect = open_effect
+ self.assertEqual(utils.open_relative_file('foo', 'bar'), mock_open_result)
+
+ mock_open_call_count += 2 # two more calls expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertIn('bar', mock_open.call_args_list[-1][0][0])
+
+ # test an IOError of type ENOENT
+ mock_open.side_effect = IOError(errno.ENOENT, 'not found')
+ with self.assertRaises(IOError):
+ # the second call still raises
+ utils.open_relative_file('foo', 'bar')
+
+ mock_open_call_count += 2 # two more calls expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+ self.assertIn('foo', mock_open.call_args_list[-1][0][0])
+ self.assertIn('bar', mock_open.call_args_list[-1][0][0])
+
+ # test an IOError other than ENOENT
+ mock_open.side_effect = IOError(errno.EBUSY, 'busy')
+ with self.assertRaises(IOError):
+ utils.open_relative_file('foo', 'bar')
+
+ mock_open_call_count += 1 # one more call expected
+ self.assertEqual(mock_open.call_count, mock_open_call_count)
+
+
+class TestMacAddressToHex(ut_base.BaseUnitTestCase):
+
+ def test_mac_address_to_hex_list(self):
+ self.assertEqual(utils.mac_address_to_hex_list("ea:3e:e1:9a:99:e8"),
+ ['0xea', '0x3e', '0xe1', '0x9a', '0x99', '0xe8'])
+
+ def test_mac_address_to_hex_list_too_short_mac(self):
+ with self.assertRaises(exceptions.InvalidMacAddress):
+ utils.mac_address_to_hex_list("ea:3e:e1:9a")
+
+ def test_mac_address_to_hex_list_no_int_mac(self):
+ with self.assertRaises(exceptions.InvalidMacAddress):
+ utils.mac_address_to_hex_list("invalid_mac")
+
+
+class TranslateToStrTestCase(ut_base.BaseUnitTestCase):
+
+ def test_translate_to_str_unicode(self):
+ input_str = u'hello'
+ output_str = utils.translate_to_str(input_str)
+
+ result = 'hello'
+ self.assertEqual(result, output_str)
+
+ def test_translate_to_str_dict_list_unicode(self):
+ input_str = {
+ u'hello': {u'hello': [u'world']}
+ }
+ output_str = utils.translate_to_str(input_str)
+
+ result = {
+ 'hello': {'hello': ['world']}
+ }
+ self.assertEqual(result, output_str)
+
+ def test_translate_to_str_non_string(self):
+ input_value = object()
+ result = utils.translate_to_str(input_value)
+ self.assertIs(input_value, result)
+
+
+class TestParseCpuInfo(ut_base.BaseUnitTestCase):
+
+ def test_single_socket_no_hyperthread(self):
+ cpuinfo = """\
+processor : 2
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel Core Processor (Haswell, no TSX)
+stepping : 1
+microcode : 0x1
+cpu MHz : 2294.684
+cache size : 4096 KB
+physical id : 0
+siblings : 5
+core id : 2
+cpu cores : 5
+apicid : 2
+initial apicid : 2
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
+bugs :
+bogomips : 4589.36
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 3
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel Core Processor (Haswell, no TSX)
+stepping : 1
+microcode : 0x1
+cpu MHz : 2294.684
+cache size : 4096 KB
+physical id : 0
+siblings : 5
+core id : 3
+cpu cores : 5
+apicid : 3
+initial apicid : 3
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
+bugs :
+bogomips : 4589.36
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 4
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel Core Processor (Haswell, no TSX)
+stepping : 1
+microcode : 0x1
+cpu MHz : 2294.684
+cache size : 4096 KB
+physical id : 0
+siblings : 5
+core id : 4
+cpu cores : 5
+apicid : 4
+initial apicid : 4
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt arat
+bugs :
+bogomips : 4589.36
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+"""
+ socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
+ self.assertEqual(sorted(socket_map.keys()), [0])
+ self.assertEqual(sorted(socket_map[0].keys()), [2, 3, 4])
+
+ def test_single_socket_hyperthread(self):
+ cpuinfo = """\
+processor : 5
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
+stepping : 3
+microcode : 0x1d
+cpu MHz : 3501.708
+cache size : 8192 KB
+physical id : 0
+siblings : 8
+core id : 1
+cpu cores : 4
+apicid : 3
+initial apicid : 3
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
+bugs :
+bogomips : 6987.36
+clflush size : 64
+cache_alignment : 64
+address sizes : 39 bits physical, 48 bits virtual
+power management:
+
+processor : 6
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
+stepping : 3
+microcode : 0x1d
+cpu MHz : 3531.829
+cache size : 8192 KB
+physical id : 0
+siblings : 8
+core id : 2
+cpu cores : 4
+apicid : 5
+initial apicid : 5
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
+bugs :
+bogomips : 6987.36
+clflush size : 64
+cache_alignment : 64
+address sizes : 39 bits physical, 48 bits virtual
+power management:
+
+processor : 7
+vendor_id : GenuineIntel
+cpu family : 6
+model : 60
+model name : Intel(R) Xeon(R) CPU E3-1275 v3 @ 3.50GHz
+stepping : 3
+microcode : 0x1d
+cpu MHz : 3500.213
+cache size : 8192 KB
+physical id : 0
+siblings : 8
+core id : 3
+cpu cores : 4
+apicid : 7
+initial apicid : 7
+fpu : yes
+fpu_exception : yes
+cpuid level : 13
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt dtherm ida arat pln pts
+bugs :
+bogomips : 6987.24
+clflush size : 64
+cache_alignment : 64
+address sizes : 39 bits physical, 48 bits virtual
+power management:
+
+"""
+ socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
+ self.assertEqual(sorted(socket_map.keys()), [0])
+ self.assertEqual(sorted(socket_map[0].keys()), [1, 2, 3])
+ self.assertEqual(sorted(socket_map[0][1]), [5])
+ self.assertEqual(sorted(socket_map[0][2]), [6])
+ self.assertEqual(sorted(socket_map[0][3]), [7])
+
+ def test_dual_socket_hyperthread(self):
+ cpuinfo = """\
+processor : 1
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.976
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 1
+cpu cores : 22
+apicid : 2
+initial apicid : 2
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4401.07
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 2
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1226.892
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 2
+cpu cores : 22
+apicid : 4
+initial apicid : 4
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4400.84
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 43
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 28
+cpu cores : 22
+apicid : 120
+initial apicid : 120
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4411.31
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 44
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 0
+cpu cores : 22
+apicid : 1
+initial apicid : 1
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4410.61
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 85
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.573
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 26
+cpu cores : 22
+apicid : 117
+initial apicid : 117
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4409.07
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 86
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 27
+cpu cores : 22
+apicid : 119
+initial apicid : 119
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4406.62
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 87
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.708
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 28
+cpu cores : 22
+apicid : 121
+initial apicid : 121
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4413.48
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+"""
+ socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
+ self.assertEqual(sorted(socket_map.keys()), [0, 1])
+ self.assertEqual(sorted(socket_map[0].keys()), [0, 1, 2])
+ self.assertEqual(sorted(socket_map[1].keys()), [26, 27, 28])
+ self.assertEqual(sorted(socket_map[0][0]), [44])
+ self.assertEqual(sorted(socket_map[0][1]), [1])
+ self.assertEqual(sorted(socket_map[0][2]), [2])
+ self.assertEqual(sorted(socket_map[1][26]), [85])
+ self.assertEqual(sorted(socket_map[1][27]), [86])
+ self.assertEqual(sorted(socket_map[1][28]), [43, 87])
+
+ def test_dual_socket_no_hyperthread(self):
+ cpuinfo = """\
+processor : 1
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.976
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 1
+cpu cores : 22
+apicid : 2
+initial apicid : 2
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4401.07
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 2
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1226.892
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 2
+cpu cores : 22
+apicid : 4
+initial apicid : 4
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4400.84
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 43
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 28
+cpu cores : 22
+apicid : 120
+initial apicid : 120
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4411.31
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 44
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 0
+siblings : 44
+core id : 0
+cpu cores : 22
+apicid : 1
+initial apicid : 1
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4410.61
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 85
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.573
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 26
+cpu cores : 22
+apicid : 117
+initial apicid : 117
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4409.07
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 86
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.305
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 27
+cpu cores : 22
+apicid : 119
+initial apicid : 119
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4406.62
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+processor : 87
+vendor_id : GenuineIntel
+cpu family : 6
+model : 79
+model name : Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz
+stepping : 1
+microcode : 0xb00001f
+cpu MHz : 1200.708
+cache size : 56320 KB
+physical id : 1
+siblings : 44
+core id : 28
+cpu cores : 22
+apicid : 121
+initial apicid : 121
+fpu : yes
+fpu_exception : yes
+cpuid level : 20
+wp : yes
+flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid dca sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch epb cat_l3 cdp_l3 intel_ppin intel_pt tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm cqm rdt_a rdseed adx smap xsaveopt cqm_llc cqm_occup_llc cqm_mbm_total cqm_mbm_local dtherm ida arat pln pts
+bugs :
+bogomips : 4413.48
+clflush size : 64
+cache_alignment : 64
+address sizes : 46 bits physical, 48 bits virtual
+power management:
+
+"""
+ socket_map = utils.SocketTopology.parse_cpuinfo(cpuinfo)
+ processors = socket_map.processors()
+ self.assertEqual(processors, [1, 2, 43, 44, 85, 86, 87])
+ cores = socket_map.cores()
+ self.assertEqual(cores, [0, 1, 2, 26, 27, 28])
+ sockets = socket_map.sockets()
+ self.assertEqual(sockets, [0, 1])
+
+
+class ChangeObjToDictTestCase(ut_base.BaseUnitTestCase):
+
+ def test_change_obj_to_dict(self):
+ class A(object):
+ def __init__(self):
+ self.name = 'yardstick'
+
+ obj = A()
+ obj_r = utils.change_obj_to_dict(obj)
+ obj_s = {'name': 'yardstick'}
+ self.assertEqual(obj_r, obj_s)
+
+
+class SetDictValueTestCase(ut_base.BaseUnitTestCase):
+
+ def test_set_dict_value(self):
+ input_dic = {
+ 'hello': 'world'
+ }
+ output_dic = utils.set_dict_value(input_dic, 'welcome.to', 'yardstick')
+ self.assertEqual(output_dic.get('welcome', {}).get('to'), 'yardstick')
+
+
+class RemoveFileTestCase(ut_base.BaseUnitTestCase):
+
+ def test_remove_file(self):
+ try:
+ utils.remove_file('notexistfile.txt')
+ except Exception as e: # pylint: disable=broad-except
+ # NOTE(ralonsoh): to narrow the scope of this exception.
+ self.assertTrue(isinstance(e, OSError))
+
+
+class ParseIniFileTestCase(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self._mock_config_parser_type = mock.patch.object(configparser,
+ 'ConfigParser')
+ self.mock_config_parser_type = self._mock_config_parser_type.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_config_parser_type.stop()
+
+ def test_parse_ini_file(self):
+ defaults = {'default1': 'value1',
+ 'default2': 'value2'}
+ s1 = {'key1': 'value11',
+ 'key2': 'value22'}
+ s2 = {'key1': 'value123',
+ 'key2': 'value234'}
+
+ mock_config_parser = mock.Mock()
+ self.mock_config_parser_type.return_value = mock_config_parser
+ mock_config_parser.read.return_value = True
+ mock_config_parser.sections.return_value = ['s1', 's2']
+ mock_config_parser.items.side_effect = iter([
+ defaults.items(),
+ s1.items(),
+ s2.items(),
+ ])
+
+ expected = {'DEFAULT': defaults,
+ 's1': s1,
+ 's2': s2}
+ result = utils.parse_ini_file('my_path')
+ self.assertDictEqual(expected, result)
+
+ @mock.patch.object(utils, 'logger')
+ def test_parse_ini_file_missing_section_header(self, *args):
+ mock_config_parser = mock.Mock()
+ self.mock_config_parser_type.return_value = mock_config_parser
+ mock_config_parser.read.side_effect = (
+ configparser.MissingSectionHeaderError(
+ mock.Mock(), 321, mock.Mock()))
+
+ with self.assertRaises(configparser.MissingSectionHeaderError):
+ utils.parse_ini_file('my_path')
+
+ def test_parse_ini_file_no_file(self):
+ mock_config_parser = mock.Mock()
+ self.mock_config_parser_type.return_value = mock_config_parser
+ mock_config_parser.read.return_value = False
+ with self.assertRaises(RuntimeError):
+ utils.parse_ini_file('my_path')
+
+ def test_parse_ini_file_no_default_section_header(self):
+ s1 = {'key1': 'value11',
+ 'key2': 'value22'}
+ s2 = {'key1': 'value123',
+ 'key2': 'value234'}
+
+ mock_config_parser = mock.Mock()
+ self.mock_config_parser_type.return_value = mock_config_parser
+ mock_config_parser.read.return_value = True
+ mock_config_parser.sections.return_value = ['s1', 's2']
+ mock_config_parser.items.side_effect = iter([
+ configparser.NoSectionError(mock.Mock()),
+ s1.items(),
+ s2.items(),
+ ])
+
+ expected = {'DEFAULT': {},
+ 's1': s1,
+ 's2': s2}
+ result = utils.parse_ini_file('my_path')
+ self.assertDictEqual(expected, result)
+
+
+class TestUtils(ut_base.BaseUnitTestCase):
+
+ @mock.patch('yardstick.common.utils.os.makedirs')
+ def test_makedirs(self, *_):
+ self.assertIsNone(utils.makedirs('a/b/c/d'))
+
+ @mock.patch('yardstick.common.utils.os.makedirs')
+ def test_makedirs_exists(self, mock_os_makedirs):
+ mock_os_makedirs.side_effect = OSError(errno.EEXIST, 'exists')
+ self.assertIsNone(utils.makedirs('a/b/c/d'))
+
+ @mock.patch('yardstick.common.utils.os.makedirs')
+ def test_makedirs_busy(self, mock_os_makedirs):
+ mock_os_makedirs.side_effect = OSError(errno.EBUSY, 'busy')
+ with self.assertRaises(OSError):
+ utils.makedirs('a/b/c/d')
+
+ @mock.patch('yardstick.common.utils.jsonify')
+ def test_result_handler(self, mock_jsonify):
+ mock_jsonify.return_value = 432
+
+ self.assertEqual(utils.result_handler('x', 234), 432)
+ mock_jsonify.assert_called_once_with({'status': 'x', 'result': 234})
+
+ @mock.patch('random.randint')
+ @mock.patch('socket.socket')
+ def test_get_free_port(self, mock_socket, mock_randint):
+ mock_randint.return_value = 7777
+ s = mock_socket('x', 'y')
+ s.connect_ex.side_effect = iter([0, 1])
+ result = utils.get_free_port('10.20.30.40')
+ self.assertEqual(result, 7777)
+ self.assertEqual(s.connect_ex.call_count, 2)
+
+ @mock.patch('subprocess.check_output')
+ def test_execute_command(self, mock_check_output):
+ expected = ['hello world', '1234']
+ mock_check_output.return_value = os.linesep.join(expected)
+ result = utils.execute_command('my_command arg1 arg2')
+ self.assertEqual(result, expected)
+
+ @mock.patch('subprocess.Popen')
+ def test_source_env(self, mock_popen):
+ base_env = deepcopy(os.environ)
+ mock_process = mock_popen()
+ output_list = [
+ 'garbage line before',
+ 'NEW_ENV_VALUE=234',
+ 'garbage line after',
+ ]
+ mock_process.communicate.return_value = os.linesep.join(output_list), '', 0
+ expected = {'NEW_ENV_VALUE': '234'}
+ result = utils.source_env('my_file')
+ self.assertDictEqual(result, expected)
+ os.environ.clear()
+ os.environ.update(base_env)
+
+ @mock.patch.object(configparser, 'ConfigParser')
+ def test_parse_ini_file(self, mock_config_parser_type):
+ defaults = {
+ 'default1': 'value1',
+ 'default2': 'value2',
+ }
+ s1 = {
+ 'key1': 'value11',
+ 'key2': 'value22',
+ }
+ s2 = {
+ 'key1': 'value123',
+ 'key2': 'value234',
+ }
+
+ mock_config_parser = mock_config_parser_type()
+ mock_config_parser.read.return_value = True
+ mock_config_parser.sections.return_value = ['s1', 's2']
+ mock_config_parser.items.side_effect = iter([
+ defaults.items(),
+ s1.items(),
+ s2.items(),
+ ])
+
+ expected = {
+ 'DEFAULT': defaults,
+ 's1': s1,
+ 's2': s2,
+ }
+ result = utils.parse_ini_file('my_path')
+ self.assertDictEqual(result, expected)
+
+ @mock.patch.object(utils, 'logger')
+ @mock.patch.object(configparser, 'ConfigParser')
+ def test_parse_ini_file_missing_section_header(
+ self, mock_config_parser_type, *args):
+ mock_config_parser = mock_config_parser_type()
+ mock_config_parser.read.side_effect = (
+ configparser.MissingSectionHeaderError(mock.Mock(), 321,
+ mock.Mock()))
+
+ with self.assertRaises(configparser.MissingSectionHeaderError):
+ utils.parse_ini_file('my_path')
+
+ @mock.patch.object(configparser, 'ConfigParser')
+ def test_parse_ini_file_no_file(self, mock_config_parser_type):
+ mock_config_parser = mock_config_parser_type()
+ mock_config_parser.read.return_value = False
+ with self.assertRaises(RuntimeError):
+ utils.parse_ini_file('my_path')
+
+ @mock.patch.object(configparser, 'ConfigParser')
+ def test_parse_ini_file_no_default_section_header(self, mock_config_parser_type):
+ s1 = {
+ 'key1': 'value11',
+ 'key2': 'value22',
+ }
+ s2 = {
+ 'key1': 'value123',
+ 'key2': 'value234',
+ }
+
+ mock_config_parser = mock_config_parser_type()
+ mock_config_parser.read.return_value = True
+ mock_config_parser.sections.return_value = ['s1', 's2']
+ mock_config_parser.items.side_effect = iter([
+ configparser.NoSectionError(mock.Mock()),
+ s1.items(),
+ s2.items(),
+ ])
+
+ expected = {
+ 'DEFAULT': {},
+ 's1': s1,
+ 's2': s2,
+ }
+ result = utils.parse_ini_file('my_path')
+ self.assertDictEqual(result, expected)
+
+ def test_join_non_strings(self):
+ self.assertEqual(utils.join_non_strings(':'), '')
+ self.assertEqual(utils.join_non_strings(':', 'a'), 'a')
+ self.assertEqual(utils.join_non_strings(':', 'a', 2, 'c'), 'a:2:c')
+ self.assertEqual(utils.join_non_strings(':', ['a', 2, 'c']), 'a:2:c')
+ self.assertEqual(utils.join_non_strings(':', 'abc'), 'abc')
+
+ def test_validate_non_string_sequence(self):
+ self.assertEqual(utils.validate_non_string_sequence([1, 2, 3]), [1, 2, 3])
+ self.assertIsNone(utils.validate_non_string_sequence('123'))
+ self.assertIsNone(utils.validate_non_string_sequence(1))
+
+ self.assertEqual(utils.validate_non_string_sequence(1, 2), 2)
+ self.assertEqual(utils.validate_non_string_sequence(1, default=2), 2)
+
+ with self.assertRaises(RuntimeError):
+ utils.validate_non_string_sequence(1, raise_exc=RuntimeError)
+
+
+class TestUtilsIpAddrMethods(ut_base.BaseUnitTestCase):
+
+ GOOD_IP_V4_ADDRESS_STR_LIST = [
+ u'0.0.0.0',
+ u'10.20.30.40',
+ u'127.0.0.1',
+ u'10.20.30.40',
+ u'172.29.50.75',
+ u'192.168.230.9',
+ u'255.255.255.255',
+ ]
+
+ GOOD_IP_V4_MASK_STR_LIST = [
+ u'/1',
+ u'/8',
+ u'/13',
+ u'/19',
+ u'/24',
+ u'/32',
+ ]
+
+ GOOD_IP_V6_ADDRESS_STR_LIST = [
+ u'::1',
+ u'fe80::250:56ff:fe89:91ff',
+ u'123:4567:89ab:cdef:123:4567:89ab:cdef',
+ ]
+
+ GOOD_IP_V6_MASK_STR_LIST = [
+ u'/1',
+ u'/16',
+ u'/29',
+ u'/64',
+ u'/99',
+ u'/128',
+ ]
+
+ INVALID_IP_ADDRESS_STR_LIST = [
+ 1,
+ u'w.x.y.z',
+ u'10.20.30.40/33',
+ u'123:4567:89ab:cdef:123:4567:89ab:cdef/129',
+ ]
+
+ def test_make_ipv4_address(self):
+ for addr in self.GOOD_IP_V4_ADDRESS_STR_LIST:
+ # test with no mask
+ expected = ipaddress.IPv4Address(addr)
+ self.assertEqual(utils.make_ipv4_address(addr), expected, addr)
+
+ def test_make_ipv4_address_error(self):
+ addr_list = self.INVALID_IP_ADDRESS_STR_LIST +\
+ self.GOOD_IP_V6_ADDRESS_STR_LIST
+ for addr in addr_list:
+ self.assertRaises(Exception, utils.make_ipv4_address, addr)
+
+ def test_get_ip_range_count(self):
+ iprange = "192.168.0.1-192.168.0.25"
+ count = utils.get_ip_range_count(iprange)
+ self.assertEqual(count, 24)
+
+ def test_get_ip_range_start(self):
+ iprange = "192.168.0.1-192.168.0.25"
+ start = utils.get_ip_range_start(iprange)
+ self.assertEqual(start, "192.168.0.1")
+
+ def test_safe_ip_address(self):
+ addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
+ for addr in addr_list:
+ # test with no mask
+ expected = ipaddress.ip_address(addr)
+ self.assertEqual(utils.safe_ip_address(addr), expected, addr)
+
+ def test_safe_ip_address_v6_ip(self):
+ addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
+ for addr in addr_list:
+ # test with no mask
+ expected = ipaddress.ip_address(addr)
+ self.assertEqual(utils.safe_ip_address(addr), expected, addr)
+
+ @mock.patch("yardstick.common.utils.logging")
+ def test_safe_ip_address_negative(self, *args):
+ # NOTE(ralonsoh): check the calls to mocked functions.
+ for value in self.INVALID_IP_ADDRESS_STR_LIST:
+ self.assertIsNone(utils.safe_ip_address(value), value)
+
+ addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
+ mask_list = self.GOOD_IP_V4_MASK_STR_LIST
+ for addr_mask_pair in product(addr_list, mask_list):
+ value = ''.join(addr_mask_pair)
+ self.assertIsNone(utils.safe_ip_address(value), value)
+
+ addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
+ mask_list = self.GOOD_IP_V6_MASK_STR_LIST
+ for addr_mask_pair in product(addr_list, mask_list):
+ value = ''.join(addr_mask_pair)
+ self.assertIsNone(utils.safe_ip_address(value), value)
+
+ def test_get_ip_version(self):
+ addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
+ for addr in addr_list:
+ # test with no mask
+ self.assertEqual(utils.get_ip_version(addr), 4, addr)
+
+ def test_get_ip_version_v6_ip(self):
+ addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
+ for addr in addr_list:
+ # test with no mask
+ self.assertEqual(utils.get_ip_version(addr), 6, addr)
+
+ @mock.patch("yardstick.common.utils.logging")
+ def test_get_ip_version_negative(self, *args):
+ # NOTE(ralonsoh): check the calls to mocked functions.
+ for value in self.INVALID_IP_ADDRESS_STR_LIST:
+ self.assertIsNone(utils.get_ip_version(value), value)
+
+ addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
+ mask_list = self.GOOD_IP_V4_MASK_STR_LIST
+ for addr_mask_pair in product(addr_list, mask_list):
+ value = ''.join(addr_mask_pair)
+ self.assertIsNone(utils.get_ip_version(value), value)
+
+ addr_list = self.GOOD_IP_V6_ADDRESS_STR_LIST
+ mask_list = self.GOOD_IP_V6_MASK_STR_LIST
+ for addr_mask_pair in product(addr_list, mask_list):
+ value = ''.join(addr_mask_pair)
+ self.assertIsNone(utils.get_ip_version(value), value)
+
+ def test_ip_to_hex(self):
+ self.assertEqual(utils.ip_to_hex('0.0.0.0'), '00000000')
+ self.assertEqual(utils.ip_to_hex('10.20.30.40'), '0a141e28')
+ self.assertEqual(utils.ip_to_hex('127.0.0.1'), '7f000001')
+ self.assertEqual(utils.ip_to_hex('172.31.90.100'), 'ac1f5a64')
+ self.assertEqual(utils.ip_to_hex('192.168.254.253'), 'c0a8fefd')
+ self.assertEqual(utils.ip_to_hex('255.255.255.255'), 'ffffffff')
+
+ def test_ip_to_hex_v6_ip(self):
+ for value in self.GOOD_IP_V6_ADDRESS_STR_LIST:
+ self.assertEqual(utils.ip_to_hex(value), value)
+
+ @mock.patch("yardstick.common.utils.logging")
+ def test_ip_to_hex_negative(self, *args):
+ # NOTE(ralonsoh): check the calls to mocked functions.
+ addr_list = self.GOOD_IP_V4_ADDRESS_STR_LIST
+ mask_list = self.GOOD_IP_V4_MASK_STR_LIST
+ value_iter = (''.join(pair) for pair in product(addr_list, mask_list))
+ for value in chain(value_iter, self.INVALID_IP_ADDRESS_STR_LIST):
+ self.assertEqual(utils.ip_to_hex(value), value)
+
+ def test_get_mask_from_ip_range_ipv4(self):
+ ip_str = '1.1.1.1'
+ for mask in range(8, 30):
+ ip = ipaddress.ip_network(ip_str + '/' + str(mask), strict=False)
+ result = utils.get_mask_from_ip_range(ip[2], ip[-2])
+ self.assertEqual(mask, result)
+
+ def test_get_mask_from_ip_range_ipv6(self):
+ ip_str = '2001::1'
+ for mask in range(8, 120):
+ ip = ipaddress.ip_network(ip_str + '/' + str(mask), strict=False)
+ result = utils.get_mask_from_ip_range(ip[2], ip[-2])
+ self.assertEqual(mask, result)
+
+
+class SafeDecodeUtf8TestCase(ut_base.BaseUnitTestCase):
+
+ @unittest.skipIf(six.PY2,
+ 'This test should only be launched with Python 3.x')
+ def test_safe_decode_utf8(self):
+ _bytes = b'this is a byte array'
+ out = utils.safe_decode_utf8(_bytes)
+ self.assertIs(type(out), str)
+ self.assertEqual('this is a byte array', out)
+
+
+class ReadMeminfoTestCase(ut_base.BaseUnitTestCase):
+
+ MEMINFO = (b'MemTotal: 65860500 kB\n'
+ b'MemFree: 28690900 kB\n'
+ b'MemAvailable: 52873764 kB\n'
+ b'Active(anon): 3015676 kB\n'
+ b'HugePages_Total: 8\n'
+ b'Hugepagesize: 1048576 kB')
+ MEMINFO_DICT = {'MemTotal': '65860500',
+ 'MemFree': '28690900',
+ 'MemAvailable': '52873764',
+ 'Active(anon)': '3015676',
+ 'HugePages_Total': '8',
+ 'Hugepagesize': '1048576'}
+
+ def test_read_meminfo(self):
+ ssh_client = ssh.SSH('user', 'host')
+ with mock.patch.object(ssh_client, 'get_file_obj') as \
+ mock_get_client, \
+ mock.patch.object(six, 'BytesIO',
+ return_value=six.BytesIO(self.MEMINFO)):
+ output = utils.read_meminfo(ssh_client)
+ mock_get_client.assert_called_once_with('/proc/meminfo', mock.ANY)
+ self.assertEqual(self.MEMINFO_DICT, output)
+
+
+class TimerTestCase(ut_base.BaseUnitTestCase):
+
+ def test__getattr(self):
+ with utils.Timer() as timer:
+ time.sleep(1)
+ self.assertEqual(1, round(timer.total_seconds(), 0))
+ self.assertEqual(1, timer.delta.seconds)
+
+ def test__enter_with_timeout(self):
+ with utils.Timer(timeout=10) as timer:
+ time.sleep(1)
+ self.assertEqual(1, round(timer.total_seconds(), 0))
+
+ def test__enter_with_timeout_exception(self):
+ with self.assertRaises(exceptions.TimerTimeout):
+ with utils.Timer(timeout=1):
+ time.sleep(2)
+
+ def test__enter_with_timeout_no_exception(self):
+ with utils.Timer(timeout=1, raise_exception=False):
+ time.sleep(2)
+
+ def test__iter(self):
+ iterations = []
+ for i in utils.Timer(timeout=2):
+ iterations.append(i)
+ time.sleep(1.1)
+ self.assertEqual(2, len(iterations))
+
+ def test_delta_time_sec(self):
+ with utils.Timer() as timer:
+ self.assertIsInstance(timer.delta_time_sec(), float)
+
+
+class WaitUntilTrueTestCase(ut_base.BaseUnitTestCase):
+
+ def test_no_timeout(self):
+ self.assertIsNone(utils.wait_until_true(lambda: True,
+ timeout=1, sleep=1))
+
+ def test_timeout_generic_exception(self):
+ with self.assertRaises(exceptions.WaitTimeout):
+ self.assertIsNone(utils.wait_until_true(lambda: False,
+ timeout=1, sleep=1))
+
+ def test_timeout_given_exception(self):
+ class MyTimeoutException(exceptions.YardstickException):
+ message = 'My timeout exception'
+
+ with self.assertRaises(MyTimeoutException):
+ self.assertIsNone(
+ utils.wait_until_true(lambda: False, timeout=1, sleep=1,
+ exception=MyTimeoutException))
+
+ def _run_thread(self):
+ with self.assertRaises(exceptions.WaitTimeout):
+ utils.wait_until_true(lambda: False, timeout=1, sleep=1)
+
+ def test_timeout_no_main_thread(self):
+ new_thread = threading.Thread(target=self._run_thread)
+ new_thread.start()
+ new_thread.join(timeout=3)
+
+
+class SendSocketCommandTestCase(unittest.TestCase):
+
+ @mock.patch.object(socket, 'socket')
+ def test_execute_correct(self, mock_socket):
+ mock_socket_obj = mock.Mock()
+ mock_socket_obj.connect_ex.return_value = 0
+ mock_socket.return_value = mock_socket_obj
+ self.assertEqual(0, utils.send_socket_command('host', 22, 'command'))
+ mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
+ mock_socket_obj.connect_ex.assert_called_once_with(('host', 22))
+ mock_socket_obj.sendall.assert_called_once_with(six.b('command'))
+ mock_socket_obj.close.assert_called_once()
+
+ @mock.patch.object(socket, 'socket')
+ def test_execute_exception(self, mock_socket):
+ mock_socket_obj = mock.Mock()
+ mock_socket_obj.connect_ex.return_value = 0
+ mock_socket.return_value = mock_socket_obj
+ mock_socket_obj.sendall.side_effect = socket.error
+ self.assertEqual(1, utils.send_socket_command('host', 22, 'command'))
+ mock_socket.assert_called_once_with(socket.AF_INET, socket.SOCK_STREAM)
+ mock_socket_obj.connect_ex.assert_called_once_with(('host', 22))
+ mock_socket_obj.sendall.assert_called_once_with(six.b('command'))
+ mock_socket_obj.close.assert_called_once()
+
+
+class GetPortMacTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ssh_client = mock.Mock()
+ self.ssh_client.execute.return_value = (0, 'foo ', '')
+
+ def test_ssh_client_execute_called(self):
+ utils.get_port_mac(self.ssh_client, 99)
+ self.ssh_client.execute.assert_called_once_with(
+ "ifconfig |grep HWaddr |grep 99 |awk '{print $5}' ",
+ raise_on_error=True)
+
+ def test_return_value(self):
+ self.assertEqual('foo', utils.get_port_mac(self.ssh_client, 99))
+
+
+class GetPortIPTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.ssh_client = mock.Mock()
+ self.ssh_client.execute.return_value = (0, 'foo ', '')
+
+ def test_ssh_client_execute_called(self):
+ utils.get_port_ip(self.ssh_client, 99)
+ self.ssh_client.execute.assert_called_once_with(
+ "ifconfig 99 |grep 'inet addr' |awk '{print $2}' |cut -d ':' -f2 ",
+ raise_on_error=True)
+
+ def test_return_value(self):
+ self.assertEqual('foo', utils.get_port_ip(self.ssh_client, 99))
+
+
+class SafeCaseTestCase(unittest.TestCase):
+
+ def test_correct_type_int(self):
+ self.assertEqual(35, utils.safe_cast('35', int, 0))
+
+ def test_correct_int_as_string(self):
+ self.assertEqual(25, utils.safe_cast('25', 'int', 0))
+
+ def test_incorrect_type_as_string(self):
+ with self.assertRaises(exceptions.InvalidType):
+ utils.safe_cast('100', 'intt', 0)
+
+ def test_default_value(self):
+ self.assertEqual(0, utils.safe_cast('', 'int', 0))
+
+
+class SetupHugepagesTestCase(unittest.TestCase):
+
+ @mock.patch.object(six, 'BytesIO', return_value=six.BytesIO(b'5\n'))
+ @mock.patch.object(utils, 'read_meminfo',
+ return_value={'Hugepagesize': '1024'})
+ def test_setup_hugepages(self, mock_meminfo, *args):
+ ssh = mock.Mock()
+ ssh.execute = mock.Mock()
+ hp_size_kb, hp_number, hp_number_set = utils.setup_hugepages(ssh, 10 * 1024)
+ mock_meminfo.assert_called_once_with(ssh)
+ ssh.execute.assert_called_once_with(
+ 'echo 10 | sudo tee /proc/sys/vm/nr_hugepages')
+ self.assertEqual(hp_size_kb, 1024)
+ self.assertEqual(hp_number, 10)
+ self.assertEqual(hp_number_set, 5)
+
+
+class GetOSSampleInfoTestCase(unittest.TestCase):
+
+ def test_get_os_version(self, *args):
+ ssh = mock.Mock()
+ ssh.execute.return_value = (0, "18.04", "")
+ utils.get_os_version(ssh)
+ ssh.execute.assert_called_once_with("cat /etc/lsb-release")
+
+ def test_get_kernel_version(self, *args):
+ ssh = mock.Mock()
+ ssh.execute.return_value = (0, "Linux", "")
+ utils.get_kernel_version(ssh)
+ ssh.execute.assert_called_once_with("uname -a")
+
+ def test_get_sample_vnf_info(self, *args):
+ json_out = """
+ {"UDP_Replay": {
+ "branch_commit": "47123bfc1b3c0d0b01884aebbce1a3e09ad7ddb0",
+ "md5": "4577702f6d6848380bd912232a1b9ca5",
+ "path_vnf": "/opt/nsb_bin/UDP_Replay"
+ }
+ }"""
+ json_file = '/opt/nsb_bin/yardstick_sample_vnf.json'
+ ssh = mock.Mock()
+ ssh.execute.return_value = (0, json_out, "")
+ utils.get_sample_vnf_info(ssh, json_file)
diff --git a/yardstick/tests/unit/common/test_yaml_loader.py b/yardstick/tests/unit/common/test_yaml_loader.py
new file mode 100644
index 000000000..e621dcbc5
--- /dev/null
+++ b/yardstick/tests/unit/common/test_yaml_loader.py
@@ -0,0 +1,24 @@
+# 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.
+
+# yardstick: this file is copied from python-heatclient and slightly modified
+
+import unittest
+
+from yardstick.common import yaml_loader
+
+
+class TemplateFormatTestCase(unittest.TestCase):
+
+ def test_parse_to_value_exception(self):
+
+ self.assertEqual(yaml_loader.yaml_load("string"), u"string")
diff --git a/yardstick/tests/unit/dispatcher/__init__.py b/yardstick/tests/unit/dispatcher/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/dispatcher/__init__.py
diff --git a/yardstick/tests/unit/dispatcher/test_influxdb.py b/yardstick/tests/unit/dispatcher/test_influxdb.py
new file mode 100644
index 000000000..c844d4bbb
--- /dev/null
+++ b/yardstick/tests/unit/dispatcher/test_influxdb.py
@@ -0,0 +1,104 @@
+##############################################################################
+# Copyright (c) 2015 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
+##############################################################################
+
+# Unittest for yardstick.dispatcher.influxdb
+
+import mock
+import unittest
+
+from yardstick.dispatcher.influxdb import InfluxdbDispatcher
+from yardstick import _init_logging
+
+
+_init_logging()
+
+
+class InfluxdbDispatcherTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.data1 = {
+ "runner_id": 8921,
+ "context_cfg": {
+ "host": {
+ "ip": "10.229.43.154",
+ "key_filename":
+ "/root/yardstick/yardstick/resources/files"
+ "/yardstick_key",
+ "name": "kvm.LF",
+ "user": "root"
+ },
+ "target": {
+ "ipaddr": "10.229.44.134"
+ }
+ },
+ "scenario_cfg": {
+ "runner": {
+ "interval": 1,
+ "object": "yardstick.benchmark.scenarios.networking.ping"
+ ".Ping",
+ "output_filename": "/tmp/yardstick.out",
+ "runner_id": 8921,
+ "duration": 10,
+ "type": "Duration"
+ },
+ "host": "kvm.LF",
+ "type": "Ping",
+ "target": "10.229.44.134",
+ "sla": {
+ "action": "monitor",
+ "max_rtt": 10
+ },
+ "tc": "ping",
+ "task_id": "ea958583-c91e-461a-af14-2a7f9d7f79e7"
+ }
+ }
+ self.data2 = {
+ "benchmark": {
+ "timestamp": "1451478117.883505",
+ "errors": "",
+ "data": {
+ "rtt": 0.613
+ },
+ "sequence": 1
+ },
+ "runner_id": 8921
+ }
+
+ self.yardstick_conf = {'dispatcher_influxdb': {}}
+
+ @mock.patch('yardstick.dispatcher.influxdb.requests')
+ def test_record_result_data(self, mock_requests):
+ type(mock_requests.post.return_value).status_code = 204
+ influxdb = InfluxdbDispatcher(self.yardstick_conf)
+ data = {
+ 'status': 1,
+ 'result': {
+ 'criteria': 'PASS',
+ 'info': {
+ },
+ 'task_id': 'b9e2bbc2-dfd8-410d-8c24-07771e9f7979',
+ 'testcases': {
+ }
+ }
+ }
+ self.assertEqual(influxdb.flush_result_data(data), 0)
+
+ def test__get_nano_timestamp(self):
+ influxdb = InfluxdbDispatcher(self.yardstick_conf)
+ results = {'timestamp': '1451461248.925574'}
+ self.assertEqual(influxdb._get_nano_timestamp(results),
+ '1451461248925574144')
+
+ @mock.patch('yardstick.dispatcher.influxdb.time')
+ def test__get_nano_timestamp_except(self, mock_time):
+ results = {}
+ influxdb = InfluxdbDispatcher(self.yardstick_conf)
+ mock_time.time.return_value = 1451461248.925574
+ self.assertEqual(influxdb._get_nano_timestamp(results),
+ '1451461248925574144')
diff --git a/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py
new file mode 100644
index 000000000..641e97fae
--- /dev/null
+++ b/yardstick/tests/unit/dispatcher/test_influxdb_line_protocol.py
@@ -0,0 +1,63 @@
+##############################################################################
+# Copyright (c) 2017 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
+##############################################################################
+# Unittest for yardstick.dispatcher.influxdb_line_protocol
+
+# yardstick comment: this file is a modified copy of
+# influxdb-python/influxdb/tests/test_line_protocol.py
+
+import unittest
+from third_party.influxdb.influxdb_line_protocol import make_lines
+
+
+class TestLineProtocol(unittest.TestCase):
+
+ def test_make_lines(self):
+ data = {
+ "tags": {
+ "empty_tag": "",
+ "none_tag": None,
+ "integer_tag": 2,
+ "string_tag": "hello"
+ },
+ "points": [
+ {
+ "measurement": "test",
+ "fields": {
+ "string_val": "hello!",
+ "int_val": 1,
+ "float_val": 1.1,
+ "none_field": None,
+ "bool_val": True,
+ }
+ }
+ ]
+ }
+
+ self.assertEqual(
+ make_lines(data),
+ 'test,integer_tag=2,string_tag=hello '
+ 'bool_val=True,float_val=1.1,int_val=1i,string_val="hello!"\n'
+ )
+
+ def test_string_val_newline(self):
+ data = {
+ "points": [
+ {
+ "measurement": "m1",
+ "fields": {
+ "multi_line": "line1\nline1\nline3"
+ }
+ }
+ ]
+ }
+
+ self.assertEqual(
+ make_lines(data),
+ 'm1 multi_line="line1\\nline1\\nline3"\n'
+ )
diff --git a/yardstick/tests/unit/network_services/__init__.py b/yardstick/tests/unit/network_services/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/__init__.py
diff --git a/yardstick/tests/unit/network_services/collector/__init__.py b/yardstick/tests/unit/network_services/collector/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/collector/__init__.py
diff --git a/yardstick/tests/unit/network_services/collector/test_publisher.py b/yardstick/tests/unit/network_services/collector/test_publisher.py
new file mode 100644
index 000000000..145441ddd
--- /dev/null
+++ b/yardstick/tests/unit/network_services/collector/test_publisher.py
@@ -0,0 +1,36 @@
+# 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.
+#
+
+import unittest
+
+from yardstick.network_services.collector import publisher
+
+
+class PublisherTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.test_publisher = publisher.Publisher()
+
+ def test_successful_init(self):
+ pass
+
+ def test_unsuccessful_init(self):
+ pass
+
+ def test_start(self):
+ self.assertIsNone(self.test_publisher.start())
+
+ def test_stop(self):
+ self.assertIsNone(self.test_publisher.stop())
diff --git a/yardstick/tests/unit/network_services/collector/test_subscriber.py b/yardstick/tests/unit/network_services/collector/test_subscriber.py
new file mode 100644
index 000000000..cffa4d492
--- /dev/null
+++ b/yardstick/tests/unit/network_services/collector/test_subscriber.py
@@ -0,0 +1,120 @@
+# 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.
+
+import copy
+import mock
+import unittest
+
+from yardstick.network_services.collector import subscriber
+from yardstick import ssh
+
+
+class MockVnfAprrox(object):
+
+ def __init__(self):
+ self.result = {}
+ self.name = "vnf__1"
+
+ def collect_kpi(self):
+ self.result = {
+ 'pkt_in_up_stream': 100,
+ 'pkt_drop_up_stream': 5,
+ 'pkt_in_down_stream': 50,
+ 'pkt_drop_down_stream': 40
+ }
+ return self.result
+
+
+class CollectorTestCase(unittest.TestCase):
+
+ NODES = {
+ 'context1': [{'name': 'node1',
+ 'ip': '1.2.3.4',
+ 'collectd': {
+ 'plugins': {'abc': 12, 'def': 34},
+ 'interval': 987}
+ }
+ ]
+ }
+
+ def setUp(self):
+ vnf = MockVnfAprrox()
+ vnf.start_collect = mock.Mock()
+ vnf.stop_collect = mock.Mock()
+ self.ssh_patch = mock.patch.object(ssh, 'AutoConnectSSH')
+ mock_ssh = self.ssh_patch.start()
+ mock_instance = mock.Mock()
+ mock_instance.execute.return_value = 0, '', ''
+ mock_ssh.from_node.return_value = mock_instance
+ self.collector = subscriber.Collector([vnf], self.NODES)
+
+ def tearDown(self):
+ self.ssh_patch.stop()
+
+ def test___init__(self, *args):
+ vnf = MockVnfAprrox()
+ collector = subscriber.Collector([vnf], self.NODES)
+ self.assertEqual(len(collector.vnfs), 1)
+ self.assertEqual(len(collector.nodes), 1)
+
+ def test___init__no_node_information(self, *args):
+ vnf = MockVnfAprrox()
+ nodes = copy.deepcopy(self.NODES)
+ nodes['context1'].append(None)
+ collector = subscriber.Collector([vnf], nodes)
+ self.assertEqual(len(collector.vnfs), 1)
+ self.assertEqual(len(collector.nodes), 1)
+
+ def test___init__no_node_information_in_context(self, *args):
+ vnf = MockVnfAprrox()
+ nodes = copy.deepcopy(self.NODES)
+ nodes['context1'] = None
+ collector = subscriber.Collector([vnf], nodes)
+ self.assertEqual(len(collector.vnfs), 1)
+ self.assertEqual(len(collector.nodes), 1)
+
+ def test_start(self, *args):
+ resource_profile = mock.MagicMock()
+ self.collector.resource_profiles = {'key': resource_profile}
+ self.collector.bin_path = 'path'
+
+ self.assertIsNone(self.collector.start())
+ for vnf in self.collector.vnfs:
+ vnf.start_collect.assert_called_once()
+
+ for resource_profile in self.collector.resource_profiles.values():
+ resource_profile.initiate_systemagent.assert_called_once_with('path')
+ resource_profile.start.assert_called_once()
+ resource_profile.amqp_process_for_nfvi_kpi.assert_called_once()
+
+ def test_stop(self, *_):
+ resource_profile = mock.MagicMock()
+ self.collector.resource_profiles = {'key': resource_profile}
+
+ self.assertIsNone(self.collector.stop())
+ for vnf in self.collector.vnfs:
+ vnf.stop_collect.assert_called_once()
+
+ for resource in self.collector.resource_profiles.values():
+ resource.stop.assert_called_once()
+
+ def test_get_kpi(self, *args):
+ result = self.collector.get_kpi()
+
+ self.assertEqual(2, len(result))
+ self.assertEqual(4, len(result["vnf__1"]))
+ self.assertEqual(result["vnf__1"]["pkt_in_up_stream"], 100)
+ self.assertEqual(result["vnf__1"]["pkt_drop_up_stream"], 5)
+ self.assertEqual(result["vnf__1"]["pkt_in_down_stream"], 50)
+ self.assertEqual(result["vnf__1"]["pkt_drop_down_stream"], 40)
diff --git a/yardstick/tests/unit/network_services/helpers/__init__.py b/yardstick/tests/unit/network_services/helpers/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/__init__.py
diff --git a/yardstick/tests/unit/network_services/helpers/acl_vnf_topology_ixia.yaml b/yardstick/tests/unit/network_services/helpers/acl_vnf_topology_ixia.yaml
new file mode 100644
index 000000000..f60834fbd
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/acl_vnf_topology_ixia.yaml
@@ -0,0 +1,50 @@
+# 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.
+
+nsd:nsd-catalog:
+ nsd:
+ - id: VACL
+ name: VACL
+ short-name: VACL
+ description: scenario with VACL,L3fwd and VNF
+ constituent-vnfd:
+ - member-vnf-index: '1'
+ vnfd-id-ref: tg__1
+ VNF model: ../../vnf_descriptors/ixia_rfc2544_tpl.yaml
+ - member-vnf-index: '2'
+ vnfd-id-ref: vnf__1
+ VNF model: ../../vnf_descriptors/acl_vnf.yaml
+
+ vld:
+ - id: uplink_1
+ name: tg__1 to vnf__1 link 1
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: tg__1 #TREX
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe0
+ vnfd-id-ref: vnf__1 #VNF
+
+ - id: downlink_1
+ name: vnf__1 to tg__1 link 2
+ type: ELAN
+ vnfd-connection-point-ref:
+ - member-vnf-index-ref: '2'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: vnf__1 #L3fwd
+ - member-vnf-index-ref: '1'
+ vnfd-connection-point-ref: xe1
+ vnfd-id-ref: tg__1 #VACL VNF
diff --git a/yardstick/tests/unit/network_services/helpers/test_cpu.py b/yardstick/tests/unit/network_services/helpers/test_cpu.py
new file mode 100644
index 000000000..a1c0826fb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/test_cpu.py
@@ -0,0 +1,215 @@
+# 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.
+#
+
+from __future__ import division
+import unittest
+import mock
+import subprocess
+
+from yardstick.network_services.helpers.cpu import \
+ CpuSysCores
+
+
+class TestCpuSysCores(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_ssh = mock.patch("yardstick.ssh.SSH")
+ self.mock_ssh = self._mock_ssh.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_ssh.stop()
+
+ def test___init__(self):
+ self.mock_ssh.execute.return_value = 1, "", ""
+ self.mock_ssh.put.return_value = 1, "", ""
+ cpu_topo = CpuSysCores(self.mock_ssh)
+ self.assertIsNotNone(cpu_topo.connection)
+
+ def test__get_core_details(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ lines = ["cpu:1", "topo:2", ""]
+ self.assertEqual([{'topo': '2', 'cpu': '1'}],
+ cpu_topo._get_core_details(lines))
+
+ def test_get_core_socket(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "cpu:1\ntest:2\n \n", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ cpu_topo._get_core_details = \
+ mock.Mock(side_effect=[[{'Core(s) per socket': '2', 'Thread(s) per core': '1'}],
+ [{'physical id': '2', 'processor': '1'}]])
+ self.assertEqual({'thread_per_core': '1', '2': ['1'],
+ 'cores_per_socket': '2'},
+ cpu_topo.get_core_socket())
+
+ def test_validate_cpu_cfg(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "cpu:1\ntest:2\n \n", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ cpu_topo._get_core_details = \
+ mock.Mock(side_effect=[[{'Core(s) per socket': '2', 'Thread(s) per core': '1'}],
+ [{'physical id': '2', 'processor': '1'}]])
+ cpu_topo.core_map = \
+ {'thread_per_core': '1', '2': ['1'], 'cores_per_socket': '2'}
+ self.assertEqual(-1, cpu_topo.validate_cpu_cfg())
+
+ def test_validate_cpu_cfg_2t(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "cpu:1\ntest:2\n \n", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ cpu_topo._get_core_details = \
+ mock.Mock(side_effect=[[{'Core(s) per socket': '2', 'Thread(s) per core': '1'}],
+ [{'physical id': '2', 'processor': '1'}]])
+ cpu_topo.core_map = \
+ {'thread_per_core': 1, '2': ['1'], 'cores_per_socket': '2'}
+ vnf_cfg = {'lb_config': 'SW', 'lb_count': 1, 'worker_config':
+ '1C/2T', 'worker_threads': 1}
+ self.assertEqual(-1, cpu_topo.validate_cpu_cfg(vnf_cfg))
+
+ def test_validate_cpu_cfg_fail(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, "cpu:1\ntest:2\n \n", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ cpu_topo._get_core_details = \
+ mock.Mock(side_effect=[[{'Core(s) per socket': '2', 'Thread(s) per core': '1'}],
+ [{'physical id': '2', 'processor': '1'}]])
+ cpu_topo.core_map = \
+ {'thread_per_core': 1, '2': [1], 'cores_per_socket': 2}
+ vnf_cfg = {'lb_config': 'SW', 'lb_count': 1, 'worker_config':
+ '1C/1T', 'worker_threads': 1}
+ self.assertEqual(-1, cpu_topo.validate_cpu_cfg(vnf_cfg))
+
+ def test_get_cpu_layout(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(
+ return_value=(1, "# CPU,Core,Socket,Node,,L1d,L1i,L2,L3\n'"
+ "0,0,0,0,,0,0,0,0\n"
+ "1,1,0,0,,1,1,1,0\n", ""))
+ ssh_mock.put = \
+ mock.Mock(return_value=(1, "", ""))
+ cpu_topo = CpuSysCores(ssh_mock)
+ subprocess.check_output = mock.Mock(return_value=0)
+ self.assertEqual({'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]},
+ cpu_topo.get_cpu_layout())
+
+ def test__str2int(self):
+ self.assertEqual(1, CpuSysCores._str2int("1"))
+
+ def test__str2int_error(self):
+ self.assertEqual(0, CpuSysCores._str2int("err"))
+
+ def test_smt_enabled(self):
+ self.assertEqual(False, CpuSysCores.smt_enabled(
+ {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}))
+
+ def test_is_smt_enabled(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ self.assertEqual(False, cpu_topo.is_smt_enabled())
+
+ def test_cpu_list_per_node(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ self.assertEqual([0, 1], cpu_topo.cpu_list_per_node(0, False))
+
+ def test_cpu_list_per_node_error(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'err': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ with self.assertRaises(RuntimeError) as raised:
+ cpu_topo.cpu_list_per_node(0, False)
+ self.assertIn('Node cpuinfo not available.', str(raised.exception))
+
+ def test_cpu_list_per_node_smt_error(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ with self.assertRaises(RuntimeError) as raised:
+ cpu_topo.cpu_list_per_node(0, True)
+ self.assertIn('SMT is not enabled.', str(raised.exception))
+
+ def test_cpu_slice_of_list_per_node(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ self.assertEqual([1],
+ cpu_topo.cpu_slice_of_list_per_node(0, 1, 0,
+ False))
+
+ def test_cpu_slice_of_list_per_node_error(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ with self.assertRaises(RuntimeError) as raised:
+ cpu_topo.cpu_slice_of_list_per_node(1, 1, 1, False)
+ self.assertIn('cpu_cnt + skip_cnt > length(cpu list).',
+ str(raised.exception))
+
+ def test_cpu_list_per_node_str(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ cpu_topo = CpuSysCores(ssh_mock)
+ cpu_topo.cpuinfo = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 1, 0, 0, 0, 1, 1, 1, 0]]}
+ self.assertEqual("1",
+ cpu_topo.cpu_list_per_node_str(0, 1, 1, ',',
+ False))
diff --git a/yardstick/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py b/yardstick/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py
new file mode 100644
index 000000000..e19311613
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/test_dpdkbindnic_helper.py
@@ -0,0 +1,632 @@
+# 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.
+
+import mock
+import unittest
+
+import os
+
+from yardstick.common import exceptions
+from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkInterface
+from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkNode
+from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelper
+from yardstick.network_services.helpers.dpdkbindnic_helper import DpdkBindHelperException
+from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_KERNEL
+from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_DPDK
+from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_KERNEL
+from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_DPDK
+from yardstick.network_services.helpers.dpdkbindnic_helper import NETWORK_OTHER
+from yardstick.network_services.helpers.dpdkbindnic_helper import CRYPTO_OTHER
+
+
+NAME = "tg_0"
+
+
+class TestDpdkInterface(unittest.TestCase):
+
+ SAMPLE_NETDEVS = {
+ 'enp11s0': {
+ 'address': '0a:de:ad:be:ef:f5',
+ 'device': '0x1533',
+ 'driver': 'igb',
+ 'ifindex': '2',
+ 'interface_name': 'enp11s0',
+ 'operstate': 'down',
+ 'pci_bus_id': '0000:0b:00.0',
+ 'subsystem_device': '0x1533',
+ 'subsystem_vendor': '0x15d9',
+ 'vendor': '0x8086'
+ },
+ 'lan': {
+ 'address': '0a:de:ad:be:ef:f4',
+ 'device': '0x153a',
+ 'driver': 'e1000e',
+ 'ifindex': '3',
+ 'interface_name': 'lan',
+ 'operstate': 'up',
+ 'pci_bus_id': '0000:00:19.0',
+ 'subsystem_device': '0x153a',
+ 'subsystem_vendor': '0x15d9',
+ 'vendor': '0x8086'
+ }
+ }
+
+ SAMPLE_VM_NETDEVS = {
+ 'eth1': {
+ 'address': 'fa:de:ad:be:ef:5b',
+ 'device': '0x0001',
+ 'driver': 'virtio_net',
+ 'ifindex': '3',
+ 'interface_name': 'eth1',
+ 'operstate': 'down',
+ 'pci_bus_id': '0000:00:04.0',
+ 'vendor': '0x1af4'
+ }
+ }
+
+ def test_parse_netdev_info(self):
+ output = """\
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/ifindex:2
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/address:0a:de:ad:be:ef:f5
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/operstate:down
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/vendor:0x8086
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/device:0x1533
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_vendor:0x15d9
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/device/subsystem_device:0x1533
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/driver:igb
+/sys/devices/pci0000:00/0000:00:1c.3/0000:0b:00.0/net/enp11s0/pci_bus_id:0000:0b:00.0
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/ifindex:3
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/address:0a:de:ad:be:ef:f4
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/operstate:up
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/vendor:0x8086
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/device:0x153a
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_vendor:0x15d9
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/device/subsystem_device:0x153a
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/driver:e1000e
+/sys/devices/pci0000:00/0000:00:19.0/net/lan/pci_bus_id:0000:00:19.0
+"""
+ res = DpdkBindHelper.parse_netdev_info(output)
+ self.assertDictEqual(res, self.SAMPLE_NETDEVS)
+
+ def test_parse_netdev_info_virtio(self):
+ output = """\
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/ifindex:3
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/address:fa:de:ad:be:ef:5b
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/operstate:down
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/vendor:0x1af4
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/device/device:0x0001
+/sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth1/driver:virtio_net
+"""
+ res = DpdkBindHelper.parse_netdev_info(output)
+ self.assertDictEqual(res, self.SAMPLE_VM_NETDEVS)
+
+ def test_probe_missing_values(self):
+ mock_dpdk_node = mock.Mock()
+ mock_dpdk_node.netdevs = self.SAMPLE_NETDEVS.copy()
+
+ interface = {'local_mac': '0a:de:ad:be:ef:f5'}
+ dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
+
+ dpdk_intf.probe_missing_values()
+ self.assertEqual(interface['vpci'], '0000:0b:00.0')
+
+ interface['local_mac'] = '0a:de:ad:be:ef:f4'
+ dpdk_intf.probe_missing_values()
+ self.assertEqual(interface['vpci'], '0000:00:19.0')
+
+ def test_probe_missing_values_no_update(self):
+ mock_dpdk_node = mock.Mock()
+ mock_dpdk_node.netdevs = self.SAMPLE_NETDEVS.copy()
+ del mock_dpdk_node.netdevs['enp11s0']['driver']
+ del mock_dpdk_node.netdevs['lan']['driver']
+
+ interface = {'local_mac': '0a:de:ad:be:ef:f5'}
+ dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
+
+ dpdk_intf.probe_missing_values()
+ self.assertNotIn('vpci', interface)
+ self.assertNotIn('driver', interface)
+
+ def test_probe_missing_values_negative(self):
+ mock_dpdk_node = mock.Mock()
+ mock_dpdk_node.netdevs.values.side_effect = (
+ exceptions.IncorrectNodeSetup(error_msg=''))
+
+ interface = {'local_mac': '0a:de:ad:be:ef:f5'}
+ dpdk_intf = DpdkInterface(mock_dpdk_node, interface)
+
+ with self.assertRaises(exceptions.IncorrectConfig):
+ dpdk_intf.probe_missing_values()
+
+
+class TestDpdkNode(unittest.TestCase):
+
+ INTERFACES = [
+ {'name': 'name1',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'pci10',
+ }},
+ {'name': 'name2',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'pci2',
+ }},
+ {'name': 'name3',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'some-pci1',
+ }},
+ ]
+
+ def test_probe_dpdk_drivers(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ interfaces = [
+ {'name': 'name1',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'pci10',
+ }},
+ {'name': 'name2',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'pci2',
+ }},
+ {'name': 'name3',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ 'vpci': 'some-pci1',
+ }},
+ ]
+
+ dpdk_node = DpdkNode(NAME, interfaces, mock_ssh_helper)
+ dpdk_helper = dpdk_node.dpdk_helper
+
+ dpdk_helper.probe_real_kernel_drivers = mock.Mock()
+ dpdk_helper.real_kernel_interface_driver_map = {
+ 'pci1': 'driver1',
+ 'pci2': 'driver2',
+ 'pci3': 'driver3',
+ 'pci4': 'driver1',
+ 'pci6': 'driver3',
+ }
+
+ dpdk_node._probe_dpdk_drivers()
+ self.assertNotIn('driver', interfaces[0]['virtual-interface'])
+ self.assertEqual(interfaces[1]['virtual-interface']['driver'], 'driver2')
+ self.assertEqual(interfaces[2]['virtual-interface']['driver'], 'driver1')
+
+ def test_check(self):
+ def update():
+ if not mock_force_rebind.called:
+ raise exceptions.IncorrectConfig(error_msg='')
+
+ interfaces[0]['virtual-interface'].update({
+ 'vpci': '0000:01:02.1',
+ 'local_ip': '10.20.30.40',
+ 'netmask': '255.255.0.0',
+ 'driver': 'ixgbe',
+ })
+
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ interfaces = [
+ {'name': 'name1',
+ 'virtual-interface': {
+ 'local_mac': 404,
+ }},
+ ]
+
+ dpdk_node = DpdkNode(NAME, interfaces, mock_ssh_helper)
+ dpdk_node._probe_missing_values = mock_probe_missing = mock.Mock(side_effect=update)
+ dpdk_node._force_rebind = mock_force_rebind = mock.Mock()
+
+ self.assertIsNone(dpdk_node.check())
+ self.assertEqual(mock_probe_missing.call_count, 2)
+
+ @mock.patch('yardstick.network_services.helpers.dpdkbindnic_helper.DpdkInterface')
+ def test_check_negative(self, mock_intf_type):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ mock_intf_type().check.side_effect = exceptions.SSHError
+
+ dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
+
+ with self.assertRaises(exceptions.IncorrectSetup):
+ dpdk_node.check()
+
+ def test_probe_netdevs(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ expected = {'key1': 500, 'key2': 'hello world'}
+ update = {'key1': 1000, 'key3': []}
+
+ dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
+ dpdk_helper = dpdk_node.dpdk_helper
+ dpdk_helper.find_net_devices = mock.Mock(side_effect=[expected, update])
+
+ self.assertDictEqual(dpdk_node.netdevs, {})
+ dpdk_node._probe_netdevs()
+ self.assertDictEqual(dpdk_node.netdevs, expected)
+
+ expected = {'key1': 1000, 'key2': 'hello world', 'key3': []}
+ dpdk_node._probe_netdevs()
+ self.assertDictEqual(dpdk_node.netdevs, expected)
+
+ def test_probe_netdevs_setup_negative(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
+ dpdk_helper = dpdk_node.dpdk_helper
+ dpdk_helper.find_net_devices = mock.Mock(side_effect=DpdkBindHelperException)
+
+ with self.assertRaises(DpdkBindHelperException):
+ dpdk_node._probe_netdevs()
+
+ def test_force_rebind(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ dpdk_node = DpdkNode(NAME, self.INTERFACES, mock_ssh_helper)
+ dpdk_helper = dpdk_node.dpdk_helper
+ dpdk_helper.force_dpdk_rebind = mock_helper_func = mock.Mock()
+
+ dpdk_node._force_rebind()
+ mock_helper_func.assert_called_once()
+
+
+class TestDpdkBindHelper(unittest.TestCase):
+ bin_path = "/opt/nsb_bin"
+ EXAMPLE_OUTPUT = """
+
+Network devices using DPDK-compatible driver
+============================================
+0000:00:04.0 'Virtio network device' drv=igb_uio unused=
+0000:00:05.0 'Virtio network device' drv=igb_uio unused=
+
+Network devices using kernel driver
+===================================
+0000:00:03.0 'Virtio network device' if=ens3 drv=virtio-pci unused=igb_uio *Active*
+
+Other network devices
+=====================
+<none>
+
+Crypto devices using DPDK-compatible driver
+===========================================
+<none>
+
+Crypto devices using kernel driver
+==================================
+<none>
+
+Other crypto devices
+====================
+<none>
+"""
+
+ PARSED_EXAMPLE = {
+ NETWORK_DPDK: [
+ {'active': False,
+ 'dev_type': 'Virtio network device',
+ 'driver': 'igb_uio',
+ 'iface': None,
+ 'unused': '',
+ 'vpci': '0000:00:04.0',
+ },
+ {'active': False,
+ 'dev_type': 'Virtio network device',
+ 'driver': 'igb_uio',
+ 'iface': None,
+ 'unused': '',
+ 'vpci': '0000:00:05.0',
+ }
+ ],
+ NETWORK_KERNEL: [
+ {'active': True,
+ 'dev_type': 'Virtio network device',
+ 'driver': 'virtio-pci',
+ 'iface': 'ens3',
+ 'unused': 'igb_uio',
+ 'vpci': '0000:00:03.0',
+ }
+ ],
+ CRYPTO_KERNEL: [],
+ CRYPTO_DPDK: [],
+ NETWORK_OTHER: [],
+ CRYPTO_OTHER: [],
+ }
+
+ CLEAN_STATUS = {
+ NETWORK_KERNEL: [],
+ NETWORK_DPDK: [],
+ CRYPTO_KERNEL: [],
+ CRYPTO_DPDK: [],
+ NETWORK_OTHER: [],
+ CRYPTO_OTHER: [],
+ }
+
+ ONE_INPUT_LINE = ("0000:00:03.0 'Virtio network device' if=ens3 "
+ "drv=virtio-pci unused=igb_uio *Active*")
+
+ ONE_INPUT_LINE_PARSED = [{
+ 'vpci': '0000:00:03.0',
+ 'dev_type': 'Virtio network device',
+ 'iface': 'ens3',
+ 'driver': 'virtio-pci',
+ 'unused': 'igb_uio',
+ 'active': True,
+ }]
+
+ def test___init__(self):
+ conn = mock.Mock()
+ conn.provision_tool = mock.Mock(return_value='path_to_tool')
+ conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ self.assertEqual(conn, dpdk_bind_helper.ssh_helper)
+ self.assertEqual(self.CLEAN_STATUS, dpdk_bind_helper.dpdk_status)
+ self.assertIsNone(dpdk_bind_helper.status_nic_row_re)
+ self.assertEqual(dpdk_bind_helper.dpdk_devbind,
+ os.path.join(self.bin_path, dpdk_bind_helper.DPDK_DEVBIND))
+ self.assertIsNone(dpdk_bind_helper._status_cmd_attr)
+
+ def test__dpdk_execute(self):
+ conn = mock.Mock()
+ conn.execute = mock.Mock(return_value=(0, 'output', 'error'))
+ conn.provision_tool = mock.Mock(return_value='tool_path')
+ dpdk_bind_helper = DpdkBindHelper(conn)
+ self.assertEqual((0, 'output', 'error'), dpdk_bind_helper._dpdk_execute('command'))
+
+ def test__dpdk_execute_failure(self):
+ conn = mock.Mock()
+ conn.execute = mock.Mock(return_value=(1, 'output', 'error'))
+ conn.provision_tool = mock.Mock(return_value='tool_path')
+ dpdk_bind_helper = DpdkBindHelper(conn)
+ with self.assertRaises(DpdkBindHelperException):
+ dpdk_bind_helper._dpdk_execute('command')
+
+ def test__addline(self):
+ conn = mock.Mock()
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ dpdk_bind_helper._add_line(NETWORK_KERNEL, self.ONE_INPUT_LINE)
+
+ self.assertIsNotNone(dpdk_bind_helper.dpdk_status)
+ self.assertEqual(self.ONE_INPUT_LINE_PARSED, dpdk_bind_helper.dpdk_status[NETWORK_KERNEL])
+
+ def test__switch_active_dict_by_header(self):
+ line = "Crypto devices using DPDK-compatible driver"
+ olddict = 'olddict'
+ self.assertEqual(CRYPTO_DPDK, DpdkBindHelper._switch_active_dict(line, olddict))
+
+ def test__switch_active_dict_by_header_empty(self):
+ line = "<none>"
+ olddict = 'olddict'
+ self.assertEqual(olddict, DpdkBindHelper._switch_active_dict(line, olddict))
+
+ def test_parse_dpdk_status_output(self):
+ conn = mock.Mock()
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+ self.maxDiff = None
+ self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.dpdk_status)
+
+ def test_kernel_bound_pci_addresses(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ expected = ['a', 'b', 3]
+
+ dpdk_helper = DpdkBindHelper(mock_ssh_helper)
+ dpdk_helper.dpdk_status = {
+ NETWORK_DPDK: [{'vpci': 4}, {'vpci': 5}, {'vpci': 'g'}],
+ NETWORK_KERNEL: [{'vpci': 'a'}, {'vpci': 'b'}, {'vpci': 3}],
+ CRYPTO_DPDK: [],
+ }
+
+ result = dpdk_helper.kernel_bound_pci_addresses
+ self.assertEqual(result, expected)
+
+ def test_find_net_devices_negative(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 1, 'error', 'debug'
+
+ dpdk_helper = DpdkBindHelper(mock_ssh_helper)
+
+ self.assertDictEqual(dpdk_helper.find_net_devices(), {})
+
+ def test_read_status(self):
+ conn = mock.Mock()
+ conn.execute = mock.Mock(return_value=(0, self.EXAMPLE_OUTPUT, ''))
+ conn.provision_tool = mock.Mock(return_value='path_to_tool')
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ self.assertEqual(self.PARSED_EXAMPLE, dpdk_bind_helper.read_status())
+
+ def test__get_bound_pci_addresses(self):
+ conn = mock.Mock()
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+ self.assertEqual(['0000:00:04.0', '0000:00:05.0'],
+ dpdk_bind_helper._get_bound_pci_addresses(NETWORK_DPDK))
+ self.assertEqual(['0000:00:03.0'],
+ dpdk_bind_helper._get_bound_pci_addresses(NETWORK_KERNEL))
+
+ def test_interface_driver_map(self):
+ conn = mock.Mock()
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ dpdk_bind_helper._parse_dpdk_status_output(self.EXAMPLE_OUTPUT)
+
+ self.assertEqual({'0000:00:04.0': 'igb_uio',
+ '0000:00:03.0': 'virtio-pci',
+ '0000:00:05.0': 'igb_uio',
+ },
+ dpdk_bind_helper.interface_driver_map)
+
+ def test_bind(self):
+ conn = mock.Mock()
+ conn.execute = mock.Mock(return_value=(0, '', ''))
+ conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+ dpdk_bind_helper.read_status = mock.Mock()
+
+ dpdk_bind_helper.bind(['0000:00:03.0', '0000:00:04.0'], 'my_driver')
+
+ conn.execute.assert_called_with('sudo /opt/nsb_bin/dpdk-devbind.py --force '
+ '-b my_driver 0000:00:03.0 0000:00:04.0')
+ dpdk_bind_helper.read_status.assert_called_once()
+
+ def test_bind_single_pci(self):
+ conn = mock.Mock()
+ conn.execute = mock.Mock(return_value=(0, '', ''))
+ conn.join_bin_path.return_value = os.path.join(self.bin_path, DpdkBindHelper.DPDK_DEVBIND)
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+ dpdk_bind_helper.read_status = mock.Mock()
+
+ dpdk_bind_helper.bind('0000:00:03.0', 'my_driver')
+
+ conn.execute.assert_called_with('sudo /opt/nsb_bin/dpdk-devbind.py --force '
+ '-b my_driver 0000:00:03.0')
+ dpdk_bind_helper.read_status.assert_called_once()
+
+ def test_rebind_drivers(self):
+ conn = mock.Mock()
+
+ dpdk_bind_helper = DpdkBindHelper(conn)
+
+ dpdk_bind_helper.bind = mock.Mock()
+ dpdk_bind_helper.used_drivers = {
+ 'd1': ['0000:05:00.0'],
+ 'd3': ['0000:05:01.0', '0000:05:02.0'],
+ }
+
+ dpdk_bind_helper.rebind_drivers()
+
+ dpdk_bind_helper.bind.assert_any_call(['0000:05:00.0'], 'd1', True)
+ dpdk_bind_helper.bind.assert_any_call(['0000:05:01.0', '0000:05:02.0'], 'd3', True)
+
+ def test_save_used_drivers(self):
+ conn = mock.Mock()
+ dpdk_bind_helper = DpdkBindHelper(conn)
+ dpdk_bind_helper.dpdk_status = self.PARSED_EXAMPLE
+
+ dpdk_bind_helper.save_used_drivers()
+
+ expected = {
+ 'igb_uio': ['0000:00:04.0', '0000:00:05.0'],
+ 'virtio-pci': ['0000:00:03.0'],
+ }
+
+ self.assertDictEqual(expected, dpdk_bind_helper.used_drivers)
+
+ def test_force_dpdk_rebind(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ dpdk_helper = DpdkBindHelper(mock_ssh_helper, 'driver2')
+ dpdk_helper.dpdk_status = {
+ NETWORK_DPDK: [
+ {
+ 'vpci': 'pci1',
+ },
+ {
+ 'vpci': 'pci3',
+ },
+ {
+ 'vpci': 'pci6',
+ },
+ {
+ 'vpci': 'pci3',
+ },
+ ]
+ }
+ dpdk_helper.real_kernel_interface_driver_map = {
+ 'pci1': 'real_driver1',
+ 'pci2': 'real_driver2',
+ 'pci3': 'real_driver1',
+ 'pci4': 'real_driver4',
+ 'pci6': 'real_driver6',
+ }
+ dpdk_helper.load_dpdk_driver = mock.Mock()
+ dpdk_helper.read_status = mock.Mock()
+ dpdk_helper.save_real_kernel_interface_driver_map = mock.Mock()
+ dpdk_helper.save_used_drivers = mock.Mock()
+ dpdk_helper.bind = mock_bind = mock.Mock()
+
+ dpdk_helper.force_dpdk_rebind()
+ self.assertEqual(mock_bind.call_count, 2)
+
+ def test_save_real_kernel_drivers(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.return_value = 0, '', ''
+
+ dpdk_helper = DpdkBindHelper(mock_ssh_helper)
+ dpdk_helper.real_kernel_drivers = {
+ 'abc': '123',
+ }
+ dpdk_helper.real_kernel_interface_driver_map = {
+ 'abc': 'AAA',
+ 'def': 'DDD',
+ 'abs': 'AAA',
+ 'ghi': 'GGG',
+ }
+
+ # save_used_drivers must be called before save_real_kernel_drivers can be
+ with self.assertRaises(AttributeError):
+ dpdk_helper.save_real_kernel_drivers()
+
+ dpdk_helper.save_used_drivers()
+
+ expected_used_drivers = {
+ 'AAA': ['abc', 'abs'],
+ 'DDD': ['def'],
+ 'GGG': ['ghi'],
+ }
+ dpdk_helper.save_real_kernel_drivers()
+ self.assertDictEqual(dpdk_helper.used_drivers, expected_used_drivers)
+ self.assertDictEqual(dpdk_helper.real_kernel_drivers, {})
+
+ def test_get_real_kernel_driver(self):
+ mock_ssh_helper = mock.Mock()
+ mock_ssh_helper.execute.side_effect = [
+ (0, 'non-matching text', ''),
+ (0, 'pre Kernel modules: real_driver1', ''),
+ (0, 'before Ethernet middle Virtio network device after', ''),
+ ]
+
+ dpdk_helper = DpdkBindHelper(mock_ssh_helper)
+
+ self.assertIsNone(dpdk_helper.get_real_kernel_driver('abc'))
+ self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), 'real_driver1')
+ self.assertEqual(dpdk_helper.get_real_kernel_driver('abc'), DpdkBindHelper.VIRTIO_DRIVER)
diff --git a/yardstick/tests/unit/network_services/helpers/test_iniparser.py b/yardstick/tests/unit/network_services/helpers/test_iniparser.py
new file mode 100644
index 000000000..1a09f0761
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/test_iniparser.py
@@ -0,0 +1,223 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import unittest
+from contextlib import contextmanager
+import mock
+
+from yardstick.tests import STL_MOCKS
+
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.helpers.iniparser import ParseError
+ from yardstick.network_services.helpers.iniparser import LineParser
+ from yardstick.network_services.helpers.iniparser import BaseParser
+ from yardstick.network_services.helpers.iniparser import ConfigParser
+
+PARSE_TEXT_1 = """\
+
+[section1]
+key1=value1
+list1: value2
+ value3
+ value4
+key3='single quote value' ; comment here
+key4=
+
+[section2] ; comment with #2 other symbol
+# here is a comment line
+list2: value5
+key with no value # mixed comment ; symbols
+; another comment line
+key5=
+
+[section1] ; reopen a section!
+key2="double quote value"
+"""
+
+PARSE_TEXT_2 = """\
+[section1]
+list1 = item1
+ item2
+ ended by eof"""
+
+PARSE_TEXT_BAD_1 = """\
+key1=value1
+"""
+
+PARSE_TEXT_BAD_2 = """\
+[section1
+"""
+
+PARSE_TEXT_BAD_3 = """\
+[]
+"""
+
+PARSE_TEXT_BAD_4 = """\
+[section1]
+ bad continuation
+"""
+
+PARSE_TEXT_BAD_5 = """\
+[section1]
+=value with no key
+"""
+
+
+class TestParseError(unittest.TestCase):
+
+ def test___str__(self):
+ error = ParseError('a', 2, 'c')
+ self.assertEqual(str(error), "at line 2, a: 'c'")
+
+
+class TestLineParser(unittest.TestCase):
+
+ def test___repr__(self):
+ line_parser = LineParser('', 101)
+ self.assertIsNotNone(repr(line_parser))
+
+ def test_error_invalid_assignment(self):
+ line_parser = LineParser('', 101)
+ self.assertIsNotNone(line_parser.error_invalid_assignment())
+
+
+class TestBaseParser(unittest.TestCase):
+
+ @staticmethod
+ def make_open(text_blob):
+ @contextmanager
+ def internal_open(*args):
+ yield text_blob.split('\n')
+
+ return internal_open
+
+ def test_parse(self):
+ parser = BaseParser()
+ parser.parse()
+
+ def test_parse_empty_string(self):
+ parser = BaseParser()
+ self.assertIsNone(parser.parse(''))
+
+ def test_not_implemented_methods(self):
+ parser = BaseParser()
+
+ with self.assertRaises(NotImplementedError):
+ parser.assignment('key', 'value', LineParser('', 100))
+
+ with self.assertRaises(NotImplementedError):
+ parser.new_section('section')
+
+ with self.assertRaises(NotImplementedError):
+ parser.comment('comment')
+
+
+class TestConfigParser(unittest.TestCase):
+
+ @staticmethod
+ def make_open(text_blob):
+ @contextmanager
+ def internal_open(*args):
+ yield text_blob.split('\n')
+
+ return internal_open
+
+ @mock.patch('yardstick.network_services.helpers.iniparser.open')
+ def test_parse(self, mock_open):
+ mock_open.side_effect = self.make_open(PARSE_TEXT_1)
+
+ existing_data = [['section0', [['key0', 'value0']]]]
+ config_parser = ConfigParser('my_file', existing_data)
+ config_parser.parse()
+
+ expected = [
+ [
+ 'section0',
+ [
+ ['key0', 'value0'],
+ ],
+ ],
+ [
+ 'section1',
+ [
+ ['key1', 'value1'],
+ ['list1', 'value2\nvalue3\nvalue4'],
+ ['key3', 'single quote value'],
+ ['key4', ''],
+ ['key2', 'double quote value'],
+ ],
+ ],
+ [
+ 'section2',
+ [
+ ['list2', 'value5'],
+ ['key with no value', '@'],
+ ['key5', ''],
+ ],
+ ],
+ ]
+
+ self.assertEqual(config_parser.sections, expected)
+ self.assertIsNotNone(config_parser.find_section('section1'))
+ self.assertIsNone(config_parser.find_section('section3'))
+ self.assertEqual(config_parser.find_section_index('section1'), 1)
+ self.assertEqual(config_parser.find_section_index('section3'), -1)
+
+ @mock.patch('yardstick.network_services.helpers.iniparser.open')
+ def test_parse_2(self, mock_open):
+ mock_open.side_effect = self.make_open(PARSE_TEXT_2)
+
+ config_parser = ConfigParser('my_file')
+ config_parser.parse()
+
+ expected = [
+ [
+ 'section1',
+ [
+ ['list1', 'item1\nitem2\nended by eof'],
+ ],
+ ],
+ ]
+
+ self.assertEqual(config_parser.sections, expected)
+
+ @mock.patch('yardstick.network_services.helpers.iniparser.open')
+ def test_parse_negative(self, mock_open):
+ bad_text_dict = {
+ 'no section': PARSE_TEXT_BAD_1,
+ 'incomplete section': PARSE_TEXT_BAD_2,
+ 'empty section name': PARSE_TEXT_BAD_3,
+ 'bad_continuation': PARSE_TEXT_BAD_4,
+ 'value with no key': PARSE_TEXT_BAD_5,
+ }
+
+ for bad_reason, bad_text in bad_text_dict.items():
+ mock_open.side_effect = self.make_open(bad_text)
+
+ config_parser = ConfigParser('my_file', [])
+
+ try:
+ # TODO: replace with assertRaises, when the UT framework supports
+ # advanced messages when exceptions fail to occur
+ config_parser.parse()
+ except ParseError:
+ pass
+ else:
+ self.fail('\n'.join([bad_reason, bad_text, str(config_parser.sections)]))
diff --git a/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py b/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
new file mode 100644
index 000000000..e66e7fbb8
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/test_samplevnf_helper.py
@@ -0,0 +1,1044 @@
+# 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.
+#
+
+import mock
+import os
+import six
+import unittest
+
+from yardstick.network_services.helpers import samplevnf_helper
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+
+
+class TestPortPairs(unittest.TestCase):
+ def test_port_pairs_list(self):
+ vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ interfaces = vnfd['vdu'][0]['external-interface']
+ port_pairs = samplevnf_helper.PortPairs(interfaces)
+ self.assertEqual(port_pairs.port_pair_list, [("xe0", "xe1")])
+
+ def test_valid_networks(self):
+ vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ interfaces = vnfd['vdu'][0]['external-interface']
+ port_pairs = samplevnf_helper.PortPairs(interfaces)
+ self.assertEqual(port_pairs.valid_networks, [
+ ("uplink_0", "downlink_0")])
+
+ def test_all_ports(self):
+ vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ interfaces = vnfd['vdu'][0]['external-interface']
+ port_pairs = samplevnf_helper.PortPairs(interfaces)
+ self.assertEqual(set(port_pairs.all_ports), {"xe0", "xe1"})
+
+ def test_uplink_ports(self):
+ vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ interfaces = vnfd['vdu'][0]['external-interface']
+ port_pairs = samplevnf_helper.PortPairs(interfaces)
+ self.assertEqual(port_pairs.uplink_ports, ["xe0"])
+
+ def test_downlink_ports(self):
+ vnfd = TestMultiPortConfig.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ interfaces = vnfd['vdu'][0]['external-interface']
+ port_pairs = samplevnf_helper.PortPairs(interfaces)
+ self.assertEqual(port_pairs.downlink_ports, ["xe1"])
+
+
+class TestMultiPortConfig(unittest.TestCase):
+
+ VNFD_0 = {'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [
+ {'virtual-interface':
+ {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'ifname': 'xe0',
+ 'local_iface_name': 'eth0',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vld_id': 'uplink_0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'ifname': 'xe1',
+ 'local_iface_name': 'eth1',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vld_id': 'downlink_0',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}
+ ]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'AclApproxVnf', 'name': 'VPEVnfSsh'}
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ]
+ }
+ }
+
+ def setUp(self):
+ self._mock_open = mock.patch.object(six.moves.builtins, 'open')
+ self.mock_open = self._mock_open.start()
+ self._mock_config_parser = mock.patch.object(
+ samplevnf_helper, 'ConfigParser')
+ self.mock_config_parser = self._mock_config_parser.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_open.stop()
+ self._mock_config_parser.stop()
+
+ def test_validate_ip_and_prefixlen(self):
+ ip_addr, prefix_len = (
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
+ '10.20.30.40', '16'))
+ self.assertEqual(ip_addr, '10.20.30.40')
+ self.assertEqual(prefix_len, 16)
+
+ ip_addr, prefix_len = (
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
+ '::1', '40'))
+ self.assertEqual(ip_addr, '0000:0000:0000:0000:0000:0000:0000:0001')
+ self.assertEqual(prefix_len, 40)
+
+ def test_validate_ip_and_prefixlen_negative(self):
+ with self.assertRaises(AttributeError):
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen('', '')
+
+ with self.assertRaises(AttributeError):
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
+ '10.20.30.400', '16')
+
+ with self.assertRaises(AttributeError):
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
+ '10.20.30.40', '33')
+
+ with self.assertRaises(AttributeError):
+ samplevnf_helper.MultiPortConfig.validate_ip_and_prefixlen(
+ '::1', '129')
+
+ @mock.patch.object(os.path, 'isfile', return_value=False)
+ def test___init__(self, *args):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ self.assertEqual(0, opnfv_vnf.swq)
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ self.assertEqual(0, opnfv_vnf.swq)
+
+ def test_update_timer(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ self.assertIsNone(opnfv_vnf.update_timer())
+
+ def test_generate_script(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = VnfdHelper(self.VNFD_0)
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'arp_route_tbl': '', 'arp_route_tbl6': '',
+ 'flows': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
+ opnfv_vnf.lb_config = 'HW'
+ self.assertIsNotNone(opnfv_vnf.generate_script(self.VNFD))
+
+ def test_generate_script_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.vnf_type = 'ACL'
+ opnfv_vnf.generate_link_config = mock.Mock()
+ opnfv_vnf.generate_arp_config = mock.Mock()
+ opnfv_vnf.generate_arp_config6 = mock.Mock()
+ opnfv_vnf.generate_action_config = mock.Mock()
+ opnfv_vnf.generate_rule_config = mock.Mock()
+ self.assertIsNotNone(opnfv_vnf.generate_script_data())
+
+ def test_generate_arp_config6(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
+ opnfv_vnf.get_netmask_gateway = mock.Mock(
+ return_value=u'255.255.255.0')
+ opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
+ opnfv_vnf.get_netmask_gateway6 = mock.Mock(
+ return_value=u'255.255.255.0')
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ self.assertIsNotNone(opnfv_vnf.generate_arp_config6())
+
+ def test_generate_arp_config(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.get_ports_gateway = mock.Mock(return_value=u'1.1.1.1')
+ opnfv_vnf.get_netmask_gateway = mock.Mock(
+ return_value=u'255.255.255.0')
+ opnfv_vnf.get_ports_gateway6 = mock.Mock(return_value=u'1.1.1.1')
+ opnfv_vnf.get_netmask_gateway6 = mock.Mock(
+ return_value=u'255.255.255.0')
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ self.assertIsNotNone(opnfv_vnf.generate_arp_config())
+
+ def test_get_ports_gateway(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.assertIsNotNone(opnfv_vnf.get_ports_gateway('xe0'))
+
+ def test_get_ports_gateway6(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.assertIsNotNone(opnfv_vnf.get_ports_gateway6('xe0'))
+
+ def test_get_netmask_gateway(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.assertIsNotNone(opnfv_vnf.get_netmask_gateway('xe0'))
+
+ def test_get_netmask_gateway6(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.interfaces = mock.MagicMock()
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.assertIsNotNone(opnfv_vnf.get_netmask_gateway6('xe0'))
+
+ def test_generate_link_config(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.get_port_pairs = mock.Mock()
+ opnfv_vnf.vnf_type = 'VFW'
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.all_ports = ['32', '1', '987']
+ opnfv_vnf.validate_ip_and_prefixlen = mock.Mock(
+ return_value=('10.20.30.40', 16))
+
+ result = opnfv_vnf.generate_link_config()
+ self.assertEqual(len(result.splitlines()), 9)
+
+ def test_generate_config(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.get_config_tpl_data = mock.MagicMock()
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.update_write_parser = mock.MagicMock()
+ opnfv_vnf.generate_script_data = \
+ mock.Mock(return_value={'link_config': 0, 'arp_config': '',
+ 'arp_config6': '', 'actions': '',
+ 'rules': ''})
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.get_ports_gateway6 = mock.Mock()
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.generate_lb_to_port_pair_mapping = mock.Mock()
+ opnfv_vnf.generate_config_data = mock.Mock()
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.is_openstack = True
+ self.assertIsNone(opnfv_vnf.generate_config())
+ opnfv_vnf.is_openstack = False
+ self.assertIsNone(opnfv_vnf.generate_config())
+
+ def test_get_config_tpl_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=True)
+ opnfv_vnf.read_parser.get = mock.Mock(return_value='filename')
+
+ self.assertIsNotNone(opnfv_vnf.get_config_tpl_data('filename'))
+
+ def test_get_txrx_tpl_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=True)
+ opnfv_vnf.read_parser.get = mock.Mock(return_value='filename')
+
+ self.assertIsNotNone(opnfv_vnf.get_txrx_tpl_data('filename'))
+
+ def test_init_write_parser_template(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=True)
+ opnfv_vnf.read_parser.get = mock.Mock(return_value='filename')
+
+ self.assertIsNone(opnfv_vnf.init_write_parser_template('filename'))
+ opnfv_vnf.write_parser.add_section = mock.MagicMock()
+ opnfv_vnf.read_parser.item = mock.Mock(return_value=[1, 2, 3])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=False)
+ opnfv_vnf.write_parser.set = mock.Mock()
+ self.assertIsNone(opnfv_vnf.init_write_parser_template('filename'))
+
+ def test_init_write_parser_template_2(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ self.assertIsNone(opnfv_vnf.init_write_parser_template('filename'))
+
+ def test_update_write_parser(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ self.assertIsNone(opnfv_vnf.update_write_parser({'filename': 1}))
+
+ def test_get_worker_threads(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ result = opnfv_vnf.get_worker_threads(1)
+ self.assertEqual(1, result)
+ opnfv_vnf.worker_config = '2t'
+ result = opnfv_vnf.get_worker_threads(2)
+ self.assertEqual(2, result)
+ opnfv_vnf.worker_config = '2t'
+ result = opnfv_vnf.get_worker_threads(3)
+ self.assertEqual(2, result)
+
+ # TODO(elfoley): Split this test into smaller tests
+ def test_generate_next_core_id(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ result = opnfv_vnf.generate_next_core_id()
+ self.assertIsNone(result)
+ opnfv_vnf.worker_config = '2t'
+ opnfv_vnf.start_core = 'a'
+ self.assertRaises(ValueError, opnfv_vnf.generate_next_core_id)
+ opnfv_vnf.worker_config = '2t'
+ opnfv_vnf.start_core = 1
+ result = opnfv_vnf.generate_next_core_id()
+ self.assertIsNone(result)
+
+ def test_generate_lb_to_port_pair_mapping(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = VnfdHelper(self.VNFD_0)
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf._port_pairs = samplevnf_helper.PortPairs(vnfd_mock.interfaces)
+ opnfv_vnf.port_pair_list = opnfv_vnf._port_pairs.port_pair_list
+ result = opnfv_vnf.generate_lb_to_port_pair_mapping()
+ self.assertIsNone(result)
+ result = opnfv_vnf.set_priv_to_pub_mapping()
+ self.assertEqual('(0,1)', result)
+
+ def test_set_priv_que_handler(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = VnfdHelper(self.VNFD_0)
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ result = opnfv_vnf.set_priv_que_handler()
+ self.assertIsNone(result)
+
+ def test_generate_arp_route_tbl(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = ""
+ vnfd_mock = mock.MagicMock()
+ vnfd_mock.port_num.side_effect = ['32', '1', '987']
+ vnfd_mock.find_interface.side_effect = [
+ {
+ 'virtual-interface': {
+ 'dst_ip': '10.20.30.40',
+ 'netmask': '20',
+ },
+ },
+ {
+ 'virtual-interface': {
+ 'dst_ip': '10.200.30.40',
+ 'netmask': '24',
+ },
+ },
+ {
+ 'virtual-interface': {
+ 'dst_ip': '10.20.3.40',
+ 'netmask': '8',
+ },
+ },
+ ]
+
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.all_ports = [3, 2, 5]
+
+ expected = 'routeadd net 32 10.20.30.40 0xfffff000\n' \
+ 'routeadd net 1 10.200.30.40 0xffffff00\n' \
+ 'routeadd net 987 10.20.3.40 0xff000000'
+ result = opnfv_vnf.generate_arp_route_tbl()
+ self.assertEqual(result, expected)
+
+ def test_generate_arpicmp_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ result = opnfv_vnf.generate_arpicmp_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'ovs'
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ result = opnfv_vnf.generate_arpicmp_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'openstack'
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ result = opnfv_vnf.generate_arpicmp_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.lb_config = 'HW'
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ result = opnfv_vnf.generate_arpicmp_data()
+ self.assertIsNotNone(result)
+
+ def test_generate_final_txrx_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.ports_len = 2
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.pktq_out_os = [1, 2]
+ result = opnfv_vnf.generate_final_txrx_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'openstack'
+ opnfv_vnf.pktq_out_os = [1, 2]
+ opnfv_vnf.lb_index = 1
+ result = opnfv_vnf.generate_final_txrx_data()
+ self.assertIsNotNone(result)
+
+ def test_generate_initial_txrx_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 2
+ result = opnfv_vnf.generate_initial_txrx_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'openstack'
+ opnfv_vnf.pktq_out_os = [1, 2]
+ result = opnfv_vnf.generate_initial_txrx_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'ovs'
+ opnfv_vnf.init_ovs = False
+ opnfv_vnf.ovs_pktq_out = ''
+ opnfv_vnf.pktq_out_os = [1, 2]
+ opnfv_vnf.lb_index = 1
+ result = opnfv_vnf.generate_initial_txrx_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.nfv_type = 'ovs'
+ opnfv_vnf.init_ovs = True
+ opnfv_vnf.pktq_out_os = [1, 2]
+ opnfv_vnf.ovs_pktq_out = ''
+ opnfv_vnf.lb_index = 1
+ result = opnfv_vnf.generate_initial_txrx_data()
+ self.assertIsNotNone(result)
+
+ def test_generate_lb_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 2
+ opnfv_vnf.prv_que_handler = 0
+ result = opnfv_vnf.generate_lb_data()
+ self.assertIsNotNone(result)
+
+ def test_generate_vnf_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 1
+ opnfv_vnf.pktq_out = ['1', '2']
+ opnfv_vnf.vnf_tpl = {'public_ip_port_range': '98164810',
+ 'vnf_set': '(2,4,5)'}
+ opnfv_vnf.prv_que_handler = 0
+ result = opnfv_vnf.generate_vnf_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.lb_config = 'HW'
+ opnfv_vnf.mul = 0.1
+ result = opnfv_vnf.generate_vnf_data()
+ self.assertIsNotNone(result)
+ opnfv_vnf.lb_config = 'HW'
+ opnfv_vnf.mul = 0.1
+ opnfv_vnf.vnf_type = 'ACL'
+ result = opnfv_vnf.generate_vnf_data()
+ self.assertIsNotNone(result)
+
+ def test_generate_config_data(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = VnfdHelper(self.VNFD_0)
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 1
+ opnfv_vnf.pktq_out = ['1', '2']
+ opnfv_vnf.prv_que_handler = 0
+ opnfv_vnf.init_write_parser_template = mock.Mock()
+ opnfv_vnf.arpicmp_tpl = mock.MagicMock()
+ opnfv_vnf.txrx_tpl = mock.MagicMock()
+ opnfv_vnf.loadb_tpl = mock.MagicMock()
+ opnfv_vnf.vnf_tpl = {'public_ip_port_range': '98164810 (1,65535)',
+ 'vnf_set': "(2,4,5)"}
+ opnfv_vnf.generate_vnf_data = mock.Mock(return_value={})
+ opnfv_vnf.update_write_parser = mock.Mock()
+ result = opnfv_vnf.generate_config_data()
+ self.assertIsNone(result)
+ opnfv_vnf.generate_final_txrx_data = mock.Mock()
+ opnfv_vnf.update_write_parser = mock.Mock()
+ result = opnfv_vnf.generate_config_data()
+ self.assertIsNone(result)
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 1
+ opnfv_vnf.pktq_out = ['1', '2']
+ opnfv_vnf.prv_que_handler = 0
+ opnfv_vnf.init_write_parser_template = mock.Mock()
+ opnfv_vnf.arpicmp_tpl = mock.MagicMock()
+ opnfv_vnf.txrx_tpl = mock.MagicMock()
+ opnfv_vnf.loadb_tpl = mock.MagicMock()
+ opnfv_vnf.vnf_type = 'CGNAPT'
+ opnfv_vnf.update_timer = mock.Mock()
+ opnfv_vnf.port_pair_list = [("xe0", "xe1"), ("xe0", "xe2")]
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.generate_arpicmp_data = mock.Mock()
+ result = opnfv_vnf.generate_config_data()
+ self.assertIsNone(result)
+
+ def test_init_eal(self):
+ topology_file = mock.Mock()
+ config_tpl = mock.Mock()
+ tmp_file = mock.Mock()
+ vnfd_mock = mock.MagicMock()
+ opnfv_vnf = samplevnf_helper.MultiPortConfig(
+ topology_file, config_tpl, tmp_file, vnfd_mock)
+ opnfv_vnf.socket = 0
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.port_pair_list = [("xe0", "xe1")]
+ opnfv_vnf.port_pairs = [("xe0", "xe1")]
+ opnfv_vnf.txrx_pipeline = ''
+ opnfv_vnf.rules = ''
+ opnfv_vnf.write_parser = mock.MagicMock()
+ opnfv_vnf.read_parser = mock.MagicMock()
+ opnfv_vnf.read_parser.sections = mock.Mock(return_value=['MASTER'])
+ opnfv_vnf.read_parser.has_option = mock.Mock(return_value=[])
+ opnfv_vnf.write_parser.set = mock.Mock()
+ opnfv_vnf.write_parser.add_section = mock.Mock()
+ opnfv_vnf.read_parser.items = mock.MagicMock()
+ opnfv_vnf.pipeline_counter = 0
+ opnfv_vnf.worker_config = '1t'
+ opnfv_vnf.start_core = 0
+ opnfv_vnf.lb_count = 1
+ opnfv_vnf.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ opnfv_vnf.interfaces = opnfv_vnf.vnfd['vdu'][0]['external-interface']
+ opnfv_vnf.lb_to_port_pair_mapping = [0, 1]
+ opnfv_vnf.lb_index = 1
+ opnfv_vnf.ports_len = 1
+ opnfv_vnf.pktq_out = ['1', '2']
+ opnfv_vnf.prv_que_handler = 0
+ opnfv_vnf.init_write_parser_template = mock.Mock()
+ opnfv_vnf.arpicmp_tpl = mock.MagicMock()
+ opnfv_vnf.txrx_tpl = mock.MagicMock()
+ opnfv_vnf.loadb_tpl = mock.MagicMock()
+ opnfv_vnf.vnf_tpl = {'public_ip_port_range': '98164810 (1,65535)'}
+ opnfv_vnf.generate_vnf_data = mock.Mock(return_value={})
+ opnfv_vnf.update_write_parser = mock.Mock()
+ opnfv_vnf.tmp_file = "/tmp/config"
+ result = opnfv_vnf.init_eal()
+ self.assertIsNone(result)
diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/__init__.py
diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py
new file mode 100644
index 000000000..d3145546a
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_multiple_loss_ratio_search.py
@@ -0,0 +1,2164 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import mock
+
+from yardstick.network_services.helpers.vpp_helpers.multiple_loss_ratio_search import \
+ MultipleLossRatioSearch
+from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \
+ NdrPdrResult
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \
+ ReceiveRateInterval
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \
+ ReceiveRateMeasurement
+from yardstick.network_services.traffic_profile.rfc2544 import PortPgIDMap
+
+
+class TestMultipleLossRatioSearch(unittest.TestCase):
+
+ def test___init__(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(True, algorithm.latency)
+ self.assertEqual(64, algorithm.pkt_size)
+ self.assertEqual(30, algorithm.final_trial_duration)
+ self.assertEqual(0.005, algorithm.final_relative_width)
+ self.assertEqual(2, algorithm.number_of_intermediate_phases)
+ self.assertEqual(1, algorithm.initial_trial_duration)
+ self.assertEqual(720, algorithm.timeout)
+ self.assertEqual(1, algorithm.doublings)
+
+ def test_double_relative_width(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(0.00997, algorithm.double_relative_width(0.005))
+
+ def test_double_step_down(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(99003.0, algorithm.double_step_down(0.005, 100000))
+
+ def test_expand_down(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(99003.0, algorithm.expand_down(0.005, 1, 100000))
+
+ def test_double_step_up(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(101007.0401907013,
+ algorithm.double_step_up(0.005, 100000))
+
+ def test_expand_up(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(101007.0401907013,
+ algorithm.expand_up(0.005, 1, 100000))
+
+ def test_half_relative_width(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(0.0025031328369998773,
+ algorithm.half_relative_width(0.005))
+
+ def test_half_step_up(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ self.assertEqual(100250.94142341711,
+ algorithm.half_step_up(0.005, 100000))
+
+ def test_init_generator(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(),
+ mock.Mock(), mock.Mock()))
+ self.assertEqual(ports, algorithm.ports)
+ self.assertEqual(port_pg_id, algorithm.port_pg_id)
+
+ def test_collect_kpi(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ algorithm.init_generator(ports, port_pg_id, mock.Mock, mock.Mock,
+ mock.Mock())
+ self.assertIsNone(algorithm.collect_kpi({}, 100000))
+
+ def test_narrow_down_ndr_and_pdr(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, 'ndrpdr') as \
+ mock_ndrpdr:
+ ndr_measured_low = ReceiveRateMeasurement(10, 13880000, 13879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(10, 14880000, 14879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(10, 11880000, 11879927,
+ 0)
+ pdr_measured_high = ReceiveRateMeasurement(10, 12880000, 12879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock_ndrpdr.return_value = MultipleLossRatioSearch.ProgressState(
+ starting_result, 2, 30, 0.005, 0.0,
+ 4857361, 4977343)
+ self.assertEqual(
+ {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 0.9327310944,
+ 'rate_total_pps': 1387992.7},
+ 'Result_NDR_UPPER': {
+ 'bandwidth_total_Gbps': 0.9999310943999999,
+ 'rate_total_pps': 1487992.7},
+ 'Result_NDR_packets_lost': {'packet_loss_ratio': 0.0,
+ 'packets_lost': 0.0},
+ 'Result_PDR_LOWER': {
+ 'bandwidth_total_Gbps': 0.7983310943999999,
+ 'rate_total_pps': 1187992.7},
+ 'Result_PDR_UPPER': {'bandwidth_total_Gbps': 0.8655310944,
+ 'rate_total_pps': 1287992.7},
+ 'Result_PDR_packets_lost': {'packet_loss_ratio': 0.0,
+ 'packets_lost': 0.0},
+ 'Result_stream0_NDR_LOWER': {'avg_latency': 3081.0,
+ 'max_latency': 3962.0,
+ 'min_latency': 1000.0},
+ 'Result_stream0_PDR_LOWER': {'avg_latency': 3081.0,
+ 'max_latency': 3962.0,
+ 'min_latency': 1000.0},
+ 'Result_stream1_NDR_LOWER': {'avg_latency': 3149.0,
+ 'max_latency': 3730.0,
+ 'min_latency': 500.0},
+ 'Result_stream1_PDR_LOWER': {'avg_latency': 3149.0,
+ 'max_latency': 3730.0,
+ 'min_latency': 500.0}},
+ algorithm.narrow_down_ndr_and_pdr(12880000, 15880000, 0.0))
+
+ def test__measure_and_update_state(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ starting_result = NdrPdrResult(starting_interval, starting_interval)
+ previous_state = MultipleLossRatioSearch.ProgressState(starting_result,
+ 2, 30, 0.005,
+ 0.0, 4857361,
+ 4977343)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure:
+ mock_measure.return_value = ReceiveRateMeasurement(1,
+ 4626121.09635,
+ 4626100, 13074)
+ state = algorithm._measure_and_update_state(previous_state,
+ 4626121.09635)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(1, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(4626121.09635,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(4626100,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(13074,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(4613026,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(4626100,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(13074.0,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(4613026.0,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00283,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(1, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(4857361,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(4857339,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(84965,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(4772374,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(4857339,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(84965.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(4772374.0,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.01749,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(1, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(4626121.09635,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(4626100,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(13074,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(4613026,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(4626100,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(13074.0,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(4613026.0,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00283,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(1, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(4857361,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(4857339,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(84965,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(4772374,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(4857339,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(84965.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(4772374.0,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.01749,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(2, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(4857361, state.minimum_transmit_rate)
+ self.assertEqual(4977343, state.maximum_transmit_rate)
+
+ def test_new_interval(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 3972540.4108, 21758482, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.0)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(3972540.4108, result.measured_low.target_tr)
+ self.assertEqual(21758482, result.measured_low.transmit_count)
+ self.assertEqual(0, result.measured_low.loss_count)
+ self.assertEqual(21758482, result.measured_low.receive_count)
+ self.assertEqual(21758482, result.measured_low.transmit_rate)
+ self.assertEqual(0.0, result.measured_low.loss_rate)
+ self.assertEqual(21758482.0, result.measured_low.receive_rate)
+ self.assertEqual(0.0, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4857361, result.measured_high.target_tr)
+ self.assertEqual(4857339, result.measured_high.transmit_count)
+ self.assertEqual(84965, result.measured_high.loss_count)
+ self.assertEqual(4772374, result.measured_high.receive_count)
+ self.assertEqual(4857339, result.measured_high.transmit_rate)
+ self.assertEqual(84965.0, result.measured_high.loss_rate)
+ self.assertEqual(4772374.0, result.measured_high.receive_rate)
+ self.assertEqual(0.01749, result.measured_high.loss_fraction)
+
+ def test_new_interval_zero(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 4977343, 21758482, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.0)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4857361.0, result.measured_low.target_tr)
+ self.assertEqual(4857339, result.measured_low.transmit_count)
+ self.assertEqual(84965, result.measured_low.loss_count)
+ self.assertEqual(4772374, result.measured_low.receive_count)
+ self.assertEqual(4857339.0, result.measured_low.transmit_rate)
+ self.assertEqual(84965.0, result.measured_low.loss_rate)
+ self.assertEqual(4772374.0, result.measured_low.receive_rate)
+ self.assertEqual(0.01749, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4977343.0, result.measured_high.target_tr)
+ self.assertEqual(21758482, result.measured_high.transmit_count)
+ self.assertEqual(0, result.measured_high.loss_count)
+ self.assertEqual(21758482, result.measured_high.receive_count)
+ self.assertEqual(21758482.0, result.measured_high.transmit_rate)
+ self.assertEqual(0.0, result.measured_high.loss_rate)
+ self.assertEqual(21758482.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0, result.measured_high.loss_fraction)
+
+ def test_new_interval_one(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 5000000, 2175848, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.0)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4857361.0, result.measured_low.target_tr)
+ self.assertEqual(4857339, result.measured_low.transmit_count)
+ self.assertEqual(84965, result.measured_low.loss_count)
+ self.assertEqual(4772374, result.measured_low.receive_count)
+ self.assertEqual(4857339.0, result.measured_low.transmit_rate)
+ self.assertEqual(84965.0, result.measured_low.loss_rate)
+ self.assertEqual(4772374.0, result.measured_low.receive_rate)
+ self.assertEqual(0.01749, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4977343.0, result.measured_high.target_tr)
+ self.assertEqual(4977320, result.measured_high.transmit_count)
+ self.assertEqual(119959, result.measured_high.loss_count)
+ self.assertEqual(4857361, result.measured_high.receive_count)
+ self.assertEqual(4977320.0, result.measured_high.transmit_rate)
+ self.assertEqual(119959.0, result.measured_high.loss_rate)
+ self.assertEqual(4857361.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0241, result.measured_high.loss_fraction)
+
+ def test_new_interval_valid_1st(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 4000000, 2175848, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.5)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4857361.0, result.measured_low.target_tr)
+ self.assertEqual(4857339, result.measured_low.transmit_count)
+ self.assertEqual(84965, result.measured_low.loss_count)
+ self.assertEqual(4772374, result.measured_low.receive_count)
+ self.assertEqual(4857339.0, result.measured_low.transmit_rate)
+ self.assertEqual(84965.0, result.measured_low.loss_rate)
+ self.assertEqual(4772374.0, result.measured_low.receive_rate)
+ self.assertEqual(0.01749, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4977343.0, result.measured_high.target_tr)
+ self.assertEqual(4977320, result.measured_high.transmit_count)
+ self.assertEqual(119959, result.measured_high.loss_count)
+ self.assertEqual(4857361, result.measured_high.receive_count)
+ self.assertEqual(4977320.0, result.measured_high.transmit_rate)
+ self.assertEqual(119959.0, result.measured_high.loss_rate)
+ self.assertEqual(4857361.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0241, result.measured_high.loss_fraction)
+
+ def test_new_interval_valid_1st_loss(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 4000000, 2175848, 1000000)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.02)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4000000.0, result.measured_low.target_tr)
+ self.assertEqual(2175848, result.measured_low.transmit_count)
+ self.assertEqual(1000000, result.measured_low.loss_count)
+ self.assertEqual(1175848, result.measured_low.receive_count)
+ self.assertEqual(2175848.0, result.measured_low.transmit_rate)
+ self.assertEqual(1000000.0, result.measured_low.loss_rate)
+ self.assertEqual(1175848.0, result.measured_low.receive_rate)
+ self.assertEqual(0.45959, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4977343.0, result.measured_high.target_tr)
+ self.assertEqual(4977320, result.measured_high.transmit_count)
+ self.assertEqual(119959, result.measured_high.loss_count)
+ self.assertEqual(4857361, result.measured_high.receive_count)
+ self.assertEqual(4977320.0, result.measured_high.transmit_rate)
+ self.assertEqual(119959.0, result.measured_high.loss_rate)
+ self.assertEqual(4857361.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0241, result.measured_high.loss_fraction)
+
+ def test_new_interval_valid_2nd(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 5000000, 2175848, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.5)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4977343.0, result.measured_low.target_tr)
+ self.assertEqual(4977320, result.measured_low.transmit_count)
+ self.assertEqual(119959, result.measured_low.loss_count)
+ self.assertEqual(4857361, result.measured_low.receive_count)
+ self.assertEqual(4977320.0, result.measured_low.transmit_rate)
+ self.assertEqual(119959.0, result.measured_low.loss_rate)
+ self.assertEqual(4857361.0, result.measured_low.receive_rate)
+ self.assertEqual(0.0241, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(5000000.0, result.measured_high.target_tr)
+ self.assertEqual(2175848, result.measured_high.transmit_count)
+ self.assertEqual(0, result.measured_high.loss_count)
+ self.assertEqual(2175848, result.measured_high.receive_count)
+ self.assertEqual(2175848.0, result.measured_high.transmit_rate)
+ self.assertEqual(0.0, result.measured_high.loss_rate)
+ self.assertEqual(2175848.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0, result.measured_high.loss_fraction)
+
+ def test_new_interval_valid_3rd(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 4867361, 2175848, 0)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.5)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4867361.0, result.measured_low.target_tr)
+ self.assertEqual(2175848, result.measured_low.transmit_count)
+ self.assertEqual(0, result.measured_low.loss_count)
+ self.assertEqual(2175848, result.measured_low.receive_count)
+ self.assertEqual(2175848.0, result.measured_low.transmit_rate)
+ self.assertEqual(0.0, result.measured_low.loss_rate)
+ self.assertEqual(2175848.0, result.measured_low.receive_rate)
+ self.assertEqual(0.0, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4977343.0, result.measured_high.target_tr)
+ self.assertEqual(4977320, result.measured_high.transmit_count)
+ self.assertEqual(119959, result.measured_high.loss_count)
+ self.assertEqual(4857361, result.measured_high.receive_count)
+ self.assertEqual(4977320.0, result.measured_high.transmit_rate)
+ self.assertEqual(119959.0, result.measured_high.loss_rate)
+ self.assertEqual(4857361.0, result.measured_high.receive_rate)
+ self.assertEqual(0.0241, result.measured_high.loss_fraction)
+
+ def test_new_interval_valid_3rd_loss(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ measured = ReceiveRateMeasurement(1, 4867361, 2175848, 1000000)
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ result = algorithm._new_interval(receive_rate_interval, measured, 0.2)
+ self.assertIsInstance(result, ReceiveRateInterval)
+ self.assertEqual(1, result.measured_low.duration)
+ self.assertEqual(4857361.0, result.measured_low.target_tr)
+ self.assertEqual(4857339, result.measured_low.transmit_count)
+ self.assertEqual(84965, result.measured_low.loss_count)
+ self.assertEqual(4772374, result.measured_low.receive_count)
+ self.assertEqual(4857339.0, result.measured_low.transmit_rate)
+ self.assertEqual(84965.0, result.measured_low.loss_rate)
+ self.assertEqual(4772374.0, result.measured_low.receive_rate)
+ self.assertEqual(0.01749, result.measured_low.loss_fraction)
+ self.assertEqual(1, result.measured_high.duration)
+ self.assertEqual(4867361.0, result.measured_high.target_tr)
+ self.assertEqual(2175848, result.measured_high.transmit_count)
+ self.assertEqual(1000000, result.measured_high.loss_count)
+ self.assertEqual(1175848, result.measured_high.receive_count)
+ self.assertEqual(2175848.0, result.measured_high.transmit_rate)
+ self.assertEqual(1000000.0, result.measured_high.loss_rate)
+ self.assertEqual(1175848.0, result.measured_high.receive_rate)
+ self.assertEqual(0.45959, result.measured_high.loss_fraction)
+
+ def test_ndrpdr(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure:
+ measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_ndr_rel_width(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ measured_low = ReceiveRateMeasurement(30, 880000, 879927, 0)
+ measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ ending_interval = ReceiveRateInterval(measured_high, measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ ending_result = NdrPdrResult(ending_interval, ending_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.005, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_pdr_rel_width(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 880000, 879927, 0)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(ndr_interval, ndr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.005, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_ndr_lo_duration(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 100)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(starting_result, -1, 30,
+ 0.005, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 50, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879827,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495994.23333,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(1e-05,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879827,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495994.23333,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(1e-05,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_ndr_hi_duration(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ measured_low = ReceiveRateMeasurement(60, 14880000, 14879927, 0)
+ measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 100)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(starting_result, -1, 30,
+ 0.005, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 50, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(60.0, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(247998.78333,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(247998.78333,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879827,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495994.23333,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(1e-05,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(60.0, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(247998.78333,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(247998.78333,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879827,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495994.23333,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(1e-05,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.005, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_error(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=0)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure:
+ measured_low = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_high = ReceiveRateMeasurement(30, 14880000, 14879927, 0)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 14880000,
+ 14880000)
+ with self.assertRaises(RuntimeError) as raised:
+ algorithm.ndrpdr(previous_state)
+
+ self.assertIn('Optimized search takes too long.',
+ str(raised.exception))
+
+ def test_ndrpdr_update_state_ndr_hi(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(pdr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_ndr_hi_duration(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(pdr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 50, 0.005, 0.0, 4880000,
+ 10880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0, state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(0, state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_ndr_lo(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 100000)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 100000)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(pdr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 100000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_pdr_lo(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 100000)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(pdr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 100000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_pdr_lo_duration(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ pdr_measured_high = ReceiveRateMeasurement(30, 14880000, 14879927,
+ 100000)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(pdr_interval, pdr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 50, 0.005, 0.0, 14880000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(14880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(12880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(12779927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(14880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(14879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(14779927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(495997.56667,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(492664.23333,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00672,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_pdr_hi(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ pdr_measured_high = ReceiveRateMeasurement(30, 13880000, 14879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(ndr_interval, ndr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 30, 0.005, 0.0, 100000,
+ 14880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(10880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(10879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(10879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(362664.23333,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(362664.23333,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(12779927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(10880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(10879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(10879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(362664.23333,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(362664.23333,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(12880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(12779927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_ndrpdr_update_state_pdr_hi_duration(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock(), mock.Mock,
+ mock.Mock()))
+ with mock.patch.object(algorithm, 'measure') as \
+ mock_measure, \
+ mock.patch.object(algorithm, '_measure_and_update_state') as \
+ mock__measure_and_update_state:
+ ndr_measured_low = ReceiveRateMeasurement(30, 10880000, 10879927,
+ 0)
+ ndr_measured_high = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 100000)
+ ndr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_low = ReceiveRateMeasurement(30, 12880000, 12879927,
+ 0)
+ pdr_measured_high = ReceiveRateMeasurement(30, 13880000, 14879927,
+ 0)
+ pdr_measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ pdr_measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ ndr_interval = ReceiveRateInterval(ndr_measured_low,
+ ndr_measured_high)
+ pdr_interval = ReceiveRateInterval(pdr_measured_low,
+ pdr_measured_high)
+ starting_result = NdrPdrResult(ndr_interval, pdr_interval)
+ ending_result = NdrPdrResult(ndr_interval, ndr_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock__measure_and_update_state.return_value = \
+ MultipleLossRatioSearch.ProgressState(ending_result, -1, 30,
+ 0.2, 0.0, 14880000,
+ 14880000)
+ previous_state = MultipleLossRatioSearch.ProgressState(
+ starting_result, -1, 50, 0.005, 0.0, 100000,
+ 10880000)
+ state = algorithm.ndrpdr(previous_state)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertIsInstance(state, MultipleLossRatioSearch.ProgressState)
+ self.assertEqual(30, state.result.ndr_interval.measured_low.duration)
+ self.assertEqual(10880000.0,
+ state.result.ndr_interval.measured_low.target_tr)
+ self.assertEqual(10879927,
+ state.result.ndr_interval.measured_low.transmit_count)
+ self.assertEqual(0,
+ state.result.ndr_interval.measured_low.loss_count)
+ self.assertEqual(10879927,
+ state.result.ndr_interval.measured_low.receive_count)
+ self.assertEqual(362664.23333,
+ state.result.ndr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_rate)
+ self.assertEqual(362664.23333,
+ state.result.ndr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.ndr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.ndr_interval.measured_high.duration)
+ self.assertEqual(12880000.0,
+ state.result.ndr_interval.measured_high.target_tr)
+ self.assertEqual(12879927,
+ state.result.ndr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.ndr_interval.measured_high.loss_count)
+ self.assertEqual(12779927,
+ state.result.ndr_interval.measured_high.receive_count)
+ self.assertEqual(429330.9,
+ state.result.ndr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.ndr_interval.measured_high.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.ndr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.ndr_interval.measured_high.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_low.duration)
+ self.assertEqual(10880000.0,
+ state.result.pdr_interval.measured_low.target_tr)
+ self.assertEqual(10879927,
+ state.result.pdr_interval.measured_low.transmit_count)
+ self.assertEqual(0,
+ state.result.pdr_interval.measured_low.loss_count)
+ self.assertEqual(10879927,
+ state.result.pdr_interval.measured_low.receive_count)
+ self.assertEqual(362664.23333,
+ state.result.pdr_interval.measured_low.transmit_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_rate)
+ self.assertEqual(362664.23333,
+ state.result.pdr_interval.measured_low.receive_rate)
+ self.assertEqual(0.0,
+ state.result.pdr_interval.measured_low.loss_fraction)
+ self.assertEqual(30, state.result.pdr_interval.measured_high.duration)
+ self.assertEqual(12880000,
+ state.result.pdr_interval.measured_high.target_tr)
+ self.assertEqual(12879927,
+ state.result.pdr_interval.measured_high.transmit_count)
+ self.assertEqual(100000,
+ state.result.pdr_interval.measured_high.loss_count)
+ self.assertEqual(12779927,
+ state.result.pdr_interval.measured_high.receive_count)
+ self.assertEqual(429330.9,
+ state.result.pdr_interval.measured_high.transmit_rate)
+ self.assertEqual(3333.33333,
+ state.result.pdr_interval.measured_high.loss_rate)
+ self.assertEqual(425997.56667,
+ state.result.pdr_interval.measured_high.receive_rate)
+ self.assertEqual(0.00776,
+ state.result.pdr_interval.measured_high.loss_fraction)
+ self.assertEqual(-1, state.phases)
+ self.assertEqual(30, state.duration)
+ self.assertEqual(0.2, state.width_goal)
+ self.assertEqual(0.0, state.packet_loss_ratio)
+ self.assertEqual(14880000, state.minimum_transmit_rate)
+ self.assertEqual(14880000, state.maximum_transmit_rate)
+
+ def test_measure(self):
+ measurer = mock.MagicMock()
+ measurer.sent = 102563094
+ measurer.loss = 30502
+ algorithm = MultipleLossRatioSearch(measurer=measurer, latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.MagicMock(),
+ mock.Mock, mock.Mock()))
+ measurement = algorithm.measure(30, 3418770.3425, True)
+ self.assertIsInstance(measurement, ReceiveRateMeasurement)
+ self.assertEqual(30, measurement.duration)
+ self.assertEqual(3418770.3425, measurement.target_tr)
+ self.assertEqual(102563094, measurement.transmit_count)
+ self.assertEqual(30502, measurement.loss_count)
+ self.assertEqual(102532592, measurement.receive_count)
+ self.assertEqual(3418769.8, measurement.transmit_rate)
+ self.assertEqual(1016.73333, measurement.loss_rate)
+ self.assertEqual(3417753.06667, measurement.receive_rate)
+ self.assertEqual(0.0003, measurement.loss_fraction)
+
+ def test_perform_additional_measurements_based_on_ndrpdr_result(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ ports = [0, 1]
+ port_pg_id = PortPgIDMap()
+ port_pg_id.add_port(0)
+ port_pg_id.add_port(1)
+ self.assertIsNone(
+ algorithm.init_generator(ports, port_pg_id, mock.Mock, mock.Mock,
+ mock.Mock()))
+ result = mock.MagicMock()
+ result.ndr_interval.measured_low.target_tr.return_result = 100000
+ self.assertIsNone(
+ algorithm.perform_additional_measurements_based_on_ndrpdr_result(
+ result))
+
+ def test_display_single_bound(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ result_samples = {}
+ self.assertIsNone(
+ algorithm.display_single_bound(result_samples, 'NDR_LOWER',
+ 4857361, 64,
+ ['20/849/1069', '40/69/183']))
+ self.assertEqual(
+ {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 3.264146592,
+ 'rate_total_pps': 4857361.0},
+ 'Result_stream0_NDR_LOWER': {'avg_latency': 849.0,
+ 'max_latency': 1069.0,
+ 'min_latency': 20.0},
+ 'Result_stream1_NDR_LOWER': {'avg_latency': 69.0,
+ 'max_latency': 183.0,
+ 'min_latency': 40.0}},
+ result_samples)
+
+ def test_check_ndrpdr_interval_validity(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ result_samples = {}
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 0)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 0)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertEqual('Minimal rate loss fraction 0.0 reach target 0.0',
+ algorithm.check_ndrpdr_interval_validity(
+ result_samples, 'NDR_LOWER',
+ receive_rate_interval))
+ self.assertEqual(
+ {'Result_NDR_LOWER_packets_lost': {'packet_loss_ratio': 0.0,
+ 'packets_lost': 0.0}},
+ result_samples)
+
+ def test_check_ndrpdr_interval_validity_fail(self):
+ algorithm = MultipleLossRatioSearch(measurer=mock.Mock(), latency=True,
+ pkt_size=64,
+ final_trial_duration=30,
+ final_relative_width=0.005,
+ number_of_intermediate_phases=2,
+ initial_trial_duration=1,
+ timeout=720)
+ result_samples = {}
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertEqual(
+ 'Minimal rate loss fraction 0.01749 does not reach target 0.005\n84965 packets lost.',
+ algorithm.check_ndrpdr_interval_validity(result_samples,
+ 'NDR_LOWER',
+ receive_rate_interval,
+ 0.005))
+ self.assertEqual({'Result_NDR_LOWER_packets_lost': {
+ 'packet_loss_ratio': 0.01749,
+ 'packets_lost': 84965.0}}, result_samples)
diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py
new file mode 100644
index 000000000..ea9c39a03
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_ndr_pdr_result.py
@@ -0,0 +1,91 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import mock
+
+from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \
+ NdrPdrResult
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \
+ ReceiveRateInterval
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \
+ ReceiveRateMeasurement
+
+
+class TestNdrPdrResult(unittest.TestCase):
+
+ def test___init__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ ndrpdr_result = NdrPdrResult(starting_interval, starting_interval)
+ self.assertIsInstance(ndrpdr_result.ndr_interval, ReceiveRateInterval)
+ self.assertIsInstance(ndrpdr_result.pdr_interval, ReceiveRateInterval)
+
+ def test___init__ndr_error(self):
+ starting_interval = mock.MagicMock()
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ end_interval = ReceiveRateInterval(measured_low, measured_high)
+ with self.assertRaises(TypeError) as raised:
+ NdrPdrResult(starting_interval, end_interval)
+ self.assertIn('ndr_interval, is not a ReceiveRateInterval: ',
+ str(raised.exception))
+
+ def test___init__pdr_error(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ end_interval = mock.MagicMock()
+ with self.assertRaises(TypeError) as raised:
+ NdrPdrResult(starting_interval, end_interval)
+ self.assertIn('pdr_interval, is not a ReceiveRateInterval: ',
+ str(raised.exception))
+
+ def test_width_in_goals(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ ndrpdr_result = NdrPdrResult(starting_interval, starting_interval)
+ self.assertEqual('ndr 4.86887; pdr 4.86887',
+ ndrpdr_result.width_in_goals(0.005))
+
+ def test___str__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ ndrpdr_result = NdrPdrResult(starting_interval, starting_interval)
+ self.assertEqual(
+ 'NDR=[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241);'
+ 'PDR=[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241)',
+ ndrpdr_result.__str__())
+
+ def test___repr__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ starting_interval = ReceiveRateInterval(measured_low, measured_high)
+ ndrpdr_result = NdrPdrResult(starting_interval, starting_interval)
+ self.assertEqual(
+ 'NdrPdrResult(ndr_interval=ReceiveRateInterval(measured_low=' \
+ 'ReceiveRateMeasurement(duration=1.0,target_tr=4857361.0,' \
+ 'transmit_count=4857339,loss_count=84965),measured_high=' \
+ 'ReceiveRateMeasurement(duration=1.0,target_tr=4977343.0,' \
+ 'transmit_count=4977320,loss_count=119959)),pdr_interval=' \
+ 'ReceiveRateInterval(measured_low=ReceiveRateMeasurement' \
+ '(duration=1.0,target_tr=4857361.0,transmit_count=4857339,' \
+ 'loss_count=84965),measured_high=ReceiveRateMeasurement' \
+ '(duration=1.0,target_tr=4977343.0,transmit_count=4977320,' \
+ 'loss_count=119959)))',
+ ndrpdr_result.__repr__())
diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py
new file mode 100644
index 000000000..bbf241613
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_interval.py
@@ -0,0 +1,100 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+import mock
+
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \
+ ReceiveRateInterval
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \
+ ReceiveRateMeasurement
+
+
+class TestReceiveRateInterval(unittest.TestCase):
+
+ def test__init__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertIsInstance(receive_rate_interval.measured_low,
+ ReceiveRateMeasurement)
+ self.assertIsInstance(receive_rate_interval.measured_high,
+ ReceiveRateMeasurement)
+
+ def test__init__measured_low_error(self):
+ measured_low = mock.MagicMock()
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ with self.assertRaises(TypeError) as raised:
+ ReceiveRateInterval(measured_low, measured_high)
+ self.assertIn('measured_low is not a ReceiveRateMeasurement: ',
+ str(raised.exception))
+
+ def test__init__measured_high_error(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = mock.MagicMock()
+ with self.assertRaises(TypeError) as raised:
+ ReceiveRateInterval(measured_low, measured_high)
+ self.assertIn('measured_high is not a ReceiveRateMeasurement: ',
+ str(raised.exception))
+
+ def test_sort(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertIsNone(receive_rate_interval.sort())
+ self.assertEqual(119982.0, receive_rate_interval.abs_tr_width)
+ self.assertEqual(0.02411,
+ receive_rate_interval.rel_tr_width)
+
+ def test_sort_swap(self):
+ measured_low = ReceiveRateMeasurement(1, 14857361, 14857339, 184965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertIsNone(receive_rate_interval.sort())
+ self.assertEqual(9880018.0, receive_rate_interval.abs_tr_width)
+ self.assertEqual(0.66499,
+ receive_rate_interval.rel_tr_width)
+
+ def test_width_in_goals(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertEqual(4.86887,
+ receive_rate_interval.width_in_goals(0.005))
+
+ def test___str__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertEqual(
+ '[d=1.0,Tr=4857361.0,Df=0.01749;d=1.0,Tr=4977343.0,Df=0.0241)',
+ receive_rate_interval.__str__())
+
+ def test___repr__(self):
+ measured_low = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ measured_high = ReceiveRateMeasurement(1, 4977343, 4977320, 119959)
+ receive_rate_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ self.assertEqual('ReceiveRateInterval(measured_low=' \
+ 'ReceiveRateMeasurement(duration=1.0,target_tr=4857361.0,' \
+ 'transmit_count=4857339,loss_count=84965),measured_high=' \
+ 'ReceiveRateMeasurement(duration=1.0,target_tr=4977343.0,' \
+ 'transmit_count=4977320,loss_count=119959))',
+ receive_rate_interval.__repr__())
diff --git a/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py
new file mode 100644
index 000000000..d4e2d7920
--- /dev/null
+++ b/yardstick/tests/unit/network_services/helpers/vpp_helpers/test_receive_rate_measurement.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \
+ ReceiveRateMeasurement
+
+
+class TestReceiveRateMeasurement(unittest.TestCase):
+
+ def test__init__(self):
+ measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ self.assertEqual(1, measured.duration)
+ self.assertEqual(4857361, measured.target_tr)
+ self.assertEqual(4857339, measured.transmit_count)
+ self.assertEqual(84965, measured.loss_count)
+ self.assertEqual(4772374, measured.receive_count)
+ self.assertEqual(4857339, measured.transmit_rate)
+ self.assertEqual(84965.0, measured.loss_rate)
+ self.assertEqual(4772374.0, measured.receive_rate)
+ self.assertEqual(0.01749, measured.loss_fraction)
+
+ def test___str__(self):
+ measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ self.assertEqual('d=1.0,Tr=4857361.0,Df=0.01749',
+ measured.__str__())
+
+ def test___repr__(self):
+ measured = ReceiveRateMeasurement(1, 4857361, 4857339, 84965)
+ self.assertEqual('ReceiveRateMeasurement(duration=1.0,' \
+ 'target_tr=4857361.0,transmit_count=4857339,loss_count=84965)',
+ measured.__repr__())
diff --git a/yardstick/tests/unit/network_services/libs/__init__.py b/yardstick/tests/unit/network_services/libs/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/libs/__init__.py
diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/__init__.py b/yardstick/tests/unit/network_services/libs/ixia_libs/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/libs/ixia_libs/__init__.py
diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
new file mode 100644
index 000000000..a20592dc7
--- /dev/null
+++ b/yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py
@@ -0,0 +1,1057 @@
+# Copyright (c) 2018-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.
+
+import mock
+import IxNetwork
+import unittest
+import re
+
+from copy import deepcopy
+from collections import OrderedDict
+
+from yardstick.common import exceptions
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
+from yardstick.network_services.traffic_profile import ixia_rfc2544
+
+
+UPLINK = 'uplink'
+DOWNLINK = 'downlink'
+
+TRAFFIC_PROFILE = {
+ 'uplink_0': {
+ 'ipv4': {
+ 'outer_l2': {
+ 'framesize': {
+ '128B': '0',
+ '1518B': '0',
+ '64B': '0',
+ '373b': '0',
+ '256B': '0',
+ '1400B': '0',
+ '570B': '0'}},
+ 'id': 1}},
+ 'description': 'Traffic profile to run RFC2544 latency',
+ 'name': 'rfc2544',
+ 'schema': 'isb:traffic_profile:0.1',
+ 'traffic_profile': {
+ 'injection_time': None,
+ 'enable_latency': True,
+ 'frame_rate': '100%',
+ 'traffic_type': 'IXIARFC2544Profile'},
+ 'downlink_0': {
+ 'ipv4': {
+ 'outer_l2': {
+ 'framesize': {
+ '128B': '0',
+ '1518B': '0',
+ '64B': '0',
+ '373b': '0',
+ '256B': '0',
+ '1400B': '0',
+ '570B': '0'}},
+ 'id': 2}}}
+
+
+TRAFFIC_PARAMETERS = {
+ UPLINK: {
+ 'id': 1,
+ 'bidir': 'False',
+ 'duration': 60,
+ 'rate': 10000.5,
+ 'rate_unit': 'fps',
+ 'outer_l2': {
+ 'framesize': {'64B': '25', '256B': '75'},
+ 'QinQ': None
+ },
+ 'outer_l3': {
+ 'count': 512,
+ 'srcseed': 10,
+ 'dstseed': 20,
+ 'dscp': 0,
+ 'proto': 'udp',
+ 'ttl': 32,
+ 'dstip': '152.16.40.20',
+ 'srcip': '152.16.100.20',
+ 'dstmask': 24,
+ 'srcmask': 24,
+ 'priority': {'raw': '0x01'}
+ },
+ 'outer_l4': {
+ 'seed': 1,
+ 'count': 1,
+ 'dstport': 2001,
+ 'srcport': 1234,
+ 'srcportmask': 0,
+ 'dstportmask': 0
+ },
+ 'traffic_type': 'continuous'
+ },
+ DOWNLINK: {
+ 'id': 2,
+ 'bidir': 'False',
+ 'duration': 60,
+ 'rate': 75.2,
+ 'rate_unit': '%',
+ 'outer_l2': {
+ 'framesize': {'128B': '35', '1024B': '65'},
+ 'QinQ': None
+ },
+ 'outer_l3': {
+ 'count': 1024,
+ 'srcseed': 30,
+ 'dstseed': 40,
+ 'dscp': 0,
+ 'proto': 'udp',
+ 'ttl': 32,
+ 'dstip': '2001::10',
+ 'srcip': '2021::10',
+ 'dstmask': 64,
+ 'srcmask': 64,
+ 'priority': {'raw': '0x01'}
+ },
+ 'outer_l4': {
+ 'seed': 1,
+ 'count': 1,
+ 'dstport': 1234,
+ 'srcport': 2001,
+ 'srcportmask': 0,
+ 'dstportmask': 0
+ },
+ 'traffic_type': 'continuous'
+ }
+}
+
+
+class TestIxNextgen(unittest.TestCase):
+
+ def setUp(self):
+ self.ixnet = mock.Mock()
+ self.ixnet.execute = mock.Mock()
+ self.ixnet.getRoot.return_value = 'my_root'
+ self.ixnet_gen = ixnet_api.IxNextgen()
+ self.ixnet_gen._ixnet = self.ixnet
+ self._mock_log = mock.patch.object(ixnet_api.log, 'info')
+ self.mock_log = self._mock_log.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self.mock_log.stop()
+
+ def test_get_config(self):
+ tg_cfg = {
+ 'vdu': [
+ {
+ 'external-interface': [
+ {'virtual-interface': {'vpci': '0000:07:00.1'}},
+ {'virtual-interface': {'vpci': '0001:08:01.2'}}
+ ]
+ },
+ ],
+ 'mgmt-interface': {
+ 'ip': 'test1',
+ 'tg-config': {
+ 'dut_result_dir': 'test2',
+ 'version': 'test3',
+ 'ixchassis': 'test4',
+ 'tcl_port': 'test5',
+ },
+ }
+ }
+
+ expected = {
+ 'machine': 'test1',
+ 'port': 'test5',
+ 'chassis': 'test4',
+ 'cards': ['0000', '0001'],
+ 'ports': ['07', '08'],
+ 'output_dir': 'test2',
+ 'version': 'test3',
+ 'bidir': True,
+ }
+
+ result = ixnet_api.IxNextgen.get_config(tg_cfg)
+ self.assertEqual(result, expected)
+
+ def test__get_config_element_by_flow_group_name(self):
+ self.ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
+ ['fg_01']]
+ self.ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_01'
+ output = self.ixnet_gen._get_config_element_by_flow_group_name(
+ 'flow_group_01')
+ self.assertEqual('traffic_item/configElement:flow_group_01', output)
+
+ def test__get_config_element_by_flow_group_name_no_match(self):
+ self.ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
+ ['fg_01']]
+ self.ixnet_gen._ixnet.getAttribute.return_value = 'flow_group_02'
+ output = self.ixnet_gen._get_config_element_by_flow_group_name(
+ 'flow_group_01')
+ self.assertIsNone(output)
+
+ def test__get_stack_item(self):
+ self.ixnet_gen._ixnet.getList.return_value = ['tcp1', 'tcp2', 'udp']
+ with mock.patch.object(
+ self.ixnet_gen, '_get_config_element_by_flow_group_name') as \
+ mock_get_cfg_element:
+ mock_get_cfg_element.return_value = 'cfg_element'
+ output = self.ixnet_gen._get_stack_item(mock.ANY, ixnet_api.PROTO_TCP)
+ self.assertEqual(['tcp1', 'tcp2'], output)
+
+ def test__get_stack_item_no_config_element(self):
+ with mock.patch.object(
+ self.ixnet_gen, '_get_config_element_by_flow_group_name',
+ return_value=None):
+ with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
+ self.ixnet_gen._get_stack_item(mock.ANY, mock.ANY)
+
+ def test__get_field_in_stack_item(self):
+ self.ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
+ output = self.ixnet_gen._get_field_in_stack_item(mock.ANY, 'field2')
+ self.assertEqual('field2', output)
+
+ def test__get_field_in_stack_item_no_field_present(self):
+ self.ixnet_gen._ixnet.getList.return_value = ['field1', 'field2']
+ with self.assertRaises(exceptions.IxNetworkFieldNotPresentInStackItem):
+ self.ixnet_gen._get_field_in_stack_item(mock.ANY, 'field3')
+
+ def test__parse_framesize(self):
+ framesize = {'64B': '75', '512b': '25'}
+ output = self.ixnet_gen._parse_framesize(framesize)
+ self.assertEqual(2, len(output))
+ self.assertIn([64, 64, 75], output)
+ self.assertIn([512, 512, 25], output)
+
+ def test_add_topology(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_topology('topology 1', 'vports')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('my_root', 'topology')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'topology 1', '-vports', 'vports')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_device_group(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_device_group('topology', 'device group 1', '1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('topology',
+ 'deviceGroup')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'device group 1', '-multiplier', '1')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_ethernet(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_ethernet('device_group', 'ethernet 1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('device_group',
+ 'ethernet')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'obj', '-name', 'ethernet 1')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_add_vlans_single(self):
+ obj = 'ethernet'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.ixnet.getList.return_value = ['vlan1', 'vlan2']
+ vlan1 = ixnet_api.Vlan(vlan_id=100, tp_id='ethertype88a8', prio=2)
+ vlan2 = ixnet_api.Vlan(vlan_id=101, tp_id='ethertype88a8', prio=3)
+ self.ixnet_gen.add_vlans(obj, [vlan1, vlan2])
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('ethernet',
+ '-vlanCount', 2)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 100)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 101)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 2)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('attr/singleValue',
+ '-value', 3)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'ethertype88a8')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_vlans_increment(self):
+ obj = 'ethernet'
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.ixnet.getList.return_value = ['vlan1']
+ vlan = ixnet_api.Vlan(vlan_id=100, vlan_id_step=1, prio=3, prio_step=2)
+ self.ixnet_gen.add_vlans(obj, [vlan])
+ self.ixnet.setMultiAttribute.assert_any_call('obj', '-start', 100,
+ '-step', 1,
+ '-direction', 'increment')
+ self.ixnet.setMultiAttribute.assert_any_call('obj', '-start', 3,
+ '-step', 2,
+ '-direction', 'increment')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_vlans_invalid(self):
+ vlans = []
+ self.assertRaises(RuntimeError, self.ixnet_gen.add_vlans, 'obj', vlans)
+
+ def test_add_ipv4(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_ipv4_single(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1', addr='100.1.1.100',
+ prefix='24', gateway='100.1.1.200')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '100.1.1.100')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '24')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '100.1.1.200')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_ipv4_counter(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_ipv4('ethernet 1', name='ipv4 1',
+ addr='100.1.1.100',
+ addr_step='1',
+ addr_direction='increment',
+ prefix='24',
+ gateway='100.1.1.200',
+ gw_step='1',
+ gw_direction='increment')
+ self.ixnet_gen.ixnet.add.assert_any_call('ethernet 1', 'ipv4')
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with('obj',
+ '-name',
+ 'ipv4 1')
+ self.ixnet_gen.ixnet.add.assert_any_call('attr', 'counter')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('obj', '-start',
+ '100.1.1.100',
+ '-step', '1',
+ '-direction',
+ 'increment')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '24')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call('obj', '-start',
+ '100.1.1.200',
+ '-step', '1',
+ '-direction',
+ 'increment')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_pppox_client(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_pppox_client('ethernet 1', 'pap', 'user', 'pwd')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ethernet 1',
+ 'pppoxclient')
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'pap')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'user')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'pwd')
+
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test_add_pppox_client_invalid_auth(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.assertRaises(NotImplementedError, self.ixnet_gen.add_pppox_client,
+ 'ethernet 1', 'invalid_auth', 'user', 'pwd')
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_not_called()
+
+ def test_add_bgp(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.ixnet.getAttribute.return_value = 'attr'
+ self.ixnet_gen.add_bgp(ipv4='ipv4 1',
+ dut_ip='10.0.0.1',
+ local_as=65000,
+ bgp_type='external')
+ self.ixnet_gen.ixnet.add.assert_called_once_with('ipv4 1', 'bgpIpv4Peer')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', '10.0.0.1')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 65000)
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'attr/singleValue', '-value', 'external')
+
+ def test_add_interface(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_interface(vport='vport',
+ ip='10.0.0.2',
+ mac='00:00:00:00:00:00',
+ gateway='10.0.0.1')
+ self.ixnet_gen.ixnet.add.assert_any_call('vport', 'interface')
+ self.ixnet_gen.ixnet.add.assert_any_call('obj', 'ipv4')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'obj/ethernet', '-macAddress', '00:00:00:00:00:00')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'obj', '-ip', '10.0.0.2')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'obj', '-gateway', '10.0.0.1')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'obj', '-enabled', 'true')
+
+ def test_add_static_ipv4(self):
+ self.ixnet_gen.ixnet.add.return_value = 'obj'
+ self.ixnet_gen.add_static_ipv4(iface='iface',
+ vport='vport',
+ start_ip='10.0.0.0',
+ count='100',
+ mask='32')
+ self.ixnet_gen.ixnet.add.assert_called_once_with(
+ 'vport/protocols/static', 'ip')
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_any_call(
+ 'obj', '-protocolInterface', 'iface',
+ '-ipStart', '10.0.0.0',
+ '-count', '100',
+ '-mask', '32',
+ '-enabled', 'true')
+
+ @mock.patch.object(IxNetwork, 'IxNet')
+ def test_connect(self, mock_ixnet):
+ mock_ixnet.return_value = self.ixnet
+ with mock.patch.object(self.ixnet_gen, 'get_config') as mock_config:
+ mock_config.return_value = {'machine': 'machine_fake',
+ 'port': 'port_fake',
+ 'version': 12345}
+ self.ixnet_gen.connect(mock.ANY)
+
+ self.ixnet.connect.assert_called_once_with(
+ 'machine_fake', '-port', 'port_fake', '-version', '12345')
+ mock_config.assert_called_once()
+
+ def test_connect_invalid_config_no_machine(self):
+ self.ixnet_gen.get_config = mock.Mock(return_value={
+ 'port': 'port_fake',
+ 'version': '12345'})
+ self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
+ self.ixnet.connect.assert_not_called()
+
+ def test_connect_invalid_config_no_port(self):
+ self.ixnet_gen.get_config = mock.Mock(return_value={
+ 'machine': 'machine_fake',
+ 'version': '12345'})
+ self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
+ self.ixnet.connect.assert_not_called()
+
+ def test_connect_invalid_config_no_version(self):
+ self.ixnet_gen.get_config = mock.Mock(return_value={
+ 'machine': 'machine_fake',
+ 'port': 'port_fake'})
+ self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
+ self.ixnet.connect.assert_not_called()
+
+ def test_connect_no_config(self):
+ self.ixnet_gen.get_config = mock.Mock(return_value={})
+ self.assertRaises(KeyError, self.ixnet_gen.connect, mock.ANY)
+ self.ixnet.connect.assert_not_called()
+
+ def test_clear_config(self):
+ self.ixnet_gen.clear_config()
+ self.ixnet.execute.assert_called_once_with('newConfig')
+
+ @mock.patch.object(ixnet_api, 'log')
+ def test_assign_ports_2_ports(self, *args):
+ self.ixnet.getAttribute.side_effect = ['up', 'down']
+ config = {
+ 'chassis': '1.1.1.1',
+ 'cards': ['1', '2'],
+ 'ports': ['2', '2']}
+ self.ixnet_gen._cfg = config
+
+ self.assertIsNone(self.ixnet_gen.assign_ports())
+ self.assertEqual(self.ixnet.execute.call_count, 1)
+ self.assertEqual(self.ixnet.commit.call_count, 3)
+ self.assertEqual(self.ixnet.getAttribute.call_count, 2)
+
+ @mock.patch.object(ixnet_api, 'log')
+ def test_assign_ports_port_down(self, mock_log):
+ self.ixnet.getAttribute.return_value = 'down'
+ config = {
+ 'chassis': '1.1.1.1',
+ 'cards': ['1', '2'],
+ 'ports': ['3', '4']}
+ self.ixnet_gen._cfg = config
+ self.ixnet_gen.assign_ports()
+ mock_log.warning.assert_called()
+
+ def test_assign_ports_no_config(self):
+ self.ixnet_gen._cfg = {}
+ self.assertRaises(KeyError, self.ixnet_gen.assign_ports)
+
+ def test__create_traffic_item(self):
+ self.ixnet.add.return_value = 'my_new_traffic_item'
+ self.ixnet.remapIds.return_value = ['my_traffic_item_id']
+
+ self.ixnet_gen._create_traffic_item()
+ self.ixnet.add.assert_called_once_with(
+ 'my_root/traffic', 'trafficItem')
+ self.ixnet.setMultiAttribute.assert_called_once_with(
+ 'my_new_traffic_item', '-name', 'RFC2544', '-trafficType', 'raw')
+ self.assertEqual(2, self.ixnet.commit.call_count)
+ self.ixnet.remapIds.assert_called_once_with('my_new_traffic_item')
+ self.ixnet.setAttribute('my_traffic_item_id/tracking',
+ '-trackBy', 'trafficGroupId0')
+
+ def test__create_flow_groups(self):
+ uplink_endpoints = ['up_endp1', 'up_endp2']
+ downlink_endpoints = ['down_endp1', 'down_endp2']
+ self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
+ self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2', 'endp3',
+ 'endp4']
+ self.ixnet_gen._create_flow_groups(uplink_endpoints, downlink_endpoints)
+ self.ixnet_gen.ixnet.add.assert_has_calls([
+ mock.call('traffic_item', 'endpointSet'),
+ mock.call('traffic_item', 'endpointSet')])
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
+ mock.call('endp1', '-name', '1', '-sources', ['up_endp1'],
+ '-destinations', ['down_endp1']),
+ mock.call('endp2', '-name', '2', '-sources', ['down_endp1'],
+ '-destinations', ['up_endp1']),
+ mock.call('endp3', '-name', '3', '-sources', ['up_endp2'],
+ '-destinations', ['down_endp2']),
+ mock.call('endp4', '-name', '4', '-sources', ['down_endp2'],
+ '-destinations', ['up_endp2'])])
+
+ def test__append_protocol_to_stack(self):
+
+ self.ixnet_gen._append_procotol_to_stack('my_protocol', 'prev_element')
+ self.ixnet.execute.assert_called_with(
+ 'append', 'prev_element',
+ 'my_root/traffic/protocolTemplate:"my_protocol"')
+
+ def test__setup_config_elements(self):
+ # the config parsed from some_file
+ yaml_data = {'traffic_profile': {}
+ }
+ traffic_profile = ixia_rfc2544.IXIARFC2544Profile(yaml_data)
+ traffic_profile.params = TRAFFIC_PROFILE
+ self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'],
+ ['cfg_element']]
+ with mock.patch.object(self.ixnet_gen, '_append_procotol_to_stack') as \
+ mock_append_proto:
+ self.ixnet_gen._setup_config_elements(traffic_profile=traffic_profile)
+ mock_append_proto.assert_has_calls([
+ mock.call(ixnet_api.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'),
+ mock.call(ixnet_api.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')])
+ self.ixnet_gen.ixnet.setAttribute.assert_has_calls([
+ mock.call('cfg_element/frameRateDistribution', '-portDistribution',
+ 'splitRateEvenly'),
+ mock.call('cfg_element/frameRateDistribution',
+ '-streamDistribution', 'splitRateEvenly')])
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
+ @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
+ def test_create_traffic_model(self, mock__setup_config_elements,
+ mock__create_flow_groups,
+ mock__create_traffic_item):
+ # the config parsed from some_file
+ yaml_data = {'traffic_profile': {}}
+ traffic_profile = ixia_rfc2544.IXIARFC2544Profile(yaml_data)
+ uplink_ports = ['port1', 'port3']
+ downlink_ports = ['port2', 'port4']
+ uplink_endpoints = ['port1/protocols', 'port3/protocols']
+ downlink_endpoints = ['port2/protocols', 'port4/protocols']
+ self.ixnet_gen.create_traffic_model(uplink_ports, downlink_ports,
+ traffic_profile=traffic_profile)
+ mock__create_traffic_item.assert_called_once_with('raw')
+ mock__create_flow_groups.assert_called_once_with(uplink_endpoints,
+ downlink_endpoints)
+ mock__setup_config_elements.assert_called_once()
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
+ @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
+ @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
+ def test_create_ipv4_traffic_model(self, mock__setup_config_elements,
+ mock__create_flow_groups,
+ mock__create_traffic_item):
+ uplink_topologies = ['up1', 'up3']
+ downlink_topologies = ['down2', 'down4']
+ traffic_profile = 'fake_profile'
+ self.ixnet_gen.create_ipv4_traffic_model(uplink_topologies,
+ downlink_topologies,
+ traffic_profile)
+ mock__create_traffic_item.assert_called_once_with('ipv4')
+ mock__create_flow_groups.assert_called_once_with(uplink_topologies,
+ downlink_topologies)
+ mock__setup_config_elements.assert_called_once_with(
+ traffic_profile='fake_profile', add_default_proto=False)
+
+ def test_flows_settings(self):
+ cfg = {'uplink_0': {
+ 'ipv4': {
+ 'outer_l2': {
+ 'framesize': {
+ '128B': '0',
+ '1518B': '0',
+ '64B': '0',
+ '373b': '0',
+ '256B': '0',
+ '1400B': '0',
+ '570B': '0'}},
+ 'id': 1}}}
+
+ expected = [
+ {'ipv4': {
+ 'id': 1,
+ 'outer_l2': {
+ 'framesize': {
+ '1518B': '0',
+ '1400B': '0',
+ '128B': '0',
+ '64B': '0',
+ '256B': '0',
+ '373b': '0',
+ '570B': '0'}}}}]
+
+ self.assertEqual(expected, self.ixnet_gen._flows_settings(cfg=cfg))
+
+ def test_is_qinq(self):
+ flow_data = {'ipv4': {
+ 'outer_l2': {},
+ 'id': 1}}
+ self.assertEqual(False, self.ixnet_gen.is_qinq(flow_data=flow_data))
+
+ flow_data = {'ipv4': {
+ 'outer_l2': {
+ 'QinQ': {
+ 'C-VLAN': {
+ 'priority': 0,
+ 'cfi': 0,
+ 'id': 512},
+ 'S-VLAN': {
+ 'priority': 0,
+ 'cfi': 0,
+ 'id': 128}},
+ },
+ 'id': 1}}
+ self.assertEqual(True, self.ixnet_gen.is_qinq(flow_data=flow_data))
+
+ def test__update_frame_mac(self):
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item') as \
+ mock_get_field:
+ mock_get_field.return_value = 'field_descriptor'
+ self.ixnet_gen._update_frame_mac('ethernet_descriptor', 'field', 'mac')
+ mock_get_field.assert_called_once_with('ethernet_descriptor', 'field')
+ self.ixnet_gen.ixnet.setMultiAttribute(
+ 'field_descriptor', '-singleValue', 'mac', '-fieldValue', 'mac',
+ '-valueType', 'singleValue')
+ self.ixnet_gen.ixnet.commit.assert_called_once()
+
+ def test_update_frame(self):
+ with mock.patch.object(
+ self.ixnet_gen, '_get_config_element_by_flow_group_name',
+ return_value='cfg_element'), \
+ mock.patch.object(self.ixnet_gen, '_update_frame_mac') as \
+ mock_update_frame, \
+ mock.patch.object(self.ixnet_gen, '_get_stack_item') as \
+ mock_get_stack_item:
+ mock_get_stack_item.side_effect = [['item1'], ['item2'],
+ ['item3'], ['item4']]
+ self.ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 50)
+
+ self.assertEqual(6, len(self.ixnet_gen.ixnet.setMultiAttribute.mock_calls))
+ self.assertEqual(4, len(mock_update_frame.mock_calls))
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
+ mock.call('cfg_element/transmissionControl',
+ '-type', 'continuous', '-duration', 50)
+ ])
+
+ def test_update_frame_qinq(self):
+ with mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name',
+ return_value='cfg_element'), \
+ mock.patch.object(self.ixnet_gen, '_update_frame_mac'),\
+ mock.patch.object(self.ixnet_gen, '_get_stack_item',
+ return_value='item'), \
+ mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field'):
+
+ traffic_parameters = deepcopy(TRAFFIC_PARAMETERS)
+ traffic_parameters[UPLINK]['outer_l2']['QinQ'] = {
+ 'S-VLAN': {'id': 128,
+ 'priority': 1,
+ 'cfi': 0},
+ 'C-VLAN': {'id': 512,
+ 'priority': 0,
+ 'cfi': 2}
+ }
+
+ self.ixnet_gen.update_frame(traffic_parameters, 50)
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
+ mock.call('field', '-auto', 'false', '-singleValue', '0x88a8',
+ '-fieldValue', '0x88a8', '-valueType', 'singleValue'),
+ mock.call('field', '-auto', 'false', '-singleValue', 1,
+ '-fieldValue', 1, '-valueType', 'singleValue'),
+ mock.call('field', '-auto', 'false', '-singleValue', 128,
+ '-fieldValue', 128, '-valueType', 'singleValue'),
+ mock.call('field', '-auto', 'false', '-singleValue', 512,
+ '-fieldValue', 512, '-valueType', 'singleValue'),
+ mock.call('field', '-auto', 'false', '-singleValue', 2,
+ '-fieldValue', 2, '-valueType', 'singleValue')
+ ], any_order=True)
+
+ def test_update_frame_flow_not_present(self):
+ with mock.patch.object(
+ self.ixnet_gen, '_get_config_element_by_flow_group_name',
+ return_value=None):
+ with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
+ self.ixnet_gen.update_frame(TRAFFIC_PARAMETERS, 40)
+
+ def test_get_statistics(self):
+ with mock.patch.object(self.ixnet_gen, '_build_stats_map') as \
+ mock_build_stats:
+ self.ixnet_gen.get_statistics()
+
+ mock_build_stats.assert_has_calls([
+ mock.call(self.ixnet_gen.PORT_STATISTICS,
+ self.ixnet_gen.PORT_STATS_NAME_MAP),
+ mock.call(self.ixnet_gen.FLOW_STATISTICS,
+ self.ixnet_gen.LATENCY_NAME_MAP)])
+
+ def test_set_flow_tracking(self):
+ self.ixnet_gen._ixnet.getList.return_value = ['traffic_item']
+ self.ixnet_gen.set_flow_tracking(track_by=['vlanVlanId0'])
+ self.ixnet_gen.ixnet.setAttribute.assert_called_once_with(
+ 'traffic_item/tracking', '-trackBy', ['vlanVlanId0'])
+ self.assertEqual(self.ixnet.commit.call_count, 1)
+
+ def test__set_egress_flow_tracking(self):
+ self.ixnet_gen._ixnet.getList.side_effect = [['traffic_item'],
+ ['encapsulation']]
+ self.ixnet_gen._set_egress_flow_tracking(encapsulation='Ethernet',
+ offset='IPv4 TOS Precedence')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'traffic_item', '-egressEnabled', True)
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'encapsulation', '-encapsulation', 'Ethernet')
+ self.ixnet_gen.ixnet.setAttribute.assert_any_call(
+ 'encapsulation', '-offset', 'IPv4 TOS Precedence')
+ self.assertEqual(self.ixnet.commit.call_count, 2)
+
+ def test__get_view_page_stats(self):
+ expected_stats = [
+ {'header1': 'row1_1', 'header2': 'row1_2'},
+ {'header1': 'row2_1', 'header2': 'row2_2'}
+ ]
+ self.ixnet_gen._ixnet.getAttribute.side_effect = [
+ ['header1', 'header2'],
+ [
+ [['row1_1', 'row1_2']],
+ [['row2_1', 'row2_2']]
+ ]
+ ]
+ stats = self.ixnet_gen._get_view_page_stats('view_obj')
+ self.assertListEqual(stats, expected_stats)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_view_page_stats')
+ def test_get_pppoe_scenario_statistics(self, mock_get_view):
+
+ pattern = re.compile('Flow 2')
+
+ expected_stats = {
+ 'port_statistics': [{
+ 'port_1': 'port_stat1',
+ 'port_2': 'port_stat2'
+ }],
+ 'flow_statistic': [{
+ 'flow_1': 'flow_stat1',
+ 'flow_2': 'flow_stat2'
+ }],
+ 'pppox_client_per_port': [{
+ 'sub_1': 'sub_stat1',
+ 'sub_2': 'sub_stat2'
+ }]
+ }
+
+ pppoe_scenario_stats = OrderedDict([
+ ('port_statistics', 'view_obj'),
+ ('flow_statistic', 'view_obj'),
+ ('pppox_client_per_port', 'view_obj')
+ ])
+
+ pppoe_scenario_stats_map = {
+ 'port_statistics': {'port_1': 'Port 1',
+ 'port_2': 'Port 2'},
+ 'flow_statistic': {'flow_1': 'Flow 1',
+ 'flow_2': pattern},
+ 'pppox_client_per_port': {'sub_1': 'Sub 1',
+ 'sub_2': 'Sub 2'}
+ }
+
+ # All stats keys
+ port_stats = [{'Port 1': 'port_stat1',
+ 'Port 2': 'port_stat2',
+ 'Port 3': 'port_stat3'}]
+ flows_stats = [{'Flow 1': 'flow_stat1',
+ 'Flow 2': 'flow_stat2',
+ 'Flow 3': 'flow_stat3'}]
+ pppoe_sub_stats = [{'Sub 1': 'sub_stat1',
+ 'Sub 2': 'sub_stat2',
+ 'Sub 3': 'sub_stat3'}]
+
+ mock_get_view.side_effect = [port_stats, flows_stats, pppoe_sub_stats]
+ self.ixnet_gen._ixnet.getAttribute.return_value = '1'
+
+ with mock.patch.multiple(ixnet_api.IxNextgen,
+ PPPOE_SCENARIO_STATS=pppoe_scenario_stats,
+ PPPOE_SCENARIO_STATS_MAP=pppoe_scenario_stats_map):
+ stats = self.ixnet_gen.get_pppoe_scenario_statistics()
+ self.assertDictEqual(stats, expected_stats)
+ self.assertEqual(self.ixnet_gen.ixnet.getAttribute.call_count, 6)
+ self.ixnet_gen.ixnet.setAttribute.assert_not_called()
+
+ def test__update_ipv4_address(self):
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_ipv4_address(mock.ANY, mock.ANY, '192.168.1.1',
+ 100, 26, 25)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'field_desc', '-seed', 100, '-fixedBits', '192.168.1.1',
+ '-randomMask', '0.0.0.63', '-valueType', 'random',
+ '-countValue', 25)
+
+ def test__update_ipv4_priority_raw(self):
+ priority = {'raw': '0x01'}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+
+ self.ixnet_gen._set_priority_field.assert_called_once_with(
+ 'field_desc', priority['raw'])
+
+ def test__update_ipv4_priority_dscp(self):
+ priority = {'dscp': {'defaultPHB': [0, 1, 2, 3]}}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+
+ self.ixnet_gen._set_priority_field.assert_called_once_with(
+ 'field_desc', priority['dscp']['defaultPHB'])
+
+ def test__update_ipv4_priority_tos(self):
+ priority = {'tos': {'precedence': [0, 4, 7]}}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+
+ self.ixnet_gen._set_priority_field.assert_called_once_with(
+ 'field_desc', priority['tos']['precedence'])
+
+ def test__update_ipv4_priority_wrong_priority_type(self):
+ priority = {'test': [0, 4, 7]}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+
+ self.ixnet_gen._set_priority_field.assert_not_called()
+
+ def test__update_ipv4_priority_not_supported_dscp_class(self):
+ priority = {'dscp': {'testPHB': [0, 4, 7]}}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ self.ixnet_gen._get_field_in_stack_item = mock.Mock()
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+ self.ixnet_gen._set_priority_field.assert_not_called()
+ self.ixnet_gen._get_field_in_stack_item.assert_not_called()
+
+ def test__update_ipv4_priority_not_supported_tos_field(self):
+ priority = {'tos': {'test': [0, 4, 7]}}
+ self.ixnet_gen._set_priority_field = mock.Mock()
+ self.ixnet_gen._get_field_in_stack_item = mock.Mock()
+ self.ixnet_gen._update_ipv4_priority('field_desc', priority)
+ self.ixnet_gen._set_priority_field.assert_not_called()
+ self.ixnet_gen._get_field_in_stack_item.assert_not_called()
+
+ def test__set_priority_field_list_value(self):
+ value = [1, 4, 7]
+ self.ixnet_gen._set_priority_field('field_desc', value)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'field_desc',
+ '-valueList', [1, 4, 7],
+ '-activeFieldChoice', 'true',
+ '-valueType', 'valueList')
+
+ def test__set_priority_field_single_value(self):
+ value = 7
+ self.ixnet_gen._set_priority_field('field_desc', value)
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'field_desc',
+ '-activeFieldChoice', 'true',
+ '-singleValue', '7')
+
+ def test__update_udp_port(self):
+ with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item',
+ return_value='field_desc'):
+ self.ixnet_gen._update_udp_port(mock.ANY, mock.ANY, 1234,
+ 2, 0, 2)
+
+ self.ixnet_gen.ixnet.setMultiAttribute.assert_called_once_with(
+ 'field_desc',
+ '-auto', 'false',
+ '-seed', 1,
+ '-fixedBits', 1234,
+ '-randomMask', 0,
+ '-valueType', 'random',
+ '-countValue', 1)
+
+ def test_update_ip_packet(self):
+ with mock.patch.object(self.ixnet_gen, '_update_ipv4_address') as \
+ mock_update_add, \
+ mock.patch.object(self.ixnet_gen, '_get_stack_item'), \
+ mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name', return_value='celm'), \
+ mock.patch.object(self.ixnet_gen, '_update_ipv4_priority') as \
+ mock_update_priority:
+ self.ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
+
+ self.assertEqual(4, len(mock_update_add.mock_calls))
+ self.assertEqual(2, len(mock_update_priority.mock_calls))
+
+ def test_update_ip_packet_exception_no_config_element(self):
+ with mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name',
+ return_value=None):
+ with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
+ self.ixnet_gen.update_ip_packet(TRAFFIC_PARAMETERS)
+
+ def test_update_l4(self):
+ with mock.patch.object(self.ixnet_gen, '_update_udp_port') as \
+ mock_update_udp, \
+ mock.patch.object(self.ixnet_gen, '_get_stack_item'), \
+ mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name', return_value='celm'):
+ self.ixnet_gen.update_l4(TRAFFIC_PARAMETERS)
+
+ self.assertEqual(4, len(mock_update_udp.mock_calls))
+
+ def test_update_l4_exception_no_config_element(self):
+ with mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name',
+ return_value=None):
+ with self.assertRaises(exceptions.IxNetworkFlowNotPresent):
+ self.ixnet_gen.update_l4(TRAFFIC_PARAMETERS)
+
+ def test_update_l4_exception_no_supported_proto(self):
+ traffic_parameters = {
+ UPLINK: {
+ 'id': 1,
+ 'outer_l3': {
+ 'proto': 'unsupported',
+ },
+ 'outer_l4': {
+ 'seed': 1
+ }
+ },
+ }
+ with mock.patch.object(self.ixnet_gen,
+ '_get_config_element_by_flow_group_name',
+ return_value='celm'):
+ with self.assertRaises(exceptions.IXIAUnsupportedProtocol):
+ self.ixnet_gen.update_l4(traffic_parameters)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
+ def test_start_traffic(self, mock_ixnextgen_get_traffic_state):
+ self.ixnet_gen._ixnet.getList.return_value = [0]
+
+ mock_ixnextgen_get_traffic_state.side_effect = [
+ 'stopped', 'started', 'started', 'started']
+
+ result = self.ixnet_gen.start_traffic()
+ self.assertIsNone(result)
+ self.ixnet.getList.assert_called_once()
+ self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
+ def test_start_traffic_traffic_running(
+ self, mock_ixnextgen_get_traffic_state):
+ self.ixnet_gen._ixnet.getList.return_value = [0]
+ mock_ixnextgen_get_traffic_state.side_effect = [
+ 'started', 'stopped', 'started']
+
+ result = self.ixnet_gen.start_traffic()
+ self.assertIsNone(result)
+ self.ixnet.getList.assert_called_once()
+ self.assertEqual(4, self.ixnet_gen._ixnet.execute.call_count)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
+ def test_start_traffic_wait_for_traffic_to_stop(
+ self, mock_ixnextgen_get_traffic_state):
+ self.ixnet_gen._ixnet.getList.return_value = [0]
+ mock_ixnextgen_get_traffic_state.side_effect = [
+ 'started', 'started', 'started', 'stopped', 'started']
+
+ result = self.ixnet_gen.start_traffic()
+ self.assertIsNone(result)
+ self.ixnet.getList.assert_called_once()
+ self.assertEqual(4, self.ixnet_gen._ixnet.execute.call_count)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_traffic_state')
+ def test_start_traffic_wait_for_traffic_start(
+ self, mock_ixnextgen_get_traffic_state):
+ self.ixnet_gen._ixnet.getList.return_value = [0]
+ mock_ixnextgen_get_traffic_state.side_effect = [
+ 'stopped', 'stopped', 'stopped', 'started']
+
+ result = self.ixnet_gen.start_traffic()
+ self.assertIsNone(result)
+ self.ixnet.getList.assert_called_once()
+ self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
+
+ def test__get_protocol_status(self):
+ self.ixnet.getAttribute.return_value = ['up']
+ self.ixnet_gen._get_protocol_status('ipv4')
+ self.ixnet.getAttribute.assert_called_once_with('ipv4',
+ '-sessionStatus')
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_protocol_status')
+ def test_is_protocols_running(self, mock_ixnextgen_get_protocol_status):
+ mock_ixnextgen_get_protocol_status.return_value = ['up', 'up']
+ result = self.ixnet_gen.is_protocols_running(['ethernet', 'ipv4'])
+ self.assertTrue(result)
+
+ @mock.patch.object(ixnet_api.IxNextgen, '_get_protocol_status')
+ def test_is_protocols_stopped(self, mock_ixnextgen_get_protocol_status):
+ mock_ixnextgen_get_protocol_status.return_value = ['down', 'down']
+ result = self.ixnet_gen.is_protocols_running(['ethernet', 'ipv4'])
+ self.assertFalse(result)
+
+ def test_start_protocols(self):
+ self.ixnet_gen.start_protocols()
+ self.ixnet.execute.assert_called_once_with('startAllProtocols')
+
+ def test_stop_protocols(self):
+ self.ixnet_gen.stop_protocols()
+ self.ixnet.execute.assert_called_once_with('stopAllProtocols')
+
+ def test_get_vports(self):
+ self.ixnet_gen._ixnet.getRoot.return_value = 'root'
+ self.ixnet_gen.get_vports()
+ self.ixnet.getList.assert_called_once_with('root', 'vport')
diff --git a/yardstick/tests/unit/network_services/nfvi/__init__.py b/yardstick/tests/unit/network_services/nfvi/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/nfvi/__init__.py
diff --git a/yardstick/tests/unit/network_services/nfvi/test_collectd.py b/yardstick/tests/unit/network_services/nfvi/test_collectd.py
new file mode 100644
index 000000000..fe59aecfb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/nfvi/test_collectd.py
@@ -0,0 +1,150 @@
+# 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.
+
+import unittest
+import multiprocessing
+import mock
+
+from yardstick.network_services.nfvi.collectd import AmqpConsumer
+
+
+class TestAmqpConsumer(unittest.TestCase):
+ def setUp(self):
+ self.queue = multiprocessing.Queue()
+ self.url = 'amqp://admin:admin@127.0.0.1:5672/%2F'
+ self.amqp_consumer = AmqpConsumer(self.url, self.queue)
+
+ def test___init__(self):
+ self.assertEqual(self.url, self.amqp_consumer._url)
+
+ def test_on_connection_open(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.add_on_close_callback = \
+ mock.Mock(return_value=0)
+ self.amqp_consumer._connection.channel = mock.Mock(return_value=0)
+ self.assertIsNone(self.amqp_consumer.on_connection_open(10))
+
+ def test_on_connection_closed(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.ioloop = mock.Mock()
+ self.amqp_consumer._connection.ioloop.stop = mock.Mock(return_value=0)
+ self.amqp_consumer._connection.add_timeout = mock.Mock(return_value=0)
+ self.amqp_consumer._closing = True
+ self.assertIsNone(
+ self.amqp_consumer.on_connection_closed("", 404, "Not Found"))
+ self.amqp_consumer._closing = False
+ self.assertIsNone(
+ self.amqp_consumer.on_connection_closed("", 404, "Not Found"))
+
+ def test_reconnect(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.ioloop = mock.Mock()
+ self.amqp_consumer._connection.ioloop.stop = mock.Mock(return_value=0)
+ self.amqp_consumer.connect = mock.Mock(return_value=0)
+ self.amqp_consumer._closing = True
+ self.assertIsNone(self.amqp_consumer.reconnect())
+
+ def test_on_channel_open(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.add_on_close_callback = \
+ mock.Mock(return_value=0)
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer.add_on_channel_close_callback = mock.Mock()
+ self.amqp_consumer._channel.exchange_declare = \
+ mock.Mock(return_value=0)
+ self.assertIsNone(
+ self.amqp_consumer.on_channel_open(self.amqp_consumer._channel))
+
+ def test_add_on_channel_close_callback(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.add_on_close_callback = \
+ mock.Mock(return_value=0)
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.add_on_close_callback = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.add_on_channel_close_callback())
+
+ def test_on_channel_closed(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.close = mock.Mock(return_value=0)
+ _channel = mock.Mock()
+ self.assertIsNone(
+ self.amqp_consumer.on_channel_closed(_channel, "", ""))
+
+ def test_ion_exchange_declareok(self):
+ self.amqp_consumer.setup_queue = mock.Mock(return_value=0)
+ self.assertIsNone(self.amqp_consumer.on_exchange_declareok(10))
+
+ def test_setup_queue(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.add_on_close_callback = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.setup_queue("collectd"))
+
+ def test_on_queue_declareok(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.queue_bind = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.on_queue_declareok(10))
+
+ def test__on_bindok(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.basic_consume = mock.Mock()
+ self.amqp_consumer.add_on_cancel_callback = mock.Mock()
+ self.assertIsNone(self.amqp_consumer._on_bindok(10))
+
+ def test_add_on_cancel_callback(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.add_on_cancel_callback = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.add_on_cancel_callback())
+
+ def test_on_consumer_cancelled(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.close = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.on_consumer_cancelled(10))
+
+ def test_on_message(self):
+ body = "msg {} cpu/cpu-0/ipc 101010:10"
+ properties = ""
+ basic_deliver = mock.Mock()
+ basic_deliver.delivery_tag = mock.Mock(return_value=0)
+ self.amqp_consumer.ack_message = mock.Mock()
+ self.assertIsNone(
+ self.amqp_consumer.on_message(10, basic_deliver, properties, body))
+
+ def test_ack_message(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.basic_ack = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.ack_message(10))
+
+ def test_on_cancelok(self):
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.close = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.on_cancelok(10))
+
+ def test_run(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer.connect = mock.Mock()
+ self.amqp_consumer._connection.ioloop.start = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.run())
+
+ def test_stop(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer.connect = mock.Mock()
+ self.amqp_consumer._connection.ioloop.start = mock.Mock()
+ self.amqp_consumer._channel = mock.Mock()
+ self.amqp_consumer._channel.basic_cancel = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.stop())
+
+ def test_close_connection(self):
+ self.amqp_consumer._connection = mock.Mock(autospec=AmqpConsumer)
+ self.amqp_consumer._connection.close = mock.Mock()
+ self.assertIsNone(self.amqp_consumer.close_connection())
diff --git a/yardstick/tests/unit/network_services/nfvi/test_resource.py b/yardstick/tests/unit/network_services/nfvi/test_resource.py
new file mode 100644
index 000000000..c06658218
--- /dev/null
+++ b/yardstick/tests/unit/network_services/nfvi/test_resource.py
@@ -0,0 +1,319 @@
+# 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.
+
+import errno
+
+import mock
+import unittest
+
+from yardstick.common import exceptions
+from yardstick.common.exceptions import ResourceCommandError
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.nfvi import resource, collectd
+
+
+class TestResourceProfile(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '172.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '172.16.100.20',
+ 'if': 'xe0'},
+ {'network': '172.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '172.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '3c:fd:fe:9e:64:38',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '172.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '172.16.100.20',
+ 'local_mac': '3c:fd:fe:a1:2b:80'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:1e:67:d0:60:5c',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '172.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '172.16.40.20',
+ 'local_mac': '3c:fd:fe:a1:2b:81'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '127.0.0.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '127.0.0.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ def setUp(self):
+ with mock.patch("yardstick.ssh.AutoConnectSSH") as ssh:
+ self.ssh_mock = mock.Mock(autospec=ssh.SSH)
+ self.ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = self.ssh_mock
+
+ mgmt = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]['mgmt-interface']
+ # interfaces = \
+ # self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]['vdu'][0]['external-interface']
+ port_names = \
+ self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]['vdu'][0]['external-interface']
+ self.resource_profile = \
+ ResourceProfile(mgmt, port_names)
+ self.resource_profile.connection = self.ssh_mock
+
+ def test___init__(self):
+ self.assertTrue(self.resource_profile.enable)
+
+ def test_check_if_system_agent_running(self):
+ self.assertEqual(self.resource_profile.check_if_system_agent_running("collectd"),
+ (0, ""))
+
+ def test_check_if_system_agent_running_excetion(self):
+ with mock.patch.object(self.resource_profile.connection, "execute") as mock_execute:
+ mock_execute.side_effect = OSError(errno.ECONNRESET, "error")
+ self.assertEqual(
+ self.resource_profile.check_if_system_agent_running("collectd"),
+ (1, None))
+
+ def test_get_cpu_data(self):
+ reskey = ["", "cpufreq", "cpufreq-0"]
+ value = "metric:10"
+ val = self.resource_profile.get_cpu_data(reskey[1], reskey[2], value)
+ self.assertIsNotNone(val)
+
+ def test_get_cpu_data_error(self):
+ reskey = ["", "", ""]
+ value = "metric:10"
+ val = self.resource_profile.get_cpu_data(reskey[0], reskey[1], value)
+ self.assertEqual(val, ('error', 'Invalid', '', ''))
+
+ def test__start_collectd(self):
+ ssh_mock = mock.Mock()
+ ssh_mock.execute = mock.Mock(return_value=(0, "", ""))
+ self.assertIsNone(self.resource_profile._start_collectd(ssh_mock,
+ "/opt/nsb_bin"))
+
+ ssh_mock.execute = mock.Mock(side_effect=exceptions.SSHError)
+ with self.assertRaises(exceptions.SSHError):
+ self.resource_profile._start_collectd(ssh_mock, "/opt/nsb_bin")
+
+ ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+ with self.assertRaises(ResourceCommandError):
+ self.resource_profile._start_collectd(ssh_mock, "/opt/nsb_bin")
+
+ def test__reset_rabbitmq(self):
+ ssh_mock = mock.Mock()
+ ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+ with self.assertRaises(exceptions.ResourceCommandError):
+ self.resource_profile._reset_rabbitmq(ssh_mock)
+
+ def test__check_rabbitmq_user(self):
+ ssh_mock = mock.Mock()
+ ssh_mock.execute = mock.Mock(return_value=(0, "title\nadmin\t[]", ""))
+ self.assertTrue(self.resource_profile._check_rabbitmq_user(ssh_mock))
+
+ def test__set_rabbitmq_admin_user(self):
+ ssh_mock = mock.Mock()
+ ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+ with self.assertRaises(exceptions.ResourceCommandError):
+ self.resource_profile._set_rabbitmq_admin_user(ssh_mock)
+
+ def test__start_rabbitmq(self):
+ ssh_mock = mock.Mock()
+ self.resource_profile._reset_rabbitmq = mock.Mock()
+ self.resource_profile._set_rabbitmq_admin_user = mock.Mock()
+
+ self.resource_profile._reset_mq_flag = True
+ ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+ with self.assertRaises(exceptions.ResourceCommandError):
+ self.resource_profile._start_rabbitmq(ssh_mock)
+
+ self.resource_profile._reset_mq_flag = False
+ self.resource_profile._check_rabbitmq_user = mock.Mock(return_value=False)
+ ssh_mock.execute = mock.Mock(return_value=(1, "", ""))
+ with self.assertRaises(exceptions.ResourceCommandError):
+ self.resource_profile._start_rabbitmq(ssh_mock)
+
+ def test__prepare_collectd_conf(self):
+ self.assertIsNone(
+ self.resource_profile._prepare_collectd_conf("/opt/nsb_bin"))
+
+ def test__setup_ovs_stats(self):
+ # TODO(elfoley): This method doesn't actually return anything, the side
+ # effects should be checked
+ self.assertIsNone(
+ self.resource_profile._setup_ovs_stats(self.ssh_mock))
+
+ def test__provide_config_file(self,):
+ loadplugin = range(5)
+ port_names = range(5)
+ kwargs = {
+ "interval": '25',
+ "loadplugin": loadplugin,
+ "port_names": port_names,
+ }
+ self.resource_profile._provide_config_file("/opt/nsb_bin", "collectd.conf", kwargs)
+ self.ssh_mock.execute.assert_called_once()
+
+ def test_initiate_systemagent(self):
+ self.resource_profile._start_collectd = mock.Mock()
+ self.resource_profile._start_rabbitmq = mock.Mock()
+ self.assertIsNone(
+ self.resource_profile.initiate_systemagent("/opt/nsb_bin"))
+
+ def test_initiate_systemagent_raise(self):
+ self.resource_profile._start_rabbitmq = mock.Mock(side_effect=RuntimeError)
+ with self.assertRaises(RuntimeError):
+ self.resource_profile.initiate_systemagent("/opt/nsb_bin")
+
+ def test__parse_hugepages(self):
+ reskey = ["cpu", "cpuFreq"]
+ value = "timestamp:12345"
+ res = self.resource_profile.parse_hugepages(reskey, value)
+ self.assertEqual({'cpu/cpuFreq': '12345'}, res)
+
+ def test__parse_dpdkstat(self):
+ reskey = ["dpdk0", "0"]
+ value = "tx:12345"
+ res = self.resource_profile.parse_dpdkstat(reskey, value)
+ self.assertEqual({'dpdk0/0': '12345'}, res)
+
+ def test__parse_virt(self):
+ reskey = ["vm0", "cpu"]
+ value = "load:45"
+ res = self.resource_profile.parse_virt(reskey, value)
+ self.assertEqual({'vm0/cpu': '45'}, res)
+
+ def test__parse_ovs_stats(self):
+ reskey = ["ovs", "stats"]
+ value = "tx:45"
+ res = self.resource_profile.parse_ovs_stats(reskey, value)
+ self.assertEqual({'ovs/stats': '45'}, res)
+
+ def test_parse_collectd_result(self):
+ res = self.resource_profile.parse_collectd_result({})
+ expected_result = {'cpu': {}, 'dpdkstat': {}, 'hugepages': {},
+ 'memory': {}, 'ovs_stats': {}, 'timestamp': '',
+ 'virt': {}}
+ self.assertDictEqual(res, expected_result)
+
+ def test_parse_collectd_result_cpu(self):
+ metric = {"nsb_stats/cpu/0/ipc": "101"}
+ self.resource_profile.get_cpu_data = mock.Mock(return_value=[1,
+ "ipc",
+ "1234",
+ ""])
+ res = self.resource_profile.parse_collectd_result(metric)
+ expected_result = {'cpu': {1: {'ipc': '1234'}}, 'dpdkstat': {}, 'hugepages': {},
+ 'memory': {}, 'ovs_stats': {}, 'timestamp': '',
+ 'virt': {}}
+ self.assertDictEqual(res, expected_result)
+
+ def test_parse_collectd_result_memory(self):
+ metric = {"nsb_stats/memory/bw": "101"}
+ res = self.resource_profile.parse_collectd_result(metric)
+ expected_result = {'cpu': {}, 'dpdkstat': {}, 'hugepages': {},
+ 'memory': {'bw': '101'}, 'ovs_stats': {}, 'timestamp': '',
+ 'virt': {}}
+ self.assertDictEqual(res, expected_result)
+
+ def test_parse_collectd_result_hugepage(self):
+ # amqp returns bytes
+ metric = {b"nsb_stats/hugepages/free": b"101"}
+ self.resource_profile.parse_hugepages = mock.Mock(return_value={"free": "101"})
+ res = self.resource_profile.parse_collectd_result(metric)
+ expected_result = {'cpu': {}, 'dpdkstat': {}, 'hugepages': {'free': '101'},
+ 'memory': {}, 'ovs_stats': {}, 'timestamp': '',
+ 'virt': {}}
+ self.assertDictEqual(res, expected_result)
+
+ def test_parse_collectd_result_dpdk_virt_ovs(self):
+ metric = {b"nsb_stats/dpdkstat/tx": b"101",
+ b"nsb_stats/ovs_stats/tx": b"101",
+ b"nsb_stats/virt/virt/memory": b"101"}
+ self.resource_profile.parse_dpdkstat = \
+ mock.Mock(return_value={"tx": "101"})
+ self.resource_profile.parse_virt = \
+ mock.Mock(return_value={"memory": "101"})
+ self.resource_profile.parse_ovs_stats = \
+ mock.Mock(return_value={"tx": "101"})
+ res = self.resource_profile.parse_collectd_result(metric)
+ expected_result = {'cpu': {}, 'dpdkstat': {'tx': '101'}, 'hugepages': {},
+ 'memory': {}, 'ovs_stats': {'tx': '101'}, 'timestamp': '',
+ 'virt': {'memory': '101'}}
+ self.assertDictEqual(res, expected_result)
+
+ def test_amqp_process_for_nfvi_kpi(self):
+ self.resource_profile.amqp_client = \
+ mock.MagicMock(side_effect=[None, mock.MagicMock()])
+ self.resource_profile.run_collectd_amqp = \
+ mock.Mock(return_value=0)
+ res = self.resource_profile.amqp_process_for_nfvi_kpi()
+ self.assertIsNone(res)
+
+ def test_amqp_collect_nfvi_kpi(self):
+ self.resource_profile.amqp_client = \
+ mock.MagicMock(side_effect=[None, mock.MagicMock()])
+ self.resource_profile.run_collectd_amqp = \
+ mock.Mock(return_value=0)
+ self.resource_profile.parse_collectd_result = mock.Mock()
+ res = self.resource_profile.amqp_collect_nfvi_kpi()
+ self.assertIsNotNone(res)
+
+ def test_run_collectd_amqp(self):
+ resource.AmqpConsumer = mock.Mock(autospec=collectd)
+ self.assertIsNone(self.resource_profile.run_collectd_amqp())
+
+ def test_start(self):
+ self.assertIsNone(self.resource_profile.start())
+
+ def test_stop(self):
+ self.assertIsNone(self.resource_profile.stop())
+
+ def test_stop_amqp_not_running(self):
+ self.resource_profile.amqp_client = mock.MagicMock()
+ # TODO(efoley): Fix this incorrect test.
+ # Should check that we don't try to stop amqp when it's not running
+ self.assertIsNone(self.resource_profile.stop())
diff --git a/yardstick/tests/unit/network_services/test_utils.py b/yardstick/tests/unit/network_services/test_utils.py
new file mode 100644
index 000000000..2b2eb7109
--- /dev/null
+++ b/yardstick/tests/unit/network_services/test_utils.py
@@ -0,0 +1,141 @@
+# 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.
+#
+
+import os
+import unittest
+import mock
+
+from yardstick.network_services import utils
+
+
+class UtilsTestCase(unittest.TestCase):
+ """Test all VNF helper methods."""
+
+ DPDK_PATH = os.path.join(utils.NSB_ROOT, "dpdk-devbind.py")
+
+ def setUp(self):
+ super(UtilsTestCase, self).setUp()
+
+ def test_get_nsb_options(self):
+ result = utils.get_nsb_option("bin_path", None)
+ self.assertEqual(result, utils.NSB_ROOT)
+
+ def test_get_nsb_option_is_invalid_key(self):
+ result = utils.get_nsb_option("bin", None)
+ self.assertEqual(result, None)
+
+ def test_get_nsb_option_default(self):
+ default = object()
+ result = utils.get_nsb_option("nosuch", default)
+ self.assertIs(result, default)
+
+ def test_provision_tool(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, self.DPDK_PATH, ""))
+ ssh.return_value = ssh_mock
+ tool_path = utils.provision_tool(ssh_mock, self.DPDK_PATH)
+ self.assertEqual(tool_path, self.DPDK_PATH)
+
+ def test_provision_tool_no_path(self):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(1, self.DPDK_PATH, ""))
+ ssh.return_value = ssh_mock
+ tool_path = utils.provision_tool(ssh_mock, self.DPDK_PATH)
+ self.assertEqual(tool_path, self.DPDK_PATH)
+
+
+class PciAddressTestCase(unittest.TestCase):
+
+ PCI_ADDRESS_DBSF = '000A:07:03.2'
+ PCI_ADDRESS_BSF = '06:02.1'
+ PCI_ADDRESS_DBSF_MULTILINE_1 = '0001:08:04.3\nother text\n'
+ PCI_ADDRESS_DBSF_MULTILINE_2 = 'first line\n 0001:08:04.3 \nother text\n'
+ # Will match and return the first address found.
+ PCI_ADDRESS_DBSF_MULTILINE_3 = ' 0001:08:04.1 \n 05:03.1 \nother\n'
+ PCI_ADDRESS_BSF_MULTILINE_1 = 'first line\n 08:04.3 \n 0002:05:03.1\n'
+ BAD_INPUT_1 = 'no address found'
+ BAD_INPUT_2 = '001:08:04.1'
+ BAD_INPUT_3 = '08:4.1'
+
+ def test_pciaddress_dbsf(self):
+ pci_address = utils.PciAddress(PciAddressTestCase.PCI_ADDRESS_DBSF)
+ self.assertEqual('000a', pci_address.domain)
+ self.assertEqual('07', pci_address.bus)
+ self.assertEqual('03', pci_address.slot)
+ self.assertEqual('2', pci_address.function)
+
+ def test_pciaddress_bsf(self):
+ pci_address = utils.PciAddress(PciAddressTestCase.PCI_ADDRESS_BSF)
+ self.assertEqual('0000', pci_address.domain)
+ self.assertEqual('06', pci_address.bus)
+ self.assertEqual('02', pci_address.slot)
+ self.assertEqual('1', pci_address.function)
+
+ def test_pciaddress_dbsf_multiline_1(self):
+ pci_address = utils.PciAddress(
+ PciAddressTestCase.PCI_ADDRESS_DBSF_MULTILINE_1)
+ self.assertEqual('0001', pci_address.domain)
+ self.assertEqual('08', pci_address.bus)
+ self.assertEqual('04', pci_address.slot)
+ self.assertEqual('3', pci_address.function)
+
+ def test_pciaddress_dbsf_multiline_2(self):
+ pci_address = utils.PciAddress(
+ PciAddressTestCase.PCI_ADDRESS_DBSF_MULTILINE_2)
+ self.assertEqual('0001', pci_address.domain)
+ self.assertEqual('08', pci_address.bus)
+ self.assertEqual('04', pci_address.slot)
+ self.assertEqual('3', pci_address.function)
+
+ def test_pciaddress_dbsf_multiline_3(self):
+ pci_address = utils.PciAddress(
+ PciAddressTestCase.PCI_ADDRESS_DBSF_MULTILINE_3)
+ self.assertEqual('0001', pci_address.domain)
+ self.assertEqual('08', pci_address.bus)
+ self.assertEqual('04', pci_address.slot)
+ self.assertEqual('1', pci_address.function)
+
+ def test_pciaddress_bsf_multiline_1(self):
+ pci_address = utils.PciAddress(
+ PciAddressTestCase.PCI_ADDRESS_BSF_MULTILINE_1)
+ self.assertEqual('0000', pci_address.domain)
+ self.assertEqual('08', pci_address.bus)
+ self.assertEqual('04', pci_address.slot)
+ self.assertEqual('3', pci_address.function)
+
+ def test_pciaddress_bad_input_no_address(self):
+ with self.assertRaises(ValueError) as exception:
+ utils.PciAddress(PciAddressTestCase.BAD_INPUT_1)
+ self.assertEqual('Invalid PCI address: {}'.format(
+ PciAddressTestCase.BAD_INPUT_1), str(exception.exception))
+
+ def test_pciaddress_bad_input_dbsf_bad_formatted(self):
+ # In this test case, the domain has only 3 characters instead of 4.
+ pci_address = utils.PciAddress(
+ PciAddressTestCase.BAD_INPUT_2)
+ self.assertEqual('0000', pci_address.domain)
+ self.assertEqual('08', pci_address.bus)
+ self.assertEqual('04', pci_address.slot)
+ self.assertEqual('1', pci_address.function)
+
+ def test_pciaddress_bad_input_bsf_bad_formatted(self):
+ with self.assertRaises(ValueError) as exception:
+ utils.PciAddress(PciAddressTestCase.BAD_INPUT_3)
+ self.assertEqual('Invalid PCI address: {}'.format(
+ PciAddressTestCase.BAD_INPUT_3), str(exception.exception))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/__init__.py b/yardstick/tests/unit/network_services/traffic_profile/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/__init__.py
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_base.py b/yardstick/tests/unit/network_services/traffic_profile/test_base.py
new file mode 100644
index 000000000..d9244e31b
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_base.py
@@ -0,0 +1,112 @@
+# 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.
+
+import sys
+
+import mock
+import unittest
+
+from yardstick.common import exceptions
+from yardstick.network_services import traffic_profile as tprofile_package
+from yardstick.network_services.traffic_profile import base
+from yardstick import tests as y_tests
+
+
+class TestTrafficProfile(unittest.TestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ def _get_res_mock(self, **kw):
+ _mock = mock.MagicMock()
+ for k, v in kw.items():
+ setattr(_mock, k, v)
+ return _mock
+
+ def test___init__(self):
+ traffic_profile = base.TrafficProfile(self.TRAFFIC_PROFILE)
+ self.assertEqual(self.TRAFFIC_PROFILE, traffic_profile.params)
+
+ def test_execute_traffic(self):
+ traffic_profile = base.TrafficProfile(self.TRAFFIC_PROFILE)
+ self.assertRaises(NotImplementedError,
+ traffic_profile.execute_traffic, {})
+
+ def test_get_existing_traffic_profile(self):
+ traffic_profile_list = [
+ 'RFC2544Profile', 'FixedProfile', 'TrafficProfileGenericHTTP',
+ 'IXIARFC2544Profile', 'ProxACLProfile', 'ProxBinSearchProfile',
+ 'ProxProfile', 'ProxRampProfile']
+ with mock.patch.dict(sys.modules, y_tests.STL_MOCKS):
+ tprofile_package.register_modules()
+
+ for tp in traffic_profile_list:
+ traffic_profile = base.TrafficProfile.get(
+ {'traffic_profile': {'traffic_type': tp}})
+ self.assertEqual(tp, traffic_profile.__class__.__name__)
+
+ def test_get_non_existing_traffic_profile(self):
+ self.assertRaises(exceptions.TrafficProfileNotImplemented,
+ base.TrafficProfile.get, self.TRAFFIC_PROFILE)
+
+
+class TestDummyProfile(unittest.TestCase):
+ def test_execute(self):
+ tp_config = {'traffic_profile': {'duration': 15}}
+ dummy_profile = base.DummyProfile(tp_config)
+ self.assertIsNone(dummy_profile.execute({}))
+
+
+class TrafficProfileConfigTestCase(unittest.TestCase):
+
+ def test__init(self):
+ tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
+ tp_config_obj = base.TrafficProfileConfig(tp_config)
+ self.assertEqual({'64B': 100}, tp_config_obj.packet_sizes)
+ self.assertEqual(base.TrafficProfileConfig.DEFAULT_DURATION,
+ tp_config_obj.duration)
+
+ def test__init_set_duration(self):
+ tp_config = {'traffic_profile': {'duration': 15}}
+ tp_config_obj = base.TrafficProfileConfig(tp_config)
+ self.assertEqual(base.TrafficProfileConfig.DEFAULT_SCHEMA,
+ tp_config_obj.schema)
+ self.assertEqual(float(base.TrafficProfileConfig.DEFAULT_FRAME_RATE),
+ tp_config_obj.frame_rate)
+ self.assertEqual(15, tp_config_obj.duration)
+
+ def test__parse_rate(self):
+ tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
+ tp_config_obj = base.TrafficProfileConfig(tp_config)
+ self.assertEqual((100.0, 'fps'), tp_config_obj.parse_rate('100 '))
+ self.assertEqual((200.5, 'fps'), tp_config_obj.parse_rate('200.5'))
+ self.assertEqual((300.8, 'fps'), tp_config_obj.parse_rate('300.8fps'))
+ self.assertEqual((400.2, 'fps'),
+ tp_config_obj.parse_rate('400.2 fps'))
+ self.assertEqual((500.3, '%'), tp_config_obj.parse_rate('500.3%'))
+ self.assertEqual((600.1, '%'), tp_config_obj.parse_rate('600.1 %'))
+
+ def test__parse_rate_exception(self):
+ tp_config = {'traffic_profile': {'packet_sizes': {'64B': 100}}}
+ tp_config_obj = base.TrafficProfileConfig(tp_config)
+ with self.assertRaises(exceptions.TrafficProfileRate):
+ tp_config_obj.parse_rate('100Fps')
+ with self.assertRaises(exceptions.TrafficProfileRate):
+ tp_config_obj.parse_rate('100 kbps')
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py b/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
new file mode 100644
index 000000000..2f6713760
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_fixed.py
@@ -0,0 +1,117 @@
+# 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.
+#
+
+import mock
+import unittest
+
+from yardstick.tests import STL_MOCKS
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.traffic_profile.base import TrafficProfile
+ from yardstick.network_services.traffic_profile.fixed import FixedProfile
+
+
+class TestFixedProfile(unittest.TestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ def test___init__(self):
+ fixed_profile = FixedProfile(self.TRAFFIC_PROFILE)
+ self.assertIsNotNone(fixed_profile)
+
+ def test_execute(self):
+ traffic_generator = mock.Mock(autospec=TrafficProfile)
+ traffic_generator.my_ports = [0, 1]
+ traffic_generator.vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ traffic_generator.client = \
+ mock.Mock(return_value=True)
+ fixed_profile = FixedProfile(self.TRAFFIC_PROFILE)
+ fixed_profile.params = self.TRAFFIC_PROFILE
+ fixed_profile.first_run = True
+ self.assertIsNone(fixed_profile.execute(traffic_generator))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_http.py b/yardstick/tests/unit/network_services/traffic_profile/test_http.py
new file mode 100644
index 000000000..874ec37d4
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_http.py
@@ -0,0 +1,47 @@
+# 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.
+
+import unittest
+
+from yardstick.network_services.traffic_profile import http
+
+
+class TestTrafficProfileGenericHTTP(unittest.TestCase):
+
+ TP_CONFIG = {'traffic_profile': {'duration': 10},
+ "uplink_0": {}, "downlink_0": {}}
+
+ def test___init__(self):
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+ self.assertIsNotNone(tp_generic_http)
+
+ def test_get_links_param(self):
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+
+ links = tp_generic_http.get_links_param()
+ self.assertEqual({"uplink_0": {}, "downlink_0": {}}, links)
+
+ def test_execute(self):
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+ traffic_generator = {}
+ self.assertIsNone(tp_generic_http.execute(traffic_generator))
+
+ def test__send_http_request(self):
+ tp_generic_http = http.TrafficProfileGenericHTTP(
+ self.TP_CONFIG)
+ self.assertIsNone(tp_generic_http._send_http_request(
+ '10.1.1.1', '250', '/req'))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_http_ixload.py b/yardstick/tests/unit/network_services/traffic_profile/test_http_ixload.py
new file mode 100644
index 000000000..996360c2e
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_http_ixload.py
@@ -0,0 +1,452 @@
+# Copyright (c) 2017-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.
+
+import unittest
+import mock
+
+from oslo_serialization import jsonutils
+
+from yardstick.network_services.traffic_profile import http_ixload
+from yardstick.network_services.traffic_profile.http_ixload import \
+ join_non_strings, validate_non_string_sequence
+
+
+class TestJoinNonStrings(unittest.TestCase):
+
+ def test_validate_non_string_sequence(self):
+ self.assertEqual(validate_non_string_sequence([1, 2, 3]), [1, 2, 3])
+ self.assertIsNone(validate_non_string_sequence('123'))
+ self.assertIsNone(validate_non_string_sequence(1))
+
+ self.assertEqual(validate_non_string_sequence(1, 2), 2)
+ self.assertEqual(validate_non_string_sequence(1, default=2), 2)
+
+ with self.assertRaises(RuntimeError):
+ validate_non_string_sequence(1, raise_exc=RuntimeError)
+
+ def test_join_non_strings(self):
+ self.assertEqual(join_non_strings(':'), '')
+ self.assertEqual(join_non_strings(':', 'a'), 'a')
+ self.assertEqual(join_non_strings(':', 'a', 2, 'c'), 'a:2:c')
+ self.assertEqual(join_non_strings(':', ['a', 2, 'c']), 'a:2:c')
+ self.assertEqual(join_non_strings(':', 'abc'), 'abc')
+
+
+class TestIxLoadTrafficGen(unittest.TestCase):
+
+ def setUp(self):
+ ports = [1, 2, 3]
+ self.test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {
+ "uplink_0": {
+ "ip": {"address": "address",
+ "gateway": "gateway",
+ "subnet_prefix": "subnet_prefix",
+ "mac": "mac"
+ }}}
+ }
+
+ def test_parse_run_test(self):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+ j = jsonutils.dump_as_bytes(test_input)
+ ixload = http_ixload.IXLOADHttpTest(j)
+ self.assertDictEqual(ixload.test_input, test_input)
+ self.assertIsNone(ixload.parse_run_test())
+ self.assertEqual(ixload.ports_to_reassign, [
+ ["IXIA_CHASSIS", "CARD", 1],
+ ["IXIA_CHASSIS", "CARD", 2],
+ ["IXIA_CHASSIS", "CARD", 3],
+ ])
+ self.assertEqual({}, ixload.links_param)
+
+ def test_format_ports_for_reassignment(self):
+ ports = [
+ ["IXIA_CHASSIS", "CARD", 1],
+ ["IXIA_CHASSIS", "CARD", 2],
+ ["IXIA_CHASSIS", "CARD", 3],
+ ]
+ formatted = http_ixload.IXLOADHttpTest.format_ports_for_reassignment(ports)
+ self.assertEqual(formatted, [
+ "IXIA_CHASSIS;CARD;1",
+ "IXIA_CHASSIS;CARD;2",
+ "IXIA_CHASSIS;CARD;3",
+ ])
+
+ def test_reassign_ports(self):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+ j = jsonutils.dump_as_bytes(test_input)
+ ixload = http_ixload.IXLOADHttpTest(j)
+ repository = mock.Mock()
+ test = mock.MagicMock()
+ test.setPorts = mock.Mock()
+ ports_to_reassign = [(1, 2, 3), (1, 2, 4)]
+ ixload.format_ports_for_reassignment = mock.Mock(return_value=["1;2;3"])
+ self.assertIsNone(ixload.reassign_ports(test, repository, ports_to_reassign))
+
+ def test_reassign_ports_error(self):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+ j = jsonutils.dump_as_bytes(test_input)
+ ixload = http_ixload.IXLOADHttpTest(j)
+ repository = mock.Mock()
+ test = "test"
+ ports_to_reassign = [(1, 2, 3), (1, 2, 4)]
+ ixload.format_ports_for_reassignment = mock.Mock(return_value=["1;2;3"])
+ ixload.ix_load = mock.MagicMock()
+ ixload.ix_load.delete = mock.Mock()
+ ixload.ix_load.disconnect = mock.Mock()
+ with self.assertRaises(Exception):
+ ixload.reassign_ports(test, repository, ports_to_reassign)
+
+ def test_stat_collector(self):
+ args = [0, 1]
+ self.assertIsNone(
+ http_ixload.IXLOADHttpTest.stat_collector(*args))
+
+ def test_IxL_StatCollectorCommand(self):
+ args = [[0, 1, 2, 3], [0, 1, 2, 3]]
+ self.assertIsNone(
+ http_ixload.IXLOADHttpTest.IxL_StatCollectorCommand(*args))
+
+ def test_set_results_dir(self):
+ test_stat_collector = mock.MagicMock()
+ test_stat_collector.setResultDir = mock.Mock()
+ results_on_windows = "c:/Results"
+ self.assertIsNone(
+ http_ixload.IXLOADHttpTest.set_results_dir(test_stat_collector,
+ results_on_windows))
+
+ def test_set_results_dir_error(self):
+ test_stat_collector = ""
+ results_on_windows = "c:/Results"
+ with self.assertRaises(Exception):
+ http_ixload.IXLOADHttpTest.set_results_dir(test_stat_collector, results_on_windows)
+
+ def test_load_config_file(self):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+ j = jsonutils.dump_as_bytes(test_input)
+ ixload = http_ixload.IXLOADHttpTest(j)
+ ixload.ix_load = mock.MagicMock()
+ ixload.ix_load.new = mock.Mock(return_value="")
+ self.assertIsNotNone(ixload.load_config_file("ixload.cfg"))
+
+ def test_load_config_file_error(self):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+ j = jsonutils.dump_as_bytes(test_input)
+ ixload = http_ixload.IXLOADHttpTest(j)
+ ixload.ix_load = "test"
+ with self.assertRaises(Exception):
+ ixload.load_config_file("ixload.cfg")
+
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.StatCollectorUtils')
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.IxLoad')
+ def test_start_http_test_connect_error(self, mock_ixload_type, *args):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+
+ j = jsonutils.dump_as_bytes(test_input)
+
+ mock_ixload_type.return_value.connect.side_effect = RuntimeError
+
+ ixload = http_ixload.IXLOADHttpTest(j)
+ ixload.results_on_windows = 'windows_result_dir'
+ ixload.result_dir = 'my_result_dir'
+
+ with self.assertRaises(RuntimeError):
+ ixload.start_http_test()
+
+ def test_update_config(self):
+ net_taraffic_0 = mock.Mock()
+ net_taraffic_0.name = "HTTP client@uplink_0"
+ net_taraffic_1 = mock.Mock()
+ net_taraffic_1.name = "HTTP client@uplink_1"
+
+ community_list = [net_taraffic_0, net_taraffic_1, Exception]
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ ixload.links_param = {"uplink_0": {"ip": {},
+ "http_client": {}}}
+
+ ixload.test = mock.Mock()
+ ixload.test.communityList = community_list
+
+ ixload.update_network_param = mock.Mock()
+ ixload.update_http_client_param = mock.Mock()
+
+ ixload.update_config()
+
+ ixload.update_network_param.assert_called_once_with(net_taraffic_0, {})
+ ixload.update_http_client_param.assert_called_once_with(net_taraffic_0,
+ {})
+
+ def test_update_network_mac_address(self):
+ ethernet = mock.MagicMock()
+ net_traffic = mock.Mock()
+ net_traffic.network.getL1Plugin.return_value = ethernet
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ ix_net_l2_ethernet_plugin = ethernet.childrenList[0]
+ ix_net_ip_v4_v6_plugin = ix_net_l2_ethernet_plugin.childrenList[0]
+ ix_net_ip_v4_v6_range = ix_net_ip_v4_v6_plugin.rangeList[0]
+
+ ixload.update_network_mac_address(net_traffic, "auto")
+ ix_net_ip_v4_v6_range.config.assert_called_once_with(
+ autoMacGeneration=True)
+
+ ixload.update_network_mac_address(net_traffic, "00:00:00:00:00:01")
+ ix_net_ip_v4_v6_range.config.assert_called_with(
+ autoMacGeneration=False)
+ mac_range = ix_net_ip_v4_v6_range.getLowerRelatedRange("MacRange")
+ mac_range.config.assert_called_once_with(mac="00:00:00:00:00:01")
+
+ net_traffic.network.getL1Plugin.return_value = Exception
+
+ with self.assertRaises(http_ixload.InvalidRxfFile):
+ ixload.update_network_mac_address(net_traffic, "auto")
+
+ def test_update_network_address(self):
+ ethernet = mock.MagicMock()
+ net_traffic = mock.Mock()
+ net_traffic.network.getL1Plugin.return_value = ethernet
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ ix_net_l2_ethernet_plugin = ethernet.childrenList[0]
+ ix_net_ip_v4_v6_plugin = ix_net_l2_ethernet_plugin.childrenList[0]
+ ix_net_ip_v4_v6_range = ix_net_ip_v4_v6_plugin.rangeList[0]
+
+ ixload.update_network_address(net_traffic, "address", "gateway",
+ "prefix")
+ ix_net_ip_v4_v6_range.config.assert_called_once_with(
+ prefix="prefix",
+ ipAddress="address",
+ gatewayAddress="gateway")
+
+ net_traffic.network.getL1Plugin.return_value = Exception
+
+ with self.assertRaises(http_ixload.InvalidRxfFile):
+ ixload.update_network_address(net_traffic, "address", "gateway",
+ "prefix")
+
+ def test_update_network_param(self):
+ net_traffic = mock.Mock()
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ ixload.update_network_address = mock.Mock()
+ ixload.update_network_mac_address = mock.Mock()
+
+ param = {"address": "address",
+ "gateway": "gateway",
+ "subnet_prefix": "subnet_prefix",
+ "mac": "mac"
+ }
+
+ ixload.update_network_param(net_traffic, param)
+
+ ixload.update_network_address.assert_called_once_with(net_traffic,
+ "address",
+ "gateway",
+ "subnet_prefix")
+
+ ixload.update_network_mac_address.assert_called_once_with(
+ net_traffic,
+ "mac")
+
+ def test_update_http_client_param(self):
+ net_traffic = mock.Mock()
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ ixload.update_page_size = mock.Mock()
+ ixload.update_user_count = mock.Mock()
+
+ param = {"page_object": "page_object",
+ "simulated_users": "simulated_users"}
+
+ ixload.update_http_client_param(net_traffic, param)
+
+ ixload.update_page_size.assert_called_once_with(net_traffic,
+ "page_object")
+ ixload.update_user_count.assert_called_once_with(net_traffic,
+ "simulated_users")
+
+ def test_update_page_size(self):
+ activity = mock.MagicMock()
+ net_traffic = mock.Mock()
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ net_traffic.activityList = [activity]
+ ix_http_command = activity.agent.actionList[0]
+ ixload.update_page_size(net_traffic, "page_object")
+ ix_http_command.config.assert_called_once_with(
+ pageObject="page_object")
+
+ net_traffic.activityList = []
+ with self.assertRaises(http_ixload.InvalidRxfFile):
+ ixload.update_page_size(net_traffic, "page_object")
+
+ def test_update_user_count(self):
+ activity = mock.MagicMock()
+ net_traffic = mock.Mock()
+
+ ixload = http_ixload.IXLOADHttpTest(
+ jsonutils.dump_as_bytes(self.test_input))
+
+ net_traffic.activityList = [activity]
+ ixload.update_user_count(net_traffic, 123)
+ activity.config.assert_called_once_with(userObjectiveValue=123)
+
+ net_traffic.activityList = []
+ with self.assertRaises(http_ixload.InvalidRxfFile):
+ ixload.update_user_count(net_traffic, 123)
+
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.IxLoad')
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.StatCollectorUtils')
+ def test_start_http_test(self, *args):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+
+ j = jsonutils.dump_as_bytes(test_input)
+
+ ixload = http_ixload.IXLOADHttpTest(j)
+ ixload.results_on_windows = 'windows_result_dir'
+ ixload.result_dir = 'my_result_dir'
+ ixload.load_config_file = mock.MagicMock()
+
+ self.assertIsNone(ixload.start_http_test())
+
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.IxLoad')
+ @mock.patch('yardstick.network_services.traffic_profile.http_ixload.StatCollectorUtils')
+ def test_start_http_test_reassign_error(self, *args):
+ ports = [1, 2, 3]
+ test_input = {
+ "remote_server": "REMOTE_SERVER",
+ "ixload_cfg": "IXLOAD_CFG",
+ "result_dir": "RESULT_DIR",
+ "ixia_chassis": "IXIA_CHASSIS",
+ "IXIA": {
+ "card": "CARD",
+ "ports": ports,
+ },
+ 'links_param': {}
+ }
+
+ j = jsonutils.dump_as_bytes(test_input)
+
+ ixload = http_ixload.IXLOADHttpTest(j)
+ ixload.load_config_file = mock.MagicMock()
+
+ reassign_ports = mock.Mock(side_effect=RuntimeError)
+ ixload.reassign_ports = reassign_ports
+ ixload.results_on_windows = 'windows_result_dir'
+ ixload.result_dir = 'my_result_dir'
+
+ ixload.start_http_test()
+ reassign_ports.assert_called_once()
+
+ @mock.patch("yardstick.network_services.traffic_profile.http_ixload.IXLOADHttpTest")
+ def test_main(self, *args):
+ args = ["1", "2", "3"]
+ http_ixload.main(args)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py
new file mode 100644
index 000000000..ddd1828ae
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_ixia_rfc2544.py
@@ -0,0 +1,1024 @@
+# Copyright (c) 2016-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.
+
+import copy
+
+import mock
+import unittest
+import collections
+
+from yardstick.network_services.traffic_profile import ixia_rfc2544
+from yardstick.network_services.traffic_profile import trex_traffic_profile
+
+
+class TestIXIARFC2544Profile(unittest.TestCase):
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+
+ PROFILE = {
+ 'description': 'Traffic profile to run RFC2544 latency',
+ 'name': 'rfc2544',
+ 'traffic_profile': {
+ 'traffic_type': 'IXIARFC2544Profile',
+ 'frame_rate': 100},
+ ixia_rfc2544.IXIARFC2544Profile.DOWNLINK: {
+ 'ipv4': {
+ 'outer_l2': {
+ 'framesize': {
+ '64B': '100',
+ '1518B': '0',
+ '128B': '0',
+ '1400B': '0',
+ '256B': '0',
+ '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4': {
+ 'dstip4': '1.1.1.1-1.15.255.255',
+ 'proto': 'udp',
+ 'count': '1',
+ 'srcip4': '90.90.1.1-90.105.255.255',
+ 'dscp': 0,
+ 'ttl': 32},
+ 'outer_l4': {
+ 'srcport': '2001',
+ 'dsrport': '1234'}}},
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {
+ 'ipv4': {
+ 'outer_l2': {
+ 'framesize': {
+ '64B': '100',
+ '1518B': '0',
+ '128B': '0',
+ '1400B': '0',
+ '256B': '0',
+ '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4': {
+ 'dstip4': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp',
+ 'count': '1',
+ 'srcip4': '1.1.1.1-1.15.255.255',
+ 'dscp': 0,
+ 'ttl': 32},
+ 'outer_l4': {
+ 'dstport': '2001',
+ 'srcport': '1234'}}},
+ 'schema': 'isb:traffic_profile:0.1'}
+
+ def test_get_ixia_traffic_profile_error(self):
+ traffic_generator = mock.Mock(
+ autospec=trex_traffic_profile.TrexProfile)
+ traffic_generator.my_ports = [0, 1]
+ traffic_generator.uplink_ports = [-1]
+ traffic_generator.downlink_ports = [1]
+ traffic_generator.client = \
+ mock.Mock(return_value=True)
+ STATIC_TRAFFIC = {
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {
+ "id": 1,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:03",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32
+ },
+ "outer_l3v6": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l4": {
+ "dstport": "2001",
+ "srcport": "1234"
+ },
+ "traffic_type": "continuous"
+ },
+ ixia_rfc2544.IXIARFC2544Profile.DOWNLINK: {
+ "id": 2,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:04",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l3v6": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l4": {
+ "dstport": "1234",
+ "srcport": "2001"
+ },
+ "traffic_type": "continuous"
+ }
+ }
+ ixia_rfc2544.STATIC_TRAFFIC = STATIC_TRAFFIC
+
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ r_f_c2544_profile.rate = 100
+ mac = {"src_mac_0": "00:00:00:00:00:01",
+ "src_mac_1": "00:00:00:00:00:02",
+ "src_mac_2": "00:00:00:00:00:02",
+ "dst_mac_0": "00:00:00:00:00:03",
+ "dst_mac_1": "00:00:00:00:00:04",
+ "dst_mac_2": "00:00:00:00:00:04"}
+ result = r_f_c2544_profile._get_ixia_traffic_profile(self.PROFILE, mac)
+ self.assertIsNotNone(result)
+
+ def test_get_ixia_traffic_profile(self):
+ traffic_generator = mock.Mock(
+ autospec=trex_traffic_profile.TrexProfile)
+ traffic_generator.my_ports = [0, 1]
+ traffic_generator.uplink_ports = [-1]
+ traffic_generator.downlink_ports = [1]
+ traffic_generator.client = \
+ mock.Mock(return_value=True)
+ STATIC_TRAFFIC = {
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {
+ "id": 1,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:03",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32,
+ "count": "1"
+ },
+ "outer_l3v6": {
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32,
+ },
+ "outer_l4": {
+ "dstport": "2001",
+ "srcport": "1234",
+ "count": "1"
+ },
+ "traffic_type": "continuous"
+ },
+ ixia_rfc2544.IXIARFC2544Profile.DOWNLINK: {
+ "id": 2,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:04",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32,
+ },
+ "outer_l3v6": {
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32,
+ },
+ "outer_l4": {
+ "dstport": "1234",
+ "srcport": "2001",
+ "count": "1"
+ },
+ "traffic_type": "continuous"
+ }
+ }
+ ixia_rfc2544.STATIC_TRAFFIC = STATIC_TRAFFIC
+
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ r_f_c2544_profile.rate = 100
+ mac = {"src_mac_0": "00:00:00:00:00:01",
+ "src_mac_1": "00:00:00:00:00:02",
+ "src_mac_2": "00:00:00:00:00:02",
+ "dst_mac_0": "00:00:00:00:00:03",
+ "dst_mac_1": "00:00:00:00:00:04",
+ "dst_mac_2": "00:00:00:00:00:04"}
+ result = r_f_c2544_profile._get_ixia_traffic_profile(self.PROFILE, mac)
+ self.assertIsNotNone(result)
+
+ @mock.patch("yardstick.network_services.traffic_profile.ixia_rfc2544.open")
+ def test_get_ixia_traffic_profile_v6(self, *args):
+ traffic_generator = mock.Mock(
+ autospec=trex_traffic_profile.TrexProfile)
+ traffic_generator.my_ports = [0, 1]
+ traffic_generator.uplink_ports = [-1]
+ traffic_generator.downlink_ports = [1]
+ traffic_generator.client = \
+ mock.Mock(return_value=True)
+ STATIC_TRAFFIC = {
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {
+ "id": 1,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:03",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "dscp": 0,
+ "dstip4": "152.16.40.20",
+ "proto": "udp",
+ "srcip4": "152.16.100.20",
+ "ttl": 32
+ },
+ "outer_l3v6": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l4": {
+ "dstport": "2001",
+ "srcport": "1234"
+ },
+ "traffic_type": "continuous"
+ },
+ ixia_rfc2544.IXIARFC2544Profile.DOWNLINK: {
+ "id": 2,
+ "bidir": "False",
+ "duration": 60,
+ "iload": "100",
+ "outer_l2": {
+ "dstmac": "00:00:00:00:00:04",
+ "framesPerSecond": True,
+ "framesize": 64,
+ "srcmac": "00:00:00:00:00:01"
+ },
+ "outer_l3": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l3v4": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l3v6": {
+ "count": 1024,
+ "dscp": 0,
+ "dstip4": "152.16.100.20",
+ "proto": "udp",
+ "srcip4": "152.16.40.20",
+ "ttl": 32
+ },
+ "outer_l4": {
+ "dstport": "1234",
+ "srcport": "2001"
+ },
+ "traffic_type": "continuous"
+ }
+ }
+ ixia_rfc2544.STATIC_TRAFFIC = STATIC_TRAFFIC
+
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ r_f_c2544_profile.rate = 100
+ mac = {"src_mac_0": "00:00:00:00:00:01",
+ "src_mac_1": "00:00:00:00:00:02",
+ "src_mac_2": "00:00:00:00:00:02",
+ "dst_mac_0": "00:00:00:00:00:03",
+ "dst_mac_1": "00:00:00:00:00:04",
+ "dst_mac_2": "00:00:00:00:00:04"}
+ profile_data = {'description': 'Traffic profile to run RFC2544',
+ 'name': 'rfc2544',
+ 'traffic_profile':
+ {'traffic_type': 'IXIARFC2544Profile',
+ 'frame_rate': 100},
+ ixia_rfc2544.IXIARFC2544Profile.DOWNLINK:
+ {'ipv4':
+ {'outer_l2': {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4': {'dstip4': '1.1.1.1-1.15.255.255',
+ 'proto': 'udp', 'count': '1',
+ 'srcip4': '90.90.1.1-90.105.255.255',
+ 'dscp': 0, 'ttl': 32},
+ 'outer_l3v6': {'dstip6': '1.1.1.1-1.15.255.255',
+ 'proto': 'udp', 'count': '1',
+ 'srcip6': '90.90.1.1-90.105.255.255',
+ 'dscp': 0, 'ttl': 32},
+ 'outer_l4': {'srcport': '2001',
+ 'dsrport': '1234'}}},
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {'ipv4':
+ {'outer_l2': {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4':
+ {'dstip4': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp', 'count': '1',
+ 'srcip4': '1.1.1.1-1.15.255.255',
+ 'dscp': 0, 'ttl': 32},
+ 'outer_l3v6':
+ {'dstip6': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp', 'count': '1',
+ 'srcip6': '1.1.1.1-1.15.255.255',
+ 'dscp': 0, 'ttl': 32},
+
+ 'outer_l4': {'dstport': '2001',
+ 'srcport': '1234'}}},
+ 'schema': 'isb:traffic_profile:0.1'}
+ result = r_f_c2544_profile._get_ixia_traffic_profile(profile_data, mac)
+ self.assertIsNotNone(result)
+
+ def test__init__(self):
+ t_profile_data = copy.deepcopy(self.TRAFFIC_PROFILE)
+ t_profile_data['traffic_profile']['frame_rate'] = 12345678
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(t_profile_data)
+ self.assertEqual(12345678, r_f_c2544_profile.rate)
+
+ def test__get_ip_and_mask_range(self):
+ ip_range = '1.2.0.2-1.2.255.254'
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ ip, mask = r_f_c2544_profile._get_ip_and_mask(ip_range)
+ self.assertEqual('1.2.0.2', ip)
+ self.assertEqual(16, mask)
+
+ def test__get_ip_and_mask_single(self):
+ ip_range = '192.168.1.10'
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ ip, mask = r_f_c2544_profile._get_ip_and_mask(ip_range)
+ self.assertEqual('192.168.1.10', ip)
+ self.assertIsNone(mask)
+
+ def test__get_fixed_and_mask_range(self):
+ fixed_mask = '8-48'
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ fixed, mask = r_f_c2544_profile._get_fixed_and_mask(fixed_mask)
+ self.assertEqual(8, fixed)
+ self.assertEqual(48, mask)
+
+ def test__get_fixed_and_mask_single(self):
+ fixed_mask = 1234
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ fixed, mask = r_f_c2544_profile._get_fixed_and_mask(fixed_mask)
+ self.assertEqual(1234, fixed)
+ self.assertEqual(0, mask)
+
+ def test__get_ixia_traffic_profile_default_args(self):
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+
+ expected = {}
+ result = r_f_c2544_profile._get_ixia_traffic_profile({})
+ self.assertDictEqual(result, expected)
+
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544Profile,
+ '_update_traffic_tracking_options')
+ def test__ixia_traffic_generate(self, mock_upd_tracking_opts):
+ traffic_generator = mock.Mock(
+ autospec=trex_traffic_profile.TrexProfile)
+ traffic_generator.networks = {
+ "uplink_0": ["xe0"],
+ "downlink_0": ["xe1"],
+ }
+ traffic_generator.client = \
+ mock.Mock(return_value=True)
+ traffic = {ixia_rfc2544.IXIARFC2544Profile.DOWNLINK: {'iload': 10},
+ ixia_rfc2544.IXIARFC2544Profile.UPLINK: {'iload': 10}}
+ ixia_obj = mock.MagicMock()
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ r_f_c2544_profile.rate = 100
+ result = r_f_c2544_profile._ixia_traffic_generate(traffic, ixia_obj,
+ traffic_generator)
+ self.assertIsNone(result)
+ mock_upd_tracking_opts.assert_called_once_with(traffic_generator)
+
+ def test__update_traffic_tracking_options(self):
+ mock_traffic_gen = mock.Mock()
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile._update_traffic_tracking_options(mock_traffic_gen)
+ mock_traffic_gen.update_tracking_options.assert_called_once()
+
+ def test__get_framesize(self):
+ traffic_profile = {
+ 'uplink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 100}}}},
+ 'downlink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 100}}}},
+ 'uplink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 100}}}},
+ 'downlink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 100}}}}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.params = traffic_profile
+ result = rfc2544_profile._get_framesize()
+ self.assertEqual(result, '64B')
+
+ def test__get_framesize_IMIX_traffic(self):
+ traffic_profile = {
+ 'uplink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 50,
+ '128B': 50}}}},
+ 'downlink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 50,
+ '128B': 50}}}},
+ 'uplink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 50,
+ '128B': 50}}}},
+ 'downlink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 50,
+ '128B': 50}}}}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.params = traffic_profile
+ result = rfc2544_profile._get_framesize()
+ self.assertEqual(result, 'IMIX')
+
+ def test__get_framesize_zero_pkt_size_weight(self):
+ traffic_profile = {
+ 'uplink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 0}}}},
+ 'downlink_0': {'ipv4': {'outer_l2': {'framesize': {'64B': 0}}}},
+ 'uplink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 0}}}},
+ 'downlink_1': {'ipv4': {'outer_l2': {'framesize': {'64B': 0}}}}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.params = traffic_profile
+ result = rfc2544_profile._get_framesize()
+ self.assertEqual(result, '')
+
+ def test_execute_traffic_first_run(self):
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.first_run = True
+ rfc2544_profile.rate = 50
+ traffic_gen = mock.Mock()
+ traffic_gen.rfc_helper.iteration.value = 0
+ with mock.patch.object(rfc2544_profile, '_get_ixia_traffic_profile') \
+ as mock_get_tp, \
+ mock.patch.object(rfc2544_profile, '_ixia_traffic_generate') \
+ as mock_tgenerate:
+ mock_get_tp.return_value = 'fake_tprofile'
+ output = rfc2544_profile.execute_traffic(traffic_gen,
+ ixia_obj=mock.ANY)
+
+ self.assertTrue(output)
+ self.assertFalse(rfc2544_profile.first_run)
+ self.assertEqual(50, rfc2544_profile.max_rate)
+ self.assertEqual(0, rfc2544_profile.min_rate)
+ mock_get_tp.assert_called_once()
+ mock_tgenerate.assert_called_once()
+
+ def test_execute_traffic_not_first_run(self):
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.first_run = False
+ rfc2544_profile.max_rate = 70
+ rfc2544_profile.min_rate = 0
+ traffic_gen = mock.Mock()
+ traffic_gen.rfc_helper.iteration.value = 0
+ with mock.patch.object(rfc2544_profile, '_get_ixia_traffic_profile') \
+ as mock_get_tp, \
+ mock.patch.object(rfc2544_profile, '_ixia_traffic_generate') \
+ as mock_tgenerate:
+ mock_get_tp.return_value = 'fake_tprofile'
+ rfc2544_profile.full_profile = mock.ANY
+ output = rfc2544_profile.execute_traffic(traffic_gen,
+ ixia_obj=mock.ANY)
+
+ self.assertFalse(output)
+ self.assertEqual(35.0, rfc2544_profile.rate)
+ mock_get_tp.assert_called_once()
+ mock_tgenerate.assert_called_once()
+
+ def test_update_traffic_profile(self):
+ traffic_generator = mock.Mock(
+ autospec=trex_traffic_profile.TrexProfile)
+ traffic_generator.networks = {
+ "uplink_0": ["xe0"], # private, one value for intfs
+ "downlink_0": ["xe1", "xe2"], # public, two values for intfs
+ "downlink_1": ["xe3"], # not in TRAFFIC PROFILE
+ "tenant_0": ["xe4"], # not public or private
+ }
+
+ ports_expected = [8, 3, 5]
+ traffic_generator.vnfd_helper.port_num.side_effect = ports_expected
+ traffic_generator.client.return_value = True
+
+ traffic_profile = copy.deepcopy(self.TRAFFIC_PROFILE)
+ traffic_profile.update({
+ "uplink_0": ["xe0"],
+ "downlink_0": ["xe1", "xe2"],
+ })
+
+ r_f_c2544_profile = ixia_rfc2544.IXIARFC2544Profile(traffic_profile)
+ r_f_c2544_profile.full_profile = {}
+ r_f_c2544_profile.get_streams = mock.Mock()
+
+ self.assertIsNone(
+ r_f_c2544_profile.update_traffic_profile(traffic_generator))
+ self.assertEqual(r_f_c2544_profile.ports, ports_expected)
+
+ def test_get_drop_percentage_completed(self):
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 23,
+ 'LatencyMin': 13,
+ 'LatencyMax': 28}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.rate = 100.0
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=100.0)
+ rfc2544_profile._get_framesize = mock.Mock(return_value='64B')
+ completed, samples = rfc2544_profile.get_drop_percentage(
+ samples, 0, 1, 4, 0.1)
+ self.assertTrue(completed)
+ self.assertEqual(66.9, samples['TxThroughput'])
+ self.assertEqual(66.833, samples['RxThroughput'])
+ self.assertEqual(0.099651, samples['DropPercentage'])
+ self.assertEqual(21.5, samples['LatencyAvg'])
+ self.assertEqual(13.0, samples['LatencyMin'])
+ self.assertEqual(28.0, samples['LatencyMax'])
+ self.assertEqual(100.0, samples['Rate'])
+ self.assertEqual('64B', samples['PktSize'])
+
+ def test_get_drop_percentage_over_drop_percentage(self):
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.rate = 1000
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=50.0)
+ completed, samples = rfc2544_profile.get_drop_percentage(
+ samples, 0, 0.05, 4, 0.1)
+ self.assertFalse(completed)
+ self.assertEqual(66.9, samples['TxThroughput'])
+ self.assertEqual(66.833, samples['RxThroughput'])
+ self.assertEqual(0.099651, samples['DropPercentage'])
+ self.assertEqual(rfc2544_profile.rate, rfc2544_profile.max_rate)
+
+ def test_get_drop_percentage_under_drop_percentage(self):
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.rate = 1000
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=50.0)
+ completed, samples = rfc2544_profile.get_drop_percentage(
+ samples, 0.2, 1, 4, 0.1)
+ self.assertFalse(completed)
+ self.assertEqual(66.9, samples['TxThroughput'])
+ self.assertEqual(66.833, samples['RxThroughput'])
+ self.assertEqual(0.099651, samples['DropPercentage'])
+ self.assertEqual(rfc2544_profile.rate, rfc2544_profile.min_rate)
+
+ @mock.patch.object(ixia_rfc2544.LOG, 'info')
+ def test_get_drop_percentage_not_flow(self, *args):
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 0,
+ 'InBytes': 64000, 'OutBytes': 0,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 0,
+ 'InBytes': 64320, 'OutBytes': 0,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.rate = 1000
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=50.0)
+ completed, samples = rfc2544_profile.get_drop_percentage(
+ samples, 0.2, 1, 4, 0.1)
+ self.assertFalse(completed)
+ self.assertEqual(0.0, samples['TxThroughput'])
+ self.assertEqual(66.833, samples['RxThroughput'])
+ self.assertEqual(100, samples['DropPercentage'])
+ self.assertEqual(rfc2544_profile.rate, rfc2544_profile.max_rate)
+
+ def test_get_drop_percentage_first_run(self):
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=50.0)
+ completed, samples = rfc2544_profile.get_drop_percentage(
+ samples, 0, 1, 4, 0.1, first_run=True)
+ self.assertTrue(completed)
+ self.assertEqual(66.9, samples['TxThroughput'])
+ self.assertEqual(66.833, samples['RxThroughput'])
+ self.assertEqual(0.099651, samples['DropPercentage'])
+ self.assertEqual(33.45, rfc2544_profile.rate)
+
+ def test_get_drop_percentage_resolution(self):
+ rfc2544_profile = ixia_rfc2544.IXIARFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile._get_next_rate = mock.Mock(return_value=0.1)
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile.rate = 0.19
+ completed, _ = rfc2544_profile.get_drop_percentage(
+ samples, 0, 0.05, 4, 0.1)
+ self.assertTrue(completed)
+
+ samples = {'iface_name_1':
+ {'InPackets': 1000, 'OutPackets': 1000,
+ 'InBytes': 64000, 'OutBytes': 64000,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25},
+ 'iface_name_2':
+ {'InPackets': 1005, 'OutPackets': 1007,
+ 'InBytes': 64320, 'OutBytes': 64448,
+ 'LatencyAvg': 20,
+ 'LatencyMin': 15,
+ 'LatencyMax': 25}
+ }
+ rfc2544_profile.rate = 0.5
+ completed, _ = rfc2544_profile.get_drop_percentage(
+ samples, 0, 0.05, 4, 0.1)
+ self.assertFalse(completed)
+
+
+class TestIXIARFC2544PppoeScenarioProfile(unittest.TestCase):
+
+ TRAFFIC_PROFILE = {
+ "schema": "nsb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100},
+ 'uplink_0': {'ipv4': {'port': 'xe0', 'id': 1}},
+ 'downlink_0': {'ipv4': {'port': 'xe2', 'id': 2}},
+ 'uplink_1': {'ipv4': {'port': 'xe1', 'id': 3}},
+ 'downlink_1': {'ipv4': {'port': 'xe2', 'id': 4}}
+ }
+
+ def setUp(self):
+ self.ixia_tp = ixia_rfc2544.IXIARFC2544PppoeScenarioProfile(
+ self.TRAFFIC_PROFILE)
+ self.ixia_tp.rate = 100.0
+ self.ixia_tp._get_next_rate = mock.Mock(return_value=50.0)
+ self.ixia_tp._get_framesize = mock.Mock(return_value='64B')
+
+ def test___init__(self):
+ self.assertIsInstance(self.ixia_tp.full_profile,
+ collections.OrderedDict)
+
+ def test__get_flow_groups_params(self):
+ expected_tp = collections.OrderedDict([
+ ('uplink_0', {'ipv4': {'id': 1, 'port': 'xe0'}}),
+ ('downlink_0', {'ipv4': {'id': 2, 'port': 'xe2'}}),
+ ('uplink_1', {'ipv4': {'id': 3, 'port': 'xe1'}}),
+ ('downlink_1', {'ipv4': {'id': 4, 'port': 'xe2'}})])
+
+ self.ixia_tp._get_flow_groups_params()
+ self.assertDictEqual(self.ixia_tp.full_profile, expected_tp)
+
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_flow_groups_params')
+ def test_update_traffic_profile(self, mock_get_flow_groups_params):
+ networks = {
+ 'uplink_0': 'data1',
+ 'downlink_0': 'data2',
+ 'uplink_1': 'data3',
+ 'downlink_1': 'data4'
+ }
+ ports = ['xe0', 'xe1', 'xe2', 'xe3']
+ mock_traffic_gen = mock.Mock()
+ mock_traffic_gen.networks = networks
+ mock_traffic_gen.vnfd_helper.port_num.side_effect = ports
+ self.ixia_tp.update_traffic_profile(mock_traffic_gen)
+ mock_get_flow_groups_params.assert_called_once()
+ self.assertEqual(self.ixia_tp.ports, ports)
+
+ def test__get_prio_flows_drop_percentage(self):
+
+ input_stats = {
+ '0': {
+ 'InPackets': 50,
+ 'OutPackets': 100,
+ 'Store-Forward_Avg_latency_ns': 10,
+ 'Store-Forward_Min_latency_ns': 10,
+ 'Store-Forward_Max_latency_ns': 10}}
+
+ result = self.ixia_tp._get_prio_flows_drop_percentage(input_stats)
+ self.assertIsNotNone(result['0'].get('DropPercentage'))
+ self.assertEqual(result['0'].get('DropPercentage'), 50.0)
+
+ def test__get_prio_flows_drop_percentage_traffic_not_flowing(self):
+ input_stats = {
+ '0': {
+ 'InPackets': 0,
+ 'OutPackets': 0,
+ 'Store-Forward_Avg_latency_ns': 0,
+ 'Store-Forward_Min_latency_ns': 0,
+ 'Store-Forward_Max_latency_ns': 0}}
+
+ result = self.ixia_tp._get_prio_flows_drop_percentage(input_stats)
+ self.assertIsNotNone(result['0'].get('DropPercentage'))
+ self.assertEqual(result['0'].get('DropPercentage'), 100)
+
+ def test__get_summary_pppoe_subs_counters(self):
+ input_stats = {
+ 'xe0': {
+ 'OutPackets': 100,
+ 'SessionsUp': 4,
+ 'SessionsDown': 0,
+ 'SessionsNotStarted': 0,
+ 'SessionsTotal': 4},
+ 'xe1': {
+ 'OutPackets': 100,
+ 'SessionsUp': 4,
+ 'SessionsDown': 0,
+ 'SessionsNotStarted': 0,
+ 'SessionsTotal': 4}
+ }
+
+ expected_stats = {
+ 'SessionsUp': 8,
+ 'SessionsDown': 0,
+ 'SessionsNotStarted': 0,
+ 'SessionsTotal': 8
+ }
+
+ res = self.ixia_tp._get_summary_pppoe_subs_counters(input_stats)
+ self.assertDictEqual(res, expected_stats)
+
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_prio_flows_drop_percentage')
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_summary_pppoe_subs_counters')
+ def test_get_drop_percentage(self, mock_get_pppoe_subs,
+ mock_sum_prio_drop_rate):
+ samples = {
+ 'priority_stats': {
+ '0': {
+ 'InPackets': 100,
+ 'OutPackets': 100,
+ 'InBytes': 6400,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10}},
+ 'xe0': {
+ 'InPackets': 100,
+ 'OutPackets': 100,
+ 'InBytes': 6400,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10}}
+
+ mock_get_pppoe_subs.return_value = {'SessionsUp': 1}
+ mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}}
+
+ self.ixia_tp._get_framesize = mock.Mock(return_value='64B')
+ status, res = self.ixia_tp.get_drop_percentage(
+ samples, tol_min=0.0, tolerance=0.0001, precision=0,
+ resolution=0.1, first_run=True)
+ self.assertIsNotNone(res.get('DropPercentage'))
+ self.assertIsNotNone(res.get('Priority'))
+ self.assertIsNotNone(res.get('SessionsUp'))
+ self.assertEqual(res['DropPercentage'], 0.0)
+ self.assertEqual(res['Rate'], 100.0)
+ self.assertEqual(res['PktSize'], '64B')
+ self.assertTrue(status)
+ mock_sum_prio_drop_rate.assert_called_once()
+ mock_get_pppoe_subs.assert_called_once()
+
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_prio_flows_drop_percentage')
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_summary_pppoe_subs_counters')
+ def test_get_drop_percentage_failed_status(self, mock_get_pppoe_subs,
+ mock_sum_prio_drop_rate):
+ samples = {
+ 'priority_stats': {
+ '0': {
+ 'InPackets': 90,
+ 'OutPackets': 100,
+ 'InBytes': 5760,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10}},
+ 'xe0': {
+ 'InPackets': 90,
+ 'OutPackets': 100,
+ 'InBytes': 5760,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10}}
+
+ mock_get_pppoe_subs.return_value = {'SessionsUp': 1}
+ mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}}
+
+ status, res = self.ixia_tp.get_drop_percentage(
+ samples, tol_min=0.0, tolerance=0.0001, precision=0,
+ resolution=0.1, first_run=True)
+ self.assertIsNotNone(res.get('DropPercentage'))
+ self.assertIsNotNone(res.get('Priority'))
+ self.assertIsNotNone(res.get('SessionsUp'))
+ self.assertEqual(res['DropPercentage'], 10.0)
+ self.assertFalse(status)
+ mock_sum_prio_drop_rate.assert_called_once()
+ mock_get_pppoe_subs.assert_called_once()
+
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_prio_flows_drop_percentage')
+ @mock.patch.object(ixia_rfc2544.IXIARFC2544PppoeScenarioProfile,
+ '_get_summary_pppoe_subs_counters')
+ def test_get_drop_percentage_priority_flow_check(self, mock_get_pppoe_subs,
+ mock_sum_prio_drop_rate):
+ samples = {
+ 'priority_stats': {
+ '0': {
+ 'InPackets': 100,
+ 'OutPackets': 100,
+ 'InBytes': 6400,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10}},
+ 'xe0': {
+ 'InPackets': 90,
+ 'OutPackets': 100,
+ 'InBytes': 5760,
+ 'OutBytes': 6400,
+ 'LatencyAvg': 10,
+ 'LatencyMin': 10,
+ 'LatencyMax': 10
+ }}
+
+ mock_get_pppoe_subs.return_value = {'SessionsUp': 1}
+ mock_sum_prio_drop_rate.return_value = {'0': {'DropPercentage': 0.0}}
+
+ tc_rfc2544_opts = {'priority': '0',
+ 'allowed_drop_rate': '0.0001 - 0.0001'}
+ status, res = self.ixia_tp.get_drop_percentage(
+ samples, tol_min=15.0000, tolerance=15.0001, precision=0,
+ resolution=0.1, first_run=True, tc_rfc2544_opts=tc_rfc2544_opts)
+ self.assertIsNotNone(res.get('DropPercentage'))
+ self.assertIsNotNone(res.get('Priority'))
+ self.assertIsNotNone(res.get('SessionsUp'))
+ self.assertTrue(status)
+ mock_sum_prio_drop_rate.assert_called_once()
+ mock_get_pppoe_subs.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py
new file mode 100644
index 000000000..afd550029
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_landslide_profile.py
@@ -0,0 +1,136 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import copy
+import unittest
+
+from yardstick.network_services.traffic_profile import landslide_profile
+
+TP_CONFIG = {
+ 'schema': "nsb:traffic_profile:0.1",
+ 'name': 'LandslideProfile',
+ 'description': 'Spirent Landslide traffic profile (Data Message Flow)',
+ 'traffic_profile': {
+ 'traffic_type': 'LandslideProfile'
+ },
+ 'dmf_config': {
+ 'dmf': {
+ 'library': 'test',
+ 'name': 'Fireball UDP',
+ 'description': "Basic data flow using UDP/IP (Fireball DMF)",
+ 'keywords': 'UDP ',
+ 'dataProtocol': 'fb_udp',
+ 'burstCount': 1,
+ 'clientPort': {
+ 'clientPort': 2002,
+ 'isClientPortRange': 'false'
+ },
+ 'serverPort': 2003,
+ 'connection': {
+ 'initiatingSide': 'Client',
+ 'disconnectSide': 'Client',
+ 'underlyingProtocol': 'none',
+ 'persistentConnection': 'false'
+ },
+ 'protocolId': 0,
+ 'persistentConnection': 'false',
+ 'transactionRate': 8.0,
+ 'transactions': {
+ 'totalTransactions': 0,
+ 'retries': 0,
+ 'dataResponseTime': 60000,
+ 'packetSize': 64
+ },
+ 'segment': {
+ 'segmentSize': 64000,
+ 'maxSegmentSize': 0
+ },
+ 'size': {
+ 'sizeDistribution': 'Fixed',
+ 'sizeDeviation': 10
+ },
+ 'interval': {
+ 'intervalDistribution': 'Fixed',
+ 'intervalDeviation': 10
+ },
+ 'ipHeader': {
+ 'typeOfService': 0,
+ 'timeToLive': 64
+ },
+ 'tcpConnection': {
+ 'force3Way': 'false',
+ 'fixedRetryTime': 0,
+ 'maxPacketsToForceAck': 0
+ },
+ 'tcp': {
+ 'windowSize': 32768,
+ 'windowScaling': -1,
+ 'disableFinAckWait': 'false'
+ },
+ 'disconnectType': 'FIN',
+ 'slowStart': 'false',
+ 'connectOnly': 'false',
+ 'vtag': {
+ 'VTagMask': '0x0',
+ 'VTagValue': '0x0'
+ },
+ 'sctpPayloadProtocolId': 0,
+ 'billingIncludeSyn': 'true',
+ 'billingIncludeSubflow': 'true',
+ 'billingRecordPerTransaction': 'false',
+ 'tcpPush': 'false',
+ 'hostDataExpansionRatio': 1
+ }
+ }
+}
+DMF_OPTIONS = {
+ 'dmf': {
+ 'transactionRate': 5,
+ 'packetSize': 512,
+ 'burstCount': 1
+ }
+}
+
+
+class TestLandslideProfile(unittest.TestCase):
+
+ def test___init__(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ self.assertListEqual([TP_CONFIG["dmf_config"]],
+ ls_traffic_profile.dmf_config)
+
+ def test___init__config_not_a_dict(self):
+ _tp_config = copy.deepcopy(TP_CONFIG)
+ _tp_config['dmf_config'] = [_tp_config['dmf_config']]
+ ls_traffic_profile = landslide_profile.LandslideProfile(_tp_config)
+ self.assertListEqual(_tp_config['dmf_config'],
+ ls_traffic_profile.dmf_config)
+
+ def test_execute(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ self.assertIsNone(ls_traffic_profile.execute(None))
+
+ def test_update_dmf_options_dict(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ ls_traffic_profile.update_dmf(DMF_OPTIONS)
+ self.assertDictContainsSubset(DMF_OPTIONS['dmf'],
+ ls_traffic_profile.dmf_config[0])
+
+ def test_update_dmf_options_list(self):
+ ls_traffic_profile = landslide_profile.LandslideProfile(TP_CONFIG)
+ _dmf_options = copy.deepcopy(DMF_OPTIONS)
+ _dmf_options['dmf'] = [_dmf_options['dmf']]
+ ls_traffic_profile.update_dmf(_dmf_options)
+ self.assertTrue(all([x in ls_traffic_profile.dmf_config[0]
+ for x in DMF_OPTIONS['dmf']]))
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_pktgen.py b/yardstick/tests/unit/network_services/traffic_profile/test_pktgen.py
new file mode 100644
index 000000000..08542b4f1
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_pktgen.py
@@ -0,0 +1,63 @@
+# Copyright (c) 2018 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+
+from yardstick.common import utils
+from yardstick.network_services.traffic_profile import pktgen
+from yardstick.tests.unit import base as ut_base
+
+
+class TestIXIARFC2544Profile(ut_base.BaseUnitTestCase):
+
+ def setUp(self):
+ self._tp_config = {'traffic_profile': {}}
+ self._host = 'localhost'
+ self._port = '12345'
+ self.tp = pktgen.PktgenTrafficProfile(self._tp_config)
+ self.tp.init(self._host, self._port)
+ self._mock_send_socket_command = mock.patch.object(
+ utils, 'send_socket_command', return_value=0)
+ self.mock_send_socket_command = self._mock_send_socket_command.start()
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_send_socket_command.stop()
+
+ def test_start(self):
+ self.tp.start()
+ self.mock_send_socket_command.assert_called_once_with(
+ self._host, self._port, 'pktgen.start("0")')
+
+ def test_stop(self):
+ self.tp.stop()
+ self.mock_send_socket_command.assert_called_once_with(
+ self._host, self._port, 'pktgen.stop("0")')
+
+ def test_rate(self):
+ rate = 75
+ self.tp.rate(rate)
+ command = 'pktgen.set("0", "rate", 75)'
+ self.mock_send_socket_command.assert_called_once_with(
+ self._host, self._port, command)
+
+ def test_clear_all_stats(self):
+ self.tp.clear_all_stats()
+ self.mock_send_socket_command.assert_called_once_with(
+ self._host, self._port, 'clr')
+
+ def test_help(self):
+ self.tp.help()
+ self.mock_send_socket_command.assert_called_once_with(
+ self._host, self._port, 'help')
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_acl.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_acl.py
new file mode 100644
index 000000000..48c449b20
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_acl.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import unittest
+import mock
+
+from yardstick.tests import STL_MOCKS
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.traffic_profile.prox_ACL import ProxACLProfile
+ from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
+
+
+class TestProxACLProfile(unittest.TestCase):
+
+ def test_run_test_with_pkt_size(self):
+ def target(*args):
+ runs.append(args[2])
+ if args[2] < 0 or args[2] > 100:
+ raise RuntimeError(' '.join([str(args), str(runs)]))
+ if args[2] > 75.0:
+ return fail_tuple, {}
+ return success_tuple, {}
+
+ tp_config = {
+ 'traffic_profile': {
+ 'upper_bound': 100.0,
+ 'lower_bound': 0.0,
+ 'tolerated_loss': 50.0,
+ 'attempts': 20
+ },
+ }
+
+ runs = []
+ success_tuple = ProxTestDataTuple(
+ 10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(
+ 10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ traffic_gen = mock.MagicMock()
+
+ profile_helper = mock.MagicMock()
+ profile_helper.run_test = target
+
+ profile = ProxACLProfile(tp_config)
+ profile.init(mock.MagicMock())
+
+ profile.prox_config["attempts"] = 20
+ profile.queue = mock.MagicMock()
+ profile.tolerated_loss = 50.0
+ profile.pkt_size = 128
+ profile.duration = 30
+ profile.test_value = 100.0
+ profile.tolerated_loss = 100.0
+ profile._profile_helper = profile_helper
+
+ profile.run_test_with_pkt_size(
+ traffic_gen, profile.pkt_size, profile.duration)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py
new file mode 100644
index 000000000..f17656328
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_binsearch.py
@@ -0,0 +1,302 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import mock
+
+from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
+from yardstick.network_services.traffic_profile import prox_binsearch
+
+
+class TestProxBinSearchProfile(unittest.TestCase):
+
+ THEOR_MAX_THROUGHPUT = 0.00012340000000000002
+
+ def setUp(self):
+ self._mock_log_info = mock.patch.object(prox_binsearch.LOG, 'info')
+ self.mock_log_info = self._mock_log_info.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_log_info.stop()
+
+ def test_execute_1(self):
+ def target(*args, **_):
+ runs.append(args[2])
+ if args[2] < 0 or args[2] > 100:
+ raise RuntimeError(' '.join([str(args), str(runs)]))
+ if args[2] > 75.0:
+ return fail_tuple, {}
+ return success_tuple, {}
+
+ def side_effect_func(arg1, arg2):
+ if arg1 == "confirmation":
+ return arg2
+ else:
+ return {}
+
+ tp_config = {
+ 'traffic_profile': {
+ 'packet_sizes': [200],
+ 'test_precision': 2.0,
+ 'tolerated_loss': 0.001,
+ },
+ }
+
+ runs = []
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ traffic_generator = mock.MagicMock()
+ attrs1 = {'get.return_value': 10}
+ traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+ attrs2 = {'__getitem__.return_value': 10, 'get.return_value': 10}
+ attrs3 = {'get.side_effect': side_effect_func}
+ traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
+ traffic_generator.scenario_helper.scenario_cfg["options"].configure_mock(**attrs3)
+
+ profile_helper = mock.MagicMock()
+ profile_helper.run_test = target
+
+ profile = prox_binsearch.ProxBinSearchProfile(tp_config)
+ profile.init(mock.MagicMock())
+ profile._profile_helper = profile_helper
+
+ profile.execute_traffic(traffic_generator)
+
+ self.assertEqual(round(profile.current_lower, 2), 74.69)
+ self.assertEqual(round(profile.current_upper, 2), 76.09)
+ self.assertEqual(len(runs), 7)
+
+ # Result Samples inc theor_max
+ result_tuple = {'Actual_throughput': 5e-07,
+ 'theor_max_throughput': self.THEOR_MAX_THROUGHPUT,
+ 'PktSize': 200,
+ 'Status': 'Result'}
+
+ test_results = profile.queue.put.call_args[0]
+ for k in result_tuple:
+ self.assertEqual(result_tuple[k], test_results[0][k])
+
+ success_result_tuple = {"CurrentDropPackets": 0.5,
+ "DropPackets": 0.5,
+ "LatencyAvg": 5.3,
+ "LatencyMax": 5.2,
+ "LatencyMin": 5.1,
+ "PktSize": 200,
+ "RxThroughput": 7.5e-07,
+ "Throughput": 7.5e-07,
+ "TxThroughput": self.THEOR_MAX_THROUGHPUT,
+ "Status": 'Success'}
+
+ calls = profile.queue.put(success_result_tuple)
+ profile.queue.put.assert_has_calls(calls)
+
+ success_result_tuple2 = {"CurrentDropPackets": 0.5,
+ "DropPackets": 0.5,
+ "LatencyAvg": 5.3,
+ "LatencyMax": 5.2,
+ "LatencyMin": 5.1,
+ "PktSize": 200,
+ "RxThroughput": 7.5e-07,
+ "Throughput": 7.5e-07,
+ "TxThroughput": 123.4,
+ "can_be_lost": 409600,
+ "drop_total": 20480,
+ "rx_total": 4075520,
+ "tx_total": 4096000,
+ "Status": 'Success'}
+
+ calls = profile.queue.put(success_result_tuple2)
+ profile.queue.put.assert_has_calls(calls)
+
+ def test_execute_2(self):
+ def target(*args, **_):
+ runs.append(args[2])
+ if args[2] < 0 or args[2] > 100:
+ raise RuntimeError(' '.join([str(args), str(runs)]))
+ if args[2] > 25.0:
+ return fail_tuple, {}
+ return success_tuple, {}
+
+ def side_effect_func(arg1, _):
+ if arg1 == "confirmation":
+ return 2
+ else:
+ return {}
+
+ tp_config = {
+ 'traffic_profile': {
+ 'packet_sizes': [200],
+ 'test_precision': 2.0,
+ 'tolerated_loss': 0.001,
+ },
+ }
+
+ runs = []
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ traffic_generator = mock.MagicMock()
+ attrs1 = {'get.return_value': 10}
+ traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+ attrs2 = {'__getitem__.return_value': 0, 'get.return_value': 0}
+ attrs3 = {'get.side_effect': side_effect_func}
+
+ traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
+ traffic_generator.scenario_helper.scenario_cfg["options"].configure_mock(**attrs3)
+
+ profile_helper = mock.MagicMock()
+ profile_helper.run_test = target
+
+ profile = prox_binsearch.ProxBinSearchProfile(tp_config)
+ profile.init(mock.MagicMock())
+ profile._profile_helper = profile_helper
+
+ profile.execute_traffic(traffic_generator)
+ self.assertEqual(round(profile.current_lower, 2), 24.06)
+ self.assertEqual(round(profile.current_upper, 2), 25.47)
+ self.assertEqual(len(runs), 21)
+
+ def test_execute_3(self):
+ def target(*args, **_):
+ runs.append(args[2])
+ if args[2] < 0 or args[2] > 100:
+ raise RuntimeError(' '.join([str(args), str(runs)]))
+ if args[2] > 75.0:
+ return fail_tuple, {}
+ return success_tuple, {}
+
+ tp_config = {
+ 'traffic_profile': {
+ 'packet_sizes': [200],
+ 'test_precision': 2.0,
+ 'tolerated_loss': 0.001,
+ },
+ }
+
+ runs = []
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ traffic_generator = mock.MagicMock()
+
+ profile_helper = mock.MagicMock()
+ profile_helper.run_test = target
+
+ profile = prox_binsearch.ProxBinSearchProfile(tp_config)
+ profile.init(mock.MagicMock())
+ profile._profile_helper = profile_helper
+
+ profile.upper_bound = 100.0
+ profile.lower_bound = 99.0
+ profile.execute_traffic(traffic_generator)
+
+ result_tuple = {'Actual_throughput': 0, 'theor_max_throughput': 0,
+ "Status": 'Result', "Next_Step": ''}
+ profile.queue.put.assert_called_with(result_tuple)
+
+ # Check for success_ tuple (None expected)
+ calls = profile.queue.put.mock_calls
+ for call in calls:
+ for call_detail in call[1]:
+ if call_detail["Status"] == 'Success':
+ self.assertRaises(AttributeError)
+
+ def test_execute_4(self):
+
+ def target(*args, **_):
+ runs.append(args[2])
+ if args[2] < 0 or args[2] > 100:
+ raise RuntimeError(' '.join([str(args), str(runs)]))
+ if args[2] > 75.0:
+ return fail_tuple, {}
+
+ return success_tuple, {}
+
+ tp_config = {
+ 'traffic_profile': {
+ 'packet_sizes': [200],
+ 'test_precision': 2.0,
+ 'tolerated_loss': 0.001,
+ },
+ }
+
+ runs = []
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ traffic_generator = mock.MagicMock()
+ attrs1 = {'get.return_value': 100000}
+ traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+ attrs2 = {'__getitem__.return_value': 0, 'get.return_value': 0}
+
+ traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
+
+ profile_helper = mock.MagicMock()
+ profile_helper.run_test = target
+
+ profile = prox_binsearch.ProxBinSearchProfile(tp_config)
+ profile.init(mock.MagicMock())
+ profile._profile_helper = profile_helper
+
+ profile.execute_traffic(traffic_generator)
+ self.assertEqual(round(profile.current_lower, 2), 74.69)
+ self.assertEqual(round(profile.current_upper, 2), 76.09)
+ self.assertEqual(len(runs), 7)
+
+ # Result Samples inc theor_max
+ result_tuple = {'Actual_throughput': 5e-07,
+ 'theor_max_throughput': self.THEOR_MAX_THROUGHPUT,
+ 'PktSize': 200,
+ "Status": 'Result'}
+
+ test_results = profile.queue.put.call_args[0]
+ for k in result_tuple:
+ self.assertEqual(result_tuple[k], test_results[0][k])
+
+ success_result_tuple = {"CurrentDropPackets": 0.5,
+ "DropPackets": 0.5,
+ "LatencyAvg": 5.3,
+ "LatencyMax": 5.2,
+ "LatencyMin": 5.1,
+ "PktSize": 200,
+ "RxThroughput": 7.5e-07,
+ "Throughput": 7.5e-07,
+ "TxThroughput": self.THEOR_MAX_THROUGHPUT,
+ "Status": 'Success'}
+
+ calls = profile.queue.put(success_result_tuple)
+ profile.queue.put.assert_has_calls(calls)
+
+ success_result_tuple2 = {"CurrentDropPackets": 0.5,
+ "DropPackets": 0.5,
+ "LatencyAvg": 5.3,
+ "LatencyMax": 5.2,
+ "LatencyMin": 5.1,
+ "PktSize": 200,
+ "RxThroughput": 7.5e-07,
+ "Throughput": 7.5e-07,
+ "TxThroughput": 123.4,
+ "can_be_lost": 409600,
+ "drop_total": 20480,
+ "rx_total": 4075520,
+ "tx_total": 4096000,
+ "Status": 'Success'}
+
+ calls = profile.queue.put(success_result_tuple2)
+ profile.queue.put.assert_has_calls(calls)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_irq.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_irq.py
new file mode 100644
index 000000000..1d9eb0887
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_irq.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2018-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.
+import time
+
+import unittest
+import mock
+
+from yardstick.network_services.traffic_profile import prox_irq
+
+
+class TestProxIrqProfile(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_log_info = mock.patch.object(prox_irq.LOG, 'info')
+ self.mock_log_info = self._mock_log_info.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_log_info.stop()
+
+ @mock.patch.object(time, 'sleep')
+ def test_execute_1(self, *args):
+ tp_config = {
+ 'traffic_profile': {
+ },
+ }
+
+ traffic_generator = mock.MagicMock()
+ attrs1 = {'get.return_value' : 10}
+ traffic_generator.scenario_helper.all_options.configure_mock(**attrs1)
+
+ attrs2 = {'__getitem__.return_value' : 10, 'get.return_value': 10}
+ traffic_generator.scenario_helper.scenario_cfg["runner"].configure_mock(**attrs2)
+
+ profile_helper = mock.MagicMock()
+
+ profile = prox_irq.ProxIrqProfile(tp_config)
+ profile.init(mock.MagicMock())
+ profile._profile_helper = profile_helper
+
+ profile.execute_traffic(traffic_generator)
+ profile.run_test()
+ is_ended_flag = profile.is_ended()
+
+ self.assertFalse(is_ended_flag)
+ self.assertEqual(profile.lower_bound, 10.0)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
new file mode 100644
index 000000000..1593a0835
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_profile.py
@@ -0,0 +1,130 @@
+# Copyright (c) 2017-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.
+#
+import time
+
+import unittest
+import mock
+
+from yardstick.tests import STL_MOCKS
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.traffic_profile.prox_profile import ProxProfile
+ from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxResourceHelper
+
+
+class TestProxProfile(unittest.TestCase):
+
+ def test_sort_vpci(self):
+ traffic_generator = mock.Mock()
+ interface_1 = {'virtual-interface': {'vpci': 'id1'}, 'name': 'name1'}
+ interface_2 = {'virtual-interface': {'vpci': 'id2'}, 'name': 'name2'}
+ interface_3 = {'virtual-interface': {'vpci': 'id3'}, 'name': 'name3'}
+ interfaces = [interface_2, interface_3, interface_1]
+ traffic_generator.vnfd_helper = {
+ 'vdu': [{'external-interface': interfaces}]}
+ output = ProxProfile.sort_vpci(traffic_generator)
+ self.assertEqual([interface_1, interface_2, interface_3], output)
+
+ def test_fill_samples(self):
+ samples = {}
+
+ traffic_generator = mock.MagicMock()
+ interfaces = [
+ ['id1', 'name1'],
+ ['id2', 'name2']
+ ]
+ traffic_generator.resource_helper.sut.port_stats.side_effect = [
+ list(range(12)),
+ list(range(10, 22)),
+ ]
+
+ expected = {
+ 'name1': {
+ 'in_packets': 6,
+ 'out_packets': 7,
+ },
+ 'name2': {
+ 'in_packets': 16,
+ 'out_packets': 17,
+ },
+ }
+ with mock.patch.object(ProxProfile, 'sort_vpci', return_value=interfaces):
+ ProxProfile.fill_samples(samples, traffic_generator)
+
+ self.assertDictEqual(samples, expected)
+
+ def test_init(self):
+ tp_config = {
+ 'traffic_profile': {},
+ }
+
+ profile = ProxProfile(tp_config)
+ queue = mock.Mock()
+ profile.init(queue)
+ self.assertIs(profile.queue, queue)
+
+ @mock.patch.object(time, 'sleep')
+ def test_execute_traffic(self, *args):
+ packet_sizes = [
+ 10,
+ 100,
+ 1000,
+ ]
+ tp_config = {
+ 'traffic_profile': {
+ 'packet_sizes': packet_sizes,
+ },
+ }
+
+ traffic_generator = mock.MagicMock()
+
+ setup_helper = traffic_generator.setup_helper
+ setup_helper.find_in_section.return_value = None
+
+ prox_resource_helper = ProxResourceHelper(setup_helper)
+ traffic_generator.resource_helper = prox_resource_helper
+
+ profile = ProxProfile(tp_config)
+
+ self.assertFalse(profile.done.is_set())
+ for _ in packet_sizes:
+ with self.assertRaises(NotImplementedError):
+ profile.execute_traffic(traffic_generator)
+
+ self.assertIsNone(profile.execute_traffic(traffic_generator))
+ self.assertTrue(profile.done.is_set())
+
+ def test_bounds_iterator(self):
+ tp_config = {
+ 'traffic_profile': {},
+ }
+
+ profile = ProxProfile(tp_config)
+ value = 0.0
+ for value in profile.bounds_iterator():
+ pass
+
+ self.assertEqual(value, 100.0)
+
+ mock_logger = mock.MagicMock()
+ for _ in profile.bounds_iterator(mock_logger):
+ pass
+
+ mock_logger.debug.assert_called_once()
+ self.assertEqual(mock_logger.info.call_count, 10)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_prox_ramp.py b/yardstick/tests/unit/network_services/traffic_profile/test_prox_ramp.py
new file mode 100644
index 000000000..7a77e3295
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_prox_ramp.py
@@ -0,0 +1,95 @@
+# Copyright (c) 2017 Intel Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+import unittest
+import mock
+
+from yardstick.tests import STL_MOCKS
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.traffic_profile.prox_ramp import ProxRampProfile
+ from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxProfileHelper
+ from yardstick.network_services.vnf_generic.vnf.prox_helpers import ProxTestDataTuple
+
+
+class TestProxRampProfile(unittest.TestCase):
+
+ def test_run_test_with_pkt_size(self):
+ tp_config = {
+ 'traffic_profile': {
+ 'lower_bound': 10.0,
+ 'upper_bound': 100.0,
+ 'step_value': 10.0,
+ },
+ }
+
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+
+ traffic_gen = mock.MagicMock()
+ traffic_gen._test_type = 'Generic'
+
+ profile_helper = ProxProfileHelper(traffic_gen.resource_helper)
+ profile_helper.run_test = run_test = mock.MagicMock(return_value=success_tuple)
+
+ profile = ProxRampProfile(tp_config)
+ profile.fill_samples = fill_samples = mock.MagicMock()
+ profile.queue = mock.MagicMock()
+ profile._profile_helper = profile_helper
+
+ profile.run_test_with_pkt_size(traffic_gen, 128, 30)
+ self.assertEqual(run_test.call_count, 10)
+ self.assertEqual(fill_samples.call_count, 10)
+
+ def test_run_test_with_pkt_size_with_fail(self):
+ tp_config = {
+ 'traffic_profile': {
+ 'lower_bound': 10.0,
+ 'upper_bound': 100.0,
+ 'step_value': 10.0,
+ },
+ }
+
+ success_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.1, 5.2, 5.3], 995, 1000, 123.4)
+ fail_tuple = ProxTestDataTuple(10.0, 1, 2, 3, 4, [5.6, 5.7, 5.8], 850, 1000, 123.4)
+
+ result_list = [
+ success_tuple,
+ success_tuple,
+ success_tuple,
+ fail_tuple,
+ success_tuple,
+ fail_tuple,
+ fail_tuple,
+ fail_tuple,
+ ]
+
+ traffic_gen = mock.MagicMock()
+ traffic_gen._test_type = 'Generic'
+
+ profile_helper = ProxProfileHelper(traffic_gen.resource_helper)
+ profile_helper.run_test = run_test = mock.MagicMock(side_effect=result_list)
+
+ profile = ProxRampProfile(tp_config)
+ profile.fill_samples = fill_samples = mock.MagicMock()
+ profile.queue = mock.MagicMock()
+ profile._profile_helper = profile_helper
+
+ profile.run_test_with_pkt_size(traffic_gen, 128, 30)
+ self.assertEqual(run_test.call_count, 4)
+ self.assertEqual(fill_samples.call_count, 3)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
new file mode 100644
index 000000000..febcfe5da
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_rfc2544.py
@@ -0,0 +1,341 @@
+# 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.
+
+import datetime
+
+import mock
+from trex_stl_lib import api as Pkt
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
+
+from yardstick.common import constants
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.tests.unit import base
+
+
+class TestRFC2544Profile(base.BaseUnitTestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100,
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ PROFILE = {'description': 'Traffic profile to run RFC2544 latency',
+ 'name': 'rfc2544',
+ 'traffic_profile': {'traffic_type': 'RFC2544Profile',
+ 'frame_rate': 100},
+ 'downlink_0':
+ {'ipv4':
+ {'outer_l2':
+ {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4':
+ {'dstip4': '1.1.1.1-1.15.255.255',
+ 'proto': 'udp',
+ 'srcip4': '90.90.1.1-90.105.255.255',
+ 'dscp': 0, 'ttl': 32, 'count': 1},
+ 'outer_l4':
+ {'srcport': '2001',
+ 'dsrport': '1234', 'count': 1}}},
+ 'uplink_0':
+ {'ipv4':
+ {'outer_l2':
+ {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'}},
+ 'outer_l3v4':
+ {'dstip4': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp',
+ 'srcip4': '1.1.1.1-1.15.255.255',
+ 'dscp': 0, 'ttl': 32, 'count': 1},
+ 'outer_l4':
+ {'dstport': '2001',
+ 'srcport': '1234', 'count': 1}}},
+ 'schema': 'isb:traffic_profile:0.1'}
+
+ def test___init__(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ self.assertEqual(rfc2544_profile.max_rate, rfc2544_profile.rate)
+ self.assertEqual(0, rfc2544_profile.min_rate)
+
+ def test_stop_traffic(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ mock_generator = mock.Mock()
+ rfc2544_profile.stop_traffic(traffic_generator=mock_generator)
+ mock_generator.client.stop.assert_called_once()
+ mock_generator.client.reset.assert_called_once()
+ mock_generator.client.remove_all_streams.assert_called_once()
+
+ def test_execute_traffic(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ mock_generator = mock.Mock()
+ mock_generator.networks = {
+ 'downlink_0': ['xe0', 'xe1'],
+ 'uplink_0': ['xe2', 'xe3'],
+ 'downlink_1': []}
+ mock_generator.port_num.side_effect = [10, 20, 30, 40]
+ mock_generator.rfc2544_helper.correlated_traffic = False
+ rfc2544_profile.params = {
+ 'downlink_0': 'profile1',
+ 'uplink_0': 'profile2'}
+
+ with mock.patch.object(rfc2544_profile, '_create_profile') as \
+ mock_create_profile:
+ rfc2544_profile.execute_traffic(traffic_generator=mock_generator)
+ mock_create_profile.assert_has_calls([
+ mock.call('profile1', rfc2544_profile.rate, mock.ANY, False),
+ mock.call('profile1', rfc2544_profile.rate, mock.ANY, False),
+ mock.call('profile2', rfc2544_profile.rate, mock.ANY, False),
+ mock.call('profile2', rfc2544_profile.rate, mock.ANY, False)])
+ mock_generator.client.add_streams.assert_has_calls([
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[30]),
+ mock.call(mock.ANY, ports=[40])])
+ mock_generator.client.start(ports=[10, 20, 30, 40],
+ duration=rfc2544_profile.config.duration,
+ force=True)
+
+ @mock.patch.object(trex_stl_streams, 'STLProfile')
+ def test__create_profile(self, mock_stl_profile):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ port_pg_id = mock.ANY
+ profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+ rate = 100
+ with mock.patch.object(rfc2544_profile, '_create_imix_data') as \
+ mock_create_imix, \
+ mock.patch.object(rfc2544_profile, '_create_vm') as \
+ mock_create_vm, \
+ mock.patch.object(rfc2544_profile, '_create_streams') as \
+ mock_create_streams:
+ mock_create_imix.return_value = 'imix_data'
+ mock_create_streams.return_value = ['stream1']
+ rfc2544_profile._create_profile(profile_data, rate, port_pg_id,
+ True)
+
+ mock_create_imix.assert_called_once_with('imix_info')
+ mock_create_vm.assert_called_once_with(
+ {'outer_l2': {'framesize': 'imix_info'}})
+ mock_create_streams.assert_called_once_with('imix_data', 100,
+ port_pg_id, True)
+ mock_stl_profile.assert_called_once_with(['stream1'])
+
+ def test__create_imix_data_mode_DIP(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ data = {'64B': 50, '128B': 50}
+ self.assertEqual(
+ {'64': 50.0, '128': 50.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+ data = {'64B': 1, '128b': 3}
+ self.assertEqual(
+ {'64': 25.0, '128': 75.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+ data = {}
+ self.assertEqual(
+ {},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+
+ def test__create_imix_data_mode_DIB(self):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ data = {'64B': 25, '128B': 25, '512B': 25, '1518B': 25}
+ byte_total = 64 * 25 + 128 * 25 + 512 * 25 + 1518 * 25
+ self.assertEqual(
+ {'64': 64 * 25.0 * 100 / byte_total,
+ '128': 128 * 25.0 * 100 / byte_total,
+ '512': 512 * 25.0 * 100 / byte_total,
+ '1518': 1518 * 25.0 * 100/ byte_total},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+ data = {}
+ self.assertEqual(
+ {},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+ data = {'64B': 100}
+ self.assertEqual(
+ {'64': 100.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+
+ def test__create_vm(self):
+ packet = {'outer_l2': 'l2_definition'}
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ with mock.patch.object(rfc2544_profile, '_set_outer_l2_fields') as \
+ mock_l2_fileds:
+ rfc2544_profile._create_vm(packet)
+ mock_l2_fileds.assert_called_once_with('l2_definition')
+
+ @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+ return_value='packet')
+ def test__create_single_packet(self, mock_pktbuilder):
+ size = 128
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.ether_packet = Pkt.Eth()
+ rfc2544_profile.ip_packet = Pkt.IP()
+ rfc2544_profile.udp_packet = Pkt.UDP()
+ rfc2544_profile.trex_vm = 'trex_vm'
+ base_pkt = (rfc2544_profile.ether_packet / rfc2544_profile.ip_packet /
+ rfc2544_profile.udp_packet)
+ pad = (size - len(base_pkt)) * 'x'
+ output = rfc2544_profile._create_single_packet(size=size)
+ mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+ vm='trex_vm')
+ self.assertEqual(output, 'packet')
+
+ @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+ return_value='packet')
+ def test__create_single_packet_qinq(self, mock_pktbuilder):
+ size = 128
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.ether_packet = Pkt.Eth()
+ rfc2544_profile.ip_packet = Pkt.IP()
+ rfc2544_profile.udp_packet = Pkt.UDP()
+ rfc2544_profile.trex_vm = 'trex_vm'
+ rfc2544_profile.qinq = True
+ rfc2544_profile.qinq_packet = Pkt.Dot1Q(vlan=1) / Pkt.Dot1Q(vlan=2)
+ base_pkt = (rfc2544_profile.ether_packet /
+ rfc2544_profile.qinq_packet / rfc2544_profile.ip_packet /
+ rfc2544_profile.udp_packet)
+ pad = (size - len(base_pkt)) * 'x'
+ output = rfc2544_profile._create_single_packet(size=size)
+ mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+ vm='trex_vm')
+ self.assertEqual(output, 'packet')
+
+ @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+ @mock.patch.object(trex_stl_streams, 'STLTXCont')
+ @mock.patch.object(trex_stl_client, 'STLStream')
+ def test__create_streams(self, mock_stream, mock_txcont, mock_latency):
+ imix_data = {'64': 25, '512': 75}
+ rate = 35
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(10)
+ mock_stream.side_effect = ['stream1', 'stream2']
+ mock_txcont.side_effect = ['txcont1', 'txcont2']
+ mock_latency.side_effect = ['latency1', 'latency2']
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ with mock.patch.object(rfc2544_profile, '_create_single_packet'):
+ output = rfc2544_profile._create_streams(imix_data, rate,
+ port_pg_id, True)
+ self.assertEqual(['stream1', 'stream2'], output)
+ mock_latency.assert_has_calls([
+ mock.call(pg_id=1), mock.call(pg_id=2)])
+ mock_txcont.assert_has_calls([
+ mock.call(percentage=float(25 * 35) / 100),
+ mock.call(percentage=float(75 * 35) / 100)], any_order=True)
+
+ @mock.patch.object(rfc2544.RFC2544Profile, '_get_framesize')
+ def test_get_drop_percentage(self, mock_get_framesize):
+ rfc2544_profile = rfc2544.RFC2544Profile(self.TRAFFIC_PROFILE)
+ rfc2544_profile.iteration = 1
+ mock_get_framesize.return_value = '64B'
+
+ samples = [
+ {'xe1': {'out_packets': 2100,
+ 'in_packets': 2010,
+ 'out_bytes': 134400,
+ 'in_bytes': 128640,
+ 'timestamp': datetime.datetime(2000, 1, 1, 1, 1, 1, 1)},
+ 'xe2': {'out_packets': 4100,
+ 'in_packets': 4010,
+ 'out_bytes': 262400,
+ 'in_bytes': 256640,
+ 'timestamp': datetime.datetime(2000, 1, 1, 1, 1, 1, 1)}},
+ {'xe1': {'out_packets': 2110,
+ 'in_packets': 2040,
+ 'out_bytes': 135040,
+ 'in_bytes': 130560,
+ 'latency': 'Latency1',
+ 'timestamp': datetime.datetime(2000, 1, 1, 1, 1, 1, 31)},
+ 'xe2': {'out_packets': 4150,
+ 'in_packets': 4010,
+ 'out_bytes': 265600,
+ 'in_bytes': 256640,
+ 'latency': 'Latency2',
+ 'timestamp': datetime.datetime(2000, 1, 1, 1, 1, 1, 31)}}
+ ]
+ completed, output = rfc2544_profile.get_drop_percentage(
+ samples, 0, 0, False, 0.1)
+ expected = {'xe1': {'OutPackets': 10,
+ 'InPackets': 30,
+ 'OutBytes': 640,
+ 'InBytes': 1920},
+ 'xe2': {'OutPackets': 50,
+ 'InPackets': 0,
+ 'OutBytes': 3200,
+ 'InBytes': 0},
+ 'DropPercentage': 50.0,
+ 'RxThroughput': 1000000.0,
+ 'TxThroughput': 2000000.0,
+ 'RxThroughputBps': 64000000.0,
+ 'TxThroughputBps': 128000000.0,
+ 'Rate': 100.0,
+ 'Iteration': 1,
+ 'PktSize': '64B',
+ 'Status': 'Failure'}
+ self.assertEqual(expected, output)
+ self.assertFalse(completed)
+
+
+class PortPgIDMapTestCase(base.BaseUnitTestCase):
+
+ def test_add_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ self.assertEqual(10, port_pg_id_map._last_port)
+ self.assertEqual([], port_pg_id_map._port_pg_id_map[10])
+
+ def test_get_pg_ids(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ port_pg_id_map.increase_pg_id()
+ port_pg_id_map.increase_pg_id()
+ port_pg_id_map.add_port(20)
+ port_pg_id_map.increase_pg_id()
+ self.assertEqual([1, 2], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual([3], port_pg_id_map.get_pg_ids(20))
+ self.assertEqual([], port_pg_id_map.get_pg_ids(30))
+
+ def test_increase_pg_id_no_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ self.assertIsNone(port_pg_id_map.increase_pg_id())
+
+ def test_increase_pg_id_last_port(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ self.assertEqual(1, port_pg_id_map.increase_pg_id())
+ self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual(10, port_pg_id_map._last_port)
+
+ def test_increase_pg_id(self):
+ port_pg_id_map = rfc2544.PortPgIDMap()
+ port_pg_id_map.add_port(10)
+ port_pg_id_map.increase_pg_id()
+ self.assertEqual(2, port_pg_id_map.increase_pg_id(port=20))
+ self.assertEqual([1], port_pg_id_map.get_pg_ids(10))
+ self.assertEqual([2], port_pg_id_map.get_pg_ids(20))
+ self.assertEqual(20, port_pg_id_map._last_port)
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_sip.py b/yardstick/tests/unit/network_services/traffic_profile/test_sip.py
new file mode 100644
index 000000000..bf26ee44d
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_sip.py
@@ -0,0 +1,51 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import mock
+
+from yardstick.network_services.traffic_profile import sip
+
+
+class TestSipProfile(unittest.TestCase):
+
+ TRAFFIC_PROFILE = {
+ "schema": "nsb:traffic_profile:0.1",
+ "name": "sip",
+ "description": "Traffic profile to run sip",
+ "traffic_profile": {
+ "traffic_type": "SipProfile",
+ "frame_rate": 100, # pps
+ "duration": 10,
+ "enable_latency": False}}
+
+ def setUp(self):
+ self.sip_profile = sip.SipProfile(self.TRAFFIC_PROFILE)
+
+ def test___init__(self):
+ self.assertIsNone(self.sip_profile.generator)
+
+ def test_execute_traffic(self):
+ self.sip_profile.generator = None
+ mock_traffic_generator = mock.Mock()
+ self.sip_profile.execute_traffic(mock_traffic_generator)
+ self.assertIsNotNone(self.sip_profile.generator)
+
+ def test_is_ended_true(self):
+ self.sip_profile.generator = mock.Mock(return_value=True)
+ self.assertTrue(self.sip_profile.is_ended())
+
+ def test_is_ended_false(self):
+ self.sip_profile.generator = None
+ self.assertFalse(self.sip_profile.is_ended())
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py b/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
new file mode 100644
index 000000000..628e85459
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_trex_traffic_profile.py
@@ -0,0 +1,277 @@
+# 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.
+
+import ipaddress
+
+import six
+import unittest
+
+from yardstick.common import exceptions as y_exc
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import trex_traffic_profile
+
+
+class TestTrexProfile(unittest.TestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ EXAMPLE_ETHERNET_ADDR = "00:00:00:00:00:01"
+ EXAMPLE_IP_ADDR = "10.0.0.1"
+ EXAMPLE_IPv6_ADDR = "0064:ff9b:0:0:0:0:9810:6414"
+
+ PROFILE = {
+ 'description': 'Traffic profile to run RFC2544 latency',
+ 'name': 'rfc2544',
+ 'traffic_profile': {'traffic_type': 'RFC2544Profile',
+ 'frame_rate': 100},
+ tp_base.TrafficProfile.DOWNLINK: {
+ 'ipv4': {'outer_l2': {'framesize': {'64B': '100',
+ '1518B': '0',
+ '128B': '0',
+ '1400B': '0',
+ '256B': '0',
+ '373b': '0',
+ '570B': '0'},
+ "srcmac": "00:00:00:00:00:02",
+ "dstmac": "00:00:00:00:00:01"},
+ 'outer_l3v4': {'dstip4': '1.1.1.1-1.1.2.2',
+ 'proto': 'udp',
+ 'srcip4': '9.9.1.1-90.1.2.2',
+ 'dscp': 0, 'ttl': 32,
+ 'count': 1},
+ 'outer_l4': {'srcport': '2001',
+ 'dsrport': '1234',
+ 'count': 1}}},
+ tp_base.TrafficProfile.UPLINK: {
+ 'ipv4':
+ {'outer_l2': {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'},
+ "srcmac": "00:00:00:00:00:01",
+ "dstmac": "00:00:00:00:00:02"},
+ 'outer_l3v4': {'dstip4': '9.9.1.1-90.105.255.255',
+ 'proto': 'udp',
+ 'srcip4': '1.1.1.1-1.15.255.255',
+ 'dscp': 0, 'ttl': 32, 'count': 1},
+ 'outer_l4': {'dstport': '2001',
+ 'srcport': '1234',
+ 'count': 1}}},
+ 'schema': 'isb:traffic_profile:0.1'}
+ PROFILE_v6 = {
+ 'description': 'Traffic profile to run RFC2544 latency',
+ 'name': 'rfc2544',
+ 'traffic_profile': {'traffic_type': 'RFC2544Profile',
+ 'frame_rate': 100},
+ tp_base.TrafficProfile.DOWNLINK: {
+ 'ipv6': {'outer_l2': {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'},
+ "srcmac": "00:00:00:00:00:02",
+ "dstmac": "00:00:00:00:00:01"},
+ 'outer_l3v4': {
+ 'dstip6':
+ '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420',
+ 'proto': 'udp',
+ 'srcip6':
+ '0064:ff9b:0:0:0:0:9810:2814-0064:ff9b:0:0:0:0:9810:2820',
+ 'dscp': 0, 'ttl': 32,
+ 'count': 1},
+ 'outer_l4': {'srcport': '2001',
+ 'dsrport': '1234',
+ 'count': 1}}},
+ tp_base.TrafficProfile.UPLINK: {
+ 'ipv6': {'outer_l2': {'framesize':
+ {'64B': '100', '1518B': '0',
+ '128B': '0', '1400B': '0',
+ '256B': '0', '373b': '0',
+ '570B': '0'},
+ "srcmac": "00:00:00:00:00:01",
+ "dstmac": "00:00:00:00:00:02"},
+ 'outer_l3v4': {
+ 'dstip6':
+ '0064:ff9b:0:0:0:0:9810:2814-0064:ff9b:0:0:0:0:9810:2820',
+ 'proto': 'udp',
+ 'srcip6':
+ '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420',
+ 'dscp': 0, 'ttl': 32,
+ 'count': 1},
+ 'outer_l4': {'dstport': '2001',
+ 'srcport': '1234',
+ 'count': 1}}},
+ 'schema': 'isb:traffic_profile:0.1'}
+
+ def test___init__(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ self.assertEqual(trex_profile.pps, 100)
+
+ def test_qinq(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
+ "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
+
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ self.assertIsNone(trex_profile.set_qinq(qinq))
+
+ qinq = {"S-VLAN": {"id": "128-130", "priority": 0, "cfi": 0},
+ "C-VLAN": {"id": "512-515", "priority": 0, "cfi": 0}}
+ self.assertIsNone(trex_profile.set_qinq(qinq))
+
+ def test__set_outer_l2_fields(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ qinq = {"S-VLAN": {"id": 128, "priority": 0, "cfi": 0},
+ "C-VLAN": {"id": 512, "priority": 0, "cfi": 0}}
+ outer_l2 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l2']
+ outer_l2['QinQ'] = qinq
+ self.assertIsNone(trex_profile._set_outer_l2_fields(outer_l2))
+
+ def test__set_outer_l3v4_fields(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l3v4 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
+ outer_l3v4['proto'] = 'tcp'
+ self.assertIsNone(trex_profile._set_outer_l3v4_fields(outer_l3v4))
+
+ def test__set_outer_l3v6_fields(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l3v6 = self.PROFILE_v6[
+ tp_base.TrafficProfile.UPLINK]['ipv6']['outer_l3v4']
+ outer_l3v6['proto'] = 'tcp'
+ outer_l3v6['tc'] = 1
+ outer_l3v6['hlim'] = 10
+ self.assertIsNone(trex_profile._set_outer_l3v6_fields(outer_l3v6))
+
+ def test__set_outer_l4_fields(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ outer_l4 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l4']
+ self.assertIsNone(trex_profile._set_outer_l4_fields(outer_l4))
+
+ def test__count_ip_ipv4(self):
+ start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+ '1.1.1.1', '1.2.3.4')
+ self.assertEqual('1.1.1.1', str(start))
+ self.assertEqual('1.2.3.4', str(end))
+ diff = (int(ipaddress.IPv4Address(six.u('1.2.3.4'))) -
+ int(ipaddress.IPv4Address(six.u('1.1.1.1'))))
+ self.assertEqual(diff, count)
+
+ def test__count_ip_ipv6(self):
+ start_ip = '0064:ff9b:0:0:0:0:9810:6414'
+ end_ip = '0064:ff9b:0:0:0:0:9810:6420'
+ start, end, count = trex_traffic_profile.TrexProfile._count_ip(
+ start_ip, end_ip)
+ self.assertEqual(0x98106414, start)
+ self.assertEqual(0x98106420, end)
+ self.assertEqual(0x98106420 - 0x98106414, count)
+
+ def test__count_ip_ipv6_exception(self):
+ start_ip = '0064:ff9b:0:0:0:0:9810:6420'
+ end_ip = '0064:ff9b:0:0:0:0:9810:6414'
+ with self.assertRaises(y_exc.IPv6RangeError):
+ trex_traffic_profile.TrexProfile._count_ip(start_ip, end_ip)
+
+ def test__dscp_range_action_partial_actual_count_zero(self):
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ dscp_partial = traffic_profile._dscp_range_action_partial()
+
+ flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
+ dscp_partial('1', '1', 'unneeded')
+ self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
+
+ def test__dscp_range_action_partial_count_greater_than_actual(self):
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ dscp_partial = traffic_profile._dscp_range_action_partial()
+
+ flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
+ dscp_partial('1', '10', '100')
+ self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
+
+ def test__udp_range_action_partial_actual_count_zero(self):
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ traffic_profile.udp['field1'] = 'value1'
+ udp_partial = traffic_profile._udp_range_action_partial('field1')
+
+ flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
+ udp_partial('1', '1', 'unneeded')
+ self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
+
+ def test__udp_range_action_partial_count_greater_than_actual(self):
+ traffic_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ traffic_profile.udp['field1'] = 'value1'
+ udp_partial = traffic_profile._udp_range_action_partial(
+ 'field1', 'not_used_count')
+ flow_vars_initial_length = len(traffic_profile.vm_flow_vars)
+ udp_partial('1', '10', '100')
+ self.assertEqual(len(traffic_profile.vm_flow_vars), flow_vars_initial_length + 2)
+
+ def test__general_single_action_partial(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+ trex_profile._general_single_action_partial(
+ trex_traffic_profile.ETHERNET)(trex_traffic_profile.SRC)(
+ self.EXAMPLE_ETHERNET_ADDR)
+ self.assertEqual(self.EXAMPLE_ETHERNET_ADDR,
+ trex_profile.ether_packet.src)
+
+ trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+ trex_traffic_profile.DST)(self.EXAMPLE_IP_ADDR)
+ self.assertEqual(self.EXAMPLE_IP_ADDR, trex_profile.ip_packet.dst)
+
+ trex_profile._general_single_action_partial(trex_traffic_profile.IPv6)(
+ trex_traffic_profile.DST)(self.EXAMPLE_IPv6_ADDR)
+ self.assertEqual(self.EXAMPLE_IPv6_ADDR, trex_profile.ip6_packet.dst)
+
+ trex_profile._general_single_action_partial(trex_traffic_profile.UDP)(
+ trex_traffic_profile.SRC_PORT)(5060)
+ self.assertEqual(5060, trex_profile.udp_packet.sport)
+
+ trex_profile._general_single_action_partial(trex_traffic_profile.IP)(
+ trex_traffic_profile.TYPE_OF_SERVICE)(0)
+ self.assertEqual(0, trex_profile.ip_packet.tos)
+
+ def test__set_proto_addr(self):
+ trex_profile = trex_traffic_profile.TrexProfile(self.PROFILE)
+
+ ether_range = "00:00:00:00:00:01-00:00:00:00:00:02"
+ ip_range = "1.1.1.2-1.1.1.10"
+ ipv6_range = '0064:ff9b:0:0:0:0:9810:6414-0064:ff9b:0:0:0:0:9810:6420'
+
+ trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+ trex_traffic_profile.SRC, ether_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.ETHERNET,
+ trex_traffic_profile.DST, ether_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IP,
+ trex_traffic_profile.SRC, ip_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IP,
+ trex_traffic_profile.DST, ip_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+ trex_traffic_profile.SRC, ipv6_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.IPv6,
+ trex_traffic_profile.DST, ipv6_range)
+ trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+ trex_traffic_profile.SRC_PORT,
+ '5060-5090')
+ trex_profile._set_proto_addr(trex_traffic_profile.UDP,
+ trex_traffic_profile.DST_PORT, '5060')
diff --git a/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py b/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py
new file mode 100644
index 000000000..8ad17b547
--- /dev/null
+++ b/yardstick/tests/unit/network_services/traffic_profile/test_vpp_rfc2544.py
@@ -0,0 +1,890 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+from trex_stl_lib import trex_stl_client
+from trex_stl_lib import trex_stl_packet_builder_scapy
+from trex_stl_lib import trex_stl_streams
+
+from yardstick.common import constants
+from yardstick.network_services.helpers.vpp_helpers.multiple_loss_ratio_search import \
+ MultipleLossRatioSearch
+from yardstick.network_services.helpers.vpp_helpers.ndr_pdr_result import \
+ NdrPdrResult
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_interval import \
+ ReceiveRateInterval
+from yardstick.network_services.helpers.vpp_helpers.receive_rate_measurement import \
+ ReceiveRateMeasurement
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544, vpp_rfc2544
+from yardstick.network_services.traffic_profile.rfc2544 import PortPgIDMap
+from yardstick.tests.unit import base
+
+
+class TestVppRFC2544Profile(base.BaseUnitTestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "duration": 30,
+ "enable_latency": True,
+ "frame_rate": 100,
+ "intermediate_phases": 2,
+ "lower_bound": 1.0,
+ "step_interval": 0.5,
+ "test_precision": 0.1,
+ "upper_bound": 100.0}}
+
+ TRAFFIC_PROFILE_MAX_RATE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "duration": 30,
+ "enable_latency": True,
+ "frame_rate": 10000,
+ "intermediate_phases": 2,
+ "lower_bound": 1.0,
+ "step_interval": 0.5,
+ "test_precision": 0.1,
+ "upper_bound": 100.0}}
+
+ PROFILE = {
+ "description": "Traffic profile to run RFC2544 latency",
+ "downlink_0": {
+ "ipv4": {
+ "id": 2,
+ "outer_l2": {
+ "framesize": {
+ "1024B": "0",
+ "1280B": "0",
+ "128B": "0",
+ "1400B": "0",
+ "1500B": "0",
+ "1518B": "0",
+ "256B": "0",
+ "373b": "0",
+ "512B": "0",
+ "570B": "0",
+ "64B": "100"
+ }
+ },
+ "outer_l3v4": {
+ "count": "1",
+ "dstip4": "10.0.0.0-10.0.0.100",
+ "proto": 61,
+ "srcip4": "20.0.0.0-20.0.0.100"
+ }
+ }
+ },
+ "name": "rfc2544",
+ "schema": "nsb:traffic_profile:0.1",
+ "traffic_profile": {
+ "duration": 30,
+ "enable_latency": True,
+ "frame_rate": 100,
+ "intermediate_phases": 2,
+ "lower_bound": 1.0,
+ "step_interval": 0.5,
+ "test_precision": 0.1,
+ "traffic_type": "VppRFC2544Profile",
+ "upper_bound": 100.0
+ },
+ "uplink": {
+ "ipv4": {
+ "id": 1,
+ "outer_l2": {
+ "framesize": {
+ "1024B": "0",
+ "1280B": "0",
+ "128B": "0",
+ "1400B": "0",
+ "1500B": "0",
+ "1518B": "0",
+ "256B": "0",
+ "373B": "0",
+ "512B": "0",
+ "570B": "0",
+ "64B": "100"
+ }
+ },
+ "outer_l3v4": {
+ "count": "10",
+ "dstip4": "20.0.0.0-20.0.0.100",
+ "proto": 61,
+ "srcip4": "10.0.0.0-10.0.0.100"
+ }
+ }
+ }
+ }
+
+ def test___init__(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ self.assertEqual(vpp_rfc2544_profile.max_rate,
+ vpp_rfc2544_profile.rate)
+ self.assertEqual(0, vpp_rfc2544_profile.min_rate)
+ self.assertEqual(2, vpp_rfc2544_profile.number_of_intermediate_phases)
+ self.assertEqual(30, vpp_rfc2544_profile.duration)
+ self.assertEqual(0.1, vpp_rfc2544_profile.precision)
+ self.assertEqual(1.0, vpp_rfc2544_profile.lower_bound)
+ self.assertEqual(100.0, vpp_rfc2544_profile.upper_bound)
+ self.assertEqual(0.5, vpp_rfc2544_profile.step_interval)
+ self.assertEqual(True, vpp_rfc2544_profile.enable_latency)
+
+ def test_init_traffic_params(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ mock_generator = mock.MagicMock()
+ mock_generator.rfc2544_helper.latency = True
+ mock_generator.rfc2544_helper.tolerance_low = 0.0
+ mock_generator.rfc2544_helper.tolerance_high = 0.005
+ mock_generator.scenario_helper.all_options = {
+ "vpp_config": {
+ "max_rate": 14880000
+ }
+ }
+ vpp_rfc2544_profile.init_traffic_params(mock_generator)
+ self.assertEqual(0.0, vpp_rfc2544_profile.tolerance_low)
+ self.assertEqual(0.005, vpp_rfc2544_profile.tolerance_high)
+ self.assertEqual(14880000, vpp_rfc2544_profile.max_rate)
+ self.assertEqual(True, vpp_rfc2544_profile.enable_latency)
+
+ def test_calculate_frame_size(self):
+ imix = {'40B': 7, '576B': 4, '1500B': 1}
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ self.assertEqual((4084 / 12, 12),
+ vpp_rfc2544_profile.calculate_frame_size(imix))
+
+ def test_calculate_frame_size_empty(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ self.assertEqual((64, 100),
+ vpp_rfc2544_profile.calculate_frame_size(None))
+
+ def test_calculate_frame_size_error(self):
+ imix = {'40B': -7, '576B': 4, '1500B': 1}
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ self.assertEqual((64, 100),
+ vpp_rfc2544_profile.calculate_frame_size(imix))
+
+ def test__gen_payload(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ self.assertIsNotNone(vpp_rfc2544_profile._gen_payload(4))
+
+ def test_register_generator(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ mock_generator = mock.MagicMock()
+ mock_generator.rfc2544_helper.latency = True
+ mock_generator.rfc2544_helper.tolerance_low = 0.0
+ mock_generator.rfc2544_helper.tolerance_high = 0.005
+ mock_generator.scenario_helper.all_options = {
+ "vpp_config": {
+ "max_rate": 14880000
+ }
+ }
+ vpp_rfc2544_profile.register_generator(mock_generator)
+ self.assertEqual(0.0, vpp_rfc2544_profile.tolerance_low)
+ self.assertEqual(0.005, vpp_rfc2544_profile.tolerance_high)
+ self.assertEqual(14880000, vpp_rfc2544_profile.max_rate)
+ self.assertEqual(True, vpp_rfc2544_profile.enable_latency)
+
+ def test_stop_traffic(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ mock_generator = mock.Mock()
+ vpp_rfc2544_profile.stop_traffic(traffic_generator=mock_generator)
+ mock_generator.client.stop.assert_called_once()
+ mock_generator.client.reset.assert_called_once()
+ mock_generator.client.remove_all_streams.assert_called_once()
+
+ def test_execute_traffic(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.init_queue(mock.MagicMock())
+ vpp_rfc2544_profile.params = {
+ 'downlink_0': 'profile1',
+ 'uplink_0': 'profile2'}
+ mock_generator = mock.MagicMock()
+ mock_generator.networks = {
+ 'downlink_0': ['xe0', 'xe1'],
+ 'uplink_0': ['xe2', 'xe3'],
+ 'uplink_1': ['xe2', 'xe3']}
+ mock_generator.port_num.side_effect = [10, 20, 30, 40]
+ mock_generator.rfc2544_helper.correlated_traffic = False
+
+ with mock.patch.object(vpp_rfc2544_profile, 'create_profile') as \
+ mock_create_profile:
+ vpp_rfc2544_profile.execute_traffic(
+ traffic_generator=mock_generator)
+ mock_create_profile.assert_has_calls([
+ mock.call('profile1', 10),
+ mock.call('profile1', 20),
+ mock.call('profile2', 30),
+ mock.call('profile2', 40)])
+ mock_generator.client.add_streams.assert_has_calls([
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[30]),
+ mock.call(mock.ANY, ports=[40])])
+
+ def test_execute_traffic_correlated_traffic(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.init_queue(mock.MagicMock())
+ vpp_rfc2544_profile.params = {
+ 'downlink_0': 'profile1',
+ 'uplink_0': 'profile2'}
+ mock_generator = mock.MagicMock()
+ mock_generator.networks = {
+ 'downlink_0': ['xe0', 'xe1'],
+ 'uplink_0': ['xe2', 'xe3']}
+ mock_generator.port_num.side_effect = [10, 20, 30, 40]
+ mock_generator.rfc2544_helper.correlated_traffic = True
+
+ with mock.patch.object(vpp_rfc2544_profile, 'create_profile') as \
+ mock_create_profile:
+ vpp_rfc2544_profile.execute_traffic(
+ traffic_generator=mock_generator)
+ mock_create_profile.assert_has_calls([
+ mock.call('profile2', 10),
+ mock.call('profile2', 20)])
+ mock_generator.client.add_streams.assert_has_calls([
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20])])
+
+ def test_execute_traffic_max_rate(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE_MAX_RATE)
+ vpp_rfc2544_profile.init_queue(mock.MagicMock())
+ vpp_rfc2544_profile.pkt_size = 64
+ vpp_rfc2544_profile.params = {
+ 'downlink_0': 'profile1',
+ 'uplink_0': 'profile2'}
+ mock_generator = mock.MagicMock()
+ mock_generator.networks = {
+ 'downlink_0': ['xe0', 'xe1'],
+ 'uplink_0': ['xe2', 'xe3']}
+ mock_generator.port_num.side_effect = [10, 20, 30, 40]
+ mock_generator.rfc2544_helper.correlated_traffic = False
+
+ with mock.patch.object(vpp_rfc2544_profile, 'create_profile') as \
+ mock_create_profile:
+ vpp_rfc2544_profile.execute_traffic(
+ traffic_generator=mock_generator)
+ mock_create_profile.assert_has_calls([
+ mock.call('profile1', 10),
+ mock.call('profile1', 20),
+ mock.call('profile2', 30),
+ mock.call('profile2', 40)])
+ mock_generator.client.add_streams.assert_has_calls([
+ mock.call(mock.ANY, ports=[10]),
+ mock.call(mock.ANY, ports=[20]),
+ mock.call(mock.ANY, ports=[30]),
+ mock.call(mock.ANY, ports=[40])])
+
+ @mock.patch.object(trex_stl_streams, 'STLProfile')
+ def test_create_profile(self, mock_stl_profile):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ port = mock.ANY
+ profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+ with mock.patch.object(vpp_rfc2544_profile, 'calculate_frame_size') as \
+ mock_calculate_frame_size, \
+ mock.patch.object(vpp_rfc2544_profile, '_create_imix_data') as \
+ mock_create_imix, \
+ mock.patch.object(vpp_rfc2544_profile, '_create_vm') as \
+ mock_create_vm, \
+ mock.patch.object(vpp_rfc2544_profile,
+ '_create_single_stream') as \
+ mock_create_single_stream:
+ mock_calculate_frame_size.return_value = 64, 100
+ mock_create_imix.return_value = 'imix_data'
+ mock_create_single_stream.return_value = ['stream1']
+ vpp_rfc2544_profile.create_profile(profile_data, port)
+
+ mock_create_imix.assert_called_once_with('imix_info')
+ mock_create_vm.assert_called_once_with(
+ {'outer_l2': {'framesize': 'imix_info'}})
+ mock_create_single_stream.assert_called_once_with(port, 'imix_data',
+ 100)
+ mock_stl_profile.assert_called_once_with(['stream1'])
+
+ @mock.patch.object(trex_stl_streams, 'STLProfile')
+ def test_create_profile_max_rate(self, mock_stl_profile):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE_MAX_RATE)
+ port = mock.ANY
+ profile_data = {'packetid_1': {'outer_l2': {'framesize': 'imix_info'}}}
+ with mock.patch.object(vpp_rfc2544_profile, 'calculate_frame_size') as \
+ mock_calculate_frame_size, \
+ mock.patch.object(vpp_rfc2544_profile, '_create_imix_data') as \
+ mock_create_imix, \
+ mock.patch.object(vpp_rfc2544_profile, '_create_vm') as \
+ mock_create_vm, \
+ mock.patch.object(vpp_rfc2544_profile,
+ '_create_single_stream') as \
+ mock_create_single_stream:
+ mock_calculate_frame_size.return_value = 64, 100
+ mock_create_imix.return_value = 'imix_data'
+ mock_create_single_stream.return_value = ['stream1']
+ vpp_rfc2544_profile.create_profile(profile_data, port)
+
+ mock_create_imix.assert_called_once_with('imix_info', 'mode_DIP')
+ mock_create_vm.assert_called_once_with(
+ {'outer_l2': {'framesize': 'imix_info'}})
+ mock_create_single_stream.assert_called_once_with(port, 'imix_data',
+ 100)
+ mock_stl_profile.assert_called_once_with(['stream1'])
+
+ def test__create_imix_data_mode_DIP(self):
+ rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(self.TRAFFIC_PROFILE)
+ data = {'64B': 50, '128B': 50}
+ self.assertEqual(
+ {'64': 50.0, '128': 50.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+ data = {'64B': 1, '128b': 3}
+ self.assertEqual(
+ {'64': 25.0, '128': 75.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+ data = {}
+ self.assertEqual(
+ {},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_PACKETS))
+
+ def test__create_imix_data_mode_DIB(self):
+ rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(self.TRAFFIC_PROFILE)
+ data = {'64B': 25, '128B': 25, '512B': 25, '1518B': 25}
+ byte_total = 64 * 25 + 128 * 25 + 512 * 25 + 1518 * 25
+ self.assertEqual(
+ {'64': 64 * 25.0 * 100 / byte_total,
+ '128': 128 * 25.0 * 100 / byte_total,
+ '512': 512 * 25.0 * 100 / byte_total,
+ '1518': 1518 * 25.0 * 100 / byte_total},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+ data = {}
+ self.assertEqual(
+ {},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+ data = {'64B': 100}
+ self.assertEqual(
+ {'64': 100.0},
+ rfc2544_profile._create_imix_data(
+ data, weight_mode=constants.DISTRIBUTION_IN_BYTES))
+
+ def test__create_vm(self):
+ packet = {'outer_l2': 'l2_definition'}
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ with mock.patch.object(vpp_rfc2544_profile, '_set_outer_l2_fields') as \
+ mock_l2_fileds:
+ vpp_rfc2544_profile._create_vm(packet)
+ mock_l2_fileds.assert_called_once_with('l2_definition')
+
+ @mock.patch.object(trex_stl_packet_builder_scapy, 'STLPktBuilder',
+ return_value='packet')
+ def test__create_single_packet(self, mock_pktbuilder):
+ size = 128
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.ether_packet = mock.MagicMock()
+ vpp_rfc2544_profile.ip_packet = mock.MagicMock()
+ vpp_rfc2544_profile.udp_packet = mock.MagicMock()
+ vpp_rfc2544_profile.trex_vm = 'trex_vm'
+ # base_pkt = (
+ # vpp_rfc2544_profile.ether_packet / vpp_rfc2544_profile.ip_packet /
+ # vpp_rfc2544_profile.udp_packet)
+ # pad = (size - len(base_pkt)) * 'x'
+ output = vpp_rfc2544_profile._create_single_packet(size=size)
+ self.assertEqual(mock_pktbuilder.call_count, 2)
+ # mock_pktbuilder.assert_called_once_with(pkt=base_pkt / pad,
+ # vm='trex_vm')
+ self.assertEqual(output, ('packet', 'packet'))
+
+ def test__set_outer_l3v4_fields(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ outer_l3v4 = self.PROFILE[
+ tp_base.TrafficProfile.UPLINK]['ipv4']['outer_l3v4']
+ outer_l3v4['proto'] = 'tcp'
+ self.assertIsNone(
+ vpp_rfc2544_profile._set_outer_l3v4_fields(outer_l3v4))
+
+ @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+ @mock.patch.object(trex_stl_streams, 'STLTXCont')
+ @mock.patch.object(trex_stl_client, 'STLStream')
+ def test__create_single_stream(self, mock_stream, mock_txcont,
+ mock_latency):
+ imix_data = {'64': 25, '512': 75}
+ mock_stream.side_effect = ['stream1', 'stream2', 'stream3', 'stream4']
+ mock_txcont.side_effect = ['txcont1', 'txcont2', 'txcont3', 'txcont4']
+ mock_latency.side_effect = ['latency1', 'latency2']
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.port_pg_id = rfc2544.PortPgIDMap()
+ vpp_rfc2544_profile.port_pg_id.add_port(10)
+ with mock.patch.object(vpp_rfc2544_profile, '_create_single_packet') as \
+ mock_create_single_packet:
+ mock_create_single_packet.return_value = 64, 100
+ output = vpp_rfc2544_profile._create_single_stream(10, imix_data,
+ 100, 0.0)
+ self.assertEqual(['stream1', 'stream2', 'stream3', 'stream4'], output)
+ mock_latency.assert_has_calls([
+ mock.call(pg_id=1), mock.call(pg_id=2)])
+ mock_txcont.assert_has_calls([
+ mock.call(percentage=25 * 100 / 100),
+ mock.call(percentage=75 * 100 / 100)], any_order=True)
+
+ @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+ @mock.patch.object(trex_stl_streams, 'STLTXCont')
+ @mock.patch.object(trex_stl_client, 'STLStream')
+ def test__create_single_stream_max_rate(self, mock_stream, mock_txcont,
+ mock_latency):
+ imix_data = {'64': 25, '512': 75}
+ mock_stream.side_effect = ['stream1', 'stream2', 'stream3', 'stream4']
+ mock_txcont.side_effect = ['txcont1', 'txcont2', 'txcont3', 'txcont4']
+ mock_latency.side_effect = ['latency1', 'latency2']
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE_MAX_RATE)
+ vpp_rfc2544_profile.pkt_size = 64
+ vpp_rfc2544_profile.port_pg_id = rfc2544.PortPgIDMap()
+ vpp_rfc2544_profile.port_pg_id.add_port(1)
+ with mock.patch.object(vpp_rfc2544_profile, '_create_single_packet') as \
+ mock_create_single_packet:
+ mock_create_single_packet.return_value = 64, 100
+ output = vpp_rfc2544_profile._create_single_stream(1, imix_data,
+ 100, 0.0)
+ self.assertEqual(['stream1', 'stream2', 'stream3', 'stream4'], output)
+ mock_latency.assert_has_calls([
+ mock.call(pg_id=1), mock.call(pg_id=2)])
+ mock_txcont.assert_has_calls([
+ mock.call(pps=int(25 * 100 / 100)),
+ mock.call(pps=int(75 * 100 / 100))], any_order=True)
+
+ @mock.patch.object(trex_stl_streams, 'STLFlowLatencyStats')
+ @mock.patch.object(trex_stl_streams, 'STLTXCont')
+ @mock.patch.object(trex_stl_client, 'STLStream')
+ def test__create_single_stream_mlr_search(self, mock_stream, mock_txcont,
+ mock_latency):
+ imix_data = {'64': 25, '512': 75}
+ mock_stream.side_effect = ['stream1', 'stream2', 'stream3', 'stream4']
+ mock_txcont.side_effect = ['txcont1', 'txcont2', 'txcont3', 'txcont4']
+ mock_latency.side_effect = ['latency1', 'latency2']
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.max_rate = 14880000
+ vpp_rfc2544_profile.port_pg_id = rfc2544.PortPgIDMap()
+ vpp_rfc2544_profile.port_pg_id.add_port(10)
+ with mock.patch.object(vpp_rfc2544_profile, '_create_single_packet') as \
+ mock_create_single_packet:
+ mock_create_single_packet.return_value = 64, 100
+ output = vpp_rfc2544_profile._create_single_stream(10, imix_data,
+ 100, 0.0)
+ self.assertEqual(['stream1', 'stream2', 'stream3', 'stream4'], output)
+ mock_latency.assert_has_calls([
+ mock.call(pg_id=1), mock.call(pg_id=2)])
+ mock_txcont.assert_has_calls([
+ mock.call(pps=25 * 100 / 100),
+ mock.call(pps=75 * 100 / 100)], any_order=True)
+
+ def test_binary_search_with_optimized(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.pkt_size = 64
+ vpp_rfc2544_profile.init_queue(mock.MagicMock())
+ mock_generator = mock.MagicMock()
+ mock_generator.vnfd_helper.interfaces = [
+ {"name": "xe0"}, {"name": "xe0"}
+ ]
+
+ vpp_rfc2544_profile.ports = [0, 1]
+ vpp_rfc2544_profile.port_pg_id = PortPgIDMap()
+ vpp_rfc2544_profile.port_pg_id.add_port(0)
+ vpp_rfc2544_profile.port_pg_id.add_port(1)
+ vpp_rfc2544_profile.profiles = mock.MagicMock()
+ vpp_rfc2544_profile.test_data = mock.MagicMock()
+ vpp_rfc2544_profile.queue = mock.MagicMock()
+
+ with mock.patch.object(MultipleLossRatioSearch, 'measure') as \
+ mock_measure, \
+ mock.patch.object(MultipleLossRatioSearch, 'ndrpdr') as \
+ mock_ndrpdr:
+ measured_low = ReceiveRateMeasurement(1, 14880000, 14879927, 0)
+ measured_high = ReceiveRateMeasurement(1, 14880000, 14879927, 0)
+ measured_low.latency = ['1000/3081/3962', '500/3149/3730']
+ measured_high.latency = ['1000/3081/3962', '500/3149/3730']
+ starting_interval = ReceiveRateInterval(measured_low,
+ measured_high)
+ starting_result = NdrPdrResult(starting_interval,
+ starting_interval)
+ mock_measure.return_value = ReceiveRateMeasurement(1, 14880000,
+ 14879927, 0)
+ mock_ndrpdr.return_value = MultipleLossRatioSearch.ProgressState(
+ starting_result, 2, 30, 0.005, 0.0,
+ 4857361, 4977343)
+
+ result_samples = vpp_rfc2544_profile.binary_search_with_optimized(
+ traffic_generator=mock_generator, duration=30,
+ timeout=720,
+ test_data={})
+
+ expected = {'Result_NDR_LOWER': {'bandwidth_total_Gbps': 9.999310944,
+ 'rate_total_pps': 14879927.0},
+ 'Result_NDR_UPPER': {'bandwidth_total_Gbps': 9.999310944,
+ 'rate_total_pps': 14879927.0},
+ 'Result_NDR_packets_lost': {'packet_loss_ratio': 0.0,
+ 'packets_lost': 0.0},
+ 'Result_PDR_LOWER': {'bandwidth_total_Gbps': 9.999310944,
+ 'rate_total_pps': 14879927.0},
+ 'Result_PDR_UPPER': {'bandwidth_total_Gbps': 9.999310944,
+ 'rate_total_pps': 14879927.0},
+ 'Result_PDR_packets_lost': {'packet_loss_ratio': 0.0,
+ 'packets_lost': 0.0},
+ 'Result_stream0_NDR_LOWER': {'avg_latency': 3081.0,
+ 'max_latency': 3962.0,
+ 'min_latency': 1000.0},
+ 'Result_stream0_PDR_LOWER': {'avg_latency': 3081.0,
+ 'max_latency': 3962.0,
+ 'min_latency': 1000.0},
+ 'Result_stream1_NDR_LOWER': {'avg_latency': 3149.0,
+ 'max_latency': 3730.0,
+ 'min_latency': 500.0},
+ 'Result_stream1_PDR_LOWER': {'avg_latency': 3149.0,
+ 'max_latency': 3730.0,
+ 'min_latency': 500.0}}
+ self.assertEqual(expected, result_samples)
+
+ def test_binary_search(self):
+ vpp_rfc2544_profile = vpp_rfc2544.VppRFC2544Profile(
+ self.TRAFFIC_PROFILE)
+ vpp_rfc2544_profile.pkt_size = 64
+ vpp_rfc2544_profile.init_queue(mock.MagicMock())
+ mock_generator = mock.MagicMock()
+ mock_generator.vnfd_helper.interfaces = [
+ {"name": "xe0"}, {"name": "xe1"}
+ ]
+ stats = {
+ "0": {
+ "ibytes": 55549120,
+ "ierrors": 0,
+ "ipackets": 867955,
+ "obytes": 55549696,
+ "oerrors": 0,
+ "opackets": 867964,
+ "rx_bps": 104339032.0,
+ "rx_bps_L1": 136944984.0,
+ "rx_pps": 203787.2,
+ "rx_util": 1.36944984,
+ "tx_bps": 134126008.0,
+ "tx_bps_L1": 176040392.0,
+ "tx_pps": 261964.9,
+ "tx_util": 1.7604039200000001
+ },
+ "1": {
+ "ibytes": 55549696,
+ "ierrors": 0,
+ "ipackets": 867964,
+ "obytes": 55549120,
+ "oerrors": 0,
+ "opackets": 867955,
+ "rx_bps": 134119648.0,
+ "rx_bps_L1": 176032032.0,
+ "rx_pps": 261952.4,
+ "rx_util": 1.76032032,
+ "tx_bps": 104338192.0,
+ "tx_bps_L1": 136943872.0,
+ "tx_pps": 203785.5,
+ "tx_util": 1.36943872
+ },
+ "flow_stats": {
+ "1": {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 6400,
+ "1": 0,
+ "total": 6400
+ },
+ "rx_pkts": {
+ "0": 100,
+ "1": 0,
+ "total": 100
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 0,
+ "1": 6400,
+ "total": 6400
+ },
+ "tx_pkts": {
+ "0": 0,
+ "1": 100,
+ "total": 100
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ "2": {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 0,
+ "1": 6464,
+ "total": 6464
+ },
+ "rx_pkts": {
+ "0": 0,
+ "1": 101,
+ "total": 101
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 6464,
+ "1": 0,
+ "total": 6464
+ },
+ "tx_pkts": {
+ "0": 101,
+ "1": 0,
+ "total": 101
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ "global": {
+ "rx_err": {
+ "0": 0,
+ "1": 0
+ },
+ "tx_err": {
+ "0": 0,
+ "1": 0
+ }
+ }
+ },
+ "global": {
+ "bw_per_core": 45.6,
+ "cpu_util": 0.1494,
+ "queue_full": 0,
+ "rx_bps": 238458672.0,
+ "rx_cpu_util": 4.751e-05,
+ "rx_drop_bps": 0.0,
+ "rx_pps": 465739.6,
+ "tx_bps": 238464208.0,
+ "tx_pps": 465750.4
+ },
+ "latency": {
+ "1": {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 63.375,
+ "histogram": {
+ "20": 1,
+ "30": 18,
+ "40": 12,
+ "50": 10,
+ "60": 12,
+ "70": 11,
+ "80": 6,
+ "90": 10,
+ "100": 20
+ },
+ "jitter": 23,
+ "last_max": 122,
+ "total_max": 123,
+ "total_min": 20
+ }
+ },
+ "2": {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 74,
+ "histogram": {
+ "60": 20,
+ "70": 10,
+ "80": 3,
+ "90": 4,
+ "100": 64
+ },
+ "jitter": 6,
+ "last_max": 83,
+ "total_max": 135,
+ "total_min": 60
+ }
+ },
+ "global": {
+ "bad_hdr": 0,
+ "old_flow": 0
+ }
+ },
+ "total": {
+ "ibytes": 111098816,
+ "ierrors": 0,
+ "ipackets": 1735919,
+ "obytes": 111098816,
+ "oerrors": 0,
+ "opackets": 1735919,
+ "rx_bps": 238458680.0,
+ "rx_bps_L1": 312977016.0,
+ "rx_pps": 465739.6,
+ "rx_util": 3.1297701599999996,
+ "tx_bps": 238464200.0,
+ "tx_bps_L1": 312984264.0,
+ "tx_pps": 465750.4,
+ "tx_util": 3.12984264
+ }
+ }
+ samples = {
+ "xe0": {
+ "in_packets": 867955,
+ "latency": {
+ "2": {
+ "avg_latency": 74.0,
+ "max_latency": 135.0,
+ "min_latency": 60.0
+ }
+ },
+ "out_packets": 867964,
+ "rx_throughput_bps": 104339032.0,
+ "rx_throughput_fps": 203787.2,
+ "tx_throughput_bps": 134126008.0,
+ "tx_throughput_fps": 261964.9
+ },
+ "xe1": {
+ "in_packets": 867964,
+ "latency": {
+ "1": {
+ "avg_latency": 63.375,
+ "max_latency": 123.0,
+ "min_latency": 20.0
+ }
+ },
+ "out_packets": 867955,
+ "rx_throughput_bps": 134119648.0,
+ "rx_throughput_fps": 261952.4,
+ "tx_throughput_bps": 104338192.0,
+ "tx_throughput_fps": 203785.5
+ }
+ }
+
+ mock_generator.loss = 0
+ mock_generator.sent = 2169700
+ mock_generator.send_traffic_on_tg = mock.Mock(return_value=stats)
+ mock_generator.generate_samples = mock.Mock(return_value=samples)
+
+ result_samples = vpp_rfc2544_profile.binary_search(
+ traffic_generator=mock_generator, duration=30,
+ tolerance_value=0.005,
+ test_data={})
+
+ expected = {'Result_theor_max_throughput': 134126008.0,
+ 'xe0': {'Result_Actual_throughput': 104339032.0},
+ 'xe1': {'Result_Actual_throughput': 134119648.0}}
+ self.assertEqual(expected, result_samples)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/__init__.py b/yardstick/tests/unit/network_services/vnf_generic/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/__init__.py
diff --git a/yardstick/tests/unit/network_services/vnf_generic/test_vnfdgen.py b/yardstick/tests/unit/network_services/vnf_generic/test_vnfdgen.py
new file mode 100644
index 000000000..55b1955bc
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/test_vnfdgen.py
@@ -0,0 +1,277 @@
+# 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.
+#
+
+from six.moves import range
+import unittest
+
+from yardstick.common.yaml_loader import yaml_load
+from yardstick.network_services.vnf_generic import vnfdgen
+
+
+UPLINK = "uplink"
+DOWNLINK = "downlink"
+
+TREX_VNFD_TEMPLATE = """
+vnfd:vnfd-catalog:
+ vnfd:
+ - id: TrexTrafficGen # ISB class mapping
+ name: trexgen
+ short-name: trexgen
+ description: TRex stateless traffic generator for RFC2544
+ mgmt-interface:
+ vdu-id: trexgen-baremetal
+ user: {{user}} # Value filled by vnfdgen
+ password: {{password}} # Value filled by vnfdgen
+ ip: {{ip}} # Value filled by vnfdgen
+ connection-point:
+ - name: xe0
+ type: VPORT
+ - name: xe1
+ type: VPORT
+ vdu:
+ - id: trexgen-baremetal
+ name: trexgen-baremetal
+ description: TRex stateless traffic generator for RFC2544
+ external-interface:
+ - name: xe0
+ virtual-interface:
+ type: PCI-PASSTHROUGH
+ vpci: '{{ interfaces.xe0.vpci}}'
+ local_ip: '{{ interfaces.xe0.local_ip }}'
+ dst_ip: '{{ interfaces.xe0.dst_ip }}'
+ local_mac: '{{ interfaces.xe0.local_mac }}'
+ dst_mac: '{{ interfaces.xe0.dst_mac }}'
+ bandwidth: 10 Gbps
+ vnfd-connection-point-ref: xe0
+ - name: xe1
+ virtual-interface:
+ type: PCI-PASSTHROUGH
+ vpci: '{{ interfaces.xe1.vpci }}'
+ local_ip: '{{ interfaces.xe1.local_ip }}'
+ dst_ip: '{{ interfaces.xe1.dst_ip }}'
+ local_mac: '{{ interfaces.xe1.local_mac }}'
+ dst_mac: '{{ interfaces.xe1.dst_mac }}'
+ bandwidth: 10 Gbps
+ vnfd-connection-point-ref: xe1
+ routing_table: {{ routing_table }}
+ nd_route_tbl: {{ nd_route_tbl }}
+
+ benchmark:
+ kpi:
+ - rx_throughput_fps
+ - tx_throughput_fps
+ - tx_throughput_mbps
+ - rx_throughput_mbps
+ - tx_throughput_pc_linerate
+ - rx_throughput_pc_linerate
+ - min_latency
+ - max_latency
+ - avg_latency
+"""
+
+COMPLETE_TREX_VNFD = \
+ {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'benchmark':
+ {'kpi':
+ ['rx_throughput_fps',
+ 'tx_throughput_fps',
+ 'tx_throughput_mbps',
+ 'rx_throughput_mbps',
+ 'tx_throughput_pc_linerate',
+ 'rx_throughput_pc_linerate',
+ 'min_latency',
+ 'max_latency',
+ 'avg_latency']},
+ 'connection-point': [{'name': 'xe0',
+ 'type': 'VPORT'},
+ {'name': 'xe1',
+ 'type': 'VPORT'}],
+ 'description': 'TRex stateless traffic generator for RFC2544',
+ 'id': 'TrexTrafficGen',
+ 'mgmt-interface': {'ip': '1.1.1.1',
+ 'password': 'berta',
+ 'user': 'berta',
+ 'vdu-id': 'trexgen-baremetal'},
+ 'name': 'trexgen',
+ 'short-name': 'trexgen',
+ 'vdu': [{'description': 'TRex stateless traffic generator for RFC2544',
+ 'external-interface':
+ [{'name': 'xe0',
+ 'virtual-interface': {'bandwidth': '10 Gbps',
+ 'dst_ip': '1.1.1.1',
+ 'dst_mac': '00:01:02:03:04:05',
+ 'local_ip': '1.1.1.2',
+ 'local_mac': '00:01:02:03:05:05',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vpci': '0000:00:10.2'},
+ 'vnfd-connection-point-ref': 'xe0'},
+ {'name': 'xe1',
+ 'virtual-interface': {'bandwidth': '10 Gbps',
+ 'dst_ip': '2.1.1.1',
+ 'dst_mac': '00:01:02:03:04:06',
+ 'local_ip': '2.1.1.2',
+ 'local_mac': '00:01:02:03:05:06',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vpci': '0000:00:10.1'},
+ 'vnfd-connection-point-ref': 'xe1'}],
+ 'id': 'trexgen-baremetal',
+ 'nd_route_tbl': [{'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ 'netmask': '112',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414'},
+ {'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ 'netmask': '112',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814'}],
+ 'routing_table': [{'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ 'netmask': '255.255.255.0',
+ 'network': '152.16.100.20'},
+ {'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ 'netmask': '255.255.255.0',
+ 'network': '152.16.40.20'}],
+ 'name': 'trexgen-baremetal'}]}]}}
+
+NODE_CFG = {'ip': '1.1.1.1',
+ 'name': 'demeter',
+ 'password': 'berta',
+ 'role': 'TrafficGen',
+ 'user': 'berta',
+ 'interfaces': {'xe0': {'dpdk_port_num': 1,
+ 'dst_ip': '1.1.1.1',
+ 'dst_mac': '00:01:02:03:04:05',
+ 'local_ip': '1.1.1.2',
+ 'local_mac': '00:01:02:03:05:05',
+ 'vpci': '0000:00:10.2'},
+ 'xe1': {'dpdk_port_num': 0,
+ 'dst_ip': '2.1.1.1',
+ 'dst_mac': '00:01:02:03:04:06',
+ 'local_ip': '2.1.1.2',
+ 'local_mac': '00:01:02:03:05:06',
+ 'vpci': '0000:00:10.1'}},
+ 'nd_route_tbl': [{u'gateway': u'0064:ff9b:0:0:0:0:9810:6414',
+ u'if': u'xe0',
+ u'netmask': u'112',
+ u'network': u'0064:ff9b:0:0:0:0:9810:6414'},
+ {u'gateway': u'0064:ff9b:0:0:0:0:9810:2814',
+ u'if': u'xe1',
+ u'netmask': u'112',
+ u'network': u'0064:ff9b:0:0:0:0:9810:2814'}],
+ 'routing_table': [{u'gateway': u'152.16.100.20',
+ u'if': u'xe0',
+ u'netmask': u'255.255.255.0',
+ u'network': u'152.16.100.20'},
+ {u'gateway': u'152.16.40.20',
+ u'if': u'xe1',
+ u'netmask': u'255.255.255.0',
+ u'network': u'152.16.40.20'}],
+ }
+
+
+# need to template, but can't use {} so use %s
+TRAFFIC_PROFILE_TPL = """
+%(0)s:
+ - ipv4:
+ outer_l2:
+ framesize:
+ 64B: "{{ get(imix, '%(0)s.imix_small', 10) }}"
+ 128B: "{{ get(imix, '%(0)s.imix_128B', 10) }}"
+ 256B: "{{ get(imix, '%(0)s.imix_256B', 10) }}"
+ 373B: "{{ get(imix, '%(0)s.imix_373B', 10) }}"
+ 570B: "{{get(imix, '%(0)s.imix_570B', 10) }}"
+ 1400B: "{{get(imix, '%(0)s.imix_1400B', 10) }}"
+ 1518B: "{{get(imix, '%(0)s.imix_1500B', 40) }}"
+""" % {"0": UPLINK}
+
+TRAFFIC_PROFILE = {
+ UPLINK: [{"ipv4": {"outer_l2":
+ {"framesize": {"64B": '10', "128B": '10',
+ "256B": '10', "373B": '10',
+ "570B": '10', "1400B": '10',
+ "1518B": '40'}}}}]}
+
+
+class TestRender(unittest.TestCase):
+
+ def test_render_none(self):
+
+ tmpl = "{{ routing_table }}"
+ self.assertEqual(vnfdgen.render(tmpl, routing_table=None), u'~')
+ self.assertIsNone(
+ yaml_load(vnfdgen.render(tmpl, routing_table=None)))
+
+ def test_render_unicode_dict(self):
+
+ tmpl = "{{ routing_table }}"
+ self.assertEqual(yaml_load(vnfdgen.render(
+ tmpl, **NODE_CFG)), NODE_CFG["routing_table"])
+
+
+class TestVnfdGen(unittest.TestCase):
+ """ Class to verify VNFS testcases """
+
+ def test_generate_vnfd(self):
+ """ Function to verify vnfd generation based on template """
+ self.maxDiff = None
+ generated_vnfd = vnfdgen.generate_vnfd(TREX_VNFD_TEMPLATE, NODE_CFG)
+ self.assertDictEqual(COMPLETE_TREX_VNFD, generated_vnfd)
+
+ def test_generate_tp_no_vars(self):
+ """ Function to verify traffic profile generation without imix """
+
+ self.maxDiff = None
+ generated_tp = vnfdgen.generate_vnfd(TRAFFIC_PROFILE_TPL, {"imix": {}})
+ self.assertDictEqual(TRAFFIC_PROFILE, generated_tp)
+
+ def test_deepgetitem(self):
+ d = {'a': 1, 'b': 2}
+ self.assertEqual(vnfdgen.deepgetitem(d, "a"), 1)
+
+ def test_dict_flatten_int(self):
+ d = {'a': 1, 'b': 2}
+ self.assertEqual(vnfdgen.deepgetitem(d, "a"), 1)
+
+ def test_dict_flatten_str_int_key_first(self):
+ d = {'0': 1, 0: 24, 'b': 2}
+ self.assertEqual(vnfdgen.deepgetitem(d, "0"), 1)
+
+ def test_dict_flatten_int_key_fallback(self):
+ d = {0: 1, 'b': 2}
+ self.assertEqual(vnfdgen.deepgetitem(d, "0"), 1)
+
+ def test_dict_flatten_list(self):
+ d = {'a': 1, 'b': list(range(2))}
+ self.assertEqual(vnfdgen.deepgetitem(d, "b.0"), 0)
+
+ def test_dict_flatten_dict(self):
+ d = {'a': 1, 'b': {x: x for x in list(range(2))}}
+ self.assertEqual(vnfdgen.deepgetitem(d, "b.0"), 0)
+
+ def test_dict_flatten_only_str_key(self):
+ d = {'0': 1, 0: 24, 'b': 2}
+ self.assertRaises(AttributeError, vnfdgen.deepgetitem, d, 0)
+
+ def test_generate_tp_single_var(self):
+ """ Function to verify traffic profile generation with imix """
+
+ generated_tp = \
+ vnfdgen.generate_vnfd(TRAFFIC_PROFILE_TPL,
+ {"imix": {UPLINK: {"imix_small": '20'}}})
+ self.maxDiff = None
+ tp2 = dict(TRAFFIC_PROFILE)
+ tp2[UPLINK][0]["ipv4"]["outer_l2"]["framesize"]["64B"] = '20'
+ self.assertDictEqual(tp2, generated_tp)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/__init__.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/__init__.py
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/tc_baremetal_rfc2544_ipv4_1flow_64B.yaml b/yardstick/tests/unit/network_services/vnf_generic/vnf/tc_baremetal_rfc2544_ipv4_1flow_64B.yaml
new file mode 100644
index 000000000..09c22ad9e
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/tc_baremetal_rfc2544_ipv4_1flow_64B.yaml
@@ -0,0 +1,41 @@
+# Copyright (c) 2016-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.
+
+---
+schema: yardstick:task:0.1
+scenarios:
+- type: NSPerf
+ traffic_profile: "../../traffic_profiles/ipv4_throughput_vpe.yaml"
+ topology: vpe_vnf_topology.yaml
+ nodes:
+ tg__0: trafficgen_0.yardstick
+ vnf__0: vnf_0.yardstick
+ tc_options:
+ rfc2544:
+ allowed_drop_rate: 0.8 - 1
+ vnf_options:
+ vpe:
+ cfg: vpe_config
+ runner:
+ type: Duration
+ duration: 400
+ interval: 35
+ traffic_options:
+ flow: "../../traffic_profiles/ipv4_1flow_Packets_vpe.yaml"
+ imix: "../../traffic_profiles/imix_voice.yaml"
+context:
+ type: Node
+ name: yardstick
+ nfvi_type: baremetal
+ file: /etc/yardstick/nodes/pod.yaml
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
new file mode 100644
index 000000000..12bb42f20
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_acl_vnf.py
@@ -0,0 +1,518 @@
+# Copyright (c) 2016-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.
+
+import unittest
+import mock
+import os
+import re
+import copy
+
+from yardstick.common import utils
+from yardstick.common import exceptions
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf import acl_vnf
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.vnf_generic.vnf.acl_vnf import AclApproxSetupEnvSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+
+name = 'vnf__1'
+
+
+@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+class TestAclApproxVnf(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'AclApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ scenario_cfg = {'options': {'packetsize': 64, 'traffic_type': 4,
+ 'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
+ 'vnf__1': {'rules': 'acl_1rule.yaml',
+ 'vnf_config': {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config':
+ '1C/1T',
+ 'worker_threads': 1}}
+ },
+ 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+ 'task_path': '/tmp',
+ 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+ 'runner': {'object': 'NetworkServiceTestCase',
+ 'interval': 35,
+ 'output_filename': '/tmp/yardstick.out',
+ 'runner_id': 74476, 'duration': 400,
+ 'type': 'Duration'},
+ 'traffic_profile': 'ipv4_throughput_acl.yaml',
+ 'traffic_options': {'flow': 'ipv4_Packets_acl.yaml',
+ 'imix': 'imix_voice.yaml'},
+ 'type': 'ISB',
+ 'nodes': {'tg__2': 'trafficgen_2.yardstick',
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'topology': 'vpe-tg-topology-baremetal.yaml'}
+
+ context_cfg = {'nodes': {'tg__2':
+ {'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens513f0',
+ 'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root'},
+ 'tg__1':
+ {'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens785f0',
+ 'vld_id': acl_vnf.AclApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root'},
+ 'vnf__1':
+ {'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens786f0',
+ 'vld_id': acl_vnf.AclApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens786f1',
+ 'vld_id': acl_vnf.AclApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'routing_table':
+ [{'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0'},
+ {'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl':
+ [{'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'password': 'r00t',
+ 'VNF model': 'acl_vnf.yaml'}}}
+
+ def test___init__(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ self.assertIsNone(acl_approx_vnf._vnf_process)
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {acl_approx_vnf.name: "mock"}
+ }
+ acl_approx_vnf.q_in = mock.MagicMock()
+ acl_approx_vnf.q_out = mock.MagicMock()
+ acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ acl_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
+ acl_approx_vnf.vnf_execute = mock.Mock(return_value="")
+ result = {
+ 'physical_node': 'mock_node',
+ 'packets_dropped': 0,
+ 'packets_fwd': 0,
+ 'packets_in': 0
+ }
+ self.assertEqual(result, acl_approx_vnf.collect_kpi())
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_vnf_execute_command(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf.q_in = mock.MagicMock()
+ acl_approx_vnf.q_out = mock.MagicMock()
+ acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ cmd = "quit"
+ self.assertEqual("", acl_approx_vnf.vnf_execute(cmd))
+
+ @mock.patch(SSH_HELPER)
+ def test_get_stats(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf.q_in = mock.MagicMock()
+ acl_approx_vnf.q_out = mock.MagicMock()
+ acl_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ result = "ACL TOTAL: pkts_processed: 100, pkts_drop: 0, spkts_received: 100"
+ acl_approx_vnf.vnf_execute = mock.Mock(return_value=result)
+ self.assertEqual(result, acl_approx_vnf.get_stats())
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.hex")
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.acl_vnf.eval")
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.acl_vnf.open')
+ @mock.patch(SSH_HELPER)
+ def test_run_acl(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf._build_config = mock.MagicMock()
+ acl_approx_vnf.queue_wrapper = mock.MagicMock()
+ acl_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ acl_approx_vnf.vnf_cfg = {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1}
+ acl_approx_vnf.all_options = {'traffic_type': '4',
+ 'topology': 'nsb_test_case.yaml'}
+ acl_approx_vnf._run()
+ acl_approx_vnf.ssh_helper.run.assert_called_once()
+
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf.deploy_helper = mock.MagicMock()
+ acl_approx_vnf.resource_helper = mock.MagicMock()
+ acl_approx_vnf._build_config = mock.MagicMock()
+ self.scenario_cfg['vnf_options'] = {'acl': {'cfg': "",
+ 'rules': ""}}
+ acl_approx_vnf.q_out.put("pipeline>")
+ acl_approx_vnf.WAIT_TIME = 0
+ self.scenario_cfg.update({"nodes": {"vnf__1": ""}})
+ self.assertIsNone(acl_approx_vnf.instantiate(self.scenario_cfg,
+ self.context_cfg))
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ acl_approx_vnf = acl_vnf.AclApproxVnf(name, vnfd)
+ acl_approx_vnf._vnf_process = mock.MagicMock()
+ acl_approx_vnf._vnf_process.terminate = mock.Mock()
+ acl_approx_vnf.used_drivers = {"01:01.0": "i40e",
+ "01:01.1": "i40e"}
+ acl_approx_vnf.vnf_execute = mock.MagicMock()
+ acl_approx_vnf.dpdk_devbind = "dpdk-devbind.py"
+ acl_approx_vnf._resource_collect_stop = mock.Mock()
+ self.assertIsNone(acl_approx_vnf.terminate())
+
+
+class TestAclApproxSetupEnvSetupEnvHelper(unittest.TestCase):
+
+ ACL_CONFIG = {"access-list-entries": [{
+ "actions": [
+ "count",
+ {"fwd": {
+ "port": 0
+ }
+ }
+ ],
+ "matches": {
+ "destination-ipv4-network": "152.16.0.0/24",
+ "destination-port-range": {
+ "lower-port": 0,
+ "upper-port": 65535
+ },
+ "source-ipv4-network": "0.0.0.0/0",
+ "source-port-range": {
+ "lower-port": 0,
+ "upper-port": 65535
+ },
+ "protocol-mask": 255,
+ "protocol": 127,
+ "priority": 1
+ },
+ "rule-name": "rule1588"
+ }
+ ]}
+
+ def test_get_default_flows(self):
+ """Check if default ACL SampleVNF CLI commands are
+ generated correctly"""
+ ssh_helper = mock.Mock()
+ vnfd_helper = VnfdHelper({'vdu': [
+ {'external-interface': [
+ {
+ 'virtual-interface': {
+ 'local_ip': '152.16.100.19',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'dst_ip': '152.16.100.20',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'local_ip': '152.16.40.19',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'dst_ip': '152.16.40.20',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ }
+ ]}
+ ]})
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper, ssh_helper, None)
+ self.check_acl_commands(setup_helper.get_flows_config(), [
+ # format: (<cli pattern>, <number of expected matches>)
+ ("^p action add [0-9]+ accept$", 2),
+ ("^p action add [0-9]+ count$", 2),
+ ("^p action add [0-9]+ fwd 1$", 1),
+ ("^p action add [0-9]+ fwd 0$", 1),
+ ("^p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+ ("^p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 [0-9]+$", 1),
+ ("^p acl applyruleset$", 1)
+ ])
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config(self, get_default_flows):
+ """Check if provided ACL config can be converted to
+ ACL SampleVNF CLI commands correctly"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ self.check_acl_commands(setup_helper.get_flows_config(self.ACL_CONFIG), [
+ # format: (<cli pattern>, <number of expected matches>)
+ ("^p action add [0-9]+ count$", 1),
+ ("^p action add [0-9]+ fwd 0$", 1),
+ ("^p acl add 1 0.0.0.0 0 152.16.0.0 24 0 65535 0 65535 127 0 [0-9]+$", 1),
+ ("^p acl applyruleset$", 1)
+ ])
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config_invalid_action(self, get_default_flows):
+ """Check if incorrect ACL config fails to convert
+ to ACL SampleVNF CLI commands"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ # duplicate config and add invald action
+ acl_config = copy.deepcopy(self.ACL_CONFIG)
+ acl_config['access-list-entries'][0]["actions"].append({"xnat": {}})
+ self.assertRaises(exceptions.AclUnknownActionTemplate,
+ setup_helper.get_flows_config, acl_config)
+
+ @mock.patch.object(AclApproxSetupEnvSetupEnvHelper, 'get_default_flows')
+ def test_get_flows_config_invalid_action_param(self, get_default_flows):
+ """Check if ACL config with invalid action parameter fails to convert
+ to ACL SampleVNF CLI commands"""
+ ssh_helper = mock.Mock()
+ setup_helper = AclApproxSetupEnvSetupEnvHelper(None, ssh_helper, None)
+ get_default_flows.return_value = ({}, [])
+ # duplicate config and add action with invalid parameter
+ acl_config = copy.deepcopy(self.ACL_CONFIG)
+ acl_config['access-list-entries'][0]["actions"].append(
+ {"nat": {"xport": 0}})
+ self.assertRaises(exceptions.AclMissingActionArguments,
+ setup_helper.get_flows_config, acl_config)
+
+ def check_acl_commands(self, config, expected_cli_patterns):
+ """Check if expected ACL CLI commands (given as a list of patterns,
+ `expected_cli_patterns` parameter) present in SampleVNF ACL
+ configuration (given as a multiline string, `config` parameter)"""
+ # Example of expected config:
+ # ---------------------------
+ # p action add 1 accept
+ # p action add 1 fwd 1
+ # p action add 2 accept
+ # p action add 2 count
+ # p action add 2 fwd 0
+ # p acl add 1 152.16.100.0 24 152.16.40.0 24 0 65535 0 65535 0 0 1
+ # p acl add 1 152.16.40.0 24 152.16.100.0 24 0 65535 0 65535 0 0 2
+ # p acl applyruleset
+ # ---------------------------
+ # NOTE: The config above consists of actions ids, which are actually
+ # unknown (generated at runtime), thus it's incorrect just to compare
+ # the example ACL config above with the configuration returned by
+ # get_flows_config() function. It's more correct to use CLI patterns
+ # (RE) to find the required SampleVNF CLI commands in the multiline
+ # string (SampleVNF ACL configuration).
+ for pattern, num_of_match in expected_cli_patterns:
+ # format: (<cli pattern>, <number of expected matches>)
+ result = re.findall(pattern, config, re.MULTILINE)
+ self.assertEqual(len(result), num_of_match)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
+ @mock.patch.object(utils, 'open_relative_file')
+ def test_build_config(self, *args):
+ vnfd_helper = mock.Mock()
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
+ scenario_helper.all_options = {}
+
+ acl_approx_setup_helper = AclApproxSetupEnvSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ acl_approx_setup_helper.get_flows_config = mock.Mock()
+ acl_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
+ acl_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
+ acl_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
+ expected = 'sudo tool_path -p 0x3 -f /tmp/acl_config -s /tmp/acl_script --hwlb 3'
+ self.assertEqual(acl_approx_setup_helper.build_config(), expected)
+ acl_approx_setup_helper.get_flows_config.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py
new file mode 100644
index 000000000..7c7fe5955
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_agnostic_vnf.py
@@ -0,0 +1,68 @@
+# Copyright (c) 2018-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.
+
+import unittest
+
+from yardstick.network_services.vnf_generic.vnf import agnostic_vnf
+
+NAME = 'vnf__0'
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'id': 'AgnosticVnf', # NSB python class mapping
+ 'name': 'AgnosticVnf',
+ 'short-name': 'AgnosticVnf',
+ 'description': 'AgnosticVnf',
+ 'mgmt-interface': {
+ 'vdu-id': 'vepcvnf-baremetal',
+ 'user': 'user',
+ 'password': 'password',
+ 'ip': 'ip'
+ },
+ 'vdu': [{
+ 'id': 'vepcvnf-baremetal',
+ 'name': 'vepc-vnf-baremetal',
+ 'description': 'vAgnosticVnf workload',
+ 'external-interface': []}],
+ 'benchmark': {
+ 'kpi': []}}]}}
+
+
+class TestAgnosticVnf(unittest.TestCase):
+
+ def setUp(self):
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.agnostic_vnf = agnostic_vnf.AgnosticVnf(NAME, self.vnfd)
+
+ def test_instantiate(self):
+ self.assertIsNone(self.agnostic_vnf.instantiate({}, {}))
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.agnostic_vnf.wait_for_instantiate())
+
+ def test_terminate(self):
+ self.assertIsNone(self.agnostic_vnf.terminate())
+
+ def test_scale(self):
+ self.assertIsNone(self.agnostic_vnf.scale())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.agnostic_vnf.collect_kpi())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.agnostic_vnf.start_collect())
+
+ def test_stop_collect(self):
+ self.assertIsNone(self.agnostic_vnf.stop_collect())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_base.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_base.py
new file mode 100644
index 000000000..1a72e042b
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_base.py
@@ -0,0 +1,236 @@
+# Copyright (c) 2016-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.
+
+import multiprocessing
+import os
+
+import mock
+import unittest
+
+from yardstick.network_services.vnf_generic.vnf import base
+from yardstick.ssh import SSH
+from yardstick.tests.unit import base as ut_base
+
+
+IP_PIPELINE_CFG_FILE_TPL = ("arp_route_tbl = ({port0_local_ip_hex},"
+ "{port0_netmask_hex},1,{port1_local_ip_hex}) "
+ "({port1_local_ip_hex},{port1_netmask_hex},0,"
+ "{port0_local_ip_hex})")
+
+IP_PIPELINE_ND_CFG_FILE_TPL = """
+nd_route_tbl = ({port1_dst_ip_hex6},"""
+"""{port1_dst_netmask_hex6},1,{port1_dst_ip_hex6})"""
+
+_LOCAL_OBJECT = object()
+
+VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+}
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ]
+ }
+}
+
+
+class FileAbsPath(object):
+ def __init__(self, module_file):
+ super(FileAbsPath, self).__init__()
+ self.module_path = os.path.dirname(os.path.abspath(module_file))
+
+ def get_path(self, filename):
+ file_path = os.path.join(self.module_path, filename)
+ return file_path
+
+
+def mock_ssh(mock_ssh_type, spec=None, exec_result=_LOCAL_OBJECT, run_result=_LOCAL_OBJECT):
+ if spec is None:
+ spec = SSH
+
+ if exec_result is _LOCAL_OBJECT:
+ exec_result = 0, "", ""
+
+ if run_result is _LOCAL_OBJECT:
+ run_result = 0, "", ""
+
+ mock_ssh_instance = mock.Mock(autospec=spec)
+ mock_ssh_instance._get_client.return_value = mock.Mock()
+ mock_ssh_instance.execute.return_value = exec_result
+ mock_ssh_instance.run.return_value = run_result
+ mock_ssh_type.from_node.return_value = mock_ssh_instance
+ return mock_ssh_instance
+
+
+class TestQueueFileWrapper(unittest.TestCase):
+ def setUp(self):
+ self.prompt = "pipeline>"
+ self.q_in = multiprocessing.Queue()
+ self.q_out = multiprocessing.Queue()
+
+ def test___init__(self):
+ queue_file_wrapper = \
+ base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
+ self.assertEqual(queue_file_wrapper.prompt, self.prompt)
+
+ def test_clear(self):
+ queue_file_wrapper = \
+ base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
+ queue_file_wrapper.bufsize = 5
+ queue_file_wrapper.write("pipeline>")
+ queue_file_wrapper.close()
+ self.assertIsNone(queue_file_wrapper.clear())
+ self.assertIsNotNone(queue_file_wrapper.q_out.empty())
+
+ def test_close(self):
+ queue_file_wrapper = \
+ base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
+ self.assertIsNone(queue_file_wrapper.close())
+
+ def test_read(self):
+ queue_file_wrapper = \
+ base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
+ queue_file_wrapper.q_in.put("pipeline>")
+ self.assertEqual("pipeline>", queue_file_wrapper.read(20))
+
+ def test_write(self):
+ queue_file_wrapper = \
+ base.QueueFileWrapper(self.q_in, self.q_out, self.prompt)
+ queue_file_wrapper.write("pipeline>")
+ self.assertIsNotNone(queue_file_wrapper.q_out.empty())
+
+
+class TestGenericVNF(ut_base.BaseUnitTestCase):
+
+ def test_definition(self):
+ """Make sure that the abstract class cannot be instantiated"""
+ with self.assertRaises(TypeError) as exc:
+ # pylint: disable=abstract-class-instantiated
+ base.GenericVNF('vnf1', VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+
+ msg = ("Can't instantiate abstract class GenericVNF with abstract "
+ "methods collect_kpi, instantiate, scale, start_collect, "
+ "stop_collect, terminate, wait_for_instantiate")
+
+ self.assertEqual(msg, str(exc.exception))
+
+
+class GenericTrafficGenTestCase(ut_base.BaseUnitTestCase):
+
+ def test_definition(self):
+ """Make sure that the abstract class cannot be instantiated"""
+ vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ name = 'vnf1'
+ with self.assertRaises(TypeError) as exc:
+ # pylint: disable=abstract-class-instantiated
+ base.GenericTrafficGen(name, vnfd)
+ msg = ("Can't instantiate abstract class GenericTrafficGen with "
+ "abstract methods collect_kpi, instantiate, run_traffic, "
+ "scale, terminate")
+ self.assertEqual(msg, str(exc.exception))
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
new file mode 100644
index 000000000..d0672dcfd
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_cgnapt_vnf.py
@@ -0,0 +1,412 @@
+# Copyright (c) 2016-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.
+
+from copy import deepcopy
+import time
+
+import mock
+import unittest
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.common import utils
+from yardstick.common import process
+from yardstick.network_services.vnf_generic.vnf import cgnapt_vnf
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.nfvi import resource
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+name = 'vnf__0'
+
+
+class TestCgnaptApproxSetupEnvHelper(unittest.TestCase):
+
+ def test__generate_ip_from_pool(self):
+
+ _ip = '1.2.3.4'
+ ip = cgnapt_vnf.CgnaptApproxSetupEnvHelper._generate_ip_from_pool(_ip)
+ self.assertEqual(next(ip), _ip)
+ self.assertEqual(next(ip), '1.2.4.4')
+ self.assertEqual(next(ip), '1.2.5.4')
+
+ def test__update_cgnat_script_file(self):
+
+ sample = """\
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+link 0 down
+link 0 config {port0_local_ip} {port0_prefixlen}
+link 0 up
+link 1 down
+link 1 config {port1_local_ip} {port1_prefixlen}
+link 1 up
+"""
+ header = "This is a header"
+
+ out = cgnapt_vnf.CgnaptApproxSetupEnvHelper._update_cgnat_script_file(
+ header, sample.splitlines())
+ self.assertNotIn("This is a header", out)
+
+ def test__get_cgnapt_config(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.uplink_ports = [{"name": 'a'}, {"name": "b"}, {"name": "c"}]
+
+ helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ vnfd_helper, mock.Mock(), mock.Mock())
+ result = helper._get_cgnapt_config()
+ self.assertIsNotNone(result)
+
+ def test_scale(self):
+ helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ mock.Mock(), mock.Mock(), mock.Mock())
+ with self.assertRaises(NotImplementedError):
+ helper.scale()
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
+ @mock.patch.object(utils, 'open_relative_file')
+ def test_build_config(self, *args):
+ vnfd_helper = mock.Mock()
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
+ scenario_helper.all_options = {}
+
+ cgnat_approx_setup_helper = cgnapt_vnf.CgnaptApproxSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+
+ cgnat_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
+ cgnat_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
+ cgnat_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
+ expected = 'sudo tool_path -p 0x3 -f /tmp/cgnapt_config -s /tmp/cgnapt_script --hwlb 3'
+ self.assertEqual(cgnat_approx_setup_helper.build_config(), expected)
+
+
+@mock.patch.object(sample_vnf, 'Process')
+class TestCgnaptApproxVnf(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'CgnaptApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ SCENARIO_CFG = {
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__0': {
+ 'napt': 'dynamic',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config':
+ '1C/1T',
+ 'worker_threads': 1,
+ },
+ },
+ 'flow': {'count': 1,
+ 'dst_ip': [{'tg__1': 'xe0'}],
+ 'public_ip': [''],
+ 'src_ip': [{'tg__0': 'xe0'}]},
+ },
+ 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+ 'task_path': '/tmp',
+ 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+ 'runner': {
+ 'object': 'NetworkServiceTestCase',
+ 'interval': 35,
+ 'output_filename': '/tmp/yardstick.out',
+ 'runner_id': 74476,
+ 'duration': 400,
+ 'type': 'Duration',
+ },
+ 'traffic_profile': 'ipv4_throughput_acl.yaml',
+ 'type': 'NSPerf',
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'tg__0': 'trafficgen_0.yardstick',
+ 'vnf__0': 'vnf.yardstick',
+ },
+ 'topology': 'vpe-tg-topology-baremetal.yaml',
+ }
+
+ context_cfg = {'nodes': {'tg__2':
+ {'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens513f0',
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root'},
+ 'tg__1':
+ {'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens785f0',
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root'},
+ 'vnf__0':
+ {'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__0',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens786f0',
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens786f1',
+ 'vld_id': cgnapt_vnf.CgnaptApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'routing_table':
+ [{'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0'},
+ {'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl':
+ [{'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'password': 'r00t',
+ 'VNF model': 'cgnapt_vnf.yaml'}}}
+
+ def setUp(self):
+ self.scenario_cfg = deepcopy(self.SCENARIO_CFG)
+
+ def test___init__(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ self.assertIsNone(cgnapt_approx_vnf._vnf_process)
+
+ @mock.patch.object(process, 'check_if_process_failed')
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {cgnapt_approx_vnf.name: "mock"}
+ }
+ cgnapt_approx_vnf._vnf_process = mock.MagicMock(
+ **{"is_alive.return_value": True, "exitcode": None})
+ cgnapt_approx_vnf.q_in = mock.MagicMock()
+ cgnapt_approx_vnf.q_out = mock.MagicMock()
+ cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ cgnapt_approx_vnf.resource = mock.Mock(
+ autospec=resource.ResourceProfile)
+ result = {
+ 'physical_node': 'mock_node',
+ 'packets_dropped': 0,
+ 'packets_fwd': 0,
+ 'packets_in': 0
+ }
+ with mock.patch.object(cgnapt_approx_vnf, 'get_stats',
+ return_value=''):
+ self.assertEqual(result, cgnapt_approx_vnf.collect_kpi())
+
+ @mock.patch.object(time, 'sleep')
+ def test_vnf_execute_command(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.q_in = mock.Mock()
+ cgnapt_approx_vnf.q_out = mock.Mock()
+ cgnapt_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ self.assertEqual("", cgnapt_approx_vnf.vnf_execute('quit'))
+
+ def test_get_stats(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ with mock.patch.object(cgnapt_approx_vnf, 'vnf_execute') as mock_exec:
+ mock_exec.return_value = 'output'
+ self.assertEqual('output', cgnapt_approx_vnf.get_stats())
+
+ mock_exec.assert_called_once_with('p cgnapt stats')
+
+ def test_run_vcgnapt(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.ssh_helper = mock.Mock()
+ cgnapt_approx_vnf.setup_helper = mock.Mock()
+ with mock.patch.object(cgnapt_approx_vnf, '_build_config'), \
+ mock.patch.object(cgnapt_approx_vnf, '_build_run_kwargs'):
+ cgnapt_approx_vnf._run()
+
+ cgnapt_approx_vnf.ssh_helper.run.assert_called_once()
+ cgnapt_approx_vnf.setup_helper.kill_vnf.assert_called_once()
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ def test_instantiate(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.deploy_helper = mock.MagicMock()
+ cgnapt_approx_vnf.resource_helper = mock.MagicMock()
+ cgnapt_approx_vnf._build_config = mock.MagicMock()
+ self.scenario_cfg['vnf_options'] = {'acl': {'cfg': "",
+ 'rules': ""}}
+ cgnapt_approx_vnf.q_out.put("pipeline>")
+ cgnapt_vnf.WAIT_TIME = 3
+ self.scenario_cfg.update({"nodes": {"vnf__0": ""}})
+ with mock.patch.object(cgnapt_approx_vnf, '_start_vnf'):
+ self.assertIsNone(cgnapt_approx_vnf.instantiate(
+ self.scenario_cfg, self.context_cfg))
+
+ @mock.patch.object(time, 'sleep')
+ def test__vnf_up_post(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.scenario_cfg['options'][name]['napt'] = 'static'
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.vnf_execute = mock.Mock()
+ cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ with mock.patch.object(cgnapt_approx_vnf, 'setup_helper') as \
+ mock_setup_helper:
+ mock_setup_helper._generate_ip_from_pool.return_value = ['ip1']
+ mock_setup_helper._get_cgnapt_config.return_value = ['gw_ip1']
+ cgnapt_approx_vnf._vnf_up_post()
+
+ def test__vnf_up_post_short(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ cgnapt_approx_vnf = cgnapt_vnf.CgnaptApproxVnf(name, vnfd)
+ cgnapt_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ cgnapt_approx_vnf._vnf_up_post()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py
new file mode 100644
index 000000000..b1bef2e39
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_epc_vnf.py
@@ -0,0 +1,92 @@
+# Copyright (c) 2018-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.
+
+import copy
+import unittest
+
+from yardstick.network_services.vnf_generic.vnf import epc_vnf
+
+NAME = 'vnf__0'
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'id': 'EPCVnf', # NSB python class mapping
+ 'name': 'EPCVnf',
+ 'short-name': 'EPCVnf',
+ 'description': 'EPCVnf',
+ 'mgmt-interface': {
+ 'vdu-id': 'vepcvnf-baremetal',
+ 'user': 'user', # Value filled by vnfdgen
+ 'password': 'password', # Value filled by vnfdgen
+ 'ip': 'ip' # Value filled by vnfdgen
+ },
+ 'vdu': [{
+ 'id': 'vepcvnf-baremetal',
+ 'name': 'vepc-vnf-baremetal',
+ 'description': 'vEPCVnf workload',
+ 'external-interface': []}],
+ 'benchmark': {
+ 'kpi': []}}]}}
+
+
+class TestEPCVnf(unittest.TestCase):
+
+ def setUp(self):
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.epc_vnf = epc_vnf.EPCVnf(NAME, self.vnfd)
+
+ def test___init__(self, *args):
+ _epc_vnf = epc_vnf.EPCVnf(NAME, self.vnfd)
+ for x in {'user', 'password', 'ip'}:
+ self.assertEqual(self.vnfd['mgmt-interface'][x],
+ _epc_vnf.vnfd_helper.mgmt_interface[x])
+ self.assertEqual(NAME, _epc_vnf.name)
+ self.assertEqual([], _epc_vnf.kpi)
+ self.assertEqual({}, _epc_vnf.config)
+ self.assertFalse(_epc_vnf.runs_traffic)
+
+ def test___init__missing_ip(self, *args):
+ _vnfd = copy.deepcopy(self.vnfd)
+ _vnfd['mgmt-interface'].pop('ip')
+ _epc_vnf = epc_vnf.EPCVnf(NAME, _vnfd)
+ for x in {'user', 'password'}:
+ self.assertEqual(_vnfd['mgmt-interface'][x],
+ _epc_vnf.vnfd_helper.mgmt_interface[x])
+ self.assertNotIn('ip', _epc_vnf.vnfd_helper.mgmt_interface)
+ self.assertEqual(NAME, _epc_vnf.name)
+ self.assertEqual([], _epc_vnf.kpi)
+ self.assertEqual({}, _epc_vnf.config)
+ self.assertFalse(_epc_vnf.runs_traffic)
+
+ def test_instantiate(self):
+ self.assertIsNone(self.epc_vnf.instantiate({}, {}))
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.epc_vnf.wait_for_instantiate())
+
+ def test_terminate(self):
+ self.assertIsNone(self.epc_vnf.terminate())
+
+ def test_scale(self):
+ self.assertIsNone(self.epc_vnf.scale())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.epc_vnf.collect_kpi())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.epc_vnf.start_collect())
+
+ def test_stop_collect(self):
+ self.assertIsNone(self.epc_vnf.stop_collect())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py
new file mode 100644
index 000000000..00dc4a5d1
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_ipsec_vnf.py
@@ -0,0 +1,2151 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from multiprocessing import Process
+
+import mock
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.common import utils
+from yardstick.network_services.helpers import cpu
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.vnf_generic.vnf import ipsec_vnf, vpp_helpers
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+from yardstick.network_services.vnf_generic.vnf.ipsec_vnf import CryptoAlg, \
+ IntegAlg, VipsecApproxSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import \
+ mock_ssh
+
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+NAME = 'vnf__1'
+
+
+class TestCryptoAlg(unittest.TestCase):
+
+ def test__init__(self):
+ encr_alg = CryptoAlg.AES_GCM_128
+ self.assertEqual('aes-gcm-128', encr_alg.alg_name)
+ self.assertEqual('AES-GCM', encr_alg.scapy_name)
+ self.assertEqual(20, encr_alg.key_len)
+
+
+class TestIntegAlg(unittest.TestCase):
+
+ def test__init__(self):
+ auth_alg = IntegAlg.AES_GCM_128
+ self.assertEqual('aes-gcm-128', auth_alg.alg_name)
+ self.assertEqual('AES-GCM', auth_alg.scapy_name)
+ self.assertEqual(20, auth_alg.key_len)
+
+
+@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+class TestVipsecApproxVnf(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "VPP IPsec",
+ "id": "VipsecApproxVnf",
+ "mgmt-interface": {
+ "ip": "10.10.10.101",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "ipsecvnf-baremetal"
+ },
+ "name": "IpsecVnf",
+ "short-name": "IpsecVnf",
+ "vdu": [
+ {
+ "description": "VPP Ipsec",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:ff:07.0"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "ipsecvnf-baremetal",
+ "name": "ipsecvnf-baremetal",
+ "routing_table": []
+ }
+ ]
+ }
+ ]}}
+
+ VNFD_ERROR = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "VPP IPsec",
+ "id": "VipsecApproxVnf",
+ "mgmt-interface": {
+ "ip": "10.10.10.101",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "ipsecvnf-baremetal"
+ },
+ "name": "IpsecVnf",
+ "short-name": "IpsecVnf",
+ "vdu": [
+ {
+ "description": "VPP Ipsec",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_1",
+ "vpci": "0000:ff:06.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:ff:07.0"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "ipsecvnf-baremetal",
+ "name": "ipsecvnf-baremetal",
+ "routing_table": []
+ }
+ ]
+ }
+ ]}}
+
+ scenario_cfg = {
+ "nodes": {
+ "tg__0": "trafficgen.yardstick-5486cc2f",
+ "vnf__0": "vnf0.yardstick-5486cc2f",
+ "vnf__1": "vnf1.yardstick-5486cc2f"
+ },
+ "options": {
+ "flow": {
+ "count": 1,
+ "dst_ip": [
+ "20.0.0.0-20.0.0.100"
+ ],
+ "src_ip": [
+ "10.0.0.0-10.0.0.100"
+ ]
+ },
+ "framesize": {
+ "downlink": {
+ "64B": 100
+ },
+ "uplink": {
+ "64B": 100
+ }
+ },
+ "rfc2544": {
+ "allowed_drop_rate": "0.0 - 0.005"
+ },
+ "tg__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "queues_per_port": 7
+ },
+ "traffic_type": 4,
+ "vnf__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vnf__1": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vpp_config": {
+ "crypto_algorithms": "aes-gcm",
+ "tunnel": 1
+ }
+ },
+ "runner": {
+ "duration": 500,
+ "interval": 10,
+ "object":
+ "yardstick.benchmark.scenarios.networking.vnf_generic.NetworkServiceTestCase",
+ "output_config": {
+ "DEFAULT": {
+ "debug": "False",
+ "dispatcher": [
+ "influxdb"
+ ]
+ },
+ "dispatcher_file": {
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "file_path": "/tmp/yardstick.out"
+ },
+ "dispatcher_http": {
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "target": "http://127.0.0.1:8000/results",
+ "timeout": "20"
+ },
+ "dispatcher_influxdb": {
+ "db_name": "yardstick",
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "password": "r00t",
+ "target": "http://192.168.100.3:8086",
+ "timeout": "20",
+ "username": "root"
+ },
+ "nsb": {
+ "bin_path": "/opt/nsb_bin",
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "trex_client_lib": "/opt/nsb_bin/trex_client/stl",
+ "trex_path": "/opt/nsb_bin/trex/scripts"
+ }
+ },
+ "runner_id": 1105,
+ "type": "Duration"
+ },
+ "task_id": "5486cc2f-d4d3-4feb-b0df-5e0bcd584c9e",
+ "task_path": "samples/vnf_samples/nsut/ipsec",
+ "tc": "tc_baremetal_rfc2544_ipv4_1flow_sw_aesgcm_4cores_64B_trex",
+ "topology": "vpp-tg-topology-2.yaml",
+ "traffic_profile": "../../traffic_profiles/ipv4_throughput_latency_vpp.yaml",
+ "type": "NSPerf"
+ }
+
+ context_cfg = {
+ "networks": {},
+ "nodes": {
+ "tg__0": {
+ "VNF model": "../../vnf_descriptors/tg_vpp_tpl.yaml",
+ "ctx_type": "Node",
+ "interfaces": {
+ "xe0": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:00:06.0"
+ },
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "xe1": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.2",
+ "dst_mac": "90:e2:ba:7c:41:a9",
+ "ifname": "xe1",
+ "local_ip": "192.168.101.1",
+ "local_mac": "90:e2:ba:7c:30:e9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.1",
+ "dst_mac": "90:e2:ba:7c:30:e9",
+ "ifname": "xe0",
+ "local_ip": "192.168.101.2",
+ "local_mac": "90:e2:ba:7c:41:a9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "tg__0",
+ "vld_id": "downlink_0",
+ "vpci": "0000:00:06.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "downlink_0",
+ "vpci": "0000:81:00.1"
+ }
+ },
+ "ip": "10.10.10.10",
+ "member-vnf-index": "1",
+ "name": "trafficgen.yardstick-5486cc2f",
+ "password": "r00t",
+ "port": 22,
+ "role": "TrafficGen",
+ "user": "root",
+ "username": "root",
+ "vnfd-id-ref": "tg__0"
+ },
+ "vnf__0": {
+ "VNF model": "../../vnf_descriptors/vpp_vnfd.yaml",
+ "ctx_type": "Node",
+ "interfaces": {
+ "xe0": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:00:06.0"
+ },
+ "xe1": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ }
+ },
+ "ip": "10.10.10.101",
+ "member-vnf-index": "2",
+ "name": "vnf0.yardstick-5486cc2f",
+ "password": "r00t",
+ "port": 22,
+ "role": "VirtualNetworkFunction",
+ "user": "root",
+ "username": "root",
+ "vnfd-id-ref": "vnf__0"
+ },
+ "vnf__1": {
+ "VNF model": "../../vnf_descriptors/vpp_vnfd.yaml",
+ "ctx_type": "Node",
+ "interfaces": {
+ "xe0": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.1",
+ "dst_mac": "90:e2:ba:7c:30:e9",
+ "ifname": "xe0",
+ "local_ip": "192.168.101.2",
+ "local_mac": "90:e2:ba:7c:41:a9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.2",
+ "dst_mac": "90:e2:ba:7c:41:a9",
+ "ifname": "xe1",
+ "local_ip": "192.168.101.1",
+ "local_mac": "90:e2:ba:7c:30:e9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__1",
+ "vld_id": "downlink_0",
+ "vpci": "0000:81:00.1"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "downlink_0",
+ "vpci": "0000:00:06.0"
+ },
+ "xe1": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ }
+ },
+ "ip": "10.10.10.102",
+ "member-vnf-index": "3",
+ "name": "vnf1.yardstick-5486cc2f",
+ "password": "r00t",
+ "port": 22,
+ "role": "VirtualNetworkFunction",
+ "user": "root",
+ "username": "root",
+ "vnfd-id-ref": "vnf__1"
+ }
+ }
+ }
+
+ def test___init__(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ self.assertIsNone(vipsec_vnf._vnf_process)
+
+ @mock.patch(SSH_HELPER)
+ def test__run(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf._build_config = mock.MagicMock()
+ vipsec_vnf.setup_helper.kill_vnf = mock.MagicMock()
+ vipsec_vnf.setup_helper.create_ipsec_tunnels = mock.MagicMock()
+ vipsec_vnf.queue_wrapper = mock.MagicMock()
+ vipsec_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ vipsec_vnf.vnf_cfg = {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1}
+ vipsec_vnf.all_options = {'traffic_type': '4',
+ 'topology': 'nsb_test_case.yaml'}
+ vipsec_vnf._run()
+ # vipsec_vnf.setup_helper.ssh_helper.execute.assert_called_once()
+
+ @mock.patch(SSH_HELPER)
+ def test_wait_for_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf.resource_helper.resource = mock.MagicMock()
+ vipsec_vnf.setup_helper = mock.MagicMock()
+ vipsec_vnf.setup_helper.check_status.return_value = True
+ vipsec_vnf._vnf_process = mock_process
+ vipsec_vnf.WAIT_TIME = 0
+ self.assertEqual(vipsec_vnf.wait_for_instantiate(), 432)
+
+ @mock.patch(SSH_HELPER)
+ def test_wait_for_instantiate_crash(self, ssh, *args):
+ mock_ssh(ssh)
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = False
+ mock_process.exitcode = 432
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf.resource_helper.resource = mock.MagicMock()
+ vipsec_vnf.setup_helper = mock.MagicMock()
+ vipsec_vnf.setup_helper.check_status.return_value = False
+ vipsec_vnf._vnf_process = mock_process
+ vipsec_vnf.WAIT_TIME = 0
+ vipsec_vnf.WAIT_TIME_FOR_SCRIPT = 0
+
+ with self.assertRaises(RuntimeError) as raised:
+ vipsec_vnf.wait_for_instantiate()
+
+ self.assertIn('VNF process died', str(raised.exception))
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ @mock.patch.object(ipsec_vnf.VipsecApproxSetupEnvHelper,
+ 'get_vpp_statistics',
+ return_value={'packets_in': 0, 'packets_fwd': 0,
+ 'packets_dropped': 0})
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {vipsec_vnf.name: "mock"}
+ }
+ result = {
+ 'collect_stats': {'packets_in': 0, 'packets_fwd': 0,
+ 'packets_dropped': 0},
+ 'physical_node': 'mock_node'
+ }
+ self.assertEqual(result, vipsec_vnf.collect_kpi())
+
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch(
+ "yardstick.network_services.vnf_generic.vnf.sample_vnf.Context")
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf.deploy_helper = mock.MagicMock()
+ vipsec_vnf.resource_helper = mock.MagicMock()
+ vipsec_vnf._build_config = mock.MagicMock()
+ vipsec_vnf.WAIT_TIME = 0
+ self.scenario_cfg.update({"nodes": {"vnf__1": ""}})
+ self.assertIsNone(vipsec_vnf.instantiate(self.scenario_cfg,
+ self.context_cfg))
+
+ @mock.patch.object(ipsec_vnf.VipsecApproxSetupEnvHelper, 'kill_vnf',
+ return_value='')
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vipsec_vnf = ipsec_vnf.VipsecApproxVnf(NAME, vnfd)
+ vipsec_vnf._vnf_process = mock.MagicMock()
+ vipsec_vnf._vnf_process.terminate = mock.Mock()
+ self.assertIsNone(vipsec_vnf.terminate())
+
+
+class TestVipsecApproxSetupEnvHelper(unittest.TestCase):
+ ALL_OPTIONS = {
+ "flow": {
+ "count": 1,
+ "dst_ip": [
+ "20.0.0.0-20.0.0.100"
+ ],
+ "src_ip": [
+ "10.0.0.0-10.0.0.100"
+ ]
+ },
+ "framesize": {
+ "downlink": {
+ "64B": 100
+ },
+ "uplink": {
+ "64B": 100
+ }
+ },
+ "rfc2544": {
+ "allowed_drop_rate": "0.0 - 0.005"
+ },
+ "tg__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "queues_per_port": 7
+ },
+ "traffic_type": 4,
+ "vnf__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vnf__1": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vpp_config": {
+ "crypto_algorithms": "aes-gcm",
+ "tunnel": 1
+ }
+ }
+
+ ALL_OPTIONS_CBC_ALGORITHMS = {
+ "flow": {
+ "count": 1,
+ "dst_ip": [
+ "20.0.0.0-20.0.0.100"
+ ],
+ "src_ip": [
+ "10.0.0.0-10.0.0.100"
+ ]
+ },
+ "framesize": {
+ "downlink": {
+ "64B": 100
+ },
+ "uplink": {
+ "64B": 100
+ }
+ },
+ "rfc2544": {
+ "allowed_drop_rate": "0.0 - 0.005"
+ },
+ "tg__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "queues_per_port": 7
+ },
+ "traffic_type": 4,
+ "vnf__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vnf__1": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vpp_config": {
+ "crypto_algorithms": "cbc-sha1",
+ "tunnel": 1
+ }
+ }
+
+ ALL_OPTIONS_ERROR = {
+ "flow_error": {
+ "count": 1,
+ "dst_ip": [
+ "20.0.0.0-20.0.0.100"
+ ],
+ "src_ip": [
+ "10.0.0.0-10.0.0.100"
+ ]
+ },
+ "framesize": {
+ "downlink": {
+ "64B": 100
+ },
+ "uplink": {
+ "64B": 100
+ }
+ },
+ "rfc2544": {
+ "allowed_drop_rate": "0.0 - 0.005"
+ },
+ "tg__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "queues_per_port": 7
+ },
+ "traffic_type": 4,
+ "vnf__0": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vnf__1": {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ },
+ "vpp_config": {
+ "crypto_algorithms": "aes-gcm",
+ "tunnel": 1
+ }
+ }
+
+ OPTIONS = {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "SW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ }
+
+ OPTIONS_HW = {
+ "collectd": {
+ "interval": 1
+ },
+ "vnf_config": {
+ "crypto_type": "HW_cryptodev",
+ "rxq": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 4
+ }
+ }
+
+ CPU_LAYOUT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 0, 1, 1, 0],
+ [2, 1, 0, 0, 0, 2, 2, 1],
+ [3, 1, 0, 0, 0, 3, 3, 1],
+ [4, 2, 0, 0, 0, 4, 4, 2],
+ [5, 2, 0, 0, 0, 5, 5, 2],
+ [6, 3, 0, 0, 0, 6, 6, 3],
+ [7, 3, 0, 0, 0, 7, 7, 3],
+ [8, 4, 0, 0, 0, 8, 8, 4],
+ [9, 5, 0, 1, 0, 9, 9, 4],
+ [10, 6, 0, 1, 0, 10, 10, 5],
+ [11, 6, 0, 1, 0, 11, 11, 5],
+ [12, 7, 0, 1, 0, 12, 12, 6],
+ [13, 7, 0, 1, 0, 13, 13, 6],
+ [14, 8, 0, 1, 0, 14, 14, 7],
+ [15, 8, 0, 1, 0, 15, 15, 7],
+ [16, 9, 0, 1, 0, 16, 16, 8],
+ [17, 9, 0, 1, 0, 17, 17, 8]]}
+ CPU_SMT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 0, 1, 1, 0],
+ [2, 1, 0, 0, 0, 2, 2, 1],
+ [3, 1, 0, 0, 0, 3, 3, 1],
+ [4, 2, 0, 0, 0, 4, 4, 2],
+ [5, 2, 0, 0, 0, 5, 5, 2],
+ [6, 3, 0, 0, 0, 6, 6, 3],
+ [7, 3, 0, 0, 0, 7, 7, 3],
+ [8, 4, 0, 0, 0, 8, 8, 4],
+ [9, 5, 0, 1, 0, 0, 0, 0],
+ [10, 6, 0, 1, 0, 1, 1, 0],
+ [11, 6, 0, 1, 0, 2, 2, 1],
+ [12, 7, 0, 1, 0, 3, 3, 1],
+ [13, 7, 0, 1, 0, 4, 4, 2],
+ [14, 8, 0, 1, 0, 5, 5, 2],
+ [15, 8, 0, 1, 0, 6, 6, 3],
+ [16, 9, 0, 1, 0, 7, 7, 3],
+ [17, 9, 0, 1, 0, 8, 8, 4]]}
+
+ VPP_INTERFACES_DUMP = [
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0,
+ "l2_address_length": 0,
+ "l2_address": [0, 0, 0, 0, 0, 0, 0, 0],
+ "interface_name": "local0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 0,
+ "link_speed": 0,
+ "mtu": 0,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length": 6,
+ "l2_address": [144, 226, 186, 124, 65, 168, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 2,
+ "sup_sw_if_index": 2,
+ "l2_address_length": 6,
+ "l2_address": [78, 144, 133, 211, 197, 19, 0, 0],
+ "interface_name": "VirtualFunctionEthernetff/7/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9206,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }
+ ]
+
+ VPP_INTERFACES_STATUS = \
+ ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \
+ 'Counter Count \n' \
+ 'TenGigabitEthernetff/6/0 1 up 9000/0/0/0 \n' \
+ 'VirtualFunctionEthernetff/7/0 2 up 9000/0/0/0 \n' \
+ 'ipsec0 2 up 9000/0/0/0 \n' \
+ 'local0 0 down 0/0/0/0 '
+
+ VPP_INTERFACES_STATUS_FALSE = \
+ ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \
+ 'Counter Count \n' \
+ 'TenGigabitEthernetff/6/0 1 down 9000/0/0/0 \n' \
+ 'VirtualFunctionEthernetff/7/0 2 down 9000/0/0/0 \n' \
+ 'ipsec0 2 down 9000/0/0/0 \n' \
+ 'local0 0 down 0/0/0/0 '
+
+ def test__get_crypto_type(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('SW_cryptodev',
+ ipsec_approx_setup_helper._get_crypto_type())
+
+ def test__get_crypto_algorithms(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('aes-gcm',
+ ipsec_approx_setup_helper._get_crypto_algorithms())
+
+ def test__get_n_tunnels(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(1, ipsec_approx_setup_helper._get_n_tunnels())
+
+ def test__get_n_connections(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(1, ipsec_approx_setup_helper._get_n_connections())
+
+ def test__get_n_connections_error(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS_ERROR
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with self.assertRaises(KeyError) as raised:
+ ipsec_approx_setup_helper._get_n_connections()
+ self.assertIn(
+ 'Missing flow definition in scenario section of the task definition file',
+ str(raised.exception))
+
+ def test__get_flow_src_start_ip(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('10.0.0.0',
+ ipsec_approx_setup_helper._get_flow_src_start_ip())
+
+ def test__get_flow_src_start_ip_vnf1(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD_ERROR['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('20.0.0.0',
+ ipsec_approx_setup_helper._get_flow_src_start_ip())
+
+ def test__get_flow_src_start_ip_error(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS_ERROR
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with self.assertRaises(KeyError) as raised:
+ ipsec_approx_setup_helper._get_flow_src_start_ip()
+ self.assertIn(
+ 'Missing flow definition in scenario section of the task definition file',
+ str(raised.exception))
+
+ def test__get_flow_dst_start_ip(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('20.0.0.0',
+ ipsec_approx_setup_helper._get_flow_dst_start_ip())
+
+ def test__get_flow_dst_start_ip_vnf1(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD_ERROR['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual('10.0.0.0',
+ ipsec_approx_setup_helper._get_flow_dst_start_ip())
+
+ def test__get_flow_dst_start_ip_error(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.all_options = self.ALL_OPTIONS_ERROR
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with self.assertRaises(KeyError) as raised:
+ ipsec_approx_setup_helper._get_flow_dst_start_ip()
+ self.assertIn(
+ 'Missing flow definition in scenario section of the task definition file',
+ str(raised.exception))
+
+ def test_build_config(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.build_config())
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual('TenGigabitEthernetff/6/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_name'))
+ self.assertEqual(1,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_sw_index'))
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+ self.assertEqual('VirtualFunctionEthernetff/7/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_name'))
+ self.assertEqual(2,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_sw_index'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 4)
+
+ def test_build_config_cbc_algorithms(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS_CBC_ALGORITHMS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.build_config())
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual('TenGigabitEthernetff/6/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_name'))
+ self.assertEqual(1,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_sw_index'))
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+ self.assertEqual('VirtualFunctionEthernetff/7/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_name'))
+ self.assertEqual(2,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_sw_index'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 4)
+
+ @mock.patch.object(utils, 'setup_hugepages')
+ def test_setup_vnf_environment(self, *args):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.nodes = [None, None]
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ self.assertIsInstance(
+ ipsec_approx_setup_helper.setup_vnf_environment(),
+ ResourceProfile)
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual('TenGigabitEthernetff/6/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_name'))
+ self.assertEqual(1,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_sw_index'))
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+ self.assertEqual('VirtualFunctionEthernetff/7/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_name'))
+ self.assertEqual(2,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_sw_index'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 4)
+
+ @mock.patch.object(utils, 'setup_hugepages')
+ def test_setup_vnf_environment_hw(self, *args):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.nodes = [None, None]
+ scenario_helper.options = self.OPTIONS_HW
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ self.assertIsInstance(
+ ipsec_approx_setup_helper.setup_vnf_environment(),
+ ResourceProfile)
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual('TenGigabitEthernetff/6/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_name'))
+ self.assertEqual(1,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_sw_index'))
+ self.assertEqual(0,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+ self.assertEqual('VirtualFunctionEthernetff/7/0',
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_name'))
+ self.assertEqual(2,
+ ipsec_approx_setup_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_sw_index'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 4)
+
+ def test_calculate_frame_size(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(16984 / 48,
+ ipsec_approx_setup_helper.calculate_frame_size(
+ {'64B': 28, '570B': 16, '1518B': 4}))
+
+ def test_calculate_frame_size_64(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(64,
+ ipsec_approx_setup_helper.calculate_frame_size({}))
+
+ def test_calculate_frame_size_64_error(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(64,
+ ipsec_approx_setup_helper.calculate_frame_size(
+ {'64B': -28, '570B': 16, '1518B': 4}))
+
+ def test_check_status(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, self.VPP_INTERFACES_STATUS, ''
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertTrue(ipsec_approx_setup_helper.check_status())
+
+ def test_check_status_false(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, self.VPP_INTERFACES_STATUS_FALSE, ''
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertFalse(ipsec_approx_setup_helper.check_status())
+
+ def test_get_vpp_statistics(self):
+ def execute(cmd):
+ if 'TenGigabitEthernetff/6/0' in cmd:
+ return 0, output_xe0, ''
+ elif 'VirtualFunctionEthernetff/7/0' in cmd:
+ return 0, output_xe1, ''
+ return 0, '0', ''
+
+ output_xe0 = \
+ ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \
+ ' Counter Count \n' \
+ 'TenGigabitEthernetff/6/0 1 up 9200/0/0/0 ' \
+ 'rx packets 23373568\n' \
+ ' ' \
+ 'rx bytes 1402414080\n' \
+ ' ' \
+ 'tx packets 20476416\n' \
+ ' ' \
+ 'tx bytes 1228584960\n' \
+ ' ' \
+ 'ip4 23373568\n' \
+ ' ' \
+ 'rx-miss 27789925'
+ output_xe1 = \
+ ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \
+ ' Counter Count \n' \
+ 'VirtualFunctionEthernetff/7/0 2 up 9200/0/0/0 ' \
+ 'rx packets 23373568\n' \
+ ' ' \
+ 'rx bytes 1402414080\n' \
+ ' ' \
+ 'tx packets 20476416\n' \
+ ' ' \
+ 'tx bytes 1228584960\n' \
+ ' ' \
+ 'ip4 23373568\n' \
+ ' ' \
+ 'rx-miss 27789925'
+
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute = execute
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertEqual({'xe0': {'packets_dropped': 27789925,
+ 'packets_fwd': 20476416,
+ 'packets_in': 23373568},
+ 'xe1': {'packets_dropped': 27789925,
+ 'packets_fwd': 20476416,
+ 'packets_in': 23373568}},
+ ipsec_approx_setup_helper.get_vpp_statistics())
+
+ def test_parser_vpp_stats(self):
+ output = \
+ ' Name Idx State MTU (L3/IP4/IP6/MPLS)' \
+ 'Counter Count \n' \
+ 'TenGigabitEthernetff/6/0 1 up 9200/0/0/0 ' \
+ 'rx packets 23373568\n' \
+ ' ' \
+ 'rx bytes 1402414080\n' \
+ ' ' \
+ 'tx packets 20476416\n' \
+ ' ' \
+ 'tx bytes 1228584960\n' \
+ ' ' \
+ 'ip4 23373568\n' \
+ ' ' \
+ 'rx-miss 27789925'
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual({'xe0': {'packets_dropped': 27789925,
+ 'packets_fwd': 20476416,
+ 'packets_in': 23373568}},
+ ipsec_approx_setup_helper.parser_vpp_stats('xe0',
+ 'TenGigabitEthernetff/6/0',
+ output))
+
+ def test_parser_vpp_stats_no_miss(self):
+ output = \
+ ' Name Idx State ' \
+ 'Counter Count \n' \
+ 'TenGigabitEthernetff/6/0 1 up ' \
+ 'rx packets 23373568\n' \
+ ' ' \
+ 'rx bytes 1402414080\n' \
+ ' ' \
+ 'tx packets 20476416\n' \
+ ' ' \
+ 'tx bytes 1228584960\n' \
+ ' ' \
+ 'ip4 23373568'
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual({'xe0': {'packets_dropped': 2897152,
+ 'packets_fwd': 20476416,
+ 'packets_in': 23373568}},
+ ipsec_approx_setup_helper.parser_vpp_stats('xe0',
+ 'TenGigabitEthernetff/6/0',
+ output))
+
+ def test_create_ipsec_tunnels(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out, \
+ mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'vpp_get_interface_data') as \
+ mock_ipsec_approx_setup_helper:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ mock_vat_terminal_exec_cmd_from_template.return_value = self.VPP_INTERFACES_DUMP
+ mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.create_ipsec_tunnels())
+ self.assertGreaterEqual(
+ mock_vat_terminal_exec_cmd_from_template.call_count, 9)
+
+ def test_create_ipsec_tunnels_cbc_algorithms(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS_CBC_ALGORITHMS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'find_encrypted_data_interface') as \
+ mock_find_encrypted_data_interface, \
+ mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'vpp_get_interface_data') as \
+ mock_ipsec_approx_setup_helper:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ mock_find_encrypted_data_interface.return_value = {
+ 'dpdk_port_num': 0,
+ 'driver': 'igb_uio',
+ 'dst_ip': '192.168.100.1',
+ 'dst_mac': '90:e2:ba:7c:30:e8',
+ 'ifname': 'xe0',
+ 'local_ip': '192.168.100.2',
+ 'local_mac': '90:e2:ba:7c:41:a8',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'vnf__1',
+ 'numa_node': 0,
+ 'peer_ifname': 'xe0',
+ 'peer_intf': {'dpdk_port_num': 0,
+ 'driver': 'igb_uio',
+ 'dst_ip': '192.168.100.2',
+ 'dst_mac': '90:e2:ba:7c:41:a8',
+ 'ifname': 'xe0',
+ 'local_ip': '192.168.100.1',
+ 'local_mac': '90:e2:ba:7c:30:e8',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'tg__0',
+ 'peer_ifname': 'xe0',
+ 'peer_name': 'vnf__0',
+ 'vld_id': 'uplink_0',
+ 'vpci': '0000:81:00.0'},
+ 'peer_name': 'tg__0',
+ 'vld_id': 'uplink_0',
+ 'vpci': '0000:ff:06.0',
+ 'vpp_name': u'TenGigabitEthernetff/6/0',
+ 'vpp_sw_index': 1}
+ mock_vat_terminal_exec_cmd_from_template.return_value = self.VPP_INTERFACES_DUMP
+ mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.create_ipsec_tunnels())
+ self.assertGreaterEqual(
+ mock_vat_terminal_exec_cmd_from_template.call_count, 9)
+
+ def test_find_raw_data_interface(self):
+ expected = {'dpdk_port_num': 0,
+ 'driver': 'igb_uio',
+ 'dst_ip': '192.168.100.1',
+ 'dst_mac': '90:e2:ba:7c:30:e8',
+ 'ifname': 'xe0',
+ 'local_ip': '192.168.100.2',
+ 'local_mac': '90:e2:ba:7c:41:a8',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'vnf__0',
+ 'numa_node': 0,
+ 'peer_ifname': 'xe0',
+ 'peer_intf': {'dpdk_port_num': 0,
+ 'driver': 'igb_uio',
+ 'dst_ip': '192.168.100.2',
+ 'dst_mac': '90:e2:ba:7c:41:a8',
+ 'ifname': 'xe0',
+ 'local_ip': '192.168.100.1',
+ 'local_mac': '90:e2:ba:7c:30:e8',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'tg__0',
+ 'peer_ifname': 'xe0',
+ 'peer_name': 'vnf__0',
+ 'vld_id': 'uplink_0',
+ 'vpci': '0000:81:00.0'},
+ 'peer_name': 'tg__0',
+ 'vld_id': 'uplink_0',
+ 'vpci': '0000:ff:06.0',
+ 'vpp_name': u'TenGigabitEthernetff/6/0',
+ 'vpp_sw_index': 1}
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(expected,
+ ipsec_approx_setup_helper.find_raw_data_interface())
+
+ def test_find_raw_data_interface_error(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD_ERROR['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ with self.assertRaises(KeyError):
+ ipsec_approx_setup_helper.find_raw_data_interface()
+
+ def test_find_encrypted_data_interface(self):
+ expected = {'dpdk_port_num': 1,
+ 'driver': 'igb_uio',
+ 'dst_ip': '1.1.1.2',
+ 'dst_mac': '0a:b1:ec:fd:a2:66',
+ 'ifname': 'xe1',
+ 'local_ip': '1.1.1.1',
+ 'local_mac': '4e:90:85:d3:c5:13',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'vnf__0',
+ 'numa_node': 0,
+ 'peer_ifname': 'xe1',
+ 'peer_intf': {'driver': 'igb_uio',
+ 'dst_ip': '1.1.1.1',
+ 'dst_mac': '4e:90:85:d3:c5:13',
+ 'ifname': 'xe1',
+ 'local_ip': '1.1.1.2',
+ 'local_mac': '0a:b1:ec:fd:a2:66',
+ 'netmask': '255.255.255.0',
+ 'network': {},
+ 'node_name': 'vnf__1',
+ 'peer_ifname': 'xe1',
+ 'peer_name': 'vnf__0',
+ 'vld_id': 'ciphertext',
+ 'vpci': '0000:00:07.0'},
+ 'peer_name': 'vnf__1',
+ 'vld_id': 'ciphertext',
+ 'vpci': '0000:ff:07.0',
+ 'vpp_name': u'VirtualFunctionEthernetff/7/0',
+ 'vpp_sw_index': 2}
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+ self.assertEqual(expected,
+ ipsec_approx_setup_helper.find_encrypted_data_interface())
+
+ def test_create_startup_configuration_of_vpp(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsInstance(
+ ipsec_approx_setup_helper.create_startup_configuration_of_vpp(),
+ vpp_helpers.VppConfigGenerator)
+
+ def test_add_worker_threads_and_rxqueues(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(
+ ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+ vpp_config_generator, 1, 1))
+ self.assertEqual(
+ 'cpu\n{\n corelist-workers 2\n main-core 1\n}\ndpdk\n{\n ' \
+ 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_worker_threads_and_rxqueues_smt(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_SMT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(
+ ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+ vpp_config_generator, 1))
+ self.assertEqual(
+ 'cpu\n{\n corelist-workers 2,6\n main-core 1\n}\ndpdk\n{\n ' \
+ 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_worker_threads_and_rxqueues_with_numa(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(
+ ipsec_approx_setup_helper.add_worker_threads_and_rxqueues(
+ vpp_config_generator, 1, 1))
+ self.assertEqual(
+ 'cpu\n{\n corelist-workers 2\n main-core 1\n}\ndpdk\n{\n ' \
+ 'dev default\n {\n num-rx-queues 1\n }\n num-mbufs 32768\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_pci_devices(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.add_pci_devices(
+ vpp_config_generator))
+ self.assertEqual(
+ 'dpdk\n{\n dev 0000:ff:06.0 \n dev 0000:ff:07.0 \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_cryptodev(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+ vpp_config_generator, 'aesni_gcm', 1))
+ self.assertEqual(
+ 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_cryptodev_hw(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS_HW
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+ vpp_config_generator, 'aesni_gcm', 1))
+ self.assertEqual(
+ 'dpdk\n{\n dev 0000:ff:01.0 \n uio-driver igb_uio\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_cryptodev_smt_used(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out:
+ mock_get_cpu_layout.return_value = self.CPU_SMT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_LAYOUT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+ vpp_config_generator, 'aesni_gcm', 1))
+ self.assertEqual(
+ 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_cryptodev_smt_used_hw(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS_HW
+ scenario_helper.all_options = self.ALL_OPTIONS
+ vpp_config_generator = vpp_helpers.VppConfigGenerator()
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout:
+ mock_get_cpu_layout.return_value = self.CPU_SMT
+ ipsec_approx_setup_helper.sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper.sys_cores.cpuinfo = self.CPU_SMT
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ ipsec_approx_setup_helper.sys_cores.get_cpu_layout())
+ self.assertIsNone(ipsec_approx_setup_helper.add_dpdk_cryptodev(
+ vpp_config_generator, 'aesni_gcm', 1))
+ self.assertEqual(
+ 'dpdk\n{\n dev 0000:ff:01.0 \n dev 0000:ff:01.1 \n uio-driver igb_uio\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_initialize_ipsec(self):
+ vnfd_helper = VnfdHelper(
+ TestVipsecApproxVnf.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+ scenario_helper.all_options = self.ALL_OPTIONS
+
+ ipsec_approx_setup_helper = VipsecApproxSetupEnvHelper(vnfd_helper,
+ ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'execute_script_json_out') as \
+ mock_execute_script_json_out, \
+ mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template, \
+ mock.patch.object(ipsec_approx_setup_helper,
+ 'vpp_get_interface_data') as \
+ mock_ipsec_approx_setup_helper:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ mock_execute_script_json_out.return_value = str(
+ self.VPP_INTERFACES_DUMP).replace("\'", "\"")
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ mock_ipsec_approx_setup_helper.return_value = self.VPP_INTERFACES_DUMP
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ ipsec_approx_setup_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ ipsec_approx_setup_helper.update_vpp_interface_data()
+ ipsec_approx_setup_helper.iface_update_numa()
+ self.assertIsNone(ipsec_approx_setup_helper.initialize_ipsec())
+ self.assertGreaterEqual(
+ mock_vat_terminal_exec_cmd_from_template.call_count, 9)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
new file mode 100644
index 000000000..32f384027
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_helpers.py
@@ -0,0 +1,2825 @@
+# Copyright (c) 2016-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.
+
+from itertools import repeat, chain
+import os
+import socket
+import time
+
+import mock
+import unittest
+
+from yardstick.common import utils
+from yardstick.network_services import constants
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+from yardstick.network_services.vnf_generic.vnf import prox_helpers
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+
+
+class TestCoreTuple(unittest.TestCase):
+ def test___init__(self):
+ core_tuple = prox_helpers.CoreSocketTuple('core 5s6')
+ self.assertEqual(core_tuple.core_id, 5)
+ self.assertEqual(core_tuple.socket_id, 6)
+ self.assertFalse(core_tuple.is_hyperthread())
+
+ core_tuple = prox_helpers.CoreSocketTuple('core 5s6h')
+ self.assertEqual(core_tuple.core_id, 5)
+ self.assertEqual(core_tuple.socket_id, 6)
+ self.assertTrue(core_tuple.is_hyperthread())
+
+ def test___init__negative(self):
+ bad_inputs = [
+ '',
+ '5',
+ '5s',
+ '6h',
+ '5s6',
+ 'core',
+ 'core h',
+ 'core 5s',
+ 'core 5 6',
+ 'core 5 6h',
+ 'core 5d6',
+ 'core 5d6h',
+ 1,
+ 2.3,
+ [],
+ {},
+ object(),
+ ]
+
+ for bad_input in bad_inputs:
+ with self.assertRaises(ValueError):
+ prox_helpers.CoreSocketTuple(bad_input)
+
+ def test_find_in_topology(self):
+ topology_in = {
+ 6: {
+ 5: {
+ 'key1': ['a', 'b'],
+ 'key2': ['c', 'd'],
+ },
+ },
+ }
+
+ core_tuple = prox_helpers.CoreSocketTuple('core 5s6')
+
+ expected = 'a'
+ result = core_tuple.find_in_topology(topology_in)
+ self.assertEqual(result, expected)
+
+ core_tuple = prox_helpers.CoreSocketTuple('core 5s6h')
+
+ expected = 'c'
+ result = core_tuple.find_in_topology(topology_in)
+ self.assertEqual(result, expected)
+
+ def test_find_in_topology_negative(self):
+ core_tuple = prox_helpers.CoreSocketTuple('core 6s5')
+ with self.assertRaises(ValueError):
+ # no socket key
+ core_tuple.find_in_topology({})
+
+ with self.assertRaises(ValueError):
+ # no core key
+ core_tuple.find_in_topology({5: {}})
+
+ with self.assertRaises(ValueError):
+ # no first value (as needed by non-hyperthread core)
+ core_tuple.find_in_topology({5: {6: {'key1': []}}})
+
+ core_tuple = prox_helpers.CoreSocketTuple('core 6s5h')
+ with self.assertRaises(ValueError):
+ # no second value (as needed by hyperthread core)
+ core_tuple.find_in_topology({5: {6: {'key1': ['e']}}})
+
+
+class TestTotStatsTuple(unittest.TestCase):
+ def test___new___negative(self):
+ with self.assertRaises(TypeError):
+ # no values
+ prox_helpers.TotStatsTuple()
+
+ with self.assertRaises(TypeError):
+ # one, non-integer value
+ prox_helpers.TotStatsTuple('a')
+
+ with self.assertRaises(TypeError):
+ # too many values
+ prox_helpers.TotStatsTuple(3, 4, 5, 6, 7)
+
+
+class TestProxTestDataTuple(unittest.TestCase):
+ def test___init__(self):
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 1, 2, 3, 4, 5, 6, 7, 8, 9)
+ self.assertEqual(prox_test_data.tolerated, 1)
+ self.assertEqual(prox_test_data.tsc_hz, 2)
+ self.assertEqual(prox_test_data.delta_rx, 3)
+ self.assertEqual(prox_test_data.delta_tx, 4)
+ self.assertEqual(prox_test_data.delta_tsc, 5)
+ self.assertEqual(prox_test_data.latency, 6)
+ self.assertEqual(prox_test_data.rx_total, 7)
+ self.assertEqual(prox_test_data.tx_total, 8)
+ self.assertEqual(prox_test_data.requested_pps, 9)
+
+ def test_properties(self):
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 1, 2, 3, 4, 5, 6, 7, 8, 9)
+ self.assertEqual(prox_test_data.pkt_loss, 12.5)
+ self.assertEqual(prox_test_data.tx_mpps, 1.6 / 1e6)
+ self.assertEqual(prox_test_data.can_be_lost, 0)
+ self.assertEqual(prox_test_data.drop_total, 1)
+ self.assertFalse(prox_test_data.success)
+
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 10, 2, 3, 4, 5, 6, 997, 998, 9)
+ self.assertTrue(prox_test_data.success)
+
+ def test_pkt_loss_zero_division(self):
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 1, 2, 3, 4, 5, 6, 7, 0, 9)
+ self.assertEqual(prox_test_data.pkt_loss, 100.0)
+
+ def test_get_samples(self):
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
+
+ expected = {
+ "Throughput": 1.2 / 1e6,
+ "DropPackets": 12.5,
+ "CurrentDropPackets": 12.5,
+ "RequestedTxThroughput": 9 / 1e6,
+ "TxThroughput": 1.6 / 1e6,
+ "RxThroughput": 1.2 / 1e6,
+ "PktSize": 64,
+ "PortSample": 1,
+ "LatencyMin": 6.1,
+ "LatencyMax": 6.9,
+ "LatencyAvg": 6.4,
+ }
+ result = prox_test_data.get_samples(64, port_samples={"PortSample": 1})
+ self.assertDictEqual(result, expected)
+
+ expected = {
+ "Throughput": 1.2 / 1e6,
+ "DropPackets": 0.123,
+ "CurrentDropPackets": 0.123,
+ "RequestedTxThroughput": 9 / 1e6,
+ "TxThroughput": 1.6 / 1e6,
+ "RxThroughput": 1.2 / 1e6,
+ "PktSize": 64,
+ "LatencyMin": 6.1,
+ "LatencyMax": 6.9,
+ "LatencyAvg": 6.4,
+ }
+ result = prox_test_data.get_samples(64, 0.123)
+ self.assertDictEqual(result, expected)
+
+ @mock.patch('yardstick.LOG_RESULT', create=True)
+ def test_log_data(self, mock_logger):
+ my_mock_logger = mock.MagicMock()
+ prox_test_data = prox_helpers.ProxTestDataTuple(
+ 1, 2, 3, 4, 5, [6.1, 6.9, 6.4], 7, 8, 9)
+ prox_test_data.log_data()
+
+ my_mock_logger.debug.assert_not_called()
+ mock_logger.debug.assert_not_called()
+
+ mock_logger.debug.reset_mock()
+ prox_test_data.log_data(my_mock_logger)
+ my_mock_logger.assert_not_called()
+ mock_logger.debug.assert_not_called()
+
+
+class TestPacketDump(unittest.TestCase):
+ PAYLOAD = "payload"
+
+ def test__init__(self):
+ prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+
+ def test___str__(self):
+ expected = '<PacketDump port: port_id payload: {}>'.format(self.PAYLOAD)
+ dump1 = prox_helpers.PacketDump(
+ "port_id", len(self.PAYLOAD), self.PAYLOAD)
+ self.assertEqual(str(dump1), expected)
+
+ def test_port_id(self):
+ p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+ self.assertEqual(p.port_id, "port_id")
+
+ def test_data_len(self):
+ p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+ self.assertEqual(p.data_len, len(self.PAYLOAD))
+
+ def test_payload(self):
+ p = prox_helpers.PacketDump("port_id", len(self.PAYLOAD), self.PAYLOAD)
+ self.assertEqual(p.payload(), self.PAYLOAD)
+
+ self.assertEqual(p.payload(3), self.PAYLOAD[3:])
+
+ self.assertEqual(p.payload(end=3), self.PAYLOAD[:4])
+
+ self.assertEqual(p.payload(2, 4), self.PAYLOAD[2:5])
+
+
+PACKET_DUMP_1 = """\
+pktdump,3,11
+hello world
+"""
+
+PACKET_DUMP_2 = """\
+pktdump,3,11
+hello world
+pktdump,2,9
+brown fox jumped over
+pktdump,4,8
+lazy
+dog
+"""
+
+PACKET_DUMP_NON_1 = """\
+not_a_dump,1,2
+other data
+"""
+
+PACKET_DUMP_MIXED_1 = """\
+pktdump,3,11
+hello world
+not_a_dump,1,2
+other data
+"""
+
+PACKET_DUMP_BAD_1 = """\
+pktdump,one,12
+bad port id
+"""
+
+PACKET_DUMP_BAD_2 = """\
+pktdump,3,twelve
+bad data length
+"""
+
+PACKET_DUMP_BAD_3 = """\
+pktdump,3
+no data length value
+"""
+
+
+class TestProxSocketHelper(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_time_sleep = mock.patch.object(time, 'sleep')
+ self.mock_time_sleep = self._mock_time_sleep.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_time_sleep.stop()
+
+ @mock.patch.object(prox_helpers, 'socket')
+ def test___init__(self, mock_socket):
+ expected = mock_socket.socket()
+ prox = prox_helpers.ProxSocketHelper()
+ result = prox._sock
+ self.assertEqual(result, expected)
+
+ def test_connect(self):
+ mock_sock = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_sock)
+ prox.connect('10.20.30.40', 23456)
+ mock_sock.connect.assert_called_once()
+
+ def test_get_sock(self):
+ mock_sock = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_sock)
+ result = prox.get_socket()
+ self.assertIs(result, mock_sock)
+
+ # TODO(elfoley): Split this into three tests
+ @mock.patch.object(prox_helpers, 'select')
+ def test_get_data(self, mock_select):
+ mock_select.select.side_effect = [[1], [0]]
+ mock_socket = mock.MagicMock()
+ mock_recv = mock_socket.recv()
+ mock_recv.decode.return_value = ""
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ ret = prox.get_data()
+ self.assertEqual(ret, "")
+ self.assertEqual(len(prox._pkt_dumps), 0)
+
+ mock_select.select.reset_mock()
+ mock_select.select.side_effect = chain([['a'], ['']],
+ repeat([1], 3))
+ mock_recv.decode.return_value = PACKET_DUMP_1
+ ret = prox.get_data()
+ self.assertEqual(mock_select.select.call_count, 2)
+ self.assertEqual(ret, 'pktdump,3,11')
+ self.assertEqual(len(prox._pkt_dumps), 1)
+
+ mock_select.select.reset_mock()
+ mock_select.select.side_effect = chain([[object()], [None]],
+ repeat([1], 3))
+ mock_recv.decode.return_value = PACKET_DUMP_2
+ ret = prox.get_data()
+ self.assertEqual(mock_select.select.call_count, 1)
+ self.assertEqual(ret, 'jumped over')
+ self.assertEqual(len(prox._pkt_dumps), 3)
+
+ @mock.patch.object(prox_helpers, 'select')
+ def test_get_string(self, mock_select):
+ mock_select.select.side_effect = [[1], [0]]
+ mock_socket = mock.MagicMock()
+ mock_recv = mock_socket.recv()
+ mock_recv.decode.return_value = ""
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ status, ret = prox.get_string()
+ self.assertEqual(ret, "")
+ self.assertTrue(status)
+ self.assertEqual(len(prox._pkt_dumps), 0)
+
+ @mock.patch.object(prox_helpers, 'select')
+ def test_get_string2(self, mock_select):
+ mock_select.select.side_effect = chain([['a'], ['']],
+ repeat([1], 3))
+ mock_socket = mock.MagicMock()
+ mock_recv = mock_socket.recv()
+ mock_recv.decode.return_value = PACKET_DUMP_1
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ status, ret = prox.get_string()
+ self.assertEqual(mock_select.select.call_count, 2)
+ self.assertEqual(ret, 'pktdump,3,11')
+ self.assertTrue(status)
+ self.assertEqual(len(prox._pkt_dumps), 1)
+
+ @mock.patch.object(prox_helpers, 'select')
+ def test_get_string3(self, mock_select):
+ mock_select.select.side_effect = chain([[object()], [None]],
+ repeat([1], 3))
+ mock_socket = mock.MagicMock()
+ mock_recv = mock_socket.recv()
+ mock_recv.decode.return_value = PACKET_DUMP_2
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ status, ret = prox.get_string()
+ self.assertTrue(status)
+ self.assertTrue(mock_select.select.assert_called_once)
+ self.assertEqual(ret, 'jumped over')
+ self.assertEqual(len(prox._pkt_dumps), 2)
+
+ def test__parse_socket_data_mixed_data(self):
+ prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
+ ret, _ = prox._parse_socket_data(PACKET_DUMP_NON_1, False)
+ self.assertEqual(ret, 'not_a_dump,1,2')
+ self.assertEqual(len(prox._pkt_dumps), 0)
+
+ ret, _ = prox._parse_socket_data(PACKET_DUMP_MIXED_1, False)
+ self.assertEqual(ret, 'not_a_dump,1,2')
+ self.assertEqual(len(prox._pkt_dumps), 1)
+
+ def test__parse_socket_data_bad_data(self):
+ prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
+ with self.assertRaises(ValueError):
+ prox._parse_socket_data(PACKET_DUMP_BAD_1, False)
+
+ with self.assertRaises(ValueError):
+ prox._parse_socket_data(PACKET_DUMP_BAD_2, False)
+
+ ret, _ = prox._parse_socket_data(PACKET_DUMP_BAD_3, False)
+ self.assertEqual(ret, 'pktdump,3')
+
+ def test__parse_socket_data_pkt_dump_only(self):
+ prox = prox_helpers.ProxSocketHelper(mock.MagicMock())
+ ret, _ = prox._parse_socket_data('', True)
+ self.assertFalse(ret)
+
+ ret, _ = prox._parse_socket_data(PACKET_DUMP_1, True)
+ self.assertTrue(ret)
+
+ ret, _ = prox._parse_socket_data(PACKET_DUMP_2, True)
+ self.assertTrue(ret)
+
+ def test_put_command(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.put_command("data")
+ mock_socket.sendall.assert_called_once()
+
+ def test_put_command_socket_error(self):
+ mock_socket = mock.MagicMock()
+ mock_socket.sendall.side_effect = OSError
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.put_command("data")
+ mock_socket.sendall.assert_called_once()
+
+ def test_get_packet_dump(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox._pkt_dumps = []
+ self.assertIsNone(prox.get_packet_dump())
+
+ prox._pkt_dumps = [234]
+ self.assertEqual(prox.get_packet_dump(), 234)
+ self.assertEqual(prox._pkt_dumps, [])
+
+ def test_stop_all_reset(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.stop_all_reset()
+ mock_socket.sendall.assert_called()
+
+ def test_stop_all(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.stop_all()
+ mock_socket.sendall.assert_called()
+
+ def test_stop(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.stop([3, 4, 5], 16)
+ mock_socket.sendall.assert_called()
+
+ def test_start_all(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.start_all()
+ mock_socket.sendall.assert_called()
+
+ def test_start(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.start([3, 4, 5])
+ mock_socket.sendall.assert_called()
+
+ def test_reset_stats(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.reset_stats()
+ mock_socket.sendall.assert_called()
+
+ def test_set_pkt_size(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_pkt_size([3, 4, 5], 1024)
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_set_value(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_value([3, 4, 5], 10, 20, 30)
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_reset_values(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.reset_values([3, 4, 5])
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_set_speed(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_speed([3, 4, 5], 1000)
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_slope_speed(self):
+ core_data = [
+ {
+ 'cores': [3, 4, 5],
+ 'speed': 1000,
+ },
+ {
+ 'cores': [9, 10, 11],
+ 'speed': '500.5',
+ },
+ ]
+
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_speed = set_speed = mock.MagicMock()
+ prox.slope_speed(core_data, 5)
+ self.assertEqual(set_speed.call_count, 20)
+
+ set_speed.reset_mock()
+ prox.slope_speed(core_data, 5, 5)
+ self.assertEqual(set_speed.call_count, 10)
+
+ def test_set_pps(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_pps([3, 4, 5], 1000, 512)
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_lat_stats(self):
+ latency_output = [
+ '1, 2 , 3', # has white space
+ '4,5', # too short
+ '7,8,9,10.5,11', # too long with float, but float is in unused portion
+ 'twelve,13,14', # value as English word
+ '15,16.2,17', # float in used portion
+ ]
+
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(side_effect=latency_output)
+
+ expected = (
+ {
+ 3: 1,
+ 5: 7,
+ },
+ {
+ 3: 2,
+ 5: 8,
+ },
+ {
+ 3: 3,
+ 5: 9,
+ },
+ )
+ result = prox.lat_stats([3, 4, 5, 6, 7], 16)
+ self.assertEqual(mock_socket.sendall.call_count, 5)
+ self.assertEqual(result, expected)
+
+ def test_get_all_tot_stats_error(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value='3,4,5')
+ expected = [0, 0, 0, 0]
+ result = prox.get_all_tot_stats()
+ self.assertEqual(result, expected)
+
+ def test_get_all_tot_stats(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value='3,4,5,6')
+ expected = 3, 4, 5, 6
+ result = prox.get_all_tot_stats()
+ self.assertEqual(result, expected)
+
+ def test_hz(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value='3,4,5,6')
+ expected = 6
+ result = prox.hz()
+ self.assertEqual(result, expected)
+
+ def test_core_stats(self):
+ core_stats = [
+ '3,4,5,6',
+ '7,8,9,10,NaN',
+ '11,12,13,14,15',
+ ]
+
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(side_effect=core_stats)
+ expected = 21, 24, 27, 14
+ result = prox.core_stats([3, 4, 5], 16)
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(prox_helpers.LOG, 'error')
+ def test_irq_core_stats(self, *args):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value=('0,1,2,3,4,5,0,1,2,3,4,5,0,1,2,3'))
+
+ data_0 = {"cpu": 0, 'bucket_0': 1, 'bucket_1': 2, 'bucket_2': 3, 'bucket_3': 4,
+ 'bucket_4': 5, 'bucket_5': 0, 'bucket_6': 1, 'bucket_7': 2, 'bucket_8': 3,
+ 'bucket_9': 4, 'bucket_10': 5, 'bucket_11': 0, 'bucket_12': 1,
+ "max_irq": 0, "overflow": 10}
+
+ data_1 = {"cpu": 1, 'bucket_0': 1, 'bucket_1': 2, 'bucket_2': 3, 'bucket_3': 4,
+ 'bucket_4': 5, 'bucket_5': 0, 'bucket_6': 1, 'bucket_7': 2, 'bucket_8': 3,
+ 'bucket_9': 4, 'bucket_10': 5, 'bucket_11': 0, 'bucket_12': 1,
+ "max_irq": 0, "overflow": 10}
+
+ expected = {"core_0": data_0, "core_1": data_1}
+
+ result = prox.irq_core_stats([[0, 1], [1, 0]])
+ self.assertDictEqual(result, expected)
+
+ @mock.patch.object(prox_helpers.LOG, 'error')
+ def test_multi_port_stats(self, *args):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_string = mock.MagicMock(return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+ expected = [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]]
+ status, result = prox.multi_port_stats([0, 1])
+ self.assertEqual(result, expected)
+ self.assertEqual(status, True)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+ status, result = prox.multi_port_stats([0])
+ self.assertEqual(status, False)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+ status, result = prox.multi_port_stats([0, 1, 2])
+ self.assertEqual(status, False)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '0,1,2,3;1,1,2,3,4,5'))
+ status, result = prox.multi_port_stats([0, 1])
+ self.assertEqual(status, False)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '99,1,2,3,4,5;1,1,2,3,4,5'))
+ status, result = prox.multi_port_stats([0, 1])
+ self.assertEqual(status, False)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '99,1,2,3,4,5;1,1,2,3,4,5'))
+ status, result = prox.multi_port_stats([99, 1])
+ expected = [[99, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]]
+ self.assertEqual(status, True)
+ self.assertEqual(result, expected)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True,
+ '2,21,22,23,24,25;1,11,12,13,14,15;0,1,2,3,4,5'))
+
+ sample1 = [0, 1, 2, 3, 4, 5]
+ sample2 = [1, 11, 12, 13, 14, 15]
+ sample3 = [2, 21, 22, 23, 24, 25]
+ expected = [sample3, sample2, sample1]
+ status, result = prox.multi_port_stats([1, 2, 0])
+ self.assertTrue(status)
+ self.assertListEqual(result, expected)
+
+ prox.get_string = mock.MagicMock(
+ return_value=(True, '6,21,22,23,24,25;1,11,12,13,14,15;0,1,2,3,4,5'))
+ ok, result = prox.multi_port_stats([1, 6, 0])
+ sample1 = [6, 21, 22, 23, 24, 25]
+ sample2 = [1, 11, 12, 13, 14, 15]
+ sample3 = [0, 1, 2, 3, 4, 5]
+ expected = [sample1, sample2, sample3]
+ self.assertListEqual(result, expected)
+ self.assertTrue(ok)
+
+ @mock.patch.object(prox_helpers.LOG, 'error')
+ def test_multi_port_stats_diff(self, *args):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_string = mock.MagicMock(return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+ _, t1 = prox.multi_port_stats([0, 1])
+
+ prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,6;1,4,8,16,32,6'))
+ _, t2 = prox.multi_port_stats([0, 1])
+
+ prox.get_string = mock.MagicMock(return_value=(True, '0,1,1,1,1,1;1,1,1,1,1,1'))
+ _, t3 = prox.multi_port_stats([0, 1])
+
+ prox.get_string = mock.MagicMock(return_value=(True, '0,2,2,2,2,2;1,2,2,2,2,2'))
+ _, t4 = prox.multi_port_stats([0, 1])
+
+ expected = [[0, 1.0, 2.0, 0, 0, 1], [1, 3.0, 6.0, 0, 0, 1]]
+ result = prox.multi_port_stats_diff(t1, t2, 1)
+
+ self.assertListEqual(result, expected)
+
+ result = prox.multi_port_stats_diff(t4, t3, 1)
+ expected = [[0, 1.0, 1.0, 0, 0, 1], [1, 1.0, 1.0, 0, 0, 1]]
+
+ self.assertListEqual(result, expected)
+
+ prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,10'))
+ ok, t5 = prox.multi_port_stats([0, 1])
+ self.assertFalse(ok)
+ self.assertListEqual(t5, [])
+
+ result = prox.multi_port_stats_diff(t5, t4, 1)
+ expected = [[0, 0.0, 0.0, 0, 0, 0], [1, 0.0, 0.0, 0, 0, 0]]
+ self.assertListEqual(result, expected)
+
+ prox.get_string = mock.MagicMock(return_value=(True, '0,10,10,20,30,0;1,30,40,50,60,0'))
+ _, t6 = prox.multi_port_stats([0, 1])
+
+ prox.get_string = \
+ mock.MagicMock(return_value=(True, '0,100,100,100,100,0;1,100,100,100,100,0'))
+ _, t7 = prox.multi_port_stats([0, 1])
+
+ result = prox.multi_port_stats_diff(t6, t7, 1)
+ expected = [[0, 0.0, 0.0, 0, 0, 0], [1, 0.0, 0.0, 0, 0, 0]]
+ self.assertListEqual(result, expected)
+
+ result = prox.multi_port_stats_diff(t1, t2, 0)
+ expected = [[0, 0.0, 0.0, 0, 0, 1], [1, 0.0, 0.0, 0, 0, 1]]
+ self.assertListEqual(result, expected)
+
+ @mock.patch.object(prox_helpers.LOG, 'error')
+ def test_multi_port_stats_tuple(self, *args):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_string = mock.MagicMock(return_value=(True, '0,1,2,3,4,5;1,1,2,3,4,5'))
+ _, result1 = prox.multi_port_stats([0, 1])
+ prox.get_string = mock.MagicMock(return_value=(True, '0,2,4,6,8,6;1,4,8,16,32,6'))
+ _, result2 = prox.multi_port_stats([0, 1])
+
+ result = prox.multi_port_stats_diff(result1, result2, 1)
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+
+ expected = {'xe0': {'in_packets': 1.0, 'out_packets': 2.0},
+ 'xe1': {'in_packets': 3.0, 'out_packets': 6.0}}
+ live_stats = prox.multi_port_stats_tuple(result, vnfd_helper.ports_iter())
+ self.assertDictEqual(live_stats, expected)
+
+ live_stats = prox.multi_port_stats_tuple(result, None)
+ expected = {}
+ self.assertDictEqual(live_stats, expected)
+
+ live_stats = prox.multi_port_stats_tuple(None, vnfd_helper.ports_iter())
+ self.assertDictEqual(live_stats, expected)
+
+ def test_port_stats(self):
+ port_stats = [
+ ','.join(str(n) for n in range(3, 15)),
+ ','.join(str(n) for n in range(8, 32, 2)),
+ ','.join(str(n) for n in range(5, 89, 7)),
+ ]
+
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(side_effect=port_stats)
+ expected = [16, 26, 36, 46, 56, 66, 76, 86, 96, 106, 116, 126]
+ result = prox.port_stats([3, 4, 5])
+ self.assertEqual(result, expected)
+
+ def test_measure_tot_stats(self):
+ start_tot = 3, 4, 5, 6
+ end_tot = 7, 9, 11, 13
+ delta_tot = 4, 5, 6, 7
+
+ get_data_output = [
+ ','.join(str(n) for n in start_tot),
+ ','.join(str(n) for n in end_tot),
+ ]
+
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(side_effect=get_data_output)
+ expected = {
+ 'start_tot': start_tot,
+ 'end_tot': end_tot,
+ 'delta': delta_tot,
+ }
+ with prox.measure_tot_stats() as result:
+ pass
+ self.assertEqual(result, expected)
+
+ def test_tot_stats(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value='3,4,5,6')
+ expected = 3, 4, 5
+ result = prox.tot_stats()
+ self.assertEqual(result, expected)
+
+ def test_tot_ierrors(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.get_data = mock.MagicMock(return_value='3,4,5,6')
+ expected = 3, 3
+ result = prox.tot_ierrors()
+ self.assertEqual(result, expected)
+
+ def test_set_count(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.set_count(432, [3, 4, 5])
+ self.assertEqual(mock_socket.sendall.call_count, 3)
+
+ def test_dump_rx(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.dump_rx(3, 5, 8)
+ mock_socket.sendall.assert_called_once()
+
+ def test_quit(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.quit()
+ mock_socket.sendall.assert_called()
+
+ def test_force_quit(self):
+ mock_socket = mock.MagicMock()
+ prox = prox_helpers.ProxSocketHelper(mock_socket)
+ prox.force_quit()
+ mock_socket.sendall.assert_called()
+
+
+class TestProxDpdkVnfSetupEnvHelper(unittest.TestCase):
+
+ VNFD0 = {
+ 'short-name': 'ProxVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'name': 'proxvnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'proxvnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'uplink_0',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.19',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'downlink_0',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'proxvnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'id': 'ProxApproxVnf',
+ 'name': 'ProxVnf',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD0,
+ ],
+ },
+ }
+
+ def test_global_section(self):
+ setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
+
+ setup_helper._prox_config_data = [('a', [])]
+
+ with self.assertRaises(KeyError):
+ _ = setup_helper.global_section
+
+ global_section = (
+ 'global', [
+ ('not_name', 'other data'),
+ ('name_not', 'more data'),
+ ('name', 'prox type'),
+ ],
+ )
+
+ setup_helper._prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ global_section,
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'tagged'),
+ ]),
+ ('section3', [
+ ('key1', 'value1'),
+ ('key2', 'value2'),
+ ('key3', 'value3'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'udp'),
+ ]),
+ ]
+
+ result = setup_helper.global_section
+ self.assertEqual(result, global_section[1])
+
+ def test_find_in_section(self):
+ setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
+
+ setup_helper._prox_config_data = [
+ ('global', [
+ ('not_name', 'other data'),
+ ('name_not', 'more data'),
+ ('name', 'prox type'),
+ ]),
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'tagged'),
+ ]),
+ ('section3', [
+ ('key1', 'value1'),
+ ('key2', 'value2'),
+ ('key3', 'value3'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'udp'),
+ ]),
+ ]
+
+ expected = 'value3'
+ result = setup_helper.find_in_section('section3', 'key3')
+ self.assertEqual(result, expected)
+
+ expected = 'default value'
+ result = setup_helper.find_in_section('section3', 'key4', 'default value')
+ self.assertEqual(result, expected)
+
+ with self.assertRaises(KeyError):
+ setup_helper.find_in_section('section4', 'key1')
+
+ with self.assertRaises(KeyError):
+ setup_helper.find_in_section('section1', 'key1')
+
+ def test__replace_quoted_with_value(self):
+ # empty string
+ input_str = ''
+ expected = ''
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat'))
+ self.assertEqual(result, expected)
+
+ # no quoted substring
+ input_str = 'lion tiger bear'
+ expected = 'lion tiger bear'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat'))
+ self.assertEqual(result, expected)
+
+ # partially quoted substring
+ input_str = 'lion "tiger bear'
+ expected = 'lion "tiger bear'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat'))
+ self.assertEqual(result, expected)
+
+ # one quoted substring
+ input_str = 'lion "tiger" bear'
+ expected = 'lion "cat" bear'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat'))
+ self.assertEqual(result, expected)
+
+ # two quoted substrings
+ input_str = 'lion "tiger" bear "shark" whale'
+ expected = 'lion "cat" bear "shark" whale'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat'))
+ self.assertEqual(result, expected)
+
+ # two quoted substrings, both replaced
+ input_str = 'lion "tiger" bear "shark" whale'
+ expected = 'lion "cat" bear "cat" whale'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _replace_quoted_with_value(input_str, 'cat', 2))
+ self.assertEqual(result, expected)
+
+ def test__get_tx_port(self):
+ # no data
+ input_data = {'section1': []}
+ expected = -1
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _get_tx_port('section1', input_data))
+ self.assertEqual(result, expected)
+
+ # data for other section
+ input_data = {
+ 'section1': [],
+ 'section2': [
+ ('rx port', '3'),
+ ('tx port', '4'),
+ ],
+ }
+ expected = -1
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _get_tx_port('section1', input_data))
+ self.assertEqual(result, expected)
+
+ # data for section
+ input_data['section1'] = section1 = [
+ ('rx port', '4', 'more', 432),
+ ('tx port', '3'),
+ ]
+ expected = 3
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _get_tx_port('section1', input_data))
+ self.assertEqual(result, expected)
+
+ # more data for section,
+ section1.extend([
+ ('rx port', '2'),
+ ('tx port', '1', 'and more', 234),
+ ])
+ expected = 1
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ _get_tx_port('section1', input_data))
+ self.assertEqual(result, expected)
+
+ # TODO(elfoley): Split this into several smaller tests
+ def test_write_prox_config(self):
+ input_data = {}
+ expected = ''
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ write_prox_config(input_data))
+ self.assertEqual(result, expected)
+
+ input_data = [
+ [
+ 'section1',
+ [],
+ ],
+ ]
+ expected = '[section1]'
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ write_prox_config(input_data))
+ self.assertEqual(result, expected)
+
+ input_data = [
+ [
+ 'section1',
+ [],
+ ],
+ [
+ 'section2',
+ [
+ ['key1', 'value1'],
+ ['__name__', 'not this one'],
+ ['key2', None],
+ ['key3', 234],
+ ['key4', 'multi-line\nvalue'],
+ ],
+ ],
+ ]
+ expected = os.linesep.join([
+ '[section1]',
+ '[section2]',
+ 'key1=value1',
+ 'key2',
+ 'key3=234',
+ 'key4=multi-line\n\tvalue',
+ ])
+ result = (prox_helpers.ProxDpdkVnfSetupEnvHelper.
+ write_prox_config(input_data))
+ self.assertEqual(result, expected)
+
+ def test_prox_config_data(self):
+ setup_helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
+
+ setup_helper.config_queue = config_queue = mock.MagicMock()
+ config_queue.get.return_value = expected = [('s', [('a', 3), ('b', 45)])]
+
+ result = setup_helper.prox_config_data
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(utils, 'find_relative_file')
+ def test_build_config_file_no_additional_file(self, mock_find_path):
+ vnf1 = {
+ 'prox_args': {'-c': ""},
+ 'prox_path': 'd',
+ 'prox_config': 'e/f',
+ 'prox_generate_parameter': False,
+ }
+
+ mock_find_path.side_effect = ['1', '2']
+
+ vnfd_helper = mock.MagicMock()
+ ssh_helper = mock.MagicMock()
+ scenario_helper = sample_vnf.ScenarioHelper('vnf1')
+ scenario_helper.scenario_cfg = {
+ 'task_path': 'a/b',
+ 'options': {
+ 'vnf1': vnf1,
+ },
+ }
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.copy_to_target = mock.MagicMock(return_value='3')
+ helper.generate_prox_config_file = mock.MagicMock(return_value='4')
+ helper.upload_prox_config = mock.MagicMock(return_value='5')
+
+ self.assertEqual(helper.additional_files, {})
+ self.assertNotEqual(helper._prox_config_data, '4')
+ self.assertNotEqual(helper.remote_path, '5')
+ helper.build_config_file()
+ self.assertEqual(helper.additional_files, {})
+ self.assertEqual(helper._prox_config_data, '4')
+ self.assertEqual(helper.remote_path, '5')
+
+ @mock.patch.object(utils, 'find_relative_file')
+ def test_build_config_file_additional_file_string(self, mock_find_path):
+ vnf1 = {
+ 'prox_args': {'-c': ""},
+ 'prox_path': 'd',
+ 'prox_config': 'e/f',
+ 'prox_files': 'g/h.i',
+ 'prox_generate_parameter': True,
+ }
+
+ mock_find_path.side_effect = ['1', '2']
+ vnfd_helper = mock.MagicMock()
+ ssh_helper = mock.MagicMock()
+ scenario_helper = sample_vnf.ScenarioHelper('vnf1')
+ scenario_helper.scenario_cfg = {
+ 'task_path': 'a/b',
+ 'options': {
+ 'vnf1': vnf1,
+ },
+ }
+
+ vnfd_helper.port_pairs.all_ports = ['xe0', 'xe1', 'xe2', 'xe3']
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.copy_to_target = mock.MagicMock(side_effect=['33', '34', '35'])
+ helper.generate_prox_config_file = mock.MagicMock(return_value='44')
+ helper.upload_prox_config = mock.MagicMock(return_value='55')
+
+ self.assertEqual(helper.additional_files, {})
+ expected = {'h.i': '33'}
+ helper.build_config_file()
+ self.assertDictEqual(helper.additional_files, expected)
+
+ @mock.patch.object(utils, 'find_relative_file')
+ def test_build_config_file_additional_file(self, mock_find_path):
+ vnf1 = {
+ 'prox_args': {'-c': ""},
+ 'prox_path': 'd',
+ 'prox_config': 'e/f',
+ 'prox_files': [
+ 'g/h.i',
+ 'j/k/l',
+ 'm_n',
+ ],
+ }
+
+ mock_find_path.side_effect = ['1', '2'] + [str(i) for i in range(len(vnf1['prox_files']))]
+ vnfd_helper = mock.MagicMock()
+ ssh_helper = mock.MagicMock()
+ scenario_helper = sample_vnf.ScenarioHelper('vnf1')
+ scenario_helper.scenario_cfg = {
+ 'task_path': 'a/b',
+ 'options': {
+ 'vnf1': vnf1,
+ },
+ }
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.copy_to_target = mock.MagicMock(side_effect=['33', '34', '35'])
+ helper.generate_prox_config_file = mock.MagicMock(return_value='44')
+ helper.upload_prox_config = mock.MagicMock(return_value='55')
+
+ self.assertEqual(helper.additional_files, {})
+ self.assertNotEqual(helper._prox_config_data, '44')
+ self.assertNotEqual(helper.remote_path, '55')
+ expected = {'h.i': '33', 'l': '34', 'm_n': '35'}
+ helper.build_config_file()
+ self.assertDictEqual(helper.additional_files, expected)
+ self.assertEqual(helper._prox_config_data, '44')
+ self.assertEqual(helper.remote_path, '55')
+
+ def test_build_config(self):
+ vnf1 = {
+ 'prox_args': {'-f': ""},
+ 'prox_path': '/opt/nsb_bin/prox',
+ 'prox_config': 'configs/gen_l2fwd-2.cfg',
+ 'prox_files': [
+ 'g/h.i',
+ 'j/k/l',
+ 'm_n',
+ ],
+ }
+
+ vnfd_helper = mock.Mock()
+ ssh_helper = mock.Mock()
+ ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/prox'
+ scenario_helper = sample_vnf.ScenarioHelper('vnf1')
+ scenario_helper.scenario_cfg = {
+ 'task_path': 'a/b',
+ 'options': {
+ 'vnf1': vnf1,
+ },
+ }
+
+ expected = ("sudo bash -c 'cd /opt/nsb_bin; /opt/nsb_bin/prox -o cli "
+ "-f -f /tmp/prox.cfg '")
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ with mock.patch.object(helper, 'build_config_file') as mock_cfg_file:
+ helper.remote_path = '/tmp/prox.cfg'
+ prox_cmd = helper.build_config()
+ self.assertEqual(prox_cmd, expected)
+ mock_cfg_file.assert_called_once()
+
+ def test__insert_additional_file(self):
+ vnfd_helper = mock.MagicMock()
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.additional_files = {"ipv4.lua": "/tmp/ipv4.lua"}
+ res = helper._insert_additional_file('dofile("ipv4.lua")')
+ self.assertEqual(res, 'dofile("/tmp/ipv4.lua")')
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ConfigParser')
+ def test_generate_prox_config_file(self, mock_parser_type):
+ def init(*args):
+ if sections_data:
+ args[-1].extend(sections_data)
+ return mock.MagicMock()
+
+ sections_data = []
+
+ mock_parser_type.side_effect = init
+
+ vnfd_helper = vnf_base.VnfdHelper(self.VNFD0)
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.additional_files = {}
+
+ expected = []
+ result = helper.generate_prox_config_file('a/b')
+ self.assertEqual(result, expected)
+
+ helper.additional_files = {"ipv4.lua": "/tmp/ipv4.lua"}
+
+ helper.remote_prox_file_name = 'remote'
+ sections_data = [
+ [
+ 'lua',
+ [
+ ['dofile("ipv4.lua")', ''],
+ ],
+ ],
+ [
+ 'port 0',
+ [
+ ['ip', ''],
+ ['mac', 'foo'],
+ ['dst mac', '@@1'],
+ ['tx port', '1'],
+ ],
+ ],
+ [
+ 'port 2',
+ [
+ ['ip', ''],
+ ['$sut_mac0', '@@dst_mac0'],
+ ['tx port', '0'],
+ ['single', '@'],
+ ['user_table', 'dofile("ipv4.lua")'],
+ ['missing_addtional_file', 'dofile("nosuch")'],
+ ],
+ ],
+ [
+ 'core 0',
+ [
+ ['name', 'p0']
+ ]
+ ],
+ [
+ 'core 1-4',
+ [
+ ['name', 'p1']
+ ]
+ ],
+ [
+ 'core 5,6',
+ [
+ ['name', 'p2']
+ ]
+ ],
+ [
+ 'core xx',
+ [
+ ['name', 'p3']
+ ]
+ ],
+ [
+ 'core $x',
+ [
+ ['name', 'p4']
+ ]
+ ]
+ ]
+
+ expected = [
+ [
+ 'lua',
+ [
+ ['dofile("/tmp/ipv4.lua")', ''],
+ ],
+ ],
+ [
+ 'port 0',
+ [
+ ['ip', ''],
+ ['mac', 'hardware'],
+ ['dst mac', '00:00:00:00:00:03'],
+ ['tx port', '1'],
+ ],
+ ],
+ [
+ 'port 2',
+ [
+ ['ip', ''],
+ ['$sut_mac0', '00 00 00 00 00 04'],
+ ['tx port', '0'],
+ ['single', '@'],
+ ['user_table', 'dofile("/tmp/ipv4.lua")'],
+ ['missing_addtional_file', 'dofile("nosuch")'],
+ ],
+ ],
+ [
+ 'core 0',
+ [
+ ['name', 'p0']
+ ]
+ ],
+ [
+ 'core 1',
+ [
+ ['name', 'p1']
+ ]
+ ],
+ [
+ 'core 2',
+ [
+ ['name', 'p1']
+ ]
+ ],
+ [
+ 'core 3',
+ [
+ ['name', 'p1']
+ ]
+ ],
+ [
+ 'core 4',
+ [
+ ['name', 'p1']
+ ]
+ ],
+ [
+ 'core 5',
+ [
+ ['name', 'p2']
+ ]
+ ],
+ [
+ 'core 6',
+ [
+ ['name', 'p2']
+ ]
+ ],
+ [
+ 'core $x',
+ [
+ ['name', 'p4']
+ ]
+ ]
+ ]
+ result = helper.generate_prox_config_file('/c/d/e')
+ self.assertEqual(result, expected, str(result))
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ConfigParser')
+ def test_generate_prox_config_file_negative(self, mock_parser_type):
+ def init(*args):
+ args[-1].update(sections_data)
+ return mock.MagicMock()
+
+ sections_data = {}
+
+ mock_parser_type.side_effect = init
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.interfaces = []
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.additional_files = {}
+ helper.remote_prox_file_name = 'remote'
+ vnfd_helper.interfaces = [
+ {
+ 'virtual-interface': {
+ 'dpdk_port_num': 3,
+ 'dst_mac': '00:00:00:de:ad:88',
+ },
+ },
+ {
+ 'virtual-interface': {
+ 'dpdk_port_num': 5,
+ 'dst_mac': '00:00:00:de:ad:ff',
+ },
+ },
+ {
+ 'virtual-interface': {
+ 'dpdk_port_num': 7,
+ 'dst_mac': '00:00:00:de:ad:ff',
+ },
+ },
+ ]
+ sections_data = {
+ 'port 3': [
+ ['ip', ''],
+ ['mac', 'foo'],
+ ['dst mac', ''],
+ ],
+ 'port 5': [
+ ['ip', ''],
+ ['dst mac', ''],
+ ['tx port', '0'],
+ ['???', 'dofile "here" 23'],
+ ],
+ }
+
+ with self.assertRaises(Exception):
+ helper.generate_prox_config_file('a/b')
+
+ def test_put_string_to_file(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.interfaces = []
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+
+ expected = 'a/b'
+ result = helper.put_string_to_file('my long string', 'a/b')
+ self.assertEqual(result, expected)
+
+ def test_copy_to_target(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.interfaces = []
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ expected = '/tmp/c'
+ result = helper.copy_to_target('a/b', 'c')
+ self.assertEqual(result, expected)
+
+ def test_upload_prox_config(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.interfaces = []
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.MagicMock()
+
+ helper = prox_helpers.ProxDpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ helper.write_prox_config = mock.MagicMock(return_value='a long string')
+ expected = '/tmp/a'
+ result = helper.upload_prox_config('a', {})
+ self.assertEqual(result, expected)
+
+
+class TestProxResourceHelper(unittest.TestCase):
+
+ VNFD0 = {
+ 'short-name': 'ProxVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'name': 'proxvnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'proxvnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'uplink_0',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.19',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'downlink_0',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'proxvnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'id': 'ProxApproxVnf',
+ 'name': 'ProxVnf',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD0,
+ ],
+ },
+ }
+
+ def test_find_pci(self):
+ input_str_list = [
+ 'no target here',
+ 'nor here',
+ 'and still not',
+ ]
+ result = prox_helpers.ProxResourceHelper.find_pci('target',
+ input_str_list)
+ self.assertFalse(result)
+
+ input_str_list = [
+ 'no target here',
+ 'nor here',
+ 'this is a target',
+ 'did we miss it',
+ ]
+ result = prox_helpers.ProxResourceHelper.find_pci('target',
+ input_str_list)
+ self.assertTrue(result)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.RETRY_INTERVAL', 0)
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ProxSocketHelper')
+ def test_sut(self, *args):
+ helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+ self.assertIsNone(helper.client)
+ result = helper.sut
+ self.assertIsNotNone(result)
+ self.assertIs(result, helper.client)
+ self.assertIs(result, helper.sut)
+
+ def test_test_type(self):
+ setup_helper = mock.MagicMock()
+ setup_helper.find_in_section.return_value = expected = 'prox type'
+
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+
+ self.assertIsNone(helper._test_type)
+ self.assertEqual(helper.test_type, expected)
+ self.assertEqual(helper._test_type, expected)
+ self.assertEqual(helper.test_type, expected)
+
+ def test_collect_collectd_kpi(self):
+ helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+ helper.resource = resource = mock.MagicMock()
+
+ resource.check_if_system_agent_running.return_value = 0, '1234'
+ resource.amqp_collect_nfvi_kpi.return_value = 543
+ resource.check_if_system_agent_running.return_value = (0, None)
+
+ expected = {'core': 543}
+ result = helper.collect_collectd_kpi()
+ self.assertDictEqual(result, expected)
+
+ def test_collect_kpi(self):
+ helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+ helper._queue = queue = mock.MagicMock()
+ helper._result = {'z': 123}
+
+ helper.client = mock.MagicMock()
+ helper.client.hz.return_value = 1
+ helper.client.multi_port_stats.return_value = \
+ (True, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+ helper.client.multi_port_stats_diff.return_value = \
+ ([0, 1, 2, 3, 4, 5, 6, 7])
+ helper.client.multi_port_stats_tuple.return_value = \
+ {"xe0": {"in_packets": 1, "out_packets": 2}}
+ helper.resource = resource = mock.MagicMock()
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+ helper.vnfd_helper = vnfd_helper
+
+ resource.check_if_system_agent_running.return_value = 0, '1234'
+ resource.amqp_collect_nfvi_kpi.return_value = 543
+ resource.check_if_system_agent_running.return_value = (0, None)
+
+ queue.empty.return_value = False
+ queue.get.return_value = {'a': 789}
+
+ expected = {'z': 123, 'a': 789,
+ 'collect_stats': {'core': 543},
+ 'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}}
+ result = helper.collect_kpi()
+ self.assertDictEqual(result, expected)
+
+ def test_collect_kpi_no_hz(self):
+ helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+ helper._queue = queue = mock.MagicMock()
+ helper._result = {'z': 123}
+
+ helper.client = mock.MagicMock()
+ helper.client.multi_port_stats.return_value = \
+ (True, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+ helper.client.multi_port_stats_diff.return_value = \
+ ([0, 1, 2, 3, 4, 5, 6, 7])
+ helper.client.multi_port_stats_tuple.return_value = \
+ {"xe0": {"in_packets": 1, "out_packets": 2}}
+ helper.resource = resource = mock.MagicMock()
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+ helper.vnfd_helper = vnfd_helper
+
+ resource.check_if_system_agent_running.return_value = 0, '1234'
+ resource.amqp_collect_nfvi_kpi.return_value = 543
+ resource.check_if_system_agent_running.return_value = (0, None)
+
+ queue.empty.return_value = False
+ queue.get.return_value = {'a': 789}
+
+ expected = {'z': 123, 'a': 789,
+ 'collect_stats': {'core': 543},
+ 'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}}
+ result = helper.collect_kpi()
+ self.assertDictEqual(result, expected)
+
+ def test_collect_kpi_bad_data(self):
+ helper = prox_helpers.ProxResourceHelper(mock.MagicMock())
+ helper._queue = queue = mock.MagicMock()
+ helper._result = {'z': 123}
+
+ helper.client = mock.MagicMock()
+ helper.client.multi_port_stats.return_value = \
+ (False, [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+ helper.client.multi_port_stats_diff.return_value = \
+ ([0, 1, 2, 3, 4, 5, 6, 7])
+ helper.client.multi_port_stats_tuple.return_value = \
+ {"xe0": {"in_packets": 1, "out_packets": 2}}
+ helper.resource = resource = mock.MagicMock()
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+ helper.vnfd_helper = vnfd_helper
+
+ resource.check_if_system_agent_running.return_value = 0, '1234'
+ resource.amqp_collect_nfvi_kpi.return_value = 543
+ resource.check_if_system_agent_running.return_value = (0, None)
+
+ queue.empty.return_value = False
+ queue.get.return_value = {'a': 789}
+
+ expected = {'z': 123, 'a': 789,
+ 'collect_stats': {'core': 543}}
+ result = helper.collect_kpi()
+ self.assertDictEqual(result, expected)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.ProxSocketHelper')
+ def test__connect(self, mock_socket_helper_type, *args):
+ client = mock_socket_helper_type()
+ client.connect.side_effect = chain(repeat(socket.error, 5), [None])
+
+ setup_helper = mock.MagicMock()
+ setup_helper.vnfd_helper.interfaces = []
+
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+
+ result = helper._connect()
+ self.assertIs(result, client)
+
+ client.connect.side_effect = chain(repeat(socket.error, 65), [None])
+
+ with self.assertRaises(Exception):
+ helper._connect()
+
+ def test_run_traffic(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ traffic_profile = mock.MagicMock()
+ traffic_profile.done.is_set.return_value = True
+ helper.run_traffic(traffic_profile)
+ self.assertEqual(helper._terminated.value, 1)
+
+ def test__run_traffic_once(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ traffic_profile = mock.MagicMock()
+ traffic_profile.done.is_set.return_value = True
+ helper._run_traffic_once(traffic_profile)
+ self.assertEqual(helper._terminated.value, 1)
+
+ def test_start_collect(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ helper.resource = resource = mock.MagicMock()
+ self.assertIsNone(helper.start_collect())
+ resource.start.assert_called_once()
+
+ def test_terminate(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ with self.assertRaises(NotImplementedError):
+ helper.terminate()
+
+ def test_up_post(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ helper.client = expected = mock.MagicMock()
+ result = helper.up_post()
+ self.assertEqual(result, expected)
+
+ def test_execute(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxResourceHelper(setup_helper)
+ helper.client = mock.MagicMock()
+
+ expected = helper.client.my_command()
+ result = helper.execute('my_command')
+ self.assertEqual(result, expected)
+
+ # TODO(elfoley): Make this a separate test: test_execute_no_client
+ helper.client = object()
+
+ result = helper.execute('my_command')
+ self.assertIsNone(result)
+
+
+class TestProxDataHelper(unittest.TestCase):
+
+ def test_totals_and_pps(self):
+ pkt_size = 180
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = list(range(4))
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True,
+ [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5],
+ [2, 1, 2, 3, 4, 5], [3, 1, 2, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, pkt_size, 25, None,
+ constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertEqual(data_helper.rx_total, 4)
+ self.assertEqual(data_helper.tx_total, 8)
+ self.assertEqual(data_helper.requested_pps, 6250000.0)
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = [3, 4]
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True,
+ [[3, 1, 2, 3, 4, 5], [4, 1, 2, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, pkt_size, 25, None,
+ constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertEqual(data_helper.rx_total, 2)
+ self.assertEqual(data_helper.tx_total, 4)
+ self.assertEqual(data_helper.requested_pps, 3125000.0)
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = [0, 1, 2, 3, 4, 6, 7]
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True,
+ [[8, 1, 2, 3, 4, 5], [9, 1, 2, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, pkt_size, 25, None,
+ constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertEqual(data_helper.rx_total, 2)
+ self.assertEqual(data_helper.tx_total, 4)
+ self.assertEqual(data_helper.requested_pps, 10937500.0)
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = []
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True,
+ [[8, 1, 2, 3, 4, 5], [9, 1, 2, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, pkt_size, 25, None,
+ constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertEqual(data_helper.rx_total, 2)
+ self.assertEqual(data_helper.tx_total, 4)
+ self.assertEqual(data_helper.requested_pps, 0.0)
+
+ def test_totals_and_pps2(self):
+ pkt_size = 180
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = list(range(4))
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True,
+ [[0, 'A', 2, 3, 4, 5], [1, 'B', 'C', 3, 4, 5],
+ ['D', 1, 2, 3, 4, 5], [3, 1, 2, 3, 4, 'F']])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, pkt_size, 25, None,
+ constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertEqual(data_helper.rx_total, 0)
+ self.assertEqual(data_helper.tx_total, 0)
+ self.assertEqual(data_helper.requested_pps, 0)
+
+ def test_samples(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True, [[0, 1, 2, 3, 4, 5], [1, 11, 12, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, None, None, None, None)
+
+ expected = {
+ 'xe0': {
+ 'in_packets': 1,
+ 'out_packets': 2,
+ },
+ 'xe1': {
+ 'in_packets': 11,
+ 'out_packets': 12,
+ },
+ }
+ result = data_helper.samples
+ self.assertDictEqual(result, expected)
+
+ def test_samples2(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe1', 3), ('xe2', 7)]
+
+ sut = mock.MagicMock()
+ sut.multi_port_stats.return_value = (True, [[3, 1, 2, 3, 4, 5], [7, 11, 12, 3, 4, 5]])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, None, None, None, None)
+
+ expected = {
+ 'xe1': {
+ 'in_packets': 1,
+ 'out_packets': 2,
+ },
+ 'xe2': {
+ 'in_packets': 11,
+ 'out_packets': 12,
+ },
+ }
+ result = data_helper.samples
+ self.assertDictEqual(result, expected)
+
+ def test___enter__(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = list(range(4))
+ vnfd_helper.ports_iter.return_value = [('xe1', 3), ('xe2', 7)]
+
+ sut = mock.MagicMock()
+
+ data_helper = prox_helpers.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': prox_helpers.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 = prox_helpers.ProxTestDataTuple(
+ 5.4, 9.8, 6.1, 6.2, 6.3, 7, 12, 32, 4.5)
+ with data_helper:
+ pass
+
+ result = data_helper.result_tuple
+ self.assertEqual(result, expected)
+
+ data_helper.make_tuple()
+ self.assertIs(data_helper.result_tuple, result)
+
+ def test___enter___negative(self):
+ vnfd_helper = mock.MagicMock()
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, None, None, None, None, None)
+
+ vnfd_helper.port_pairs.all_ports = []
+ with self.assertRaises(AssertionError):
+ with data_helper:
+ pass
+
+ vnfd_helper.port_pairs.all_ports = [0, 1, 2]
+ with self.assertRaises(AssertionError):
+ with data_helper:
+ pass
+
+ def test_measure_tot_stats(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = list(range(4))
+
+ start = (3, 4, 1, 2)
+ end = (9, 7, 6, 8)
+
+ sut = prox_helpers.ProxSocketHelper(mock.MagicMock())
+ sut.get_all_tot_stats = mock.MagicMock(side_effect=[start, end])
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, None, None, 5.4, None)
+
+ self.assertIsNone(data_helper.measured_stats)
+
+ expected = {
+ 'start_tot': start,
+ 'end_tot': end,
+ 'delta': prox_helpers.TotStatsTuple(6, 3, 5, 6),
+ }
+ with data_helper.measure_tot_stats():
+ pass
+
+ self.assertEqual(data_helper.measured_stats, expected)
+
+ def test_capture_tsc_hz(self):
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.port_pairs.all_ports = list(range(4))
+
+ sut = mock.MagicMock()
+ sut.hz.return_value = '54.6'
+
+ data_helper = prox_helpers.ProxDataHelper(
+ vnfd_helper, sut, None, None, None, None)
+
+ self.assertIsNone(data_helper.tsc_hz)
+
+ expected = 54.6
+ data_helper.capture_tsc_hz()
+ self.assertEqual(data_helper.tsc_hz, expected)
+
+
+class TestProxProfileHelper(unittest.TestCase):
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.utils')
+ def test_get_cls(self, mock_utils):
+ mock_type1 = mock.MagicMock()
+ mock_type1.__prox_profile_type__ = 'another_type'
+ mock_type2 = mock.MagicMock()
+ mock_type2.__prox_profile_type__ = 'my_type'
+ mock_utils.itersubclasses.return_value = [mock_type1, mock_type2]
+
+ self.assertEqual(prox_helpers.ProxProfileHelper.get_cls('my_type'),
+ mock_type2)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.utils')
+ def test_get_cls_default(self, mock_utils):
+ mock_utils.itersubclasses.return_value = []
+ prox_helpers.ProxProfileHelper.get_cls('my_type')
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.SocketTopology')
+ def test_cpu_topology(self, mock_socket_topology):
+ mock_socket_topology.parse_cpuinfo.return_value = 432
+
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.ssh_helper.execute.return_value = 0, 'output', ''
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ self.assertIsNone(helper._cpu_topology)
+ result = helper.cpu_topology
+ self.assertEqual(result, 432)
+ self.assertIs(result, helper._cpu_topology)
+ self.assertIs(result, helper.cpu_topology)
+
+ # TODO(elfoley): Split this test; there are two sets of inputs/outputs
+ def test_test_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = []
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._cpu_topology = []
+
+ expected = []
+ result = helper.test_cores
+ self.assertEqual(result, expected)
+
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1s3', []),
+ ('core 2s5', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3s1', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ]),
+ ('core 4s9h', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 1: {
+ 3: {
+ 'key1': (23, 32),
+ 'key2': (12, 21),
+ 'key3': (44, 33),
+ },
+ },
+ 9: {
+ 4: {
+ 'key1': (44, 32),
+ 'key2': (23, 21),
+ 'key3': (12, 33),
+ },
+ },
+ }
+
+ self.assertIsNone(helper._test_cores)
+ expected = [3, 4]
+ result = helper.test_cores
+ self.assertEqual(result, expected)
+ self.assertIs(result, helper._test_cores)
+ self.assertIs(result, helper.test_cores)
+
+ # TODO(elfoley): Split this test; there are two sets of inputs/outputs
+ def test_latency_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = []
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._cpu_topology = []
+
+ expected = []
+ result = helper.latency_cores
+ self.assertEqual(result, expected)
+
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1s3', []),
+ ('core 2s5', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3s1', [
+ ('index', 5),
+ ('mode', 'lat'),
+ ]),
+ ('core 4s9h', [
+ ('index', 7),
+ ('mode', 'lat'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 1: {
+ 3: {
+ 'key1': (23, 32),
+ 'key2': (12, 21),
+ 'key3': (44, 33),
+ },
+ },
+ 9: {
+ 4: {
+ 'key1': (44, 32),
+ 'key2': (23, 21),
+ 'key3': (12, 33),
+ },
+ },
+ }
+
+ self.assertIsNone(helper._latency_cores)
+ expected = [3, 4]
+ result = helper.latency_cores
+ self.assertEqual(result, expected)
+ self.assertIs(result, helper._latency_cores)
+ self.assertIs(result, helper.latency_cores)
+
+ def test_all_rx_cores(self):
+ helper = prox_helpers.ProxBngProfileHelper(mock.MagicMock())
+ helper._latency_cores = expected = [3, 4, 6]
+ helper._test_cores = [5, 2, 1]
+
+ result = helper.all_rx_cores
+ self.assertEqual(result, expected)
+
+ def test_get_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ }
+ }
+
+ expected = [3, 4]
+ result = helper.get_cores(helper.PROX_CORE_GEN_MODE)
+ self.assertEqual(result, expected)
+
+ def test_get_latency(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.vnfd_helper.interfaces = []
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+ helper._latency_cores = []
+
+ expected = []
+ result = helper.get_latency()
+ self.assertEqual(result, expected)
+
+ helper._latency_cores = [1, 2]
+ helper.client = mock.MagicMock()
+
+ expected = helper.sut.lat_stats()
+ result = helper.get_latency()
+ self.assertIs(result, expected)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
+ def test_traffic_context(self, *args):
+ setup_helper = mock.MagicMock()
+ setup_helper.vnfd_helper.interfaces = []
+
+ helper = prox_helpers.ProxProfileHelper(setup_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ }
+ }
+
+ setup_helper.prox_config_data = [
+ ('global', [
+ ('not_name', 'other data'),
+ ('name_not', 'more data'),
+ ('name', helper.__prox_profile_type__),
+ ]),
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'tagged'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'udp'),
+ ]),
+ ]
+
+ client = mock.MagicMock()
+ client.hz.return_value = 2
+
+ helper.client = client
+ helper.get_latency = mock.MagicMock(return_value=[3.3, 3.6, 3.8])
+
+ helper._test_cores = [3, 4]
+
+ with helper.traffic_context(64, 1):
+ pass
+
+ @mock.patch.object(time, 'sleep')
+ def test_run_test(self, *args):
+ resource_helper = mock.MagicMock()
+ resource_helper.step_delta = 0.4
+ resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
+ resource_helper.sut.multi_port_stats.return_value = (True, [[0, 1, 1, 2, 4, 5],
+ [1, 1, 2, 3, 4, 5]])
+
+ helper = prox_helpers.ProxProfileHelper(resource_helper)
+
+ helper.run_test(pkt_size=120, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+ self.assertTrue(resource_helper.sut.multi_port_stats.called)
+ self.assertTrue(resource_helper.sut.stop_all.called)
+ self.assertTrue(resource_helper.sut.reset_stats.called)
+
+class TestProxMplsProfileHelper(unittest.TestCase):
+
+ def test_mpls_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'tagged'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'udp'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxMplsProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ }
+ }
+
+ expected_tagged = [3]
+ expected_plain = [4]
+ self.assertIsNone(helper._cores_tuple)
+ self.assertEqual(helper.tagged_cores, expected_tagged)
+ self.assertEqual(helper.plain_cores, expected_plain)
+ self.assertEqual(helper._cores_tuple, (expected_tagged, expected_plain))
+
+ def test_traffic_context(self):
+ setup_helper = mock.MagicMock()
+ helper = prox_helpers.ProxMplsProfileHelper(setup_helper)
+
+ with helper.traffic_context(120, 5.4):
+ pass
+
+
+class TestProxBngProfileHelper(unittest.TestCase):
+
+ def test_bng_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'cpe'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'inet'),
+ ]),
+ ('core 6', [
+ ('index', 3),
+ ('mode', 'gen'),
+ ('name', 'arp_task'),
+ ]),
+ ('core 9', [
+ ('index', 2),
+ ('mode', 'gen'),
+ ('name', 'arp'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxBngProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ 6: {
+ 1: (4, 8, 0)
+ },
+ 9: {
+ 2: (3, 7, 0)
+ },
+ }
+ }
+
+ expected_cpe = [3]
+ expected_inet = [4]
+ expected_arp = [6, 9]
+ expected_arp_task = [0, 6]
+ expected_combined = (expected_cpe, expected_inet, expected_arp, expected_arp_task)
+
+ self.assertIsNone(helper._cores_tuple)
+ self.assertEqual(helper.cpe_cores, expected_cpe)
+ self.assertEqual(helper.inet_cores, expected_inet)
+ self.assertEqual(helper.arp_cores, expected_arp)
+ self.assertEqual(helper.arp_task_cores, expected_arp_task)
+ self.assertEqual(helper._cores_tuple, expected_combined)
+
+ @mock.patch.object(time, 'sleep')
+ def test_run_test(self, *args):
+ resource_helper = mock.MagicMock()
+ resource_helper.step_delta = 0.4
+ resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
+ resource_helper.sut.multi_port_stats.return_value = (True, [[0, 1, 1, 2, 4, 5],
+ [1, 1, 2, 3, 4, 5]])
+
+ helper = prox_helpers.ProxBngProfileHelper(resource_helper)
+
+ helper.run_test(pkt_size=120, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+ self.assertTrue(resource_helper.sut.multi_port_stats.called)
+ self.assertTrue(resource_helper.sut.stop_all.called)
+ self.assertTrue(resource_helper.sut.reset_stats.called)
+
+ resource_helper.reset_mock()
+
+ # negative pkt_size is the only way to make ratio > 1
+ helper.run_test(pkt_size=-1000, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ self.assertTrue(resource_helper.sut.multi_port_stats.called)
+ self.assertTrue(resource_helper.sut.stop_all.called)
+ self.assertTrue(resource_helper.sut.reset_stats.called)
+
+class TestProxVpeProfileHelper(unittest.TestCase):
+
+ def test_vpe_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'cpe'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'inet'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ }
+ }
+
+ expected_cpe = [3]
+ expected_inet = [4]
+ expected_combined = (expected_cpe, expected_inet)
+
+ self.assertIsNone(helper._cores_tuple)
+ self.assertEqual(helper.cpe_cores, expected_cpe)
+ self.assertEqual(helper.inet_cores, expected_inet)
+ self.assertEqual(helper._cores_tuple, expected_combined)
+
+ def test_vpe_ports(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('port 3', [
+ ('index', '5'),
+ ('name', 'cpe'),
+ ('mac', 'hardware'),
+ ]),
+ ('port 4', [
+ ('index', '7'),
+ ('name', 'inet'),
+ ('mac', 'hardware'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
+ helper._port_list = {
+ 0: {
+ 1: {
+ 5: 'cpe'
+ },
+ 2: {
+ 6: 'inet'
+ },
+ 3: {
+ 7: 'cpe'
+ },
+ 4: {
+ 8: 'inet'
+ },
+ }
+ }
+
+ expected_cpe = [3]
+ expected_inet = [4]
+ expected_combined = (expected_cpe, expected_inet)
+
+ self.assertIsNone(helper._ports_tuple)
+ self.assertEqual(helper.cpe_ports, expected_cpe)
+ self.assertEqual(helper.inet_ports, expected_inet)
+ self.assertEqual(helper._ports_tuple, expected_combined)
+
+ @mock.patch.object(time, 'sleep')
+ def test_run_test(self, *args):
+ resource_helper = mock.MagicMock()
+ resource_helper.step_delta = 0.4
+ resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
+ resource_helper.sut.multi_port_stats.return_value = (True, [[0, 1, 1, 2, 4, 5],
+ [1, 1, 2, 3, 4, 5]])
+
+ helper = prox_helpers.ProxVpeProfileHelper(resource_helper)
+
+ helper.run_test(pkt_size=120, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ # negative pkt_size is the only way to make ratio > 1
+ helper.run_test(pkt_size=-1000, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+class TestProxlwAFTRProfileHelper(unittest.TestCase):
+
+ def test_lwaftr_cores(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('core 1', []),
+ ('core 2', [
+ ('index', 8),
+ ('mode', ''),
+ ]),
+ ('core 3', [
+ ('index', 5),
+ ('mode', 'gen'),
+ ('name', 'tun'),
+ ]),
+ ('core 4', [
+ ('index', 7),
+ ('mode', 'gen'),
+ ('name', 'inet'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
+ helper._cpu_topology = {
+ 0: {
+ 1: {
+ 5: (5, 1, 0)
+ },
+ 2: {
+ 6: (6, 2, 0)
+ },
+ 3: {
+ 7: (7, 3, 0)
+ },
+ 4: {
+ 8: (8, 3, 0)
+ },
+ }
+ }
+
+ expected_tun = [3]
+ expected_inet = [4]
+ expected_combined = (expected_tun, expected_inet)
+
+ self.assertIsNone(helper._cores_tuple)
+ self.assertEqual(helper.tun_cores, expected_tun)
+ self.assertEqual(helper.inet_cores, expected_inet)
+ self.assertEqual(helper._cores_tuple, expected_combined)
+
+ def test_tun_ports(self):
+ resource_helper = mock.MagicMock()
+ resource_helper.setup_helper.prox_config_data = [
+ ('section1', []),
+ ('section2', [
+ ('a', 'b'),
+ ('c', 'd'),
+ ]),
+ ('port 3', [
+ ('index', '5'),
+ ('name', 'lwB4'),
+ ('mac', 'hardware'),
+ ]),
+ ('port 4', [
+ ('index', '7'),
+ ('name', 'inet'),
+ ('mac', 'hardware'),
+ ]),
+ ]
+
+ helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
+ helper._port_list = {
+ 0: {
+ 1: {
+ 5: 'lwB4'
+ },
+ 2: {
+ 6: 'inet'
+ },
+ 3: {
+ 7: 'lwB4'
+ },
+ 4: {
+ 8: 'inet'
+ },
+ }
+ }
+
+ expected_tun = [3]
+ expected_inet = [4]
+ expected_combined = (expected_tun, expected_inet)
+
+ self.assertIsNone(helper._ports_tuple)
+ self.assertEqual(helper.tun_ports, expected_tun)
+ self.assertEqual(helper.inet_ports, expected_inet)
+ self.assertEqual(helper._ports_tuple, expected_combined)
+
+ @mock.patch.object(time, 'sleep')
+ def test_run_test(self, *args):
+ resource_helper = mock.MagicMock()
+ resource_helper.step_delta = 0.4
+ resource_helper.vnfd_helper.port_pairs.all_ports = list(range(2))
+ resource_helper.sut.multi_port_stats.return_value = (True, [[0, 1, 2, 4, 6, 5],
+ [1, 1, 2, 3, 4, 5]])
+
+ helper = prox_helpers.ProxlwAFTRProfileHelper(resource_helper)
+
+ helper.run_test(pkt_size=120, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+ # negative pkt_size is the only way to make ratio > 1
+ helper.run_test(pkt_size=-1000, duration=5, value=6.5, tolerated_loss=0.0,
+ line_speed=constants.NIC_GBPS_DEFAULT * constants.ONE_GIGABIT_IN_BITS)
+
+
+class TestProxIrqProfileHelper(unittest.TestCase):
+
+ def test_run_test(self, *args):
+ resource_helper = mock.MagicMock()
+ helper = prox_helpers.ProxIrqProfileHelper(resource_helper)
+ self.assertIsNone(helper._cores_tuple)
+ self.assertIsNone(helper._ports_tuple)
+ self.assertIsNone(helper._latency_cores)
+ self.assertIsNone(helper._test_cores)
+ self.assertIsNone(helper._cpu_topology)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py
new file mode 100644
index 000000000..94197c3be
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_irq.py
@@ -0,0 +1,828 @@
+# Copyright (c) 2017-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.
+
+import unittest
+import mock
+import errno
+
+from yardstick.tests import STL_MOCKS
+from yardstick.common import exceptions as y_exceptions
+from yardstick.network_services.vnf_generic.vnf.prox_irq import ProxIrqGen
+from yardstick.network_services.vnf_generic.vnf.prox_irq import ProxIrqVNF
+from yardstick.benchmark.contexts import base as ctx_base
+
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.vnf_generic.vnf import prox_vnf
+ from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+
+VNF_NAME = "vnf__1"
+
+class TestProxIrqVNF(unittest.TestCase):
+
+ SCENARIO_CFG = {
+ 'task_path': "",
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'runner': {
+ 'duration': 600, 'type': 'Duration'},
+ 'topology': 'prox-tg-topology-2.yaml',
+ 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml',
+ 'type': 'NSPerf',
+ 'options': {
+ 'tg__1': {'prox_args': {'-e': '',
+ '-t': ''},
+ 'prox_config': 'configs/l3-gen-2.cfg',
+ 'prox_path':
+ '/root/dppd-PROX-v035/build/prox'},
+ 'vnf__1': {
+ 'prox_args': {'-t': ''},
+ 'prox_config': 'configs/l3-swap-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'}}}
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ]
+ }
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__2': {
+ 'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens513f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root',
+ },
+ 'tg__1': {
+ 'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens785f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root',
+ },
+ 'vnf__1': {
+ 'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens786f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens786f1',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'password': 'r00t',
+ 'VNF model': 'prox_vnf.yaml',
+ },
+ },
+ }
+
+ def test___init__(self):
+ prox_irq_vnf = ProxIrqVNF('vnf1', self.VNFD_0)
+
+ self.assertEqual(prox_irq_vnf.name, 'vnf1')
+ self.assertDictEqual(prox_irq_vnf.vnfd_helper, self.VNFD_0)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ resource_helper = mock.MagicMock()
+
+ resource_helper = mock.MagicMock()
+
+ core_1 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5,
+ 'bucket_6': 6, 'bucket_7': 7, 'bucket_8': 8, 'bucket_9': 9, 'bucket_10': 10,
+ 'bucket_11': 11, 'bucket_12': 12, 'bucket_0': 100, 'cpu': 1, 'max_irq': 12,
+ 'overflow': 10}
+ core_2 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5,
+ 'bucket_6': 0, 'bucket_7': 0, 'bucket_8': 0, 'bucket_9': 0, 'bucket_10': 0,
+ 'bucket_11': 0, 'bucket_12': 0, 'bucket_0': 100, 'cpu': 2, 'max_irq': 12,
+ 'overflow': 10}
+
+ irq_data = {'core_1': core_1, 'core_2': core_2}
+ resource_helper.execute.return_value = (irq_data)
+
+ build_config_file = mock.MagicMock()
+ build_config_file.return_value = None
+
+ prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd)
+
+ startup = ["global", [["eal", "-4"]]]
+ master_0 = ["core 0", [["mode", "master"]]]
+ core_1 = ["core 1", [["mode", "irq"]]]
+ core_2 = ["core 2", [["mode", "irq"], ["task", "2"]]]
+
+ prox_irq_vnf.setup_helper._prox_config_data = \
+ [startup, master_0, core_1, core_2]
+
+ prox_irq_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ prox_irq_vnf.resource_helper = resource_helper
+ prox_irq_vnf.setup_helper.build_config_file = build_config_file
+
+ result = prox_irq_vnf.collect_kpi()
+ self.assertDictEqual(result["collect_stats"], {})
+
+ result = prox_irq_vnf.collect_kpi()
+ self.assertFalse('bucket_10' in result["collect_stats"]['core_2'])
+ self.assertFalse('bucket_11' in result["collect_stats"]['core_2'])
+ self.assertFalse('bucket_12' in result["collect_stats"]['core_2'])
+ self.assertEqual(result["collect_stats"]['core_2']['max_irq'], 12)
+
+
+ @mock.patch(SSH_HELPER)
+ def test_vnf_execute_oserror(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd)
+ prox_irq_vnf.resource_helper = resource_helper = mock.Mock()
+
+ resource_helper.execute.side_effect = OSError(errno.EPIPE, "")
+ prox_irq_vnf.vnf_execute("", _ignore_errors=True)
+
+ resource_helper.execute.side_effect = OSError(errno.ESHUTDOWN, "")
+ prox_irq_vnf.vnf_execute("", _ignore_errors=True)
+
+ resource_helper.execute.side_effect = OSError(errno.EADDRINUSE, "")
+ with self.assertRaises(OSError):
+ prox_irq_vnf.vnf_execute("", _ignore_errors=True)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+
+ mock_ssh(ssh, exec_result=(1, "", ""))
+ prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd)
+
+ prox_irq_vnf._terminated = mock.MagicMock()
+ prox_irq_vnf._traffic_process = mock.MagicMock()
+ prox_irq_vnf._traffic_process.terminate = mock.Mock()
+ prox_irq_vnf.ssh_helper = mock.MagicMock()
+ prox_irq_vnf.setup_helper = mock.MagicMock()
+ prox_irq_vnf.resource_helper = mock.MagicMock()
+ prox_irq_vnf._vnf_wrapper.setup_helper = mock.MagicMock()
+ prox_irq_vnf._vnf_wrapper._vnf_process = mock.MagicMock(**{"is_alive.return_value": False})
+ prox_irq_vnf._vnf_wrapper.resource_helper = mock.MagicMock()
+
+ prox_irq_vnf._run_prox = mock.Mock(return_value=0)
+ prox_irq_vnf.q_in = mock.Mock()
+ prox_irq_vnf.q_out = mock.Mock()
+
+ self.assertIsNone(prox_irq_vnf.terminate())
+
+ @mock.patch(SSH_HELPER)
+ def test_wait_for_instantiate_panic(self, ssh, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+
+ mock_ssh(ssh, exec_result=(1, "", ""))
+ prox_irq_vnf = ProxIrqVNF(VNF_NAME, vnfd)
+
+ prox_irq_vnf._terminated = mock.MagicMock()
+ prox_irq_vnf._traffic_process = mock.MagicMock()
+ prox_irq_vnf._traffic_process.terminate = mock.Mock()
+ prox_irq_vnf.ssh_helper = mock.MagicMock()
+ prox_irq_vnf.setup_helper = mock.MagicMock()
+ prox_irq_vnf.resource_helper = mock.MagicMock()
+ prox_irq_vnf._vnf_wrapper.setup_helper = mock.MagicMock()
+ prox_irq_vnf._vnf_wrapper._vnf_process = mock.MagicMock(**{"is_alive.return_value": False})
+ prox_irq_vnf._vnf_wrapper.resource_helper = mock.MagicMock()
+
+ prox_irq_vnf._run_prox = mock.Mock(return_value=0)
+ prox_irq_vnf.q_in = mock.Mock()
+ prox_irq_vnf.q_out = mock.Mock()
+ prox_irq_vnf.WAIT_TIME = 0
+ with self.assertRaises(RuntimeError):
+ prox_irq_vnf.wait_for_instantiate()
+
+class TestProxIrqGen(unittest.TestCase):
+
+ SCENARIO_CFG = {
+ 'task_path': "",
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'runner': {
+ 'duration': 600, 'type': 'Duration'},
+ 'topology': 'prox-tg-topology-2.yaml',
+ 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml',
+ 'type': 'NSPerf',
+ 'options': {
+ 'tg__1': {'prox_args': {'-e': '',
+ '-t': ''},
+ 'prox_config': 'configs/l3-gen-2.cfg',
+ 'prox_path':
+ '/root/dppd-PROX-v035/build/prox'},
+ 'vnf__1': {
+ 'prox_args': {'-t': ''},
+ 'prox_config': 'configs/l3-swap-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'}}}
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'driver': 'i40e',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'driver': 'ixgbe',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__2': {
+ 'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens513f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root',
+ },
+ 'tg__1': {
+ 'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens785f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root',
+ },
+ 'vnf__1': {
+ 'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens786f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens786f1',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'password': 'r00t',
+ 'VNF model': 'prox_vnf.yaml',
+ },
+ },
+ }
+
+
+ def test__check_status(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+
+ with self.assertRaises(NotImplementedError):
+ prox_irq_gen._check_status()
+
+ def test_listen_traffic(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+
+ prox_irq_gen.listen_traffic(mock.Mock())
+
+ def test_verify_traffic(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+
+ prox_irq_gen.verify_traffic(mock.Mock())
+
+ mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ prox_traffic_gen = ProxIrqGen(VNF_NAME, vnfd)
+ prox_traffic_gen._terminated = mock.MagicMock()
+ prox_traffic_gen._traffic_process = mock.MagicMock()
+ prox_traffic_gen._traffic_process.terminate = mock.Mock()
+ prox_traffic_gen.ssh_helper = mock.MagicMock()
+ prox_traffic_gen.setup_helper = mock.MagicMock()
+ prox_traffic_gen.resource_helper = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper.setup_helper = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper._vnf_process = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper.resource_helper = mock.MagicMock()
+ self.assertIsNone(prox_traffic_gen.terminate())
+
+ def test__wait_for_process(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+ with mock.patch.object(prox_irq_gen, '_check_status',
+ return_value=0) as mock_status, \
+ mock.patch.object(prox_irq_gen, '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = True
+ mock_proc.exitcode = 234
+ self.assertEqual(prox_irq_gen._wait_for_process(), 234)
+ mock_proc.is_alive.assert_called_once()
+ mock_status.assert_called_once()
+
+ def test__wait_for_process_not_alive(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+ with mock.patch.object(prox_irq_gen, '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = False
+ self.assertRaises(RuntimeError, prox_irq_gen._wait_for_process)
+ mock_proc.is_alive.assert_called_once()
+
+ def test__wait_for_process_delayed(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+ with mock.patch.object(prox_irq_gen, '_check_status',
+ side_effect=[1, 0]) as mock_status, \
+ mock.patch.object(prox_irq_gen,
+ '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = True
+ mock_proc.exitcode = 234
+ self.assertEqual(prox_irq_gen._wait_for_process(), 234)
+ mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()])
+ mock_status.assert_has_calls([mock.call(), mock.call()])
+
+ def test_scale(self):
+ prox_irq_gen = ProxIrqGen('tg1', self.VNFD_0)
+ self.assertRaises(y_exceptions.FunctionNotImplemented,
+ prox_irq_gen.scale)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ resource_helper = mock.MagicMock()
+
+ core_1 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5,
+ 'bucket_6': 6, 'bucket_7': 7, 'bucket_8': 8, 'bucket_9': 9, 'bucket_10': 10,
+ 'bucket_11': 11, 'bucket_12': 12, 'bucket_0': 100, 'cpu': 1, 'max_irq': 12,
+ 'overflow': 10}
+ core_2 = {'bucket_1': 1, 'bucket_2': 2, 'bucket_3': 3, 'bucket_4': 4, 'bucket_5': 5,
+ 'bucket_6': 0, 'bucket_7': 0, 'bucket_8': 0, 'bucket_9': 0, 'bucket_10': 0,
+ 'bucket_11': 0, 'bucket_12': 0, 'bucket_0': 100, 'cpu': 2, 'max_irq': 12,
+ 'overflow': 10}
+
+ irq_data = {'core_1': core_1, 'core_2': core_2}
+ resource_helper.sut.irq_core_stats.return_value = (irq_data)
+
+ build_config_file = mock.MagicMock()
+ build_config_file.return_value = None
+
+ prox_irq_gen = ProxIrqGen(VNF_NAME, vnfd)
+
+ startup = ["global", [["eal", "-4"]]]
+ master_0 = ["core 0", [["mode", "master"]]]
+ core_1 = ["core 1", [["mode", "irq"]]]
+ core_2 = ["core 2", [["mode", "irq"], ["task", "2"]]]
+
+ prox_irq_gen.setup_helper._prox_config_data = \
+ [startup, master_0, core_1, core_2]
+
+ prox_irq_gen.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ prox_irq_gen.resource_helper = resource_helper
+ prox_irq_gen.setup_helper.build_config_file = build_config_file
+
+ result = prox_irq_gen.collect_kpi()
+ self.assertDictEqual(result["collect_stats"], {})
+
+ result = prox_irq_gen.collect_kpi()
+ self.assertFalse('bucket_10' in result["collect_stats"]['core_2'])
+ self.assertFalse('bucket_11' in result["collect_stats"]['core_2'])
+ self.assertFalse('bucket_12' in result["collect_stats"]['core_2'])
+ self.assertEqual(result["collect_stats"]['core_2']['max_irq'], 12)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py
new file mode 100644
index 000000000..76fd74dfe
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_prox_vnf.py
@@ -0,0 +1,513 @@
+# Copyright (c) 2016-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.
+#
+
+import errno
+import os
+import unittest
+import mock
+from copy import deepcopy
+
+from yardstick.tests import STL_MOCKS
+from yardstick.benchmark.contexts import base as ctx_base
+
+
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+STLClient = mock.MagicMock()
+stl_patch = mock.patch.dict("sys.modules", STL_MOCKS)
+stl_patch.start()
+
+if stl_patch:
+ from yardstick.network_services.vnf_generic.vnf import prox_vnf
+ from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+
+
+NAME = "vnf__1"
+
+
+@mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
+class TestProxApproxVnf(unittest.TestCase):
+
+ VNFD0 = {
+ 'short-name': 'ProxVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'name': 'proxvnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'proxvnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe1',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'proxvnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ 'curr_packets_fwd',
+ 'curr_packets_in'
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'ProxApproxVnf',
+ 'name': 'ProxVnf',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD0,
+ ],
+ },
+ }
+
+ SCENARIO_CFG = {
+ 'task_path': "",
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'runner': {
+ 'duration': 600, 'type': 'Duration'},
+ 'topology': 'prox-tg-topology-2.yaml',
+ 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml',
+ 'type': 'NSPerf',
+ 'options': {
+ 'tg__1': {'prox_args': {'-e': '',
+ '-t': ''},
+ 'prox_config': 'configs/l3-gen-2.cfg',
+ 'prox_path':
+ '/root/dppd-PROX-v035/build/prox'},
+ 'vnf__1': {
+ 'prox_args': {'-t': ''},
+ 'prox_config': 'configs/l3-swap-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'}}}
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__2': {
+ 'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens513f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root',
+ },
+ 'tg__1': {
+ 'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens785f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root',
+ },
+ 'vnf__1': {
+ 'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens786f0',
+ 'vld_id': prox_vnf.ProxApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens786f1',
+ 'vld_id': prox_vnf.ProxApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'password': 'r00t',
+ 'VNF model': 'prox_vnf.yaml',
+ },
+ },
+ }
+
+ @mock.patch(SSH_HELPER)
+ def test___init__(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ self.assertIsNone(prox_approx_vnf._vnf_process)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi_no_client(self, ssh, *args):
+ mock_ssh(ssh)
+
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_approx_vnf.name: "mock"}
+ }
+ prox_approx_vnf.resource_helper = None
+ expected = {
+ 'physical_node': 'mock_node',
+ 'packets_in': 0,
+ 'packets_dropped': 0,
+ 'packets_fwd': 0,
+ 'curr_packets_in': 0,
+ 'curr_packets_fwd': 0,
+ 'collect_stats': {'core': {}}
+ }
+ result = prox_approx_vnf.collect_kpi()
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ resource_helper = mock.MagicMock()
+ resource_helper.execute.return_value = (True,
+ [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]])
+ resource_helper.collect_collectd_kpi.return_value = {'core': {'result': 234}}
+
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_approx_vnf.name: "mock"}
+ }
+ prox_approx_vnf.resource_helper = resource_helper
+ prox_approx_vnf.tsc_hz = 1000
+
+ expected = {
+ 'curr_packets_in': 200,
+ 'curr_packets_fwd': 400,
+ 'physical_node': 'mock_node',
+ 'packets_in': 2,
+ 'packets_dropped': 2,
+ 'packets_fwd': 4,
+ 'collect_stats': {'core': {'result': 234}},
+ }
+ result = prox_approx_vnf.collect_kpi()
+ self.assertEqual(result['packets_in'], expected['packets_in'])
+ self.assertEqual(result['packets_dropped'], expected['packets_dropped'])
+ self.assertEqual(result['packets_fwd'], expected['packets_fwd'])
+ self.assertEqual(result['curr_packets_in'], expected['curr_packets_in'])
+ self.assertEqual(result['curr_packets_fwd'], expected['curr_packets_fwd'])
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi_bad_input(self, ssh, *args):
+ mock_ssh(ssh)
+
+ resource_helper = mock.MagicMock()
+ resource_helper.execute.return_value = (True,
+ [[0, 'A', 'B', 'C', 'D', 'E'],
+ ['F', 1, 2, 3, 4, 5]])
+
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_approx_vnf.name: "mock"}
+ }
+ prox_approx_vnf.resource_helper = resource_helper
+
+ result = prox_approx_vnf.collect_kpi()
+ self.assertDictEqual(result, {})
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi_bad_input2(self, ssh, *args):
+ mock_ssh(ssh)
+
+ resource_helper = mock.MagicMock()
+ resource_helper.execute.return_value = (False,
+ [[0, 'A', 'B', 'C', 'D', 'E'],
+ ['F', 1, 2, 3, 4, 5]])
+
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_approx_vnf.name: "mock"}
+ }
+ prox_approx_vnf.resource_helper = resource_helper
+
+ result = prox_approx_vnf.collect_kpi()
+ self.assertDictEqual(result, {})
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi_error(self, ssh, *args):
+ mock_ssh(ssh)
+
+ resource_helper = mock.MagicMock()
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, deepcopy(self.VNFD0))
+ prox_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_approx_vnf.name: "mock"}
+ }
+ prox_approx_vnf.resource_helper = resource_helper
+ prox_approx_vnf.vnfd_helper['vdu'][0]['external-interface'] = []
+ prox_approx_vnf.vnfd_helper.port_pairs.interfaces = []
+
+ with self.assertRaises(RuntimeError):
+ prox_approx_vnf.collect_kpi()
+
+ def _get_file_abspath(self, filename, *args):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ @mock.patch('yardstick.common.utils.open', create=True)
+ @mock.patch('yardstick.benchmark.scenarios.networking.vnf_generic.open', create=True)
+ @mock.patch('yardstick.network_services.helpers.iniparser.open', create=True)
+ @mock.patch(SSH_HELPER)
+ def test_run_prox(self, ssh, *_):
+ mock_ssh(ssh)
+
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ prox_approx_vnf.ssh_helper.join_bin_path.return_value = '/tool_path12/tool_file34'
+ prox_approx_vnf.setup_helper.remote_path = 'configs/file56.cfg'
+
+ expected = "sudo bash -c 'cd /tool_path12; " \
+ "/tool_path12/tool_file34 -o cli -t -f /tmp/l3-swap-2.cfg '"
+
+ prox_approx_vnf._run()
+ result = prox_approx_vnf.ssh_helper.run.call_args[0][0]
+ self.assertEqual(result, expected)
+
+ @mock.patch(SSH_HELPER)
+ def bad_test_instantiate(self, *args):
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.scenario_helper = mock.MagicMock()
+ prox_approx_vnf.setup_helper = mock.MagicMock()
+ # we can't mock super
+ prox_approx_vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG)
+ prox_approx_vnf.setup_helper.build_config.assert_called_once()
+
+ @mock.patch(SSH_HELPER)
+ def test_wait_for_instantiate_panic(self, ssh, *args):
+ mock_ssh(ssh, exec_result=(1, "", ""))
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf._vnf_process = mock.MagicMock(**{"is_alive.return_value": True})
+ prox_approx_vnf._run_prox = mock.Mock(return_value=0)
+ prox_approx_vnf.WAIT_TIME = 0
+ prox_approx_vnf.q_out.put("PANIC")
+ with self.assertRaises(RuntimeError):
+ prox_approx_vnf.wait_for_instantiate()
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf._vnf_process = mock.MagicMock()
+ prox_approx_vnf._vnf_process.terminate = mock.Mock()
+ prox_approx_vnf.ssh_helper = mock.MagicMock()
+ prox_approx_vnf.setup_helper = mock.Mock()
+ prox_approx_vnf.resource_helper = mock.MagicMock()
+
+ self.assertIsNone(prox_approx_vnf.terminate())
+
+ @mock.patch(SSH_HELPER)
+ def test__vnf_up_post(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.resource_helper = resource_helper = mock.Mock()
+
+ prox_approx_vnf._vnf_up_post()
+ resource_helper.up_post.assert_called_once()
+
+ @mock.patch(SSH_HELPER)
+ def test_vnf_execute_oserror(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_approx_vnf = prox_vnf.ProxApproxVnf(NAME, self.VNFD0)
+ prox_approx_vnf.resource_helper = resource_helper = mock.Mock()
+
+ resource_helper.execute.side_effect = OSError(errno.EPIPE, "")
+ prox_approx_vnf.vnf_execute("", _ignore_errors=True)
+
+ resource_helper.execute.side_effect = OSError(errno.ESHUTDOWN, "")
+ prox_approx_vnf.vnf_execute("", _ignore_errors=True)
+
+ resource_helper.execute.side_effect = OSError(errno.EADDRINUSE, "")
+ with self.assertRaises(OSError):
+ prox_approx_vnf.vnf_execute("", _ignore_errors=True)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_router_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_router_vnf.py
new file mode 100644
index 000000000..b8f3fcaca
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_router_vnf.py
@@ -0,0 +1,262 @@
+# Copyright (c) 2016-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.
+
+import unittest
+import mock
+
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.router_vnf import RouterVNF
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+
+name = 'vnf__1'
+
+
+class TestRouterVNF(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'RouterVNF',
+ 'vdu':
+ [{'routing_table': [],
+ 'description': 'RouterVNF',
+ 'name': 'router-baremetal',
+ 'nd_route_tbl': [],
+ 'id': 'router-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'RouterVNF',
+ 'mgmt-interface':
+ {'vdu-id': 'router-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'RouterVNF', 'name': 'VPEVnfSsh'}]}}
+
+ scenario_cfg = {'nodes': {'cpt__0': 'compute_0.compute_nodes',
+ 'tg__0': 'trafficgen_1.baremetal',
+ 'vnf__0': 'vnf.yardstick'},
+ 'options': {'flow': {'count': 128000,
+ 'dst_ip': ['10.0.3.26-10.0.3.105'],
+ 'dst_port': ['2001-2004'],
+ 'src_ip': ['10.0.2.26-10.0.2.105'],
+ 'src_port': ['1234-1238']},
+ 'framesize': {'downlink': {'1024B': 100},
+ 'uplink': {'1024B': 100}},
+ 'rfc2544': {'allowed_drop_rate': '0.0001 - 0.1'},
+ 'tg__0': {'queues_per_port': 7},
+ 'traffic_type': 4,
+ 'vnf__0': {'nfvi_enable': True}},
+ 'runner': {'interval': 35,
+ 'iterations': 10,
+ 'type': 'Iteration'},
+ 'topology': 'router-tg-topology.yaml',
+ 'traffic_profile': '../../traffic_profiles/ipv4_throughput.yaml',
+ 'type': 'NSPerf'}
+
+ context_cfg = {'nodes': {'tg__1':
+ {'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens785f0',
+ 'vld_id': RouterVNF.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root'},
+ 'vnf__1':
+ {'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens786f0',
+ 'vld_id': RouterVNF.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens786f1',
+ 'vld_id': RouterVNF.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'routing_table': [],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [],
+ 'password': 'r00t',
+ 'VNF model': 'router_vnf.yaml'}}}
+
+ IP_SHOW_STATS_OUTPUT = """\
+2: em1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
+ link/ether d4:c9:ef:52:7c:4d brd ff:ff:ff:ff:ff:ff
+ RX: bytes packets errors dropped overrun mcast
+ 2781945429 3202213 0 0 0 30131
+ RX errors: length crc frame fifo missed
+ 0 0 0 0 0
+ TX: bytes packets errors dropped carrier collsns
+ 646221183 2145799 0 0 0 0
+ TX errors: aborted fifo window heartbeat
+ 0 0 0 0
+"""
+ STATS = {
+ 'RX:bytes': '2781945429',
+ 'RX:dropped': '0',
+ 'RX:errors': '0',
+ 'RX:mcast': '30131',
+ 'RX:overrun': '0',
+ 'RX:packets': '3202213',
+ 'RX errors:length': '0',
+ 'RX errors:crc': '0',
+ 'RX errors:frame': '0',
+ 'RX errors:fifo': '0',
+ 'RX errors:missed': '0',
+ 'TX:bytes': '646221183',
+ 'TX:carrier': '0',
+ 'TX:collsns': '0',
+ 'TX:dropped': '0',
+ 'TX:errors': '0',
+ 'TX:packets': '2145799',
+ 'TX errors:aborted': '0',
+ 'TX errors:fifo': '0',
+ 'TX errors:window': '0',
+ 'TX errors:heartbeat': '0',
+ }
+
+ def test___init__(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ router_vnf = RouterVNF(name, vnfd)
+ self.assertIsNone(router_vnf._vnf_process)
+
+ def test_get_stats(self):
+ stats = RouterVNF.get_stats(self.IP_SHOW_STATS_OUTPUT)
+ self.assertDictEqual(stats, self.STATS)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ m = mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ router_vnf = RouterVNF(name, vnfd)
+ router_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {router_vnf.name: "mock"}
+ }
+ router_vnf.ssh_helper = m
+ result = {
+ 'physical_node': 'mock_node',
+ 'packets_dropped': 0,
+ 'packets_fwd': 0,
+ 'packets_in': 0,
+ 'link_stats': {}
+ }
+ self.assertEqual(result, router_vnf.collect_kpi())
+
+ @mock.patch(SSH_HELPER)
+ def test_run_router(self, ssh):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ router_vnf = RouterVNF(name, vnfd)
+ router_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ router_vnf._run()
+ router_vnf.ssh_helper.drop_connection.assert_called_once()
+
+ @mock.patch.object(ctx_base, 'Context')
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ router_vnf = RouterVNF(name, vnfd)
+ router_vnf.WAIT_TIME = 0
+ router_vnf.INTERFACE_WAIT = 0
+ self.scenario_cfg.update({"nodes": {"vnf__1": ""}})
+ self.assertIsNone(router_vnf.instantiate(self.scenario_cfg,
+ self.context_cfg))
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, _):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ router_vnf = RouterVNF(name, vnfd)
+ router_vnf._vnf_process = mock.MagicMock()
+ router_vnf._vnf_process.terminate = mock.Mock()
+ self.assertIsNone(router_vnf.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
new file mode 100644
index 000000000..21f0c5e1f
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_sample_vnf.py
@@ -0,0 +1,1532 @@
+# Copyright (c) 2017-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.
+
+from copy import deepcopy
+
+import unittest
+import mock
+import six
+import subprocess
+import time
+
+import paramiko
+
+from yardstick.common import exceptions as y_exceptions
+from yardstick.common import utils
+from yardstick.network_services.nfvi import resource
+from yardstick.network_services.vnf_generic.vnf import base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import vnf_ssh_helper
+from yardstick import ssh
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
+from yardstick.benchmark.contexts import base as ctx_base
+
+
+class MockError(Exception):
+ pass
+
+
+class TestVnfSshHelper(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ 'driver': 'i40e',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ 'driver': 'ixgbe',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ]
+ }
+ }
+
+ def setUp(self):
+ self.ssh_helper = vnf_ssh_helper.VnfSshHelper(
+ self.VNFD_0['mgmt-interface'], 'my/bin/path')
+ self.ssh_helper._run = mock.Mock()
+
+ def assertAll(self, iterable, message=None):
+ self.assertTrue(all(iterable), message)
+
+ def test_get_class(self):
+ self.assertIs(vnf_ssh_helper.VnfSshHelper.get_class(),
+ vnf_ssh_helper.VnfSshHelper)
+
+ @mock.patch.object(ssh, 'paramiko')
+ def test_copy(self, _):
+ self.ssh_helper.execute('ls')
+ self.assertTrue(self.ssh_helper.is_connected)
+ result = self.ssh_helper.copy()
+ self.assertIsInstance(result, vnf_ssh_helper.VnfSshHelper)
+ self.assertFalse(result.is_connected)
+ self.assertEqual(result.bin_path, self.ssh_helper.bin_path)
+ self.assertEqual(result.host, self.ssh_helper.host)
+ self.assertEqual(result.port, self.ssh_helper.port)
+ self.assertEqual(result.user, self.ssh_helper.user)
+ self.assertEqual(result.password, self.ssh_helper.password)
+ self.assertEqual(result.key_filename, self.ssh_helper.key_filename)
+
+ @mock.patch.object(paramiko, 'SSHClient')
+ def test_upload_config_file(self, mock_paramiko):
+ self.assertFalse(self.ssh_helper.is_connected)
+ cfg_file = self.ssh_helper.upload_config_file('/my/prefix', 'my content')
+ self.assertTrue(self.ssh_helper.is_connected)
+ mock_paramiko.assert_called_once()
+ self.assertEqual(cfg_file, '/my/prefix')
+
+ @mock.patch.object(paramiko, 'SSHClient')
+ def test_upload_config_file_path_does_not_exist(self, mock_paramiko):
+ self.assertFalse(self.ssh_helper.is_connected)
+ cfg_file = self.ssh_helper.upload_config_file('my/prefix', 'my content')
+ self.assertTrue(self.ssh_helper.is_connected)
+ mock_paramiko.assert_called_once()
+ self.assertTrue(cfg_file.startswith('/tmp'))
+
+ def test_join_bin_path(self):
+ expected_start = 'my'
+ expected_middle_list = ['bin']
+ expected_end = 'path'
+ result = self.ssh_helper.join_bin_path()
+ self.assertTrue(result.startswith(expected_start))
+ self.assertAll(middle in result for middle in expected_middle_list)
+ self.assertTrue(result.endswith(expected_end))
+
+ expected_middle_list.append(expected_end)
+ expected_end = 'some_file.sh'
+ result = self.ssh_helper.join_bin_path('some_file.sh')
+ self.assertTrue(result.startswith(expected_start))
+ self.assertAll(middle in result for middle in expected_middle_list)
+ self.assertTrue(result.endswith(expected_end))
+
+ expected_middle_list.append('some_dir')
+ expected_end = 'some_file.sh'
+ result = self.ssh_helper.join_bin_path('some_dir', 'some_file.sh')
+ self.assertTrue(result.startswith(expected_start))
+ self.assertAll(middle in result for middle in expected_middle_list)
+ self.assertTrue(result.endswith(expected_end))
+
+ @mock.patch.object(paramiko, 'SSHClient')
+ @mock.patch.object(ssh, 'provision_tool')
+ def test_provision_tool(self, mock_provision_tool, mock_paramiko):
+ self.assertFalse(self.ssh_helper.is_connected)
+ self.ssh_helper.provision_tool()
+ self.assertTrue(self.ssh_helper.is_connected)
+ mock_paramiko.assert_called_once()
+ mock_provision_tool.assert_called_once()
+
+ self.ssh_helper.provision_tool(tool_file='my_tool.sh')
+ self.assertTrue(self.ssh_helper.is_connected)
+ mock_paramiko.assert_called_once()
+ self.assertEqual(mock_provision_tool.call_count, 2)
+
+ self.ssh_helper.provision_tool('tool_path', 'my_tool.sh')
+ self.assertTrue(self.ssh_helper.is_connected)
+ mock_paramiko.assert_called_once()
+ self.assertEqual(mock_provision_tool.call_count, 3)
+
+
+class TestSetupEnvHelper(unittest.TestCase):
+
+ VNFD_0 = TestVnfSshHelper.VNFD_0
+
+ def setUp(self):
+ self.setup_env_helper = sample_vnf.SetupEnvHelper(
+ mock.Mock(), mock.Mock(), mock.Mock())
+
+ def test_build_config(self):
+ with self.assertRaises(NotImplementedError):
+ self.setup_env_helper.build_config()
+
+ def test_setup_vnf_environment(self):
+ self.assertIsNone(self.setup_env_helper.setup_vnf_environment())
+
+ def test_tear_down(self):
+ with self.assertRaises(NotImplementedError):
+ self.setup_env_helper.tear_down()
+
+
+class TestDpdkVnfSetupEnvHelper(unittest.TestCase):
+
+ VNFD_0 = TestVnfSshHelper.VNFD_0
+
+ VNFD = TestVnfSshHelper.VNFD
+
+ def setUp(self):
+ self.vnfd_helper = base.VnfdHelper(deepcopy(self.VNFD_0))
+ self.scenario_helper = mock.Mock()
+ self.ssh_helper = mock.Mock()
+ self.dpdk_setup_helper = sample_vnf.DpdkVnfSetupEnvHelper(
+ self.vnfd_helper, self.ssh_helper, self.scenario_helper)
+
+ def test__update_packet_type(self):
+ ip_pipeline_cfg = 'pkt_type = ipv4'
+ pkt_type = {'pkt_type': '1'}
+
+ expected = "pkt_type = 1"
+ result = self.dpdk_setup_helper._update_packet_type(
+ ip_pipeline_cfg, pkt_type)
+ self.assertEqual(result, expected)
+
+ def test__update_packet_type_no_op(self):
+ ip_pipeline_cfg = 'pkt_type = ipv6'
+ pkt_type = {'pkt_type': '1'}
+
+ expected = "pkt_type = ipv6"
+ result = self.dpdk_setup_helper._update_packet_type(
+ ip_pipeline_cfg, pkt_type)
+ self.assertEqual(result, expected)
+
+ def test__update_packet_type_multi_op(self):
+ ip_pipeline_cfg = 'pkt_type = ipv4\npkt_type = 1\npkt_type = ipv4'
+ pkt_type = {'pkt_type': '1'}
+ expected = 'pkt_type = 1\npkt_type = 1\npkt_type = 1'
+
+ result = self.dpdk_setup_helper._update_packet_type(
+ ip_pipeline_cfg, pkt_type)
+ self.assertEqual(result, expected)
+
+ def test__update_traffic_type(self):
+ ip_pipeline_cfg = 'pkt_type = ipv4'
+ traffic_options = {
+ "vnf_type": sample_vnf.DpdkVnfSetupEnvHelper.APP_NAME,
+ "traffic_type": 4}
+ expected = "pkt_type = ipv4"
+
+ result = self.dpdk_setup_helper._update_traffic_type(
+ ip_pipeline_cfg, traffic_options)
+ self.assertEqual(result, expected)
+
+ def test__update_traffic_type_ipv6(self):
+ ip_pipeline_cfg = 'pkt_type = ipv4'
+ traffic_options = {
+ "vnf_type": sample_vnf.DpdkVnfSetupEnvHelper.APP_NAME,
+ "traffic_type": 6}
+ expected = "pkt_type = ipv6"
+
+ result = self.dpdk_setup_helper._update_traffic_type(
+ ip_pipeline_cfg, traffic_options)
+ self.assertEqual(result, expected)
+
+ def test__update_traffic_type_not_app_name(self):
+ ip_pipeline_cfg = 'traffic_type = 4'
+ vnf_type = ''.join(["Not", sample_vnf.DpdkVnfSetupEnvHelper.APP_NAME])
+ traffic_options = {"vnf_type": vnf_type, 'traffic_type': 8}
+ expected = "traffic_type = 8"
+
+ result = self.dpdk_setup_helper._update_traffic_type(
+ ip_pipeline_cfg, traffic_options)
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(six.moves.builtins, 'open')
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch.object(sample_vnf, 'MultiPortConfig')
+ def test_build_config(self, mock_multi_port_config_class,
+ mock_find, *args):
+ mock_multi_port_config = mock_multi_port_config_class()
+ self.scenario_helper.vnf_cfg = {}
+ self.scenario_helper.options = {}
+ self.scenario_helper.all_options = {}
+
+ self.dpdk_setup_helper.PIPELINE_COMMAND = expected = 'pipeline command'
+ result = self.dpdk_setup_helper.build_config()
+ self.assertEqual(result, expected)
+ self.assertGreaterEqual(self.ssh_helper.upload_config_file.call_count, 2)
+ mock_find.assert_called()
+ mock_multi_port_config.generate_config.assert_called()
+ mock_multi_port_config.generate_script.assert_called()
+
+ @mock.patch.object(six.moves.builtins, 'open')
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch.object(sample_vnf, 'MultiPortConfig')
+ @mock.patch.object(utils, 'open_relative_file')
+ def test_build_config2(self, mock_open_rf, mock_multi_port_config_class,
+ mock_find, *args):
+ mock_multi_port_config = mock_multi_port_config_class()
+ self.scenario_helper.options = {'rules': 'fake_file'}
+ self.scenario_helper.vnf_cfg = {'file': 'fake_file'}
+ self.scenario_helper.all_options = {}
+ mock_open_rf.side_effect = mock.mock_open(read_data='fake_data')
+ self.dpdk_setup_helper.PIPELINE_COMMAND = expected = 'pipeline command'
+
+ result = self.dpdk_setup_helper.build_config()
+
+ mock_open_rf.assert_called()
+ self.assertEqual(result, expected)
+ self.assertGreaterEqual(self.ssh_helper.upload_config_file.call_count, 2)
+ mock_find.assert_called()
+ mock_multi_port_config.generate_config.assert_called()
+ mock_multi_port_config.generate_script.assert_called()
+
+ def test__build_pipeline_kwargs(self):
+ self.ssh_helper.provision_tool.return_value = 'tool_path'
+ self.dpdk_setup_helper.CFG_CONFIG = 'config'
+ self.dpdk_setup_helper.CFG_SCRIPT = 'script'
+ self.dpdk_setup_helper.pipeline_kwargs = {}
+ self.dpdk_setup_helper.all_ports = [0, 1, 2]
+ self.dpdk_setup_helper.scenario_helper.vnf_cfg = {'lb_config': 'HW',
+ 'worker_threads': 1}
+
+ expected = {
+ 'cfg_file': 'config',
+ 'script': 'script',
+ 'port_mask_hex': '0x3',
+ 'tool_path': 'tool_path',
+ 'hwlb': ' --hwlb 1',
+ }
+ self.dpdk_setup_helper._build_pipeline_kwargs()
+ self.assertDictEqual(self.dpdk_setup_helper.pipeline_kwargs, expected)
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(ssh, 'SSH')
+ def test_setup_vnf_environment(self, *args):
+ self.scenario_helper.nodes = [None, None]
+
+ def execute(cmd):
+ if cmd.startswith('which '):
+ return exec_failure
+ return exec_success
+
+ exec_success = (0, 'good output', '')
+ exec_failure = (1, 'bad output', 'error output')
+ self.ssh_helper.execute = execute
+
+ self.dpdk_setup_helper._validate_cpu_cfg = mock.Mock(return_value=[])
+
+ with mock.patch.object(self.dpdk_setup_helper, '_setup_dpdk'):
+ self.assertIsInstance(
+ self.dpdk_setup_helper.setup_vnf_environment(),
+ resource.ResourceProfile)
+
+ @mock.patch.object(utils, 'setup_hugepages')
+ def test__setup_dpdk(self, mock_setup_hugepages):
+ self.ssh_helper.execute = mock.Mock()
+ self.ssh_helper.execute.return_value = (0, 0, 0)
+ self.scenario_helper.all_options = {'hugepages_gb': 8}
+ self.dpdk_setup_helper._setup_dpdk()
+ mock_setup_hugepages.assert_called_once_with(
+ self.ssh_helper, 8*1024*1024)
+ self.ssh_helper.execute.assert_has_calls([
+ mock.call('sudo modprobe uio && sudo modprobe igb_uio'),
+ mock.call('lsmod | grep -i igb_uio')
+ ])
+
+ @mock.patch.object(ssh, 'SSH')
+ def test__setup_resources(self, _):
+ self.dpdk_setup_helper._validate_cpu_cfg = mock.Mock()
+ self.dpdk_setup_helper.bound_pci = [v['virtual-interface']["vpci"] for v in
+ self.vnfd_helper.interfaces]
+ result = self.dpdk_setup_helper._setup_resources()
+ self.assertIsInstance(result, resource.ResourceProfile)
+ self.assertEqual(self.dpdk_setup_helper.socket, 0)
+
+ @mock.patch.object(ssh, 'SSH')
+ def test__setup_resources_socket_1(self, _):
+ self.vnfd_helper.interfaces[0]['virtual-interface']['vpci'] = \
+ '0000:55:00.0'
+ self.vnfd_helper.interfaces[1]['virtual-interface']['vpci'] = \
+ '0000:35:00.0'
+
+ self.dpdk_setup_helper._validate_cpu_cfg = mock.Mock()
+ self.dpdk_setup_helper.bound_pci = [v['virtual-interface']["vpci"] for v in
+ self.vnfd_helper.interfaces]
+ result = self.dpdk_setup_helper._setup_resources()
+ self.assertIsInstance(result, resource.ResourceProfile)
+ self.assertEqual(self.dpdk_setup_helper.socket, 1)
+
+ @mock.patch.object(time, 'sleep')
+ def test__detect_and_bind_drivers(self, *args):
+ self.scenario_helper.nodes = [None, None]
+ rv = ['0000:05:00.1', '0000:05:00.0']
+
+ self.dpdk_setup_helper.dpdk_bind_helper._get_bound_pci_addresses = \
+ mock.Mock(return_value=rv)
+ self.dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
+ self.dpdk_setup_helper.dpdk_bind_helper.read_status = mock.Mock()
+
+ self.assertIsNone(self.dpdk_setup_helper._detect_and_bind_drivers())
+
+ intf_0 = self.vnfd_helper.vdu[0]['external-interface'][0]['virtual-interface']
+ intf_1 = self.vnfd_helper.vdu[0]['external-interface'][1]['virtual-interface']
+ self.assertEqual(0, intf_0['dpdk_port_num'])
+ self.assertEqual(1, intf_1['dpdk_port_num'])
+
+ def test_tear_down(self):
+ self.scenario_helper.nodes = [None, None]
+
+ self.dpdk_setup_helper.dpdk_bind_helper.bind = mock.Mock()
+ self.dpdk_setup_helper.dpdk_bind_helper.used_drivers = {
+ 'd1': ['0000:05:00.0'],
+ 'd3': ['0000:05:01.0'],
+ }
+
+ self.assertIsNone(self.dpdk_setup_helper.tear_down())
+ self.dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call(
+ ['0000:05:00.0'], 'd1', True)
+ self.dpdk_setup_helper.dpdk_bind_helper.bind.assert_any_call(
+ ['0000:05:01.0'], 'd3', True)
+
+
+class TestResourceHelper(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'driver': 'i40e',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'driver': 'ixgbe',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ def setUp(self):
+ self.vnfd_helper = base.VnfdHelper(self.VNFD_0)
+ self.dpdk_setup_helper = sample_vnf.DpdkVnfSetupEnvHelper(
+ self.vnfd_helper, mock.Mock(), mock.Mock())
+ self.resource_helper = sample_vnf.ResourceHelper(self.dpdk_setup_helper)
+
+ def test_setup(self):
+ resource = object()
+ self.dpdk_setup_helper.setup_vnf_environment = (
+ mock.Mock(return_value=resource))
+ resource_helper = sample_vnf.ResourceHelper(self.dpdk_setup_helper)
+
+ self.assertIsNone(resource_helper.setup())
+ self.assertIs(resource_helper.resource, resource)
+
+ def test_generate_cfg(self):
+ self.assertIsNone(self.resource_helper.generate_cfg())
+
+ def test_stop_collect(self):
+ self.resource_helper.resource = mock.Mock()
+
+ self.assertIsNone(self.resource_helper.stop_collect())
+
+ def test_stop_collect_none(self):
+ self.resource_helper.resource = None
+
+ self.assertIsNone(self.resource_helper.stop_collect())
+
+
+class TestClientResourceHelper(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'driver': 'i40e',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'driver': 'ixgbe',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:13',
+ 'vpci': '0000:05:00.2',
+ 'driver': 'ixgbe',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 2,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.30',
+ 'local_mac': '00:00:00:00:00:11'
+ },
+ 'vnfd-connection-point-ref': 'xe2',
+ 'name': 'xe2'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ def setUp(self):
+ vnfd_helper = base.VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ dpdk_setup_helper = sample_vnf.DpdkVnfSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+ self.client_resource_helper = (
+ sample_vnf.ClientResourceHelper(dpdk_setup_helper))
+
+ @mock.patch.object(sample_vnf, 'LOG')
+ @mock.patch.object(sample_vnf, 'STLError', new_callable=lambda: MockError)
+ def test_get_stats_not_connected(self, mock_stl_error, *args):
+ self.client_resource_helper.client = mock.Mock()
+ self.client_resource_helper.client.get_stats.side_effect = \
+ mock_stl_error
+
+ self.assertEqual(self.client_resource_helper.get_stats(), {})
+ self.client_resource_helper.client.get_stats.assert_called_once()
+
+ def test_clear_stats(self):
+ self.client_resource_helper.client = mock.Mock()
+
+ self.assertIsNone(self.client_resource_helper.clear_stats())
+ self.assertEqual(
+ self.client_resource_helper.client.clear_stats.call_count, 1)
+
+ def test_clear_stats_of_ports(self):
+ self.client_resource_helper.client = mock.Mock()
+
+ self.assertIsNone(self.client_resource_helper.clear_stats([3, 4]))
+ self.client_resource_helper.client.clear_stats.assert_called_once()
+
+ def test_start(self):
+ self.client_resource_helper.client = mock.Mock()
+
+ self.assertIsNone(self.client_resource_helper.start())
+ self.client_resource_helper.client.start.assert_called_once()
+
+ def test_start_ports(self):
+ self.client_resource_helper.client = mock.Mock()
+
+ self.assertIsNone(self.client_resource_helper.start([3, 4]))
+ self.client_resource_helper.client.start.assert_called_once()
+
+ def test_collect_kpi_with_queue(self):
+ self.client_resource_helper._result = {
+ 'existing': 43,
+ 'replaceable': 12}
+ self.client_resource_helper._queue = mock.Mock()
+ self.client_resource_helper._queue.empty.return_value = False
+ self.client_resource_helper._queue.get.return_value = {
+ 'incoming': 34,
+ 'replaceable': 99}
+
+ expected = {
+ 'existing': 43,
+ 'incoming': 34,
+ 'replaceable': 99,
+ }
+ result = self.client_resource_helper.collect_kpi()
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(sample_vnf, 'STLError')
+ def test__connect_with_failures(self, mock_stl_error, *args):
+ client = mock.MagicMock()
+ client.connect.side_effect = mock_stl_error(msg='msg')
+
+ self.assertIs(self.client_resource_helper._connect(client), client)
+
+
+class TestRfc2544ResourceHelper(unittest.TestCase):
+
+ RFC2544_CFG_1 = {
+ 'latency': True,
+ 'correlated_traffic': True,
+ 'allowed_drop_rate': '0.1 - 0.15',
+ }
+
+ RFC2544_CFG_2 = {
+ 'allowed_drop_rate': ' 0.25 - 0.05 ',
+ }
+
+ RFC2544_CFG_3 = {
+ 'allowed_drop_rate': '0.2',
+ }
+
+ RFC2544_CFG_4 = {
+ 'latency': True,
+ }
+
+ SCENARIO_CFG_1 = {
+ 'options': {
+ 'rfc2544': RFC2544_CFG_1,
+ }
+ }
+
+ SCENARIO_CFG_2 = {
+ 'options': {
+ 'rfc2544': RFC2544_CFG_2,
+ }
+ }
+
+ SCENARIO_CFG_3 = {
+ 'options': {
+ 'rfc2544': RFC2544_CFG_3,
+ }
+ }
+
+ SCENARIO_CFG_4 = {
+ 'options': {
+ 'rfc2544': RFC2544_CFG_4,
+ }
+ }
+
+ def setUp(self):
+ self.scenario_helper = sample_vnf.ScenarioHelper('name1')
+ self.rfc2544_resource_helper = \
+ sample_vnf.Rfc2544ResourceHelper(self.scenario_helper)
+
+ def test_property_rfc2544(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
+
+ self.assertIsNone(self.rfc2544_resource_helper._rfc2544)
+ self.assertEqual(self.rfc2544_resource_helper.rfc2544,
+ self.RFC2544_CFG_1)
+ self.assertEqual(self.rfc2544_resource_helper._rfc2544,
+ self.RFC2544_CFG_1)
+ # ensure that resource_helper caches
+ self.scenario_helper.scenario_cfg = {}
+ self.assertEqual(self.rfc2544_resource_helper.rfc2544,
+ self.RFC2544_CFG_1)
+
+ def test_property_tolerance_high(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
+
+ self.assertIsNone(self.rfc2544_resource_helper._tolerance_high)
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_high, 0.15)
+ self.assertEqual(self.rfc2544_resource_helper._tolerance_high, 0.15)
+ self.assertEqual(self.rfc2544_resource_helper._tolerance_precision, 2)
+ # ensure that resource_helper caches
+ self.scenario_helper.scenario_cfg = {}
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_high, 0.15)
+
+ def test_property_tolerance_low(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
+
+ self.assertIsNone(self.rfc2544_resource_helper._tolerance_low)
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_low, 0.1)
+ self.assertEqual(self.rfc2544_resource_helper._tolerance_low, 0.1)
+ # ensure that resource_helper caches
+ self.scenario_helper.scenario_cfg = {}
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_low, 0.1)
+
+ def test_property_tolerance_high_range_swap(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_high, 0.25)
+
+ def test_property_tolerance_low_range_swap(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_low, 0.05)
+
+ def test_property_tolerance_high_not_range(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_high, 0.2)
+ self.assertEqual(self.rfc2544_resource_helper._tolerance_precision, 1)
+
+ def test_property_tolerance_low_not_range(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_3
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_low, 0.2)
+
+ def test_property_tolerance_high_default(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_high, 0.0001)
+
+ def test_property_tolerance_low_default(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_4
+
+ self.assertEqual(self.rfc2544_resource_helper.tolerance_low, 0.0001)
+
+ def test_property_latency(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
+
+ self.assertIsNone(self.rfc2544_resource_helper._latency)
+ self.assertTrue(self.rfc2544_resource_helper.latency)
+ self.assertTrue(self.rfc2544_resource_helper._latency)
+ # ensure that resource_helper caches
+ self.scenario_helper.scenario_cfg = {}
+ self.assertTrue(self.rfc2544_resource_helper.latency)
+
+ def test_property_latency_default(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
+
+ self.assertFalse(self.rfc2544_resource_helper.latency)
+
+ def test_property_correlated_traffic(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_1
+
+ self.assertIsNone(self.rfc2544_resource_helper._correlated_traffic)
+ self.assertTrue(self.rfc2544_resource_helper.correlated_traffic)
+ self.assertTrue(self.rfc2544_resource_helper._correlated_traffic)
+ # ensure that resource_helper caches
+ self.scenario_helper.scenario_cfg = {}
+ self.assertTrue(self.rfc2544_resource_helper.correlated_traffic)
+
+ def test_property_correlated_traffic_default(self):
+ self.scenario_helper.scenario_cfg = self.SCENARIO_CFG_2
+
+ self.assertFalse(self.rfc2544_resource_helper.correlated_traffic)
+
+
+class TestSampleVNFDeployHelper(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_time_sleep = mock.patch.object(time, 'sleep')
+ self.mock_time_sleep = self._mock_time_sleep.start()
+ self._mock_check_output = mock.patch.object(subprocess, 'check_output')
+ self.mock_check_output = self._mock_check_output.start()
+ self.addCleanup(self._stop_mocks)
+
+ self.ssh_helper = mock.Mock()
+ self.sample_vnf_deploy_helper = sample_vnf.SampleVNFDeployHelper(
+ mock.Mock(), self.ssh_helper)
+ self.ssh_helper.join_bin_path.return_value = 'joined_path'
+ self.ssh_helper.put.return_value = None
+
+ def _stop_mocks(self):
+ self._mock_time_sleep.stop()
+ self._mock_check_output.stop()
+
+ def test_deploy_vnfs_disabled(self):
+ self.ssh_helper.execute.return_value = 1, 'bad output', 'error output'
+
+ self.sample_vnf_deploy_helper.deploy_vnfs('name1')
+ self.sample_vnf_deploy_helper.DISABLE_DEPLOY = True
+ self.assertEqual(self.ssh_helper.execute.call_count, 5)
+ self.ssh_helper.put.assert_called_once()
+
+ def test_deploy_vnfs(self):
+ self.ssh_helper.execute.return_value = 1, 'bad output', 'error output'
+ self.sample_vnf_deploy_helper.DISABLE_DEPLOY = False
+
+ self.sample_vnf_deploy_helper.deploy_vnfs('name1')
+ self.assertEqual(self.ssh_helper.execute.call_count, 5)
+ self.ssh_helper.put.assert_called_once()
+
+ def test_deploy_vnfs_early_success(self):
+ self.ssh_helper.execute.return_value = 0, 'output', ''
+ self.sample_vnf_deploy_helper.DISABLE_DEPLOY = False
+
+ self.sample_vnf_deploy_helper.deploy_vnfs('name1')
+ self.ssh_helper.execute.assert_called_once()
+ self.ssh_helper.put.assert_not_called()
+
+
+class TestScenarioHelper(unittest.TestCase):
+
+ def setUp(self):
+ self.scenario_helper = sample_vnf.ScenarioHelper('name1')
+
+ def test_property_task_path(self):
+ self.scenario_helper.scenario_cfg = {
+ 'task_path': 'my_path',
+ }
+
+ self.assertEqual(self.scenario_helper.task_path, 'my_path')
+
+ def test_property_nodes(self):
+ nodes = ['node1', 'node2']
+ self.scenario_helper.scenario_cfg = {
+ 'nodes': nodes,
+ }
+
+ self.assertEqual(self.scenario_helper.nodes, nodes)
+
+ def test_property_all_options(self):
+ data = {
+ 'name1': {
+ 'key3': 'value3',
+ },
+ 'name2': {}
+ }
+ self.scenario_helper.scenario_cfg = {
+ 'options': data,
+ }
+
+ self.assertDictEqual(self.scenario_helper.all_options, data)
+
+ def test_property_options(self):
+ data = {
+ 'key1': 'value1',
+ 'key2': 'value2',
+ }
+ self.scenario_helper.scenario_cfg = {
+ 'options': {
+ 'name1': data,
+ },
+ }
+
+ self.assertDictEqual(self.scenario_helper.options, data)
+
+ def test_property_vnf_cfg(self):
+ self.scenario_helper.scenario_cfg = {
+ 'options': {
+ 'name1': {
+ 'vnf_config': 'my_config',
+ },
+ },
+ }
+
+ self.assertEqual(self.scenario_helper.vnf_cfg, 'my_config')
+
+ def test_property_vnf_cfg_default(self):
+ self.scenario_helper.scenario_cfg = {
+ 'options': {
+ 'name1': {},
+ },
+ }
+
+ self.assertEqual(self.scenario_helper.vnf_cfg,
+ sample_vnf.ScenarioHelper.DEFAULT_VNF_CFG)
+
+ def test_property_topology(self):
+ self.scenario_helper.scenario_cfg = {
+ 'topology': 'my_topology',
+ }
+
+ self.assertEqual(self.scenario_helper.topology, 'my_topology')
+
+
+class TestSampleVnf(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01'
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ]
+ }
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+ def setUp(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.vnf = sample_vnf.SampleVNF('vnf1', vnfd)
+ self.vnf.APP_NAME = 'sample1'
+
+ def test___init__(self):
+ vnf = sample_vnf.SampleVNF('vnf1', self.VNFD_0)
+
+ self.assertEqual(vnf.name, 'vnf1')
+ self.assertDictEqual(vnf.vnfd_helper, self.VNFD_0)
+
+ # test the default setup helper is SetupEnvHelper, not subclass
+ self.assertEqual(type(vnf.setup_helper),
+ sample_vnf.SetupEnvHelper)
+
+ # test the default resource helper is ResourceHelper, not subclass
+ self.assertEqual(type(vnf.resource_helper), sample_vnf.ResourceHelper)
+
+ def test___init___alt_types(self):
+ class MySetupEnvHelper(sample_vnf.SetupEnvHelper):
+ pass
+
+ class MyResourceHelper(sample_vnf.ResourceHelper):
+ pass
+
+ vnf = sample_vnf.SampleVNF('vnf1', self.VNFD_0,
+ MySetupEnvHelper, MyResourceHelper)
+
+ self.assertEqual(vnf.name, 'vnf1')
+ self.assertDictEqual(vnf.vnfd_helper, self.VNFD_0)
+
+ # test the default setup helper is MySetupEnvHelper, not subclass
+ self.assertEqual(type(vnf.setup_helper), MySetupEnvHelper)
+
+ # test the default resource helper is MyResourceHelper, not subclass
+ self.assertEqual(type(vnf.resource_helper), MyResourceHelper)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.Process')
+ def test__start_vnf(self, *args):
+ self.vnf._run = mock.Mock()
+
+ self.assertIsNone(self.vnf.queue_wrapper)
+ self.assertIsNone(self.vnf._vnf_process)
+ self.vnf._start_vnf()
+ self.assertIsNotNone(self.vnf.queue_wrapper)
+ self.assertIsNotNone(self.vnf._vnf_process)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ @mock.patch.object(ssh, "SSH")
+ def test_instantiate(self, ssh, *args):
+ test_base.mock_ssh(ssh)
+ nodes = {
+ 'vnf1': 'name1',
+ 'vnf2': 'name2',
+ }
+ self.vnf._start_server = mock.Mock(return_value=0)
+ self.vnf._vnf_process = mock.MagicMock()
+ self.vnf._vnf_process._is_alive.return_value = 1
+ self.vnf.ssh_helper = mock.MagicMock()
+ self.vnf.deploy_helper = mock.MagicMock()
+ self.vnf.resource_helper.ssh_helper = mock.MagicMock()
+ scenario_cfg = {
+ 'nodes': nodes,
+ }
+
+ self.assertIsNone(self.vnf.instantiate(scenario_cfg, {}))
+
+ def test__update_collectd_options(self):
+ scenario_cfg = {'options':
+ {'collectd':
+ {'interval': 3,
+ 'plugins':
+ {'plugin3': {'param': 3}}},
+ 'vnf1':
+ {'collectd':
+ {'interval': 2,
+ 'plugins':
+ {'plugin3': {'param': 2},
+ 'plugin2': {'param': 2}}}}}}
+ context_cfg = {'nodes':
+ {'vnf1':
+ {'collectd':
+ {'interval': 1,
+ 'plugins':
+ {'plugin3': {'param': 1},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}}}}
+ expected = {'interval': 1,
+ 'plugins':
+ {'plugin3': {'param': 1},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+
+ self.vnf._update_collectd_options(scenario_cfg, context_cfg)
+ self.assertEqual(self.vnf.setup_helper.collectd_options, expected)
+
+ def test__update_options(self):
+ options1 = {'interval': 1,
+ 'param1': 'value1',
+ 'plugins':
+ {'plugin3': {'param': 3},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+ options2 = {'interval': 2,
+ 'param2': 'value2',
+ 'plugins':
+ {'plugin4': {'param': 4},
+ 'plugin2': {'param': 2},
+ 'plugin1': {'param': 2}}}
+ expected = {'interval': 1,
+ 'param1': 'value1',
+ 'param2': 'value2',
+ 'plugins':
+ {'plugin4': {'param': 4},
+ 'plugin3': {'param': 3},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+
+ self.vnf._update_options(options2, options1)
+ self.assertEqual(options2, expected)
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(ssh, 'SSH')
+ def test_wait_for_instantiate_empty_queue(self, ssh, *args):
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
+
+ queue_size_list = [
+ 0,
+ 1,
+ 0,
+ 1,
+ ]
+
+ queue_get_list = [
+ 'some output',
+ 'pipeline> ',
+ ]
+
+ self.vnf.WAIT_TIME_FOR_SCRIPT = 0
+ self.vnf._start_server = mock.Mock(return_value=0)
+ self.vnf._vnf_process = mock.MagicMock()
+ self.vnf._vnf_process.exitcode = 0
+ self.vnf._vnf_process._is_alive.return_value = 1
+ self.vnf.queue_wrapper = mock.Mock()
+ self.vnf.q_out = mock.Mock()
+ self.vnf.q_out.qsize.side_effect = iter(queue_size_list)
+ self.vnf.q_out.get.side_effect = iter(queue_get_list)
+ self.vnf.ssh_helper = mock.MagicMock()
+ self.vnf.resource_helper.ssh_helper = mock.MagicMock()
+ self.vnf.resource_helper.start_collect = mock.MagicMock()
+
+ self.assertEqual(self.vnf.wait_for_instantiate(), 0)
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(ssh, 'SSH')
+ def test_wait_for_initialize(self, ssh, *args):
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
+ queue_get_list = [
+ 'some output',
+ 'pipeline> ',
+ 'run non_existent_script_name',
+ 'Cannot open file "non_existent_script_name"'
+ ]
+ queue_size_list = [
+ 0,
+ len(queue_get_list[0]),
+ 0,
+ len(queue_get_list[1]),
+ len(queue_get_list[2]),
+ 0,
+ len(queue_get_list[3])
+ ]
+ self.vnf.WAIT_TIME_FOR_SCRIPT = 0
+ self.vnf._start_server = mock.Mock(return_value=0)
+ self.vnf._vnf_process = mock.MagicMock()
+ self.vnf._vnf_process.exitcode = 0
+ self.vnf._vnf_process._is_alive.return_value = 1
+ self.vnf.queue_wrapper = mock.Mock()
+ self.vnf.q_out = mock.Mock()
+ self.vnf.q_out.qsize.side_effect = iter(queue_size_list)
+ self.vnf.q_out.get.side_effect = iter(queue_get_list)
+ self.vnf.ssh_helper = mock.MagicMock()
+ self.vnf.resource_helper.ssh_helper = mock.MagicMock()
+ self.vnf.resource_helper.start_collect = mock.MagicMock()
+
+ self.assertEqual(self.vnf.wait_for_initialize(), 0)
+
+ @mock.patch.object(time, "sleep")
+ def test_vnf_execute_with_queue_data(self, *args):
+ queue_size_list = [
+ 1,
+ 1,
+ 0,
+ ]
+
+ queue_get_list = [
+ 'hello ',
+ 'world'
+ ]
+ self.vnf.q_out = mock.Mock()
+ self.vnf.q_out.qsize.side_effect = iter(queue_size_list)
+ self.vnf.q_out.get.side_effect = iter(queue_get_list)
+
+ self.assertEqual(self.vnf.vnf_execute('my command'), 'hello world')
+
+ def test_terminate_without_vnf_process(self):
+ self.vnf.vnf_execute = mock.Mock()
+ self.vnf.ssh_helper = mock.Mock()
+ self.vnf._tear_down = mock.Mock()
+ self.vnf.resource_helper = mock.Mock()
+
+ self.assertIsNone(self.vnf.terminate())
+
+ def test_get_stats(self):
+ self.vnf.APP_WORD = 'sample1'
+ self.vnf.vnf_execute = mock.Mock(return_value='the stats')
+
+ self.assertEqual(self.vnf.get_stats(), 'the stats')
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ self.vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {self.vnf.name: "mock"}
+ }
+ self.vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
+ self.vnf.COLLECT_MAP = {
+ 'k1': 3,
+ 'k2': 1,
+ 'k3': 2,
+ }
+ self.vnf.get_stats = mock.Mock(return_value='index0: 34 -- 91, 27')
+ self.vnf.resource_helper = mock.Mock()
+ self.vnf.resource_helper.collect_kpi.return_value = {}
+
+ expected = {
+ 'k1': 27,
+ 'k2': 34,
+ 'k3': 91,
+ 'collect_stats': {},
+ 'physical_node': 'mock_node'
+ }
+ result = self.vnf.collect_kpi()
+ self.assertEqual(result, expected)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ def test_collect_kpi_default(self, *args):
+ self.vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {self.vnf.name: "mock"}
+ }
+ self.vnf.COLLECT_KPI = r'\s(\d+)\D*(\d+)\D*(\d+)'
+ self.vnf.get_stats = mock.Mock(return_value='')
+
+ expected = {
+ 'physical_node': 'mock_node',
+ 'packets_in': 0,
+ 'packets_fwd': 0,
+ 'packets_dropped': 0,
+ }
+ result = self.vnf.collect_kpi()
+ self.assertEqual(result, expected)
+
+ def test_scale(self):
+ self.assertRaises(y_exceptions.FunctionNotImplemented, self.vnf.scale)
+
+ def test__run(self):
+ test_cmd = 'test cmd'
+ run_kwargs = {'arg1': 'val1', 'arg2': 'val2'}
+ self.vnf.ssh_helper = mock.Mock()
+ self.vnf.setup_helper = mock.Mock()
+ with mock.patch.object(self.vnf, '_build_config',
+ return_value=test_cmd), \
+ mock.patch.object(self.vnf, '_build_run_kwargs'):
+ self.vnf.run_kwargs = run_kwargs
+ self.vnf._run()
+ self.vnf.ssh_helper.drop_connection.assert_called_once()
+ self.vnf.ssh_helper.run.assert_called_once_with(test_cmd, **run_kwargs)
+ self.vnf.setup_helper.kill_vnf.assert_called_once()
+
+
+class TestSampleVNFTrafficGen(unittest.TestCase):
+
+ VNFD_0 = TestSampleVnf.VNFD_0
+ VNFD = TestSampleVnf.VNFD
+
+ TRAFFIC_PROFILE = TestSampleVnf.TRAFFIC_PROFILE
+
+ def setUp(self):
+ self.sample_vnf_tg = sample_vnf.SampleVNFTrafficGen(
+ 'tg1', self.VNFD_0)
+
+ def test__check_status(self):
+
+ with self.assertRaises(NotImplementedError):
+ self.sample_vnf_tg._check_status()
+
+ def test_listen_traffic(self):
+ self.sample_vnf_tg.listen_traffic(mock.Mock())
+
+ def test_verify_traffic(self):
+ self.sample_vnf_tg.verify_traffic(mock.Mock())
+
+ def test_terminate(self):
+ self.sample_vnf_tg._traffic_process = mock.Mock()
+ self.sample_vnf_tg._tg_process = mock.Mock()
+
+ self.sample_vnf_tg.terminate()
+
+ @mock.patch.object(time, 'sleep')
+ def test__wait_for_process(self, *args):
+ with mock.patch.object(self.sample_vnf_tg, '_check_status',
+ return_value=0) as mock_status, \
+ mock.patch.object(self.sample_vnf_tg, '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = True
+ mock_proc.exitcode = 234
+ self.assertEqual(self.sample_vnf_tg._wait_for_process(), 234)
+ mock_proc.is_alive.assert_called_once()
+ mock_status.assert_called_once()
+
+ def test__wait_for_process_not_alive(self):
+ with mock.patch.object(self.sample_vnf_tg, '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = False
+ self.assertRaises(RuntimeError, self.sample_vnf_tg._wait_for_process)
+ mock_proc.is_alive.assert_called_once()
+
+ @mock.patch.object(time, 'sleep')
+ def test__wait_for_process_delayed(self, *args):
+ with mock.patch.object(self.sample_vnf_tg, '_check_status',
+ side_effect=[1, 0]) as mock_status, \
+ mock.patch.object(self.sample_vnf_tg,
+ '_tg_process') as mock_proc:
+ mock_proc.is_alive.return_value = True
+ mock_proc.exitcode = 234
+ self.assertEqual(self.sample_vnf_tg._wait_for_process(), 234)
+ mock_proc.is_alive.assert_has_calls([mock.call(), mock.call()])
+ mock_status.assert_has_calls([mock.call(), mock.call()])
+
+ def test_scale(self):
+ self.assertRaises(y_exceptions.FunctionNotImplemented,
+ self.sample_vnf_tg.scale)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_imsbench_sipp.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_imsbench_sipp.py
new file mode 100644
index 000000000..698b1b03f
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_imsbench_sipp.py
@@ -0,0 +1,481 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import mock
+import unittest
+from collections import deque
+
+from yardstick.network_services.vnf_generic.vnf import tg_imsbench_sipp
+from yardstick import ssh
+
+
+class TestSippVnf(unittest.TestCase):
+
+ VNFD = {
+ "short-name": "SippVnf",
+ "vdu": [
+ {
+ "id": "sippvnf-baremetal",
+ "routing_table": "",
+ "external-interface": [
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe0",
+ "name": "xe0"
+ },
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe1",
+ "name": "xe1"
+ }
+ ],
+ "name": "sippvnf-baremetal",
+ "description": "Sipp"
+ }
+ ],
+ "description": "ImsbenchSipp",
+ "mgmt-interface": {
+ "vdu-id": "sipp-baremetal",
+ "password": "r00t",
+ "user": "root",
+ "ip": "10.80.3.11"
+ },
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "id": "SippVnf",
+ "name": "SippVnf"
+ }
+
+ SCENARIO_CFG = {
+ "task_id": "ba636744-898e-4783-a4aa-0a79c60953cc",
+ "tc": "tc_vims_baremetal_sipp",
+ "runner": {
+ "interval": 1,
+ "output_config": {
+ "DEFAULT": {
+ "debug": "False",
+ "dispatcher": [
+ "influxdb"
+ ]
+ },
+ "nsb": {
+ "debug": "False",
+ "trex_client_lib": "/opt/nsb_bin/trex_client/stl",
+ "bin_path": "/opt/nsb_bin",
+ "trex_path": "/opt/nsb_bin/trex/scripts",
+ "dispatcher": "influxdb"
+ },
+ "dispatcher_influxdb": {
+ "username": "root",
+ "target": "http://10.80.3.11:8086",
+ "db_name": "yardstick",
+ "timeout": "5",
+ "debug": "False",
+ "password": "root",
+ "dispatcher": "influxdb"
+ },
+ "dispatcher_http": {
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "timeout": "5",
+ "target": "http://127.0.0.1:8000/results"
+ },
+ "dispatcher_file": {
+ "debug": "False",
+ "backup_count": "0",
+ "max_bytes": "0",
+ "dispatcher": "influxdb",
+ "file_path": "/tmp/yardstick.out"
+ }
+ },
+ "runner_id": 18148,
+ "duration": 60,
+ "type": "Vims"
+ },
+ "nodes": {
+ "vnf__0": "pcscf.yardstick-ba636744",
+ "vnf__1": "hss.yardstick-ba636744",
+ "tg__0": "sipp.yardstick-ba636744"
+ },
+ "topology": "vims-topology.yaml",
+ "type": "NSPerf",
+ "traffic_profile": "../../traffic_profiles/ipv4_throughput.yaml",
+ "task_path": "samples/vnf_samples/nsut/vims",
+ "options": {
+ "init_reg_max": 5000,
+ "end_user": 10000,
+ "reg_cps": 20,
+ "rereg_cps": 20,
+ "rereg_step": 10,
+ "wait_time": 5,
+ "start_user": 1,
+ "msgc_cps": 10,
+ "dereg_step": 10,
+ "call_cps": 10,
+ "reg_step": 10,
+ "init_reg_cps": 50,
+ "dereg_cps": 20,
+ "msgc_step": 5,
+ "call_step": 5,
+ "hold_time": 15,
+ "port": 5060,
+ "run_mode": "nortp"
+ }
+ }
+ CONTEXT_CFG = {
+ "nodes": {
+ "tg__0": {
+ "ip": "10.80.3.11",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "xe1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/tg_sipp_vnfd.yaml",
+ "name": "sipp.yardstick-a75a3aff",
+ "vnfd-id-ref": "tg__0",
+ "member-vnf-index": "1",
+ "role": "TrafficGen",
+ "ctx_type": "Node"
+ },
+ "vnf__0": {
+ "ip": "10.80.3.7",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "tg__0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/vims_pcscf_vnfd.yaml",
+ "name": "pcscf.yardstick-a75a3aff",
+ "vnfd-id-ref": "vnf__0",
+ "member-vnf-index": "2",
+ "role": "VirtualNetworkFunction",
+ "ctx_type": "Node"
+ },
+ "vnf__1": {
+ "ip": "10.80.3.7",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "tg__0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/vims_hss_vnfd.yaml",
+ "name": "hss.yardstick-a75a3aff",
+ "vnfd-id-ref": "vnf__1",
+ "member-vnf-index": "3",
+ "role": "VirtualNetworkFunction",
+ "ctx_type": "Node"
+ }
+ },
+ "networks": {}
+ }
+
+ FILE = "timestamp:1000 reg:100 reg_saps:0"
+
+ QUEUE = {'reg_saps': 0.0, 'timestamp': 1000.0, 'reg': 100.0}
+
+ TRAFFIC_PROFILE = {
+ "schema": "nsb:traffic_profile:0.1",
+ "name": "sip",
+ "description": "Traffic profile to run sip",
+ "traffic_profile": {
+ "traffic_type": "SipProfile",
+ "frame_rate": 100, # pps
+ "enable_latency": False
+ },
+ }
+
+ def setUp(self):
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+
+ self.addCleanup(self._stop_mocks)
+ self.sipp_vnf = tg_imsbench_sipp.SippVnf('tg__0', self.VNFD)
+
+ def _stop_mocks(self):
+ self._mock_ssh.stop()
+
+ def test___init__(self):
+ self.assertIsInstance(self.sipp_vnf.resource_helper,
+ tg_imsbench_sipp.SippResourceHelper)
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.sipp_vnf.wait_for_instantiate())
+
+ @mock.patch('six.moves.builtins.open', new_callable=mock.mock_open, read_data=FILE)
+ def test_handle_result_files(self, mock_file):
+ result_deque = deque([self.QUEUE])
+ file = "/tmp/test.txt"
+ test = self.sipp_vnf.handle_result_files(file)
+ self.assertEqual(result_deque, test)
+ mock_file.assert_called_with(file, 'r')
+
+ @mock.patch.object(ssh.SSH, 'get')
+ def test_get_result_files(self, mock_get):
+ self.sipp_vnf.get_result_files()
+ mock_get.assert_called()
+
+ def test_collect_kpi(self):
+ self.sipp_vnf.queue = deque([self.QUEUE])
+ self.assertEqual(self.QUEUE, self.sipp_vnf.collect_kpi())
+
+ def test_collect_kpi_empty(self):
+ self.sipp_vnf.queue = deque([])
+ self.assertEqual({}, self.sipp_vnf.collect_kpi())
+
+ @mock.patch('six.moves.builtins.open', new_callable=mock.mock_open, read_data=FILE)
+ def test_count_line_num(self, mock_file):
+ file = "/tmp/test.txt"
+ mock_file.return_value.__iter__.return_value = self.FILE.splitlines()
+ self.assertEqual(1, self.sipp_vnf.count_line_num(file))
+ mock_file.assert_called_with(file, 'r')
+
+ @mock.patch('six.moves.builtins.open', new_callable=mock.mock_open, read_data='')
+ def test_count_line_num_file_empty(self, mock_file):
+ file = "/tmp/test.txt"
+ self.assertEqual(0, self.sipp_vnf.count_line_num(file))
+ mock_file.assert_called_with(file, 'r')
+
+ @mock.patch('six.moves.builtins.open', new_callable=mock.mock_open, read_data=FILE)
+ def test_count_line_num_file_error(self, mock_file):
+ file = "/tmp/test.txt"
+ mock_file.side_effect = IOError()
+ self.assertEqual(0, self.sipp_vnf.count_line_num(file))
+
+ def test_is_ended_false(self):
+ self.sipp_vnf.count_line_num = mock.Mock(return_value=1)
+ not_end = self.sipp_vnf.is_ended()
+ self.assertFalse(not_end)
+
+ def test_is_ended_true(self):
+ self.sipp_vnf.count_line_num = mock.Mock(return_value=0)
+ end = self.sipp_vnf.is_ended()
+ self.assertTrue(end)
+
+ def test_terminate(self):
+ self.sipp_vnf.ssh_helper = mock.MagicMock()
+ self.sipp_vnf.resource_helper.ssh_helper = mock.MagicMock()
+ self.assertIsNone(self.sipp_vnf.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py
new file mode 100644
index 000000000..dd1c277c3
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ixload.py
@@ -0,0 +1,287 @@
+# Copyright (c) 2016-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.
+
+import subprocess
+
+import mock
+import six
+
+from yardstick import ssh
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.common import utils
+from yardstick.network_services.vnf_generic.vnf import tg_ixload
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.tests.unit import base as ut_base
+
+
+NAME = "tg__1"
+
+
+class TestIxLoadTrafficGen(ut_base.BaseUnitTestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vld_id': 'uplink_0',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vld_id': 'downlink_0',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ def setUp(self):
+ self._mock_call = mock.patch.object(subprocess, 'call')
+ self.mock_call = self._mock_call.start()
+ self._mock_open = mock.patch.object(tg_ixload, 'open')
+ self.mock_open = self._mock_open.start()
+ self._mock_ssh = mock.patch.object(ssh, 'SSH')
+ self.mock_ssh = self._mock_ssh.start()
+ ssh_obj_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_obj_mock.execute = mock.Mock(return_value=(0, '', ''))
+ ssh_obj_mock.run = mock.Mock(return_value=(0, '', ''))
+ self.mock_ssh.from_node.return_value = ssh_obj_mock
+ self.addCleanup(self._stop_mock)
+
+ def _stop_mock(self):
+ self._mock_call.stop()
+ self._mock_open.stop()
+ self._mock_ssh.stop()
+
+ def test___init__(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ self.assertIsNone(ixload_traffic_gen.resource_helper.data)
+
+ def test_update_gateways(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ links = {'uplink_0': {'ip': {}},
+ 'downlink_1': {'ip': {}}}
+
+ ixload_traffic_gen.update_gateways(links)
+
+ self.assertEqual("152.16.100.20", links["uplink_0"]["ip"]["gateway"])
+ self.assertEqual("0.0.0.0", links["downlink_1"]["ip"]["gateway"])
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ ixload_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {ixload_traffic_gen.name: "mock"}
+ }
+ ixload_traffic_gen.data = {}
+ result = ixload_traffic_gen.collect_kpi()
+
+ expected = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {}}
+ self.assertEqual(expected, result)
+
+ def test_listen_traffic(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ self.assertIsNone(ixload_traffic_gen.listen_traffic({}))
+
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch.object(utils, 'makedirs')
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch.object(tg_ixload, 'shutil')
+ def test_instantiate(self, mock_shutil, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ scenario_cfg = {'tc': "nsb_test_case",
+ 'ixia_profile': "ixload.cfg",
+ 'task_path': "/path/to/task"}
+ ixload_traffic_gen.RESULTS_MOUNT = "/tmp/result"
+ mock_shutil.copy = mock.Mock()
+ scenario_cfg.update(
+ {'options':
+ {'packetsize': 64, 'traffic_type': 4,
+ 'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
+ 'vnf__1': {'rules': 'acl_1rule.yaml',
+ 'vnf_config': {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config':
+ '1C/1T',
+ 'worker_threads': 1}}
+ }
+ }
+ )
+ scenario_cfg.update({'nodes': {ixload_traffic_gen.name: "mock"}})
+ with mock.patch.object(six.moves.builtins, 'open',
+ create=True) as mock_open:
+ mock_open.return_value = mock.MagicMock()
+ ixload_traffic_gen.instantiate(scenario_cfg, {})
+
+ @mock.patch.object(tg_ixload, 'open')
+ @mock.patch.object(tg_ixload, 'min')
+ @mock.patch.object(tg_ixload, 'max')
+ @mock.patch.object(tg_ixload, 'len')
+ @mock.patch.object(tg_ixload, 'shutil')
+ def test_run_traffic(self, *args):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = '64'
+ mock_traffic_profile.get_links_param.return_value = {
+ 'uplink_0': {'ip': {}}}
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vnfd['mgmt-interface'].update({'tg-config': {}})
+ vnfd['mgmt-interface']['tg-config'].update({'ixchassis': '1.1.1.1'})
+ vnfd['mgmt-interface']['tg-config'].update({'py_bin_path': '/root'})
+ sut = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ sut.connection = mock.Mock()
+ sut._traffic_runner = mock.Mock(return_value=0)
+ result = sut.run_traffic(mock_traffic_profile)
+ self.assertIsNone(result)
+
+ @mock.patch.object(tg_ixload, 'open')
+ @mock.patch.object(tg_ixload, 'min')
+ @mock.patch.object(tg_ixload, 'max')
+ @mock.patch.object(tg_ixload, 'len')
+ @mock.patch.object(tg_ixload, 'shutil')
+ def test_run_traffic_csv(self, *args):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = '64'
+ mock_traffic_profile.get_links_param.return_value = {
+ 'uplink_0': {'ip': {}}}
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vnfd['mgmt-interface'].update({'tg-config': {}})
+ vnfd['mgmt-interface']['tg-config'].update({'ixchassis': '1.1.1.1'})
+ vnfd['mgmt-interface']['tg-config'].update({'py_bin_path': '/root'})
+ sut = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ sut.connection = mock.Mock()
+ sut._traffic_runner = mock.Mock(return_value=0)
+ subprocess.call(['touch', '/tmp/1.csv'])
+ sut.rel_bin_path = mock.Mock(return_value='/tmp/*.csv')
+ result = sut.run_traffic(mock_traffic_profile)
+ self.assertIsNone(result)
+
+ def test_terminate(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ self.assertIsNone(ixload_traffic_gen.terminate())
+
+ def test_parse_csv_read(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ kpi_data = {
+ 'HTTP Total Throughput (Kbps)': 1,
+ 'HTTP Simulated Users': 2,
+ 'HTTP Concurrent Connections': '3',
+ 'HTTP Connection Rate': 4.3,
+ 'HTTP Transaction Rate': True,
+ }
+ http_reader = [kpi_data]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ result = ixload_traffic_gen.resource_helper.result
+ ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
+ for k_left, k_right in tg_ixload.IxLoadResourceHelper.KPI_LIST.items():
+ self.assertEqual(result[k_left][-1], int(kpi_data[k_right]))
+
+ def test_parse_csv_read_value_error(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ http_reader = [{
+ 'HTTP Total Throughput (Kbps)': 1,
+ 'HTTP Simulated Users': 2,
+ 'HTTP Concurrent Connections': "not a number",
+ 'HTTP Connection Rate': 4,
+ 'HTTP Transaction Rate': 5,
+ }]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ init_value = ixload_traffic_gen.resource_helper.result
+ ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
+ self.assertDictEqual(ixload_traffic_gen.resource_helper.result,
+ init_value)
+
+ def test_parse_csv_read_error(self,):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ http_reader = [{
+ 'HTTP Total Throughput (Kbps)': 1,
+ 'HTTP Simulated Users': 2,
+ 'HTTP Concurrent Connections': 3,
+ 'HTTP Transaction Rate': 5,
+ }]
+ ixload_traffic_gen = tg_ixload.IxLoadTrafficGen(NAME, vnfd)
+ with self.assertRaises(KeyError):
+ ixload_traffic_gen.resource_helper.parse_csv_read(http_reader)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py
new file mode 100644
index 000000000..2d8c01bec
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_landslide.py
@@ -0,0 +1,1951 @@
+# Copyright (c) 2018-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.
+
+import copy
+import mock
+import requests
+import time
+import unittest
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.common import exceptions
+from yardstick.common import utils as common_utils
+from yardstick.common import yaml_loader
+from yardstick.network_services import utils as net_serv_utils
+from yardstick.network_services.traffic_profile import landslide_profile
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_landslide
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+
+NAME = "tg__0"
+
+EXAMPLE_URL = 'http://example.com/'
+TCL_SUCCESS_RESPONSE = 'ls_ok'
+
+TEST_SERVERS = [
+ {'ip': '192.168.122.101',
+ 'phySubnets': [
+ {'mask': '/24',
+ 'base': '10.42.32.100',
+ 'numIps': 20,
+ 'name': 'eth1'}
+ ],
+ 'role': 'SGW_Node',
+ 'name': 'TestServer_1'},
+ {'ip': '192.168.122.102',
+ 'phySubnets': [
+ {'mask': '/24',
+ 'base': '10.42.32.1',
+ 'numIps': 100,
+ 'name': 'eth1'
+ },
+ {'mask': '/24',
+ 'base': '10.42.33.1',
+ 'numIps': 100,
+ 'name': 'eth2'}
+ ],
+ 'preResolvedArpAddress': [
+ {'NumNodes': 1,
+ 'StartingAddress': '10.42.33.5'}
+ ],
+ 'role': 'SGW_Nodal',
+ 'name': 'TestServer_2',
+ 'thread_model': 'Fireball'
+ }
+]
+
+TS1_SUTS = [
+ {'name': 'SGW - C TestNode',
+ 'role': 'SgwControlAddr',
+ 'managementIp': '12.0.1.1',
+ 'ip': '10.42.32.100',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'SGW - U TestNode',
+ 'role': 'SgwUserAddr',
+ 'managementIp': '12.0.1.2',
+ 'ip': '10.42.32.101',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ }
+]
+
+TS2_SUTS = [
+ {'name': 'eNodeB TestNode',
+ 'role': 'EnbUserAddr',
+ 'managementIp': '12.0.2.1',
+ 'ip': '10.42.32.2',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'MME TestNode',
+ 'role': 'MmeControlAddr',
+ 'managementIp': '12.0.3.1',
+ 'ip': '10.42.32.1',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'NetHost TestNode',
+ 'role': 'NetworkHostAddrLocal',
+ 'managementIp': '12.0.4.1',
+ 'ip': '10.42.33.1',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'PGW TestNode',
+ 'role': 'PgwV4Sut',
+ 'managementIp': '12.0.5.1',
+ 'ip': '10.42.32.105',
+ 'phy': 'eth5',
+ 'nextHop': '10.42.32.5'
+ },
+ {'name': 'SGW - C SUT',
+ 'role': 'SgwSut',
+ 'managementIp': '12.0.6.1',
+ 'ip': '10.42.32.100'
+ },
+ {'name': 'SGW - U SUT',
+ 'role': 'SgwUserSut',
+ 'managementIp': '12.0.6.2',
+ 'ip': '10.42.32.101'}
+]
+
+VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [{
+ 'short-name': 'landslide',
+ 'vdu': [{
+ 'description': 'AB client interface details',
+ 'name': 'abclient-baremetal',
+ 'id': 'abclient-baremetal',
+ 'external-interface': []}],
+ 'description': 'Spirent Landslide traffic generator',
+ 'config': [{'test_server': TEST_SERVERS[0], 'suts': TS1_SUTS},
+ {'test_server': TEST_SERVERS[1], 'suts': TS2_SUTS}],
+ 'mgmt-interface': {
+ 'vdu-id': 'landslide-tas',
+ 'user': 'user',
+ 'password': 'user',
+ 'super-user': 'super-user',
+ 'super-user-password': 'super-user-password',
+ 'cfguser_password': 'cfguser_password',
+ 'license': 48,
+ 'proto': 'http',
+ 'ip': '1.1.1.1'},
+ 'benchmark': {
+ 'kpi': [
+ 'tx_throughput_mbps',
+ 'rx_throughput_mbps',
+ 'in_packets',
+ 'out_packets',
+ 'activation_rate_sessps',
+ 'deactivation_rate_sessps']},
+ 'id': 'LandslideTrafficGen',
+ 'name': 'LandslideTrafficGen'}]}}
+
+TAS_INFO = VNFD['vnfd:vnfd-catalog']['vnfd'][0]['mgmt-interface']
+
+DMF_CFG = {
+ "dmf": {
+ "library": "test",
+ "name": "Basic UDP"
+ },
+ "clientPort": {
+ "clientPort": 2002,
+ "isClientPortRange": "false"
+ },
+ "dataProtocol": "udp",
+ "serverPort": 2003
+}
+
+RESERVATIONS = [
+ {'tsName': TEST_SERVERS[0]['name'],
+ 'phySubnets': TEST_SERVERS[0]['phySubnets'],
+ 'tsId': TEST_SERVERS[0]['name'],
+ 'tsIndex': 0},
+ {'tsName': TEST_SERVERS[1]['name'],
+ 'phySubnets': TEST_SERVERS[1]['phySubnets'],
+ 'tsId': TEST_SERVERS[1]['name'],
+ 'tsIndex': 1}]
+
+SESSION_PROFILE = {
+ 'keywords': '',
+ 'duration': 60,
+ 'iterations': 1,
+ 'description': 'UE default bearer creation test case',
+ 'name': 'default_bearer_capacity',
+ 'reportOptions': {'format': 'CSV'},
+ 'reservePorts': 'false',
+ 'tsGroups': [
+ {
+ 'testCases': [{
+ 'type': 'SGW_Node',
+ 'name': '',
+ 'linked': "false",
+ 'AssociatedPhys': '',
+ 'parameters': {
+ 'SgiPtpTunnelEn': 'false',
+ 'Gtp2Imsi': '505024101215074',
+ 'Sessions': '100000',
+ 'S5Protocol': 'GTPv2',
+ 'TrafficMtu': '1500',
+ 'Gtp2Version': '13.6.0',
+ 'BearerV4AddrPool': '1.0.0.1',
+ 'Gtp2Imei': '50502410121507',
+ 'PgwNodeEn': 'true',
+ 'DedicatedsPerDefaultBearer': '0',
+ 'DefaultBearers': '1',
+ 'SgwUserAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'SGW_USER_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'SgwControlAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'SGW_CONTROL_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500,
+ 'nextHop': 'SGW_CONTROL_NEXT_HOP'
+ },
+ 'BearerAddrPool': '2001::1',
+ 'TestType': 'SGW-NODE'
+ }
+ }],
+ 'tsId': TEST_SERVERS[0]['name']},
+ {
+ 'testCases': [{
+ 'type': 'SGW_Nodal',
+ 'name': '',
+ 'parameters': {
+ 'DataTraffic': 'Continuous',
+ 'TrafficStartType': 'When All Sessions Established',
+ 'NetworkHost': 'Local',
+ 'Gtp2Imsi': '505024101215074',
+ 'Dmf': {
+ 'mainflows': [
+ {
+ 'name': 'Basic UDP',
+ 'library': 'test'
+ }
+ ],
+ 'class': 'Dmf',
+ 'instanceGroups': [
+ {
+ 'startPaused': "false",
+ 'rate': 0,
+ 'mainflowIdx': 0,
+ 'mixType': ''
+ }
+ ]
+ },
+ 'S5Protocol': 'GTPv2',
+ 'DataUserCfgFileEn': 'false',
+ 'PgwUserSutEn': 'false',
+ 'MmeControlAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'MME_CONTROL_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'SgwUserSut': {
+ 'class': 'Sut',
+ 'name': 'SGW_USER_NAME'
+ },
+ 'TestActivity': 'Capacity Test',
+ 'NetworkHostAddrLocal': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth2',
+ 'forcedEthInterface': '',
+ 'ip': 'NET_HOST_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'DedicatedsPerDefaultBearer': '0',
+ 'DisconnectRate': '1000.0',
+ 'Sessions': '100000',
+ 'SgwSut': {
+ 'class': 'Sut',
+ 'name': 'SGW_CONTROL_NAME'
+ },
+ 'TrafficMtu': '1500',
+ 'Gtp2Version': '13.6.0',
+ 'Gtp2Imei': '50502410121507',
+ 'PgwNodeEn': 'false',
+ 'StartRate': '1000.0',
+ 'PgwV4Sut': {
+ 'class': 'Sut',
+ 'name': 'PGW_SUT_NAME'
+ },
+ 'DefaultBearers': '1',
+ 'EnbUserAddr': {
+ 'numLinksOrNodes': 1,
+ 'phy': 'eth1',
+ 'forcedEthInterface': '',
+ 'ip': 'ENB_USER_IP',
+ 'class': 'TestNode',
+ 'ethStatsEnabled': "false",
+ 'mtu': 1500
+ },
+ 'TestType': 'SGW-NODAL'
+ }
+ }],
+ 'tsId': TEST_SERVERS[1]['name']
+ }
+ ]
+}
+
+
+class TestLandslideTrafficGen(unittest.TestCase):
+ SCENARIO_CFG = {
+ 'session_profile': '/traffic_profiles/landslide/'
+ 'landslide_session_default_bearer.yaml',
+ 'task_path': '',
+ 'runner': {
+ 'type': 'Iteration',
+ 'iterations': 1
+ },
+ 'nodes': {
+ 'tg__0': 'tg__0.traffic_gen',
+ 'vnf__0': 'vnf__0.vnf_epc'
+ },
+ 'topology': 'landslide_tg_topology.yaml',
+ 'type': 'NSPerf',
+ 'traffic_profile': '../../traffic_profiles/landslide/'
+ 'landslide_dmf_udp.yaml',
+ 'options': {
+ 'traffic_duration': 71,
+ 'test_cases': [
+ {
+ 'BearerAddrPool': '2002::2',
+ 'type': 'SGW_Node',
+ 'BearerV4AddrPool': '2.0.0.2',
+ 'Sessions': '90000'
+ },
+ {
+ 'StartRate': '900.0',
+ 'type': 'SGW_Nodal',
+ 'DisconnectRate': '900.0',
+ 'Sessions': '90000'
+ }
+ ],
+ 'dmf':
+ {
+ 'transactionRate': 1000,
+ 'packetSize': 512
+ }
+ }
+ }
+
+ CONTEXT_CFG = {
+ 'contexts': [
+ {
+ 'type': 'Node',
+ 'name': 'traffic_gen',
+ 'file': '/etc/yardstick/nodes/pod_landslide.yaml'
+ },
+ {
+ 'type': 'Node',
+ 'name': 'vnf_epc',
+ 'file': '/etc/yardstick/nodes/pod_vepc_sut.yaml'
+ }
+ ]
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "nsb:traffic_profile:0.1",
+ "name": "LandslideProfile",
+ "description": "Spirent Landslide traffic profile",
+ "traffic_profile": {
+ "traffic_type": "LandslideProfile"
+ },
+ "dmf_config": {
+ "dmf": {
+ "library": "test",
+ "name": "Basic UDP"
+ },
+ "description": "Basic data flow using UDP/IP",
+ "keywords": "UDP",
+ "dataProtocol": "udp"
+ }
+ }
+
+ SUCCESS_CREATED_CODE = 201
+ SUCCESS_OK_CODE = 200
+ SUCCESS_RECORD_ID = 5
+ TEST_USER_ID = 11
+
+ def setUp(self):
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ self.mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper.start()
+ self.vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.ls_tg = tg_landslide.LandslideTrafficGen(
+ NAME, self.vnfd)
+ self.session_profile = copy.deepcopy(SESSION_PROFILE)
+ self.ls_tg.session_profile = self.session_profile
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+ self.mock_ssh_helper.stop()
+
+ @mock.patch.object(net_serv_utils, 'get_nsb_option')
+ def test___init__(self, mock_get_nsb_option, *args):
+ _path_to_nsb = 'path/to/nsb'
+ mock_get_nsb_option.return_value = _path_to_nsb
+ ls_tg = tg_landslide.LandslideTrafficGen(NAME, self.vnfd)
+ self.assertIsInstance(ls_tg.resource_helper,
+ tg_landslide.LandslideResourceHelper)
+ mock_get_nsb_option.assert_called_once_with('bin_path')
+ self.assertEqual(_path_to_nsb, ls_tg.bin_path)
+ self.assertEqual(NAME, ls_tg.name)
+ self.assertTrue(ls_tg.runs_traffic)
+ self.assertFalse(ls_tg.traffic_finished)
+ self.assertIsNone(ls_tg.session_profile)
+
+ def test_listen_traffic(self):
+ _traffic_profile = {}
+ self.assertIsNone(self.ls_tg.listen_traffic(_traffic_profile))
+
+ def test_terminate(self, *args):
+ self.ls_tg.resource_helper._tcl = mock.Mock()
+ self.assertIsNone(self.ls_tg.terminate())
+ self.ls_tg.resource_helper._tcl.disconnect.assert_called_once()
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate(self, *args):
+ self.ls_tg._tg_process = mock.Mock()
+ self.ls_tg._tg_process.start = mock.Mock()
+ self.ls_tg.resource_helper.connect = mock.Mock()
+ self.ls_tg.resource_helper.create_test_servers = mock.Mock()
+ self.ls_tg.resource_helper.create_suts = mock.Mock()
+ self.ls_tg._load_session_profile = mock.Mock()
+ self.assertIsNone(self.ls_tg.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
+ self.ls_tg.resource_helper.connect.assert_called_once()
+ self.ls_tg.resource_helper.create_test_servers.assert_called_once()
+ _suts_blocks_num = len([item['suts'] for item in self.vnfd['config']])
+ self.assertEqual(_suts_blocks_num,
+ self.ls_tg.resource_helper.create_suts.call_count)
+ self.ls_tg._load_session_profile.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_run_traffic(self, mock_get_tests, *args):
+ self.ls_tg.resource_helper._url = EXAMPLE_URL
+ self.ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_traffic_profile = mock.Mock(
+ spec=landslide_profile.LandslideProfile)
+ mock_traffic_profile.dmf_config = {
+ 'keywords': 'UDP',
+ 'dataProtocol': 'udp',
+ 'dmf': {'library': 'test', 'name': 'name'}}
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ self.ls_tg.resource_helper._user_id = self.TEST_USER_ID
+ mock_get_tests.return_value = [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'COMPLETE'}]
+ mock_post = mock.Mock()
+ mock_post.status_code = self.SUCCESS_CREATED_CODE
+ mock_post.json.return_value = {'id': self.SUCCESS_RECORD_ID}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value = mock_post
+ self.ls_tg.resource_helper.session = mock_session
+ self.ls_tg.resource_helper._tcl = mock.Mock()
+ _tcl = self.ls_tg.resource_helper._tcl
+ self.assertIsNone(self.ls_tg.run_traffic(mock_traffic_profile))
+ self.assertEqual(self.SUCCESS_RECORD_ID,
+ self.ls_tg.resource_helper.run_id)
+ mock_traffic_profile.update_dmf.assert_called_with(
+ self.ls_tg.scenario_helper.all_options)
+ _tcl.create_dmf.assert_called_with(mock_traffic_profile.dmf_config)
+ _tcl.create_test_session.assert_called_with(self.session_profile)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ def test_collect_kpi(self, mock_check_running_test_state, *args):
+ self.ls_tg.resource_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_check_running_test_state.return_value = 'COMPLETE'
+ self.assertEqual({'done': True}, self.ls_tg.collect_kpi())
+ mock_check_running_test_state.assert_called_once()
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.ls_tg.wait_for_instantiate())
+ self.ls_tg.wait_for_instantiate()
+
+ def test__update_session_suts_no_tc_role(self, *args):
+ _suts = [{'role': 'epc_role'}]
+ _testcase = {'parameters': {'diff_epc_role': {'class': 'Sut'}}}
+ res = self.ls_tg._update_session_suts(_suts, _testcase)
+ self.assertEqual(_testcase, res)
+
+ def test__update_session_suts(self, *args):
+
+ def get_testnode_param(role, key, session_prof):
+ """ Get value by key from the deep nested dict to avoid calls like:
+ e.g. session_prof['tsGroups'][0]['testCases'][1]['parameters'][key]
+ """
+ for group in session_prof['tsGroups']:
+ for tc in group['testCases']:
+ tc_params = tc['parameters']
+ if tc_params.get(role):
+ return tc_params[role][key]
+
+ def get_sut_param(role, key, suts):
+ """ Search list of dicts for one with specific role.
+ Return the value of related dict by key. Expect key presence.
+ """
+ for sut in suts:
+ if sut.get('role') == role:
+ return sut[key]
+
+ # TestNode to verify
+ testnode_role = 'SgwControlAddr'
+ # SUT to verify
+ sut_role = 'SgwUserSut'
+
+ config_suts = [config['suts'] for config in self.vnfd['config']]
+ session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
+ for _tc in _ts_group['testCases']]
+ for suts, tc in zip(config_suts, session_tcs):
+ self.assertEqual(tc, self.ls_tg._update_session_suts(suts, tc))
+
+ # Verify TestNode class objects keys were updated
+ for _key in {'ip', 'phy', 'nextHop'}:
+ self.assertEqual(
+ get_testnode_param(testnode_role, _key, self.ls_tg.session_profile),
+ get_sut_param(testnode_role, _key, TS1_SUTS))
+ # Verify Sut class objects name was updated
+ self.assertEqual(
+ get_testnode_param(sut_role, 'name', self.ls_tg.session_profile),
+ get_sut_param(sut_role, 'name', TS2_SUTS))
+
+ def test__update_session_test_servers(self, *args):
+ for ts_index, ts in enumerate(TEST_SERVERS):
+ self.assertIsNone(
+ self.ls_tg._update_session_test_servers(ts, ts_index))
+ # Verify preResolvedArpAddress key was added
+ self.assertTrue(any(
+ _item.get('preResolvedArpAddress')
+ for _item in self.ls_tg.session_profile['tsGroups']))
+ # Verify reservations key was added to session profile
+ self.assertEqual(RESERVATIONS,
+ self.ls_tg.session_profile.get('reservations'))
+ self.assertEqual('true',
+ self.ls_tg.session_profile.get('reservePorts'))
+
+ def test__update_session_tc_params_assoc_phys(self):
+ _tc_options = {'AssociatedPhys': 'eth1'}
+ _testcase = {}
+ _testcase_orig = copy.deepcopy(_testcase)
+ res = self.ls_tg._update_session_tc_params(_tc_options, _testcase)
+ self.assertNotEqual(_testcase_orig, res)
+ self.assertEqual(_tc_options, _testcase)
+
+ def test__update_session_tc_params(self, *args):
+
+ def get_session_tc_param_value(param, tc_type, session_prof):
+ """ Get param value from the deep nested dict to avoid calls like:
+ session_prof['tsGroups'][0]['testCases'][0]['parameters'][key]
+ """
+ for test_group in session_prof['tsGroups']:
+ session_tc = test_group['testCases'][0]
+ if session_tc['type'] == tc_type:
+ return session_tc['parameters'].get(param)
+
+ session_tcs = [_tc for _ts_group in self.ls_tg.session_profile['tsGroups']
+ for _tc in _ts_group['testCases']]
+ scenario_tcs = [_tc for _tc in
+ self.SCENARIO_CFG['options']['test_cases']]
+ for tc_options, tc in zip(scenario_tcs, session_tcs):
+ self.assertEqual(
+ tc,
+ self.ls_tg._update_session_tc_params(tc_options, tc))
+
+ # Verify that each test case parameter was updated
+ # Params been compared are deeply nested. Using loops to ease access.
+ for _tc in self.SCENARIO_CFG['options']['test_cases']:
+ for _key, _val in _tc.items():
+ if _key != 'type':
+ self.assertEqual(
+ _val,
+ get_session_tc_param_value(_key, _tc.get('type'),
+ self.ls_tg.session_profile))
+
+ def test__update_session_library_name(self, *args):
+ _session = copy.deepcopy(SESSION_PROFILE)
+ _session['tsGroups'].pop(0)
+ self.ls_tg.vnfd_helper = mock.MagicMock()
+ self.ls_tg.vnfd_helper.mgmt_interface.__getitem__.side_effect = {
+ 'user': TAS_INFO['user']}
+ self.ls_tg._update_session_library_name(_session)
+ _dmf = _session['tsGroups'][0]['testCases'][0]['parameters']['Dmf']
+ # Expect DMF library name updated in Nodal test types
+ self.assertEqual(TAS_INFO['user'], _dmf['mainflows'][0]['library'])
+
+ def test__update_session_library_name_wrong_tc_type(self, *args):
+ _session = copy.deepcopy(SESSION_PROFILE)
+ _session['tsGroups'].pop(1)
+ self.ls_tg.vnfd_helper = mock.MagicMock()
+ self.ls_tg.vnfd_helper.mgmt_interface.__getitem__.side_effect = {
+ 'user': TAS_INFO['user']}
+ # Expect DMF library name not updated in Node test types
+ self.assertNotIn('Dmf',
+ _session['tsGroups'][0]['testCases'][0]['parameters'])
+ self.ls_tg._update_session_library_name(_session)
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_test_servers')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_suts')
+ @mock.patch.object(tg_landslide.LandslideTrafficGen,
+ '_update_session_tc_params')
+ def test__load_session_profile(self, mock_upd_ses_tc_params,
+ mock_upd_ses_suts, mock_upd_ses_ts,
+ mock_yaml_load, *args):
+ self.ls_tg.scenario_helper.scenario_cfg = \
+ copy.deepcopy(self.SCENARIO_CFG)
+ mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
+ self.assertIsNone(self.ls_tg._load_session_profile())
+ self.assertIsNotNone(self.ls_tg.session_profile)
+ # Number of blocks in configuration files
+ # Number of test servers, suts and tc params blocks should be equal
+ _config_files_blocks_num = len([item['test_server']
+ for item in self.vnfd['config']])
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_ts.call_count)
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_suts.call_count)
+ self.assertEqual(_config_files_blocks_num,
+ mock_upd_ses_tc_params.call_count)
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ def test__load_session_profile_unequal_num_of_cfg_blocks(
+ self, mock_yaml_load, *args):
+ vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ls_traffic_gen = tg_landslide.LandslideTrafficGen(NAME, vnfd)
+ ls_traffic_gen.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_yaml_load.return_value = copy.deepcopy(SESSION_PROFILE)
+ # Delete test_servers item from pod file to make it not valid
+ ls_traffic_gen.vnfd_helper['config'].pop()
+ with self.assertRaises(RuntimeError):
+ ls_traffic_gen._load_session_profile()
+
+ @mock.patch.object(common_utils, 'open_relative_file')
+ @mock.patch.object(yaml_loader, 'yaml_load')
+ def test__load_session_profile_test_type_mismatch(self, mock_yaml_load,
+ *args):
+ vnfd = copy.deepcopy(VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ # Swap test servers data in pod file
+ vnfd['config'] = list(reversed(vnfd['config']))
+ ls_tg = tg_landslide.LandslideTrafficGen(NAME, vnfd)
+ ls_tg.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+ mock_yaml_load.return_value = SESSION_PROFILE
+ with self.assertRaises(RuntimeError):
+ ls_tg._load_session_profile()
+
+
+class TestLandslideResourceHelper(unittest.TestCase):
+
+ PROTO_PORT = 8080
+ EXAMPLE_URL = ''.join([TAS_INFO['proto'], '://', TAS_INFO['ip'], ':',
+ str(PROTO_PORT), '/api/'])
+ SUCCESS_CREATED_CODE = 201
+ SUCCESS_OK_CODE = 200
+ INVALID_REST_CODE = '400'
+ NOT_MODIFIED_CODE = 500810
+ ERROR_CODE = 500800
+ SUCCESS_RECORD_ID = 11
+ EXPIRE_DATE = '2020/01/01 12:00 FLE Standard Time'
+ TEST_USER = 'test'
+ TEST_TERMINATED = 1
+ AUTH_DATA = {'user': TAS_INFO['user'], 'password': TAS_INFO['password']}
+ TEST_SESSION_NAME = 'default_bearer_capacity'
+
+ USERS_DATA = {
+ "users": [{
+ "url": ''.join([EXAMPLE_URL, 'users/', str(SUCCESS_RECORD_ID)]),
+ "id": SUCCESS_RECORD_ID,
+ "level": 1,
+ "username": TEST_USER
+ }]
+ }
+
+ CREATE_USER_DATA = {'username': TAS_INFO['user'],
+ 'expiresOn': EXPIRE_DATE,
+ 'level': 1,
+ 'contactInformation': '',
+ 'fullName': 'Test User',
+ 'password': TAS_INFO['password'],
+ 'isActive': 'true'}
+
+ SUTS_DATA = {
+ "suts": [
+ {
+ "url": ''.join([EXAMPLE_URL, 'suts/', str(SUCCESS_RECORD_ID)]),
+ "id": SUCCESS_RECORD_ID,
+ "name": "10.41.32.1"
+ }]}
+
+ TEST_SERVERS_DATA = {
+ "testServers": [
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/1"]),
+ "id": 1,
+ "name": TEST_SERVERS[0]['name'],
+ "state": "READY",
+ "version": "16.4.0.10"
+ },
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/2"]),
+ "id": 2,
+ "name": TEST_SERVERS[1]['name'],
+ "state": "READY",
+ "version": "16.4.0.10"
+ }
+
+ ]
+ }
+
+ RUN_ID = 3
+
+ RUNNING_TESTS_DATA = {
+ "runningTests": [{
+ "url": ''.join([EXAMPLE_URL, "runningTests/{}".format(RUN_ID)]),
+ "measurementsUrl": ''.join(
+ [EXAMPLE_URL,
+ "runningTests/{}/measurements".format(RUN_ID)]),
+ "criteriaUrl": ''.join(
+ [EXAMPLE_URL,
+ "runningTests/{}/criteria".format(RUN_ID)]),
+ "noteToUser": "",
+ "id": RUN_ID,
+ "library": SUCCESS_RECORD_ID,
+ "name": "default_bearer_capacity",
+ "user": TEST_USER,
+ "criteriaStatus": "NA",
+ "testStateOrStep": "COMPLETE"
+ }]}
+
+ TEST_RESULTS_DATA = {
+ "interval": 0,
+ "elapsedTime": 138,
+ "actualTime": 1521548057296,
+ "iteration": 1,
+ "tabs": {
+ "Test Summary": {
+ "Start Time": "Tue Mar 20 07:11:55 CDT 2018",
+ "Actual Dedicated Bearer Session Connects": "100",
+ "Actual Dedicated Bearer Session Disconnects": "100",
+ "Actual Disconnect Rate(Sessions / Second)(P - I)": "164.804",
+ "Average Session Disconnect Time(P - I)": "5.024 s",
+ "Total Data Sent + Received Packets / Sec(P - I)": "1,452.294"
+ }}}
+
+ def setUp(self):
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ mock_env_helper = mock.Mock()
+ self.res_helper = tg_landslide.LandslideResourceHelper(mock_env_helper)
+ self.res_helper._url = EXAMPLE_URL
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+ self.res_helper._url = None
+
+ def test___init__(self, *args):
+ self.assertIsInstance(self.res_helper,
+ tg_landslide.LandslideResourceHelper)
+ self.assertEqual({}, self.res_helper._result)
+ self.assertIsNone(self.res_helper.run_id)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests_no_running_tests(self, mock_get_tests,
+ mock_stop_tests, *args):
+ tests_data = [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'COMPLETE'}]
+ mock_get_tests.return_value = tests_data
+ self.assertIsNone(self.res_helper.abort_running_tests())
+ mock_stop_tests.assert_not_called()
+
+ @mock.patch.object(time, 'sleep')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests(self, mock_get_tests, mock_stop_tests, *args):
+ test_states_seq = iter(['RUNNING', 'COMPLETE'])
+
+ def configure_mock(*args):
+ return [{'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': next(test_states_seq)}]
+
+ mock_get_tests.side_effect = configure_mock
+ self.assertIsNone(self.res_helper.abort_running_tests())
+ mock_stop_tests.assert_called_once_with(
+ running_test_id=self.SUCCESS_RECORD_ID,
+ force=True)
+ self.assertEqual(2, mock_get_tests.call_count)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'stop_running_tests')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests')
+ def test_abort_running_tests_error(self, mock_get_tests, mock_stop_tests,
+ *args):
+ tests_data = {'id': self.SUCCESS_RECORD_ID,
+ 'testStateOrStep': 'RUNNING'}
+ mock_get_tests.return_value = [tests_data]
+ with self.assertRaises(RuntimeError):
+ self.res_helper.abort_running_tests(timeout=1, delay=1)
+ mock_stop_tests.assert_called_with(
+ running_test_id=self.SUCCESS_RECORD_ID,
+ force=True)
+
+ def test__build_url(self, *args):
+ resource = 'users'
+ action = {'action': 'userCreate'}
+ expected_url = ''.join([EXAMPLE_URL, 'users?action=userCreate'])
+ self.assertEqual(expected_url,
+ self.res_helper._build_url(resource, action))
+
+ def test__build_url_error(self, *args):
+ resource = ''
+ action = {'action': 'userCreate'}
+
+ with self.assertRaises(ValueError):
+ self.res_helper._build_url(resource, action)
+
+ def test_get_response_params(self, *args):
+ method = 'get'
+ resource = 'users'
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.USERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ resp = self.res_helper.get_response_params(method, resource)
+ self.assertTrue(resp)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, '_get_users')
+ @mock.patch.object(time, 'time')
+ def test__create_user(self, mock_time, mock_get_users, *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertEqual(self.SUCCESS_RECORD_ID,
+ self.res_helper._create_user(self.AUTH_DATA))
+ mock_get_users.assert_not_called()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, '_modify_user')
+ @mock.patch.object(time, 'time')
+ def test__create_user_username_exists(self, mock_time, mock_modify_user,
+ *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ mock_modify_user.return_value = {'id': self.SUCCESS_RECORD_ID,
+ 'result': 'No changes requested'}
+ post_resp_data = {
+ 'status_code': self.ERROR_CODE,
+ 'json.return_value': {'id': self.SUCCESS_OK_CODE,
+ 'apiCode': self.NOT_MODIFIED_CODE}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper._create_user(self.AUTH_DATA)
+ mock_modify_user.assert_called_once_with(TAS_INFO['user'],
+ {'isActive': 'true'})
+ self.assertEqual(self.SUCCESS_RECORD_ID, res)
+
+ @mock.patch.object(time, 'time')
+ def test__create_user_error(self, mock_time, *args):
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'apiCode': self.ERROR_CODE}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper._create_user(self.AUTH_DATA)
+
+ def test__modify_user(self, *args):
+ post_data = {'username': 'test_user'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper._modify_user(username=self.TEST_USER,
+ fields=post_data)
+ self.assertEqual(self.SUCCESS_RECORD_ID, res['id'])
+
+ def test__modify_user_rest_resp_fail(self, *args):
+ post_data = {'non-existing-key': ''}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.ok = False
+ self.res_helper.session = mock_session
+ self.assertRaises(exceptions.RestApiError,
+ self.res_helper._modify_user,
+ username=self.TEST_USER, fields=post_data)
+ mock_session.post.assert_called_once()
+
+ def test__delete_user(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper._delete_user(
+ username=self.TEST_USER))
+
+ def test__get_users(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.USERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertEqual(self.USERS_DATA['users'],
+ self.res_helper._get_users())
+
+ def test_exec_rest_request(self, *args):
+ resource = 'testServers'
+ action = {'action': 'modify'}
+ expected_url = ''.join([EXAMPLE_URL, 'testServers?action=modify'])
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.res_helper.exec_rest_request('post', resource, action)
+ self.res_helper.session.post.assert_called_once_with(expected_url,
+ json={})
+
+ def test_exec_rest_request_unsupported_method_error(self, *args):
+ resource = 'testServers'
+ action = {'action': 'modify'}
+ with self.assertRaises(ValueError):
+ self.res_helper.exec_rest_request('patch', resource, action)
+
+ def test_exec_rest_request_missed_action_arg(self, *args):
+ resource = 'testServers'
+ with self.assertRaises(ValueError):
+ self.res_helper.exec_rest_request('post', resource)
+
+ def test_exec_rest_request_raise_exc(self):
+ resource = 'users'
+ action = {'action': 'modify'}
+ post_resp_data = {'status_code': self.ERROR_CODE,
+ 'json.return_value': {
+ 'status_code': self.ERROR_CODE}}
+ mock_session = mock.Mock(spec=requests.Session)
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.assertRaises(exceptions.RestApiError,
+ self.res_helper.exec_rest_request,
+ 'post', resource, action, raise_exc=True)
+
+ @mock.patch.object(time, 'time')
+ def test_connect(self, mock_time, *args):
+ vnfd = VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ mock_time.strftime.return_value = self.EXPIRE_DATE
+ self.res_helper.vnfd_helper = vnfd
+
+ self.res_helper._tcl = mock.Mock()
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session = mock.Mock(spec=requests.Session, headers={})
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.connect(), requests.Session)
+ self.res_helper._tcl.connect.assert_called_once_with(
+ TAS_INFO['ip'],
+ TAS_INFO['user'],
+ TAS_INFO['password'])
+
+ def test_disconnect(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.disconnect())
+ self.assertIsNone(self.res_helper.session)
+ self.res_helper._tcl.disconnect.assert_called_once()
+
+ def test_terminate(self, *args):
+ self.assertIsNone(self.res_helper.terminate())
+ self.assertEqual(self.TEST_TERMINATED,
+ self.res_helper._terminated.value)
+
+ def test_create_dmf(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.res_helper.vnfd_helper = mock.Mock(spec=vnf_base.VnfdHelper)
+ self.res_helper.vnfd_helper.mgmt_interface = {'user': TAS_INFO['user']}
+ self.assertIsNone(self.res_helper.create_dmf(DMF_CFG))
+ self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_create_dmf_as_list(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.res_helper.vnfd_helper = mock.Mock(spec=vnf_base.VnfdHelper)
+ self.res_helper.vnfd_helper.mgmt_interface = {'user': TAS_INFO['user']}
+ self.assertIsNone(self.res_helper.create_dmf([DMF_CFG]))
+ self.res_helper._tcl.create_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_delete_dmf(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.delete_dmf(DMF_CFG))
+ self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
+
+ def test_delete_dmf_as_list(self, *args):
+ self.res_helper._tcl = mock.Mock()
+ self.assertIsNone(self.res_helper.delete_dmf([DMF_CFG]))
+ self.res_helper._tcl.delete_dmf.assert_called_once_with(DMF_CFG)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
+ def test_create_suts(self, mock_configure_sut, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.create_suts(TS1_SUTS))
+ mock_configure_sut.assert_not_called()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper, 'configure_sut')
+ def test_create_suts_sut_exists(self, mock_configure_sut, *args):
+ sut_name = 'test_sut'
+ suts = [
+ {'name': sut_name,
+ 'role': 'SgwControlAddr',
+ 'managementIp': '12.0.1.1',
+ 'ip': '10.42.32.100'
+ }
+ ]
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.create_suts(suts))
+ mock_configure_sut.assert_called_once_with(
+ sut_name=sut_name,
+ json_data={k: v for k, v in suts[0].items()
+ if k not in {'phy', 'nextHop', 'role', 'name'}})
+
+ def test_get_suts(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.get_suts(), list)
+
+ def test_get_suts_single_id(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA['suts'][0]}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsInstance(self.res_helper.get_suts(suts_id=2), dict)
+
+ def test_configure_sut(self, *args):
+ post_data = {'managementIp': '2.2.2.2'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': {'id': self.SUCCESS_RECORD_ID}}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.configure_sut('test_name',
+ post_data))
+ mock_session.post.assert_called_once()
+
+ def test_configure_sut_error(self, *args):
+ post_data = {'managementIp': '2.2.2.2'}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper.configure_sut('test_name', post_data)
+
+ def test_delete_suts(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.SUTS_DATA}
+ delete_resp_data = {'status_code': self.SUCCESS_OK_CODE}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ mock_session.delete.return_value.configure_mock(**delete_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_suts())
+ mock_session.delete.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_test_servers')
+ def test__check_test_servers_state(self, mock_get_test_servers, *args):
+ mock_get_test_servers.return_value = \
+ self.TEST_SERVERS_DATA['testServers']
+ self.res_helper._check_test_servers_state()
+ mock_get_test_servers.assert_called_once()
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_test_servers')
+ def test__check_test_servers_state_server_not_ready(
+ self, mock_get_test_servers, *args):
+ test_servers_not_ready = [
+ {
+ "url": ''.join([EXAMPLE_URL, "testServers/1"]),
+ "id": 1,
+ "name": "TestServer_1",
+ "state": "NOT_READY",
+ "version": "16.4.0.10"
+ }
+ ]
+
+ mock_get_test_servers.return_value = test_servers_not_ready
+ with self.assertRaises(RuntimeError):
+ self.res_helper._check_test_servers_state(timeout=1, delay=0)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ '_check_test_servers_state')
+ def test_create_test_servers(self, mock_check_ts_state, *args):
+ test_servers_ids = [
+ ts['id'] for ts in self.TEST_SERVERS_DATA['testServers']]
+
+ self.res_helper.license_data['lic_id'] = TAS_INFO['license']
+ self.res_helper._tcl.create_test_server = mock.Mock()
+ self.res_helper._tcl.create_test_server.side_effect = test_servers_ids
+ self.assertIsNone(self.res_helper.create_test_servers(TEST_SERVERS))
+ mock_check_ts_state.assert_called_once_with(test_servers_ids)
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name')
+ @mock.patch.object(tg_landslide.LsTclHandler, 'execute')
+ def test_create_test_servers_error(self, mock_execute,
+ mock_resolve_ts_name, *args):
+ self.res_helper.license_data['lic_id'] = TAS_INFO['license']
+ # Return message for case test server wasn't created
+ mock_execute.return_value = 'TS not found'
+ # Return message for case test server name wasn't resolved
+ mock_resolve_ts_name.return_value = 'TS not found'
+ with self.assertRaises(RuntimeError):
+ self.res_helper.create_test_servers(TEST_SERVERS)
+
+ def test_get_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_servers()
+ self.assertEqual(self.TEST_SERVERS_DATA['testServers'], res)
+
+ def test_get_test_servers_by_id(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+
+ _ts = self.TEST_SERVERS_DATA['testServers'][0]
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': _ts}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_servers(test_server_ids=[_ts['id']])
+ self.assertEqual([_ts], res)
+
+ def test_configure_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.configure_test_servers(
+ action={'action': 'recycle'})
+ self.assertEqual(
+ [x['id'] for x in self.TEST_SERVERS_DATA['testServers']],
+ res)
+ self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
+ mock_session.post.call_count)
+
+ def test_delete_test_servers(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_SERVERS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_test_servers())
+ self.assertEqual(len(self.TEST_SERVERS_DATA['testServers']),
+ mock_session.delete.call_count)
+
+ def test_create_test_session_res_helper(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper._tcl = mock.Mock()
+ self.res_helper.scenario_helper.all_options = {'traffic_duration': 71}
+ _session = {'name': 'test', 'duration': 60}
+ self.assertIsNone(self.res_helper.create_test_session(_session))
+ self.res_helper._tcl.create_test_session.assert_called_once_with(
+ {'name': _session['name'],
+ 'duration': 71,
+ 'library': self.SUCCESS_RECORD_ID})
+
+ def test_create_test_session_res_helper_no_traffic_duration(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper._tcl = mock.Mock()
+ self.res_helper.scenario_helper.all_options = {}
+ _session = {'name': 'test', 'duration': 60}
+ self.assertIsNone(self.res_helper.create_test_session(_session))
+ self.res_helper._tcl.create_test_session.assert_called_once_with(
+ {'name': _session['name'],
+ 'duration': 60,
+ 'library': self.SUCCESS_RECORD_ID})
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name',
+ return_value='Not Found')
+ def test_create_test_session_ts_name_not_found(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ test_session = {
+ 'duration': 60,
+ 'description': 'UE default bearer creation test case',
+ 'name': 'default_bearer_capacity',
+ 'tsGroups': [{'testCases': [{'type': 'SGW_Node',
+ 'name': ''}],
+ 'tsId': 'TestServer_3'}]
+ }
+ with self.assertRaises(RuntimeError):
+ self.res_helper.create_test_session(test_session)
+
+ def test_get_test_session(self, *args):
+ test_session = {"name": self.TEST_SESSION_NAME}
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': test_session}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_test_session(self.TEST_SESSION_NAME)
+ self.assertEqual(test_session, res)
+
+ def test_configure_test_session(self, *args):
+ test_session = {'name': self.TEST_SESSION_NAME}
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
+ self.res_helper.test_session_uri)
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper.configure_test_session(self.TEST_SESSION_NAME,
+ test_session)
+ self.assertIsNotNone(res)
+ mock_session.post.assert_called_once()
+
+ def test_delete_test_session(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ self.res_helper.user_lib_uri = 'libraries/{{}}/{}'.format(
+ self.res_helper.test_session_uri)
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper.delete_test_session(self.TEST_SESSION_NAME)
+ self.assertIsNotNone(res)
+ mock_session.delete.assert_called_once()
+
+ def test_create_running_tests(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ test_session = {'id': self.SUCCESS_RECORD_ID}
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.SUCCESS_CREATED_CODE,
+ 'json.return_value': test_session}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
+ self.assertEqual(self.SUCCESS_RECORD_ID, self.res_helper.run_id)
+
+ def test_create_running_tests_error(self, *args):
+ self.res_helper._user_id = self.SUCCESS_RECORD_ID
+ mock_session = mock.Mock(spec=requests.Session)
+ post_resp_data = {'status_code': self.NOT_MODIFIED_CODE}
+ mock_session.post.return_value.configure_mock(**post_resp_data)
+ self.res_helper.session = mock_session
+ with self.assertRaises(exceptions.RestApiError):
+ self.res_helper.create_running_tests(self.TEST_SESSION_NAME)
+
+ def test_get_running_tests(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_running_tests()
+ self.assertEqual(self.RUNNING_TESTS_DATA['runningTests'], res)
+
+ def test_delete_running_tests(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ delete_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA}
+ mock_session.delete.return_value.configure_mock(**delete_resp_data)
+ self.res_helper.session = mock_session
+ self.assertIsNone(self.res_helper.delete_running_tests())
+
+ def test__running_tests_action(self, *args):
+ action = 'abort'
+ mock_session = mock.Mock(spec=requests.Session)
+ self.res_helper.session = mock_session
+ res = self.res_helper._running_tests_action(self.SUCCESS_RECORD_ID,
+ action)
+ self.assertIsNone(res)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ '_running_tests_action')
+ def test_stop_running_tests(self, mock_tests_action, *args):
+ res = self.res_helper.stop_running_tests(self.SUCCESS_RECORD_ID)
+ self.assertIsNone(res)
+ mock_tests_action.assert_called_once()
+
+ def test_check_running_test_state(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {
+ 'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.RUNNING_TESTS_DATA["runningTests"][0]}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.check_running_test_state(self.SUCCESS_RECORD_ID)
+ self.assertEqual(
+ self.RUNNING_TESTS_DATA["runningTests"][0]['testStateOrStep'],
+ res)
+
+ def test_get_running_tests_results(self, *args):
+ mock_session = mock.Mock(spec=requests.Session)
+ get_resp_data = {'status_code': self.SUCCESS_OK_CODE,
+ 'json.return_value': self.TEST_RESULTS_DATA}
+ mock_session.get.return_value.configure_mock(**get_resp_data)
+ self.res_helper.session = mock_session
+ res = self.res_helper.get_running_tests_results(
+ self.SUCCESS_RECORD_ID)
+ self.assertEqual(self.TEST_RESULTS_DATA, res)
+
+ def test__write_results(self, *args):
+ res = self.res_helper._write_results(self.TEST_RESULTS_DATA)
+ exp_res = {
+ "Test Summary::Actual Dedicated Bearer Session Connects": 100.0,
+ "Test Summary::Actual Dedicated Bearer Session Disconnects": 100.0,
+ "Test Summary::Actual Disconnect Rate(Sessions / Second)(P - I)": 164.804,
+ "Test Summary::Average Session Disconnect Time(P - I)": 5.024,
+ "Test Summary::Total Data Sent + Received Packets / Sec(P - I)": 1452.294
+ }
+ self.assertEqual(exp_res, res)
+
+ def test__write_results_no_tabs(self, *args):
+ _res_data = copy.deepcopy(self.TEST_RESULTS_DATA)
+ del _res_data['tabs']
+ # Return None if tabs not found in test results dict
+ self.assertIsNone(self.res_helper._write_results(_res_data))
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests_results')
+ def test_collect_kpi_test_running(self, mock_tests_results,
+ mock_tests_state, *args):
+ self.res_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_tests_state.return_value = 'RUNNING'
+ mock_tests_results.return_value = self.TEST_RESULTS_DATA
+ res = self.res_helper.collect_kpi()
+ self.assertNotIn('done', res)
+ mock_tests_state.assert_called_once_with(self.res_helper.run_id)
+ mock_tests_results.assert_called_once_with(self.res_helper.run_id)
+
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'check_running_test_state')
+ @mock.patch.object(tg_landslide.LandslideResourceHelper,
+ 'get_running_tests_results')
+ def test_collect_kpi_test_completed(self, mock_tests_results,
+ mock_tests_state, *args):
+ self.res_helper.run_id = self.SUCCESS_RECORD_ID
+ mock_tests_state.return_value = 'COMPLETE'
+ res = self.res_helper.collect_kpi()
+ self.assertIsNotNone(res)
+ mock_tests_state.assert_called_once_with(self.res_helper.run_id)
+ mock_tests_results.assert_not_called()
+ self.assertDictContainsSubset({'done': True}, res)
+
+
+class TestLandslideTclClient(unittest.TestCase):
+ def setUp(self):
+ self.mock_tcl_handler = mock.Mock(spec=tg_landslide.LsTclHandler)
+ self.ls_res_helper = mock.Mock(
+ spec=tg_landslide.LandslideResourceHelper)
+ self.ls_tcl_client = tg_landslide.LandslideTclClient(
+ self.mock_tcl_handler,
+ self.ls_res_helper)
+
+ def test___init__(self, *args):
+ self.ls_tcl_client = tg_landslide.LandslideTclClient(
+ self.mock_tcl_handler,
+ self.ls_res_helper)
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+ self.assertEqual(set(), self.ls_tcl_client.ts_ids)
+ self.assertIsInstance(self.ls_tcl_client._tc_types, set)
+ self.assertIsNotNone(self.ls_tcl_client._tc_types)
+
+ def test_connect_login_success(self, *args):
+ lib_id = '123'
+ exec_responses = ['java0x2', lib_id, lib_id]
+ auth = ('user', 'password')
+ self.mock_tcl_handler.execute.side_effect = exec_responses
+ self.ls_tcl_client.connect(TAS_INFO['ip'], *auth)
+ self.assertEqual(lib_id, self.ls_tcl_client._library_id)
+ self.assertEqual(lib_id, self.ls_tcl_client._basic_library_id)
+ self.assertEqual(TAS_INFO['ip'], self.ls_tcl_client.tcl_server_ip)
+ self.assertEqual(auth[0], self.ls_tcl_client._user)
+ self.assertEqual(len(exec_responses),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call("ls::login 1.1.1.1 user password"),
+ mock.call("ls::get [ls::query LibraryInfo -userLibraryName user] -Id"),
+ ])
+
+ def test_connect_login_failed(self, *args):
+ exec_responses = ['Login failed']
+ auth = ('user', 'password')
+ self.mock_tcl_handler.execute.side_effect = exec_responses
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client.connect,
+ TAS_INFO['ip'],
+ *auth)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertEqual(len(exec_responses),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_called_with(
+ "ls::login 1.1.1.1 user password")
+
+ def test_disconnect(self, *args):
+ self.ls_tcl_client.disconnect()
+ self.mock_tcl_handler.execute.assert_called_once_with("ls::logout")
+ self.assertIsNone(self.ls_tcl_client.tcl_server_ip)
+ self.assertIsNone(self.ls_tcl_client._user)
+ self.assertIsNone(self.ls_tcl_client._library_id)
+ self.assertIsNone(self.ls_tcl_client._basic_library_id)
+
+ def test_create_test_server(self, *args):
+ return_value = '2'
+ self.ls_tcl_client._ts_context.vnfd_helper = \
+ VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': return_value}
+ self.mock_tcl_handler.execute.return_value = return_value
+ self.ls_tcl_client._set_thread_model = mock.Mock()
+ res = self.ls_tcl_client.create_test_server(TEST_SERVERS[1])
+ self.assertEqual(3, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId TestServer_2'),
+ mock.call('set ts [ls::retrieve TsInfo -Name "TestServer_2"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ ])
+ self.ls_tcl_client._set_thread_model.assert_called_once_with(
+ TEST_SERVERS[1]['name'],
+ TEST_SERVERS[1]['thread_model'])
+ self.assertEqual(int(return_value), res)
+
+ def test_create_test_server_fail_limit_reach(self, *args):
+ self.mock_tcl_handler.execute.side_effect = ['TS not found',
+ 'Add failed']
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client.create_test_server,
+ TEST_SERVERS[0])
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId TestServer_1'),
+ mock.call('ls::perform AddTs -Name "TestServer_1" '
+ '-Ip "192.168.122.101"'),
+ ])
+
+ def test__add_test_server(self):
+ ts_id = '2'
+ self.mock_tcl_handler.execute.side_effect = ['TS not found', ts_id]
+ self.assertEqual(ts_id,
+ self.ls_tcl_client._add_test_server('name', 'ip'))
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId name'),
+ mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
+ ])
+
+ def test__add_test_server_failed(self):
+ self.mock_tcl_handler.execute.side_effect = ['TS not found',
+ 'Add failed']
+ self.assertRaises(RuntimeError, self.ls_tcl_client._add_test_server,
+ 'name', 'ip')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::query TsId name'),
+ mock.call('ls::perform AddTs -Name "name" -Ip "ip"'),
+ ])
+
+ def test__update_license(self):
+ curr_lic_id = '111'
+ new_lic_id = '222'
+ exec_resp = ['java0x4',
+ curr_lic_id,
+ TCL_SUCCESS_RESPONSE,
+ TCL_SUCCESS_RESPONSE]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._update_license('name')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ mock.call('ls::config $ts -RequestedLicense 222'),
+ mock.call('ls::perform ModifyTs $ts'),
+ ])
+
+ def test__update_license_same_as_current(self):
+ curr_lic_id = '111'
+ new_lic_id = '111'
+ exec_resp = ['java0x4', curr_lic_id]
+ self.ls_tcl_client._ts_context.license_data = {'lic_id': new_lic_id}
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._update_license('name')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set ts [ls::retrieve TsInfo -Name "name"]'),
+ mock.call('ls::get $ts -RequestedLicense'),
+ ])
+
+ def test__set_thread_model_update_needed(self):
+ self.ls_tcl_client._ts_context.vnfd_helper = {
+ 'mgmt-interface': {
+ 'cfguser_password': 'cfguser_password'
+ }
+ }
+ exec_resp = ['java0x4', 'V0', '', '']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._set_thread_model('name', 'Fireball')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set tsc [ls::perform RetrieveTsConfiguration '
+ '-name "name" cfguser_password]'),
+ mock.call('ls::get $tsc -ThreadModel'),
+ mock.call('ls::config $tsc -ThreadModel "V1_FB3"'),
+ mock.call('ls::perform ApplyTsConfiguration $tsc cfguser_password'),
+ ])
+
+ def test__set_thread_model_no_update_needed(self):
+ self.ls_tcl_client._ts_context.vnfd_helper = {
+ 'mgmt-interface': {
+ 'cfguser_password': 'cfguser_password'
+ }
+ }
+ exec_resp = ['java0x4', 'V0']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._set_thread_model('name', 'Legacy')
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set tsc [ls::perform RetrieveTsConfiguration '
+ '-name "name" cfguser_password]'),
+ mock.call('ls::get $tsc -ThreadModel'),
+ ])
+
+ @mock.patch.object(tg_landslide.LandslideTclClient,
+ 'resolve_test_server_name', side_effect=['4', '2'])
+ def test_create_test_session(self, *args):
+ _session_profile = copy.deepcopy(SESSION_PROFILE)
+ _session_profile['reservations'] = RESERVATIONS
+ self.ls_tcl_client._save_test_session = mock.Mock()
+ self.ls_tcl_client._configure_ts_group = mock.Mock()
+ self.ls_tcl_client._library_id = 42
+ self.ls_tcl_client.create_test_session(_session_profile)
+ self.assertEqual(17, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set test_ [ls::create TestSession]'),
+ mock.call('ls::config $test_ -Library 42 '
+ '-Name "default_bearer_capacity"'),
+ mock.call('ls::config $test_ -Description ' \
+ '"UE default bearer creation test case"'),
+ mock.call('ls::config $test_ -Keywords ""'),
+ mock.call('ls::config $test_ -Duration "60"'),
+ mock.call('ls::config $test_ -Iterations "1"'),
+ # _configure_reservation
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 0 '
+ '-TsId 4 -TsName "TestServer_1"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.100" '
+ '-Mask "/24" -NumIps 20'),
+ # _configure_reservation
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 1 '
+ '-TsId 2 -TsName "TestServer_2"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" -Base "10.42.32.1" '
+ '-Mask "/24" -NumIps 100'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth2" -Base "10.42.33.1" '
+ '-Mask "/24" -NumIps 100'),
+ # _configure_report_options
+ mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
+ ])
+
+ def test_create_dmf(self):
+ self.mock_tcl_handler.execute.return_value = '2'
+ self.ls_tcl_client._save_dmf = mock.Mock()
+ self.ls_tcl_client.create_dmf(copy.deepcopy(DMF_CFG))
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+ # This is needed because the dictionary is unordered and the arguments
+ # can come in either order
+ call1 = mock.call(
+ 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
+ call2 = mock.call(
+ 'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
+ self.assertTrue(
+ call1 in self.mock_tcl_handler.execute.mock_calls or
+ call2 in self.mock_tcl_handler.execute.mock_calls)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set dmf_ [ls::create Dmf]'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName user] -Id'),
+ mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
+ mock.call('ls::config $dmf_ -dataProtocol "udp"'),
+ # mock.call(
+ # 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
+ mock.call('ls::config $dmf_ -serverPort 2003'),
+ ], any_order=True)
+
+ def test_configure_dmf(self):
+ self.mock_tcl_handler.execute.return_value = '2'
+ self.ls_tcl_client._save_dmf = mock.Mock()
+ self.ls_tcl_client.configure_dmf(DMF_CFG)
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+ # This is need because the dictionary is unordered and the arguments
+ # can come in either order
+ call1 = mock.call(
+ 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"')
+ call2 = mock.call(
+ 'ls::config $dmf_ -isClientPortRange "false" -clientPort 2002')
+ self.assertTrue(
+ call1 in self.mock_tcl_handler.execute.mock_calls or
+ call2 in self.mock_tcl_handler.execute.mock_calls)
+
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set dmf_ [ls::create Dmf]'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName user] -Id'),
+ mock.call('ls::config $dmf_ -Library 2 -Name "Basic UDP"'),
+ mock.call('ls::config $dmf_ -dataProtocol "udp"'),
+ # mock.call(
+ # 'ls::config $dmf_ -clientPort 2002 -isClientPortRange "false"'),
+ mock.call('ls::config $dmf_ -serverPort 2003'),
+ ], any_order=True)
+
+ def test_delete_dmf(self):
+ self.assertRaises(NotImplementedError,
+ self.ls_tcl_client.delete_dmf,
+ DMF_CFG)
+
+ def test__save_dmf_valid(self):
+ exec_resp = [TCL_SUCCESS_RESPONSE, TCL_SUCCESS_RESPONSE]
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.ls_tcl_client._save_dmf()
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -Dmf $dmf_'),
+ mock.call('ls::save $dmf_ -overwrite'),
+ ])
+
+ def test__save_dmf_invalid(self):
+ exec_resp = ['Invalid', 'List of errors and warnings']
+ self.mock_tcl_handler.execute.side_effect = exec_resp
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._save_dmf)
+ self.assertEqual(len(exec_resp),
+ self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -Dmf $dmf_'),
+ mock.call('ls::get $dmf_ -ErrorsAndWarnings'),
+ ])
+
+ def test__configure_report_options(self):
+ _options = {'format': 'CSV', 'PerInterval': 'false'}
+ self.ls_tcl_client._configure_report_options(_options)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::config $test_.ReportOptions -Format 1 -Ts -3 -Tc -3'),
+ mock.call('ls::config $test_.ReportOptions -PerInterval false'),
+ ],
+ any_order=True)
+
+ def test___configure_ts_group(self, *args):
+ _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
+ self.ls_tcl_client._configure_tc_type = mock.Mock()
+ self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='2')
+ self.ls_tcl_client._configure_ts_group(_ts_group, 0)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'set tss_ [ls::create TsGroup -under $test_ -tsId 2 ]')
+
+ def test___configure_ts_group_resolve_ts_fail(self, *args):
+ _ts_group = copy.deepcopy(SESSION_PROFILE['tsGroups'][0])
+ self.ls_tcl_client._configure_tc_type = mock.Mock()
+ self.ls_tcl_client._configure_preresolved_arp = mock.Mock()
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='TS Not Found')
+ self.assertRaises(RuntimeError, self.ls_tcl_client._configure_ts_group,
+ _ts_group, 0)
+ self.mock_tcl_handler.execute.assert_not_called()
+
+ def test__configure_tc_type(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.ls_tcl_client._configure_tc_type(_tc, 0)
+ self.assertEqual(7, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_tc_type_optional_param_omitted(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ del _tc['linked']
+ self.mock_tcl_handler.execute.return_value = TCL_SUCCESS_RESPONSE
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.ls_tcl_client._configure_tc_type(_tc, 0)
+ self.assertEqual(6, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_tc_type_wrong_type(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ _tc['type'] = 'not_supported'
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client._configure_tc_type,
+ _tc, 0)
+ self.mock_tcl_handler.assert_not_called()
+
+ def test__configure_tc_type_not_found_basic_lib(self):
+ _tc = copy.deepcopy(SESSION_PROFILE['tsGroups'][0]['testCases'][0])
+ self.ls_tcl_client._configure_parameters = mock.Mock()
+ self.mock_tcl_handler.execute.return_value = 'Invalid'
+ self.assertRaises(RuntimeError,
+ self.ls_tcl_client._configure_tc_type,
+ _tc, 0)
+
+ def test__configure_parameters(self):
+ _params = copy.deepcopy(
+ SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
+ self.ls_tcl_client._configure_parameters(_params)
+ self.assertEqual(16, self.mock_tcl_handler.execute.call_count)
+
+ def test__configure_array_param(self):
+ _array = {"class": "Array",
+ "array": ["0"]}
+ self.ls_tcl_client._configure_array_param('name', _array)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Array-name -under $p_ ;'),
+ mock.call('ls::create ArrayItem -under $p_.name -Value "0"'),
+ ])
+
+ def test__configure_test_node_param(self):
+ _params = copy.deepcopy(
+ SESSION_PROFILE['tsGroups'][0]['testCases'][0]['parameters'])
+ self.ls_tcl_client._configure_test_node_param('SgwUserAddr',
+ _params['SgwUserAddr'])
+ cmd = ('ls::create -TestNode-SgwUserAddr -under $p_ -Type "eth" '
+ '-Phy "eth1" -Ip "SGW_USER_IP" -NumLinksOrNodes 1 '
+ '-NextHop "SGW_CONTROL_NEXT_HOP" -Mac "" -MTU 1500 '
+ '-ForcedEthInterface "" -EthStatsEnabled false -VlanId 0 '
+ '-VlanUserPriority 0 -NumVlan 1 -UniqueVlanAddr false;')
+ self.mock_tcl_handler.execute.assert_called_once_with(cmd)
+
+ def test__configure_sut_param(self):
+ _params = {'name': 'name'}
+ self.ls_tcl_client._configure_sut_param('name', _params)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'ls::create -Sut-name -under $p_ -Name "name";')
+
+ def test__configure_dmf_param(self):
+ _params = {"mainflows": [{"library": '111',
+ "name": "Basic UDP"}],
+ "instanceGroups": [{
+ "mainflowIdx": 0,
+ "mixType": "",
+ "rate": 0.0,
+ "rows": [{
+ "clientPort": 0,
+ "context": 0,
+ "node": 0,
+ "overridePort": "false",
+ "ratingGroup": 0,
+ "role": 0,
+ "serviceId": 0,
+ "transport": "Any"}]
+ }]}
+ self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
+ res = self.ls_tcl_client._configure_dmf_param('name', _params)
+ self.assertEqual(5, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Dmf-name -under $p_ ;'),
+ mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0) -mixType '),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0) -rate 0.0'),
+ mock.call('ls::config $p_.Dmf.InstanceGroup(0).Row(0) -Node 0 '
+ '-OverridePort false -ClientPort 0 -Context 0 -Role 0 '
+ '-PreferredTransport Any -RatingGroup 0 '
+ '-ServiceID 0'),
+ ])
+
+ def test__configure_dmf_param_no_instance_groups(self):
+ _params = {"mainflows": [{"library": '111',
+ "name": "Basic UDP"}]}
+ self.ls_tcl_client._get_library_id = mock.Mock(return_value='111')
+ res = self.ls_tcl_client._configure_dmf_param('name', _params)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::create -Dmf-name -under $p_ ;'),
+ mock.call('ls::perform AddDmfMainflow $p_.Dmf 111 "Basic UDP"'),
+ ])
+
+ def test__configure_reservation(self):
+ _reservation = copy.deepcopy(RESERVATIONS[0])
+ self.ls_tcl_client.resolve_test_server_name = mock.Mock(
+ return_value='4')
+ res = self.ls_tcl_client._configure_reservation(_reservation)
+ self.assertIsNone(res)
+ self.assertEqual(4, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('set reservation_ [ls::create Reservation -under $test_]'),
+ mock.call('ls::config $reservation_ -TsIndex 0 -TsId 4 ' + \
+ '-TsName "TestServer_1"'),
+ mock.call('set physubnet_ [ls::create PhySubnet -under $reservation_]'),
+ mock.call('ls::config $physubnet_ -Name "eth1" ' + \
+ '-Base "10.42.32.100" -Mask "/24" -NumIps 20'),
+ ])
+
+ def test__configure_preresolved_arp(self):
+ _arp = [{'StartingAddress': '10.81.1.10',
+ 'NumNodes': 1}]
+ res = self.ls_tcl_client._configure_preresolved_arp(_arp)
+ self.mock_tcl_handler.execute.assert_called_once()
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_called_once_with(
+ 'ls::create PreResolvedArpAddress -under $tss_ ' + \
+ '-StartingAddress "10.81.1.10" -NumNodes 1')
+
+ def test__configure_preresolved_arp_none(self):
+ res = self.ls_tcl_client._configure_preresolved_arp(None)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_not_called()
+
+ def test_delete_test_session(self):
+ self.assertRaises(NotImplementedError,
+ self.ls_tcl_client.delete_test_session, {})
+
+ def test__save_test_session(self):
+ self.mock_tcl_handler.execute.side_effect = [TCL_SUCCESS_RESPONSE,
+ TCL_SUCCESS_RESPONSE]
+ res = self.ls_tcl_client._save_test_session()
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertIsNone(res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -TestSession $test_'),
+ mock.call('ls::save $test_ -overwrite'),
+ ])
+
+ def test__save_test_session_invalid(self):
+ self.mock_tcl_handler.execute.side_effect = ['Invalid', 'Errors']
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._save_test_session)
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call('ls::perform Validate -TestSession $test_'),
+ mock.call('ls::get $test_ -ErrorsAndWarnings'),
+ ])
+
+ def test__get_library_id_system_lib(self):
+ self.mock_tcl_handler.execute.return_value = '111'
+ res = self.ls_tcl_client._get_library_id('name')
+ self.mock_tcl_handler.execute.assert_called_once()
+ self.assertEqual('111', res)
+ self.mock_tcl_handler.execute.assert_called_with(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id')
+
+ def test__get_library_id_user_lib(self):
+ self.mock_tcl_handler.execute.side_effect = ['Not found', '222']
+ res = self.ls_tcl_client._get_library_id('name')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.assertEqual('222', res)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
+ ])
+
+ def test__get_library_id_exception(self):
+ self.mock_tcl_handler.execute.side_effect = ['Not found', 'Not found']
+ self.assertRaises(exceptions.LandslideTclException,
+ self.ls_tcl_client._get_library_id,
+ 'name')
+ self.assertEqual(2, self.mock_tcl_handler.execute.call_count)
+ self.mock_tcl_handler.execute.assert_has_calls([
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -systemLibraryName name] -Id'),
+ mock.call(
+ 'ls::get [ls::query LibraryInfo -userLibraryName name] -Id'),
+ ])
+
+
+class TestLsTclHandler(unittest.TestCase):
+
+ def setUp(self):
+ self.mock_lsapi = mock.patch.object(tg_landslide, 'LsApi')
+ self.mock_lsapi.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self.mock_lsapi.stop()
+
+ def test___init__(self, *args):
+ self.ls_tcl_handler = tg_landslide.LsTclHandler()
+ self.assertEqual({}, self.ls_tcl_handler.tcl_cmds)
+ self.ls_tcl_handler._ls.tcl.assert_called_once()
+
+ def test_execute(self, *args):
+ self.ls_tcl_handler = tg_landslide.LsTclHandler()
+ self.ls_tcl_handler.execute('command')
+ self.assertIn('command', self.ls_tcl_handler.tcl_cmds)
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py
new file mode 100644
index 000000000..a3e4384cf
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_ping.py
@@ -0,0 +1,298 @@
+# Copyright (c) 2016-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.
+#
+
+from multiprocessing import Queue
+import multiprocessing
+
+import mock
+import unittest
+
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.tg_ping import PingParser
+from yardstick.network_services.vnf_generic.vnf.tg_ping import PingTrafficGen
+from yardstick.network_services.vnf_generic.vnf.tg_ping import PingResourceHelper
+from yardstick.network_services.vnf_generic.vnf.tg_ping import PingSetupEnvHelper
+from yardstick.network_services.vnf_generic.vnf.vnf_ssh_helper import VnfSshHelper
+
+
+SSH_HELPER = "yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper"
+
+
+class TestPingResourceHelper(unittest.TestCase):
+ def test___init__(self):
+ setup_helper = mock.Mock()
+ helper = PingResourceHelper(setup_helper)
+
+ self.assertIsInstance(helper._queue, multiprocessing.queues.Queue)
+ self.assertIsInstance(helper._parser, PingParser)
+
+ def test_run_traffic(self):
+ setup_helper = mock.Mock()
+ traffic_profile = mock.Mock()
+ traffic_profile.params = {
+ 'traffic_profile': {
+ 'frame_size': 64,
+ },
+ }
+
+ helper = PingResourceHelper(setup_helper)
+ helper.cmd_kwargs = {'target_ip': '10.0.0.2',
+ 'local_ip': '10.0.0.1',
+ 'local_if_name': 'eth0',
+ }
+ helper.ssh_helper = mock.Mock()
+ helper.run_traffic(traffic_profile)
+ helper.ssh_helper.run.called_with('ping-s 64 10.0.0.2')
+
+
+class TestPingParser(unittest.TestCase):
+ def test___init__(self):
+ q_out = Queue()
+ ping_parser = PingParser(q_out)
+ self.assertIsNotNone(ping_parser.queue)
+
+ def test_clear(self):
+ sample_out = """
+64 bytes from 10.102.22.93: icmp_seq=3 ttl=64 time=0.296 ms
+ """
+ q_out = Queue()
+ ping_parser = PingParser(q_out)
+ ping_parser.write(sample_out)
+ ping_parser.clear()
+ self.assertTrue(q_out.empty())
+
+ def test_close(self):
+ q_out = Queue()
+ ping_parser = PingParser(q_out)
+ self.assertIsNone(ping_parser.close())
+
+ def test_write(self):
+ sample_out = """
+64 bytes from 10.102.22.93: icmp_seq=3 ttl=64 time=0.296 ms
+ """
+ q_out = Queue()
+ ping_parser = PingParser(q_out)
+ ping_parser.write(sample_out)
+
+ self.assertEqual({"packets_received": 3.0, "rtt": 0.296}, q_out.get())
+
+
+class TestPingTrafficGen(unittest.TestCase):
+ VNFD_0_EXT_IF_0 = {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': u'152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': u'152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ }
+
+ VNFD_0_EXT_IF_1 = {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': u'152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': u'152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ }
+
+ VNFD_0_EXT_IF_LIST = [
+ VNFD_0_EXT_IF_0,
+ VNFD_0_EXT_IF_1,
+ ]
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': u'152.16.100.20',
+ 'netmask': u'255.255.255.0',
+ 'gateway': u'152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': u'152.16.40.20',
+ 'netmask': u'255.255.255.0',
+ 'gateway': u'152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': VNFD_0_EXT_IF_LIST,
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf',
+ 'name': 'VPEVnfSsh',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+
+ CMD_KWARGS = {
+ 'target_ip': u'152.16.100.20',
+ 'local_ip': u'152.16.100.19',
+ 'local_if_name': u'xe0_fake',
+ }
+
+ @mock.patch("yardstick.ssh.SSH")
+ def test___init__(self, ssh):
+ ssh.from_node.return_value.execute.return_value = 0, "success", ""
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+
+ self.assertIsInstance(ping_traffic_gen.setup_helper, PingSetupEnvHelper)
+ self.assertIsInstance(ping_traffic_gen.resource_helper, PingResourceHelper)
+ self.assertEqual(ping_traffic_gen._result, {})
+
+ @mock.patch("yardstick.ssh.SSH")
+ def test__bind_device_kernel_with_failure(self, ssh):
+ mock_ssh(ssh)
+
+ execute_result_data = [
+ (1, 'bad stdout messages', 'error messages'),
+ (0, '', ''),
+ (0, 'if_name_1', ''),
+ (0, 'if_name_2', ''),
+ ]
+ ssh.from_node.return_value.execute.side_effect = iter(execute_result_data)
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+ ext_ifs = ping_traffic_gen.vnfd_helper.interfaces
+ self.assertNotEqual(ext_ifs[0]['virtual-interface']['local_iface_name'], 'if_name_1')
+ self.assertNotEqual(ext_ifs[1]['virtual-interface']['local_iface_name'], 'if_name_2')
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch("yardstick.ssh.SSH")
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh, exec_result=(0, "success", ""))
+
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+ ping_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {ping_traffic_gen.name: "mock"}
+ }
+ ping_traffic_gen._queue = Queue()
+ ping_traffic_gen._queue.put({})
+ expected = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {}
+ }
+ # NOTE: Why we check _result but not collect_kpi() return value
+ # self.assertEqual(ping_traffic_gen._result, {})
+ self.assertEqual(ping_traffic_gen.collect_kpi(), expected)
+
+
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh):
+ mock_ssh(ssh, spec=VnfSshHelper, exec_result=(0, "success", ""))
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+ ping_traffic_gen.setup_helper.ssh_helper = mock.MagicMock(
+ **{"execute.return_value": (0, "xe0_fake", "")})
+ self.assertIsInstance(ping_traffic_gen.ssh_helper, mock.Mock)
+ self.assertEqual(ping_traffic_gen._result, {})
+
+ self.assertIsNone(ping_traffic_gen.instantiate({}, {}))
+
+ self.assertEqual(
+ ping_traffic_gen.vnfd_helper.interfaces[0]['virtual-interface']['local_iface_name'],
+ 'xe0_fake')
+ self.assertEqual(self.CMD_KWARGS, ping_traffic_gen.resource_helper.cmd_kwargs)
+ self.assertIsNotNone(ping_traffic_gen._result)
+
+ def test_listen_traffic(self):
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+ self.assertIsNone(ping_traffic_gen.listen_traffic({}))
+
+ @mock.patch("yardstick.ssh.SSH")
+ def test_terminate(self, ssh):
+ ssh.from_node.return_value.execute.return_value = 0, "success", ""
+ ssh.from_node.return_value.run.return_value = 0, "success", ""
+
+ ping_traffic_gen = PingTrafficGen('vnf1', self.VNFD_0)
+ self.assertIsNone(ping_traffic_gen.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_pktgen.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_pktgen.py
new file mode 100644
index 000000000..1ecb6ffc9
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_pktgen.py
@@ -0,0 +1,66 @@
+# Copyright (c) 2018-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.
+
+import mock
+
+from yardstick.common import constants
+from yardstick.common import exceptions
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+from yardstick.network_services.vnf_generic.vnf import tg_pktgen
+from yardstick.tests.unit import base as ut_base
+
+
+class PktgenTrafficGenTestCase(ut_base.BaseUnitTestCase):
+
+ SERVICE_PORTS = [{'port': constants.LUA_PORT,
+ 'node_port': '34501'}]
+ VNFD = {'mgmt-interface': {'ip': '1.2.3.4',
+ 'service_ports': SERVICE_PORTS},
+ 'vdu': [{'external-interface': 'interface'}],
+ 'benchmark': {'kpi': 'fake_kpi'}
+ }
+
+ def test__init(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ self.assertTrue(isinstance(tg, vnf_base.GenericTrafficGen))
+
+ def test_run_traffic(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ mock_tp = mock.Mock()
+ with mock.patch.object(tg, '_is_running', return_value=True):
+ tg.run_traffic(mock_tp)
+
+ mock_tp.init.assert_called_once_with(tg._node_ip, tg._lua_node_port)
+
+ def test__get_lua_node_port(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ service_ports = [{'port': constants.LUA_PORT,
+ 'node_port': '12345'}]
+ self.assertEqual(12345, tg._get_lua_node_port(service_ports))
+
+ def test__get_lua_node_port_no_lua_port(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ service_ports = [{'port': '333'}]
+ self.assertIsNone(tg._get_lua_node_port(service_ports))
+
+ def test__is_running(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ with mock.patch.object(tg, '_traffic_profile'):
+ self.assertTrue(tg._is_running())
+
+ def test__is_running_exception(self):
+ tg = tg_pktgen.PktgenTrafficGen('name1', self.VNFD)
+ with mock.patch.object(tg, '_traffic_profile') as mock_tp:
+ mock_tp.help.side_effect = exceptions.PktgenActionError()
+ self.assertFalse(tg._is_running())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py
new file mode 100644
index 000000000..0aaf17790
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_prox.py
@@ -0,0 +1,441 @@
+# Copyright (c) 2017-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.
+#
+
+import unittest
+import mock
+
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.tg_prox import ProxTrafficGen
+from yardstick.network_services.traffic_profile.base import TrafficProfile
+
+
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+NAME = 'vnf__1'
+
+
+@mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.time')
+class TestProxTrafficGen(unittest.TestCase):
+ VNFD0 = {
+ 'short-name': 'ProxVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'name': 'proxvnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'proxvnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': '',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': '',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'PROX approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'proxvnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'ProxApproxVnf',
+ 'name': 'ProxVnf',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD0,
+ ],
+ },
+ }
+
+ SCENARIO_CFG = {
+ 'task_path': "",
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'runner': {
+ 'duration': 600, 'type': 'Duration'},
+ 'topology': 'prox-tg-topology-2.yaml',
+ 'traffic_profile': '../../traffic_profiles/prox_binsearch.yaml',
+ 'type': 'NSPerf',
+ 'options': {
+ 'tg__1': {'prox_args': {'-e': '',
+ '-t': ''},
+ 'prox_config': 'configs/l3-gen-2.cfg',
+ 'prox_path':
+ '/root/dppd-PROX-v035/build/prox'},
+ 'vnf__1': {
+ 'prox_args': {'-t': ''},
+ 'prox_config': 'configs/l3-swap-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'}}}
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__2': {
+ 'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens513f0',
+ 'vld_id': ProxTrafficGen.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root',
+ },
+ 'tg__1': {
+ 'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens785f0',
+ 'vld_id': ProxTrafficGen.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root',
+ },
+ 'vnf__1': {
+ 'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens786f0',
+ 'vld_id': ProxTrafficGen.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens786f1',
+ 'vld_id': ProxTrafficGen.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'password': 'r00t',
+ 'VNF model': 'prox_vnf.yaml',
+ },
+ },
+ }
+
+ TRAFFIC_PROFILE = {
+ 'description': 'Binary search for max no-drop throughput over given packet sizes',
+ 'name': 'prox_binsearch',
+ 'schema': 'nsb:traffic_profile:0.1',
+ 'traffic_profile': {
+ 'duration': 5,
+ 'lower_bound': 0.0,
+ 'packet_sizes': [64, 65],
+ 'test_precision': 1.0,
+ 'tolerated_loss': 0.0,
+ 'traffic_type': 'ProxBinSearchProfile',
+ 'upper_bound': 100.0}}
+
+ @mock.patch(SSH_HELPER)
+ def test___init__(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_traffic_gen = ProxTrafficGen(NAME, self.VNFD0)
+ self.assertIsNone(prox_traffic_gen._tg_process)
+ self.assertIsNone(prox_traffic_gen._traffic_process)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+ prox_traffic_gen = ProxTrafficGen(NAME, self.VNFD0)
+ prox_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {prox_traffic_gen.name: "mock"}
+ }
+ prox_traffic_gen._vnf_wrapper.resource_helper.resource = mock.MagicMock(
+ **{"self.check_if_system_agent_running.return_value": [False]})
+
+ vnfd_helper = mock.MagicMock()
+ vnfd_helper.ports_iter.return_value = [('xe0', 0), ('xe1', 1)]
+ prox_traffic_gen.resource_helper.vnfd_helper = vnfd_helper
+
+ prox_traffic_gen._vnf_wrapper.resource_helper.client = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper.resource_helper.client.multi_port_stats.return_value = \
+ [[0, 1, 2, 3, 4, 5], [1, 1, 2, 3, 4, 5]]
+ prox_traffic_gen._vnf_wrapper.resource_helper.client.multi_port_stats_diff.return_value = \
+ [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7]
+ prox_traffic_gen._vnf_wrapper.resource_helper.client.\
+ multi_port_stats_tuple.return_value = \
+ {"xe0": {"in_packets": 1, "out_packets": 2}}
+
+ prox_traffic_gen._vnf_wrapper.vnf_execute = mock.Mock(return_value="")
+ expected = {
+ 'collect_stats': {'live_stats': {'xe0': {'in_packets': 1, 'out_packets': 2}}},
+ 'physical_node': 'mock_node'
+ }
+ result = prox_traffic_gen.collect_kpi()
+ self.assertDictEqual(result, expected)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.find_relative_file')
+ @mock.patch(
+ 'yardstick.network_services.vnf_generic.vnf.sample_vnf.CpuSysCores')
+ @mock.patch(SSH_HELPER)
+ def bad_test_instantiate(self, ssh, mock_cpu_sys_cores, *args):
+ mock_ssh(ssh)
+
+ mock_cpu_sys_cores.get_core_socket.return_value = {'0': '01234'}
+
+ mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ prox_traffic_gen = ProxTrafficGen(NAME, vnfd)
+ ssh_helper = mock.MagicMock(
+ **{"execute.return_value": (0, "", ""), "bin_path": ""})
+ prox_traffic_gen.ssh_helper = ssh_helper
+ prox_traffic_gen.setup_helper.dpdk_bind_helper.ssh_helper = ssh_helper
+ prox_traffic_gen.setup_helper._setup_resources = mock.MagicMock()
+ prox_traffic_gen.setup_hugepages = mock.MagicMock()
+ prox_traffic_gen.generate_prox_config_file = mock.MagicMock()
+ prox_traffic_gen.upload_prox_config = mock.MagicMock()
+ prox_traffic_gen.setup_helper._find_used_drivers = mock.MagicMock()
+ prox_traffic_gen.setup_helper.used_drivers = {}
+ prox_traffic_gen.setup_helper.bound_pci = []
+ prox_traffic_gen._start_server = mock.Mock(return_value=0)
+ prox_traffic_gen._tg_process = mock.MagicMock()
+ prox_traffic_gen._tg_process.start = mock.Mock()
+ prox_traffic_gen._tg_process.exitcode = 0
+ prox_traffic_gen._tg_process._is_alive = mock.Mock(return_value=1)
+ prox_traffic_gen.ssh_helper = mock.MagicMock()
+ prox_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ scenario_cfg = {
+ 'task_path': '',
+ 'options': {'tg__1': {'prox_args': {'-e': '',
+ '-t': ''},
+ 'prox_config': 'configs/l3-gen-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'},
+ 'vnf__1': {'prox_args': {'-t': ''},
+ 'prox_config': 'configs/l3-swap-2.cfg',
+ 'prox_path': '/root/dppd-PROX-v035/build/prox'}
+ }
+ }
+ prox_traffic_gen.instantiate(scenario_cfg, {})
+
+ @mock.patch(SSH_HELPER)
+ def test__traffic_runner(self, ssh, *args):
+ mock_ssh(ssh)
+
+ mock_traffic_profile = mock.Mock(autospec=TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.execute_traffic.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = ProxTrafficGen(NAME, vnfd)
+ sut._get_socket = mock.MagicMock()
+ sut.ssh_helper = mock.Mock()
+ sut.ssh_helper.run = mock.Mock()
+ sut.setup_helper.prox_config_dict = {}
+ sut._connect_client = mock.Mock(autospec=mock.Mock())
+ sut._connect_client.get_stats = mock.Mock(return_value="0")
+ sut._traffic_runner(mock_traffic_profile)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+ @mock.patch(SSH_HELPER)
+ def test_listen_traffic(self, ssh, *args):
+ mock_ssh(ssh)
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ prox_traffic_gen = ProxTrafficGen(NAME, vnfd)
+ self.assertIsNone(prox_traffic_gen.listen_traffic(mock.Mock()))
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.prox_helpers.socket')
+ @mock.patch(SSH_HELPER)
+ def test_terminate(self, ssh, *args):
+ mock_ssh(ssh)
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ prox_traffic_gen = ProxTrafficGen(NAME, vnfd)
+ prox_traffic_gen._terminated = mock.MagicMock()
+ prox_traffic_gen._traffic_process = mock.MagicMock()
+ prox_traffic_gen._traffic_process.terminate = mock.Mock()
+ prox_traffic_gen.ssh_helper = mock.MagicMock()
+ prox_traffic_gen.setup_helper = mock.MagicMock()
+ prox_traffic_gen.resource_helper = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper.setup_helper = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper._vnf_process = mock.MagicMock()
+ prox_traffic_gen._vnf_wrapper.resource_helper = mock.MagicMock()
+ self.assertIsNone(prox_traffic_gen.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
new file mode 100644
index 000000000..c3f3e5f67
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py
@@ -0,0 +1,1265 @@
+# Copyright (c) 2016-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.
+
+import os
+
+import mock
+import six
+import unittest
+import ipaddress
+import time
+from collections import OrderedDict
+
+from yardstick.common import utils
+from yardstick.common import exceptions
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.libs.ixia_libs.ixnet import ixnet_api
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia
+from yardstick.network_services.traffic_profile import ixia_rfc2544
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+
+NAME = "tg__1"
+
+
+class TestIxiaResourceHelper(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen')
+ self.mock_IxNextgen = self._mock_IxNextgen.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_IxNextgen.stop()
+
+ def test___init___with_custom_rfc_helper(self):
+ class MyRfcHelper(tg_rfc2544_ixia.IxiaRfc2544Helper):
+ pass
+
+ ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(
+ mock.Mock(), MyRfcHelper)
+ self.assertIsInstance(ixia_resource_helper.rfc_helper, MyRfcHelper)
+
+ def test__init_ix_scenario(self):
+ mock_scenario = mock.Mock()
+ mock_scenario_helper = mock.Mock()
+ mock_scenario_helper.scenario_cfg = {'ixia_config': 'TestScenario',
+ 'options': 'scenario_options'}
+ mock_setup_helper = mock.Mock(scenario_helper=mock_scenario_helper)
+ ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock_setup_helper)
+ ixia_resource_helper._ixia_scenarios = {'TestScenario': mock_scenario}
+ ixia_resource_helper.client = 'client'
+ ixia_resource_helper.context_cfg = 'context'
+ ixia_resource_helper._init_ix_scenario()
+ mock_scenario.assert_called_once_with('client', 'context', 'scenario_options')
+
+ def test__init_ix_scenario_not_supported_cfg_type(self):
+ mock_scenario_helper = mock.Mock()
+ mock_scenario_helper.scenario_cfg = {'ixia_config': 'FakeScenario',
+ 'options': 'scenario_options'}
+ mock_setup_helper = mock.Mock(scenario_helper=mock_scenario_helper)
+ ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock_setup_helper)
+ ixia_resource_helper._ixia_scenarios = {'TestScenario': mock.Mock()}
+ with self.assertRaises(RuntimeError):
+ ixia_resource_helper._init_ix_scenario()
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaResourceHelper, '_init_ix_scenario')
+ def test_setup(self, mock__init_ix_scenario):
+ ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
+ ixia_resource_helper.setup()
+ mock__init_ix_scenario.assert_called_once()
+
+ def test_stop_collect_with_client(self):
+ mock_client = mock.Mock()
+ ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
+ ixia_resource_helper.client = mock_client
+ ixia_resource_helper._ix_scenario = mock.Mock()
+ ixia_resource_helper.stop_collect()
+ self.assertEqual(1, ixia_resource_helper._terminated.value)
+ ixia_resource_helper._ix_scenario.stop_protocols.assert_called_once()
+
+ def test_run_traffic(self):
+ mock_tprofile = mock.Mock()
+ mock_tprofile.config.duration = 10
+ mock_tprofile.get_drop_percentage.return_value = True, 'fake_samples'
+ ixia_rhelper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
+ ixia_rhelper.rfc_helper = mock.Mock()
+ ixia_rhelper.vnfd_helper = mock.Mock()
+ ixia_rhelper._ix_scenario = mock.Mock()
+ ixia_rhelper.vnfd_helper.port_pairs.all_ports = []
+ with mock.patch.object(ixia_rhelper, 'generate_samples'), \
+ mock.patch.object(ixia_rhelper, '_build_ports'), \
+ mock.patch.object(ixia_rhelper, '_initialize_client'), \
+ mock.patch.object(utils, 'wait_until_true'):
+ ixia_rhelper.run_traffic(mock_tprofile)
+
+ self.assertEqual('fake_samples', ixia_rhelper._queue.get())
+ mock_tprofile.update_traffic_profile.assert_called_once()
+
+ def test_run_test(self):
+ expected_result = {'test': 'fake_samples', 'Iteration': 1}
+ mock_tprofile = mock.Mock()
+ mock_tprofile.config.duration = 10
+ mock_tprofile.get_drop_percentage.return_value = \
+ True, {'test': 'fake_samples', 'Iteration': 1}
+ ixia_rhelper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock())
+ tasks_queue = mock.Mock()
+ tasks_queue.get.return_value = 'RUN_TRAFFIC'
+ results_queue = mock.Mock()
+ ixia_rhelper.rfc_helper = mock.Mock()
+ ixia_rhelper.vnfd_helper = mock.Mock()
+ ixia_rhelper._ix_scenario = mock.Mock()
+ ixia_rhelper.vnfd_helper.port_pairs.all_ports = []
+ with mock.patch.object(ixia_rhelper, 'generate_samples'), \
+ mock.patch.object(ixia_rhelper, '_build_ports'), \
+ mock.patch.object(ixia_rhelper, '_initialize_client'), \
+ mock.patch.object(utils, 'wait_until_true'):
+ ixia_rhelper.run_test(mock_tprofile, tasks_queue, results_queue)
+
+ self.assertEqual(expected_result, ixia_rhelper._queue.get())
+ mock_tprofile.update_traffic_profile.assert_called_once()
+ tasks_queue.task_done.assert_called_once()
+ results_queue.put.assert_called_once_with('COMPLETE')
+
+
+@mock.patch.object(tg_rfc2544_ixia, 'ixnet_api')
+class TestIXIATrafficGen(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd',
+ 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64}}
+
+ TC_YAML = {'scenarios': [{'tc_options':
+ {'rfc2544': {'allowed_drop_rate': '0.8 - 1'}},
+ 'runner': {'duration': 400,
+ 'interval': 35, 'type': 'Duration'},
+ 'traffic_options':
+ {'flow': 'ipv4_1flow_Packets_vpe.yaml',
+ 'imix': 'imix_voice.yaml'},
+ 'vnf_options': {'vpe': {'cfg': 'vpe_config'}},
+ 'traffic_profile': 'ipv4_throughput_vpe.yaml',
+ 'type': 'NSPerf',
+ 'nodes': {'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'topology': 'vpe_vnf_topology.yaml'}],
+ 'context': {'nfvi_type': 'baremetal',
+ 'type': contexts.CONTEXT_NODE,
+ 'name': 'yardstick',
+ 'file': '/etc/yardstick/nodes/pod.yaml'},
+ 'schema': 'yardstick:task:0.1'}
+
+ def test___init__(self, *args):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = ssh_mock
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ # NOTE(ralonsoh): check the object returned.
+ tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
+
+ def test_listen_traffic(self, *args):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = ssh_mock
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
+ self.assertIsNone(ixnet_traffic_gen.listen_traffic({}))
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+ def test_instantiate(self, *args):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh_mock.run = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = ssh_mock
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
+ scenario_cfg = {'tc': "nsb_test_case",
+ "topology": ""}
+ scenario_cfg.update(
+ {
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1'},
+ 'vnf__1': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1}}}})
+ scenario_cfg.update({
+ 'nodes': {ixnet_traffic_gen.name: "mock"}
+ })
+ ixnet_traffic_gen.topology = ""
+ ixnet_traffic_gen.get_ixobj = mock.MagicMock()
+ ixnet_traffic_gen._ixia_traffic_gen = mock.MagicMock()
+ ixnet_traffic_gen._ixia_traffic_gen._connect = mock.Mock()
+ self.assertRaises(
+ IOError,
+ ixnet_traffic_gen.instantiate(scenario_cfg, {}))
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = ssh_mock
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd)
+ ixnet_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {ixnet_traffic_gen.name: "mock"}
+ }
+ ixnet_traffic_gen.data = {}
+ restult = ixnet_traffic_gen.collect_kpi()
+
+ expected = {'collect_stats': {},
+ 'physical_node': 'mock_node'}
+
+ self.assertEqual(expected, restult)
+
+ def test_terminate(self, *args):
+ with mock.patch("yardstick.ssh.SSH") as ssh:
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ ssh_mock = mock.Mock(autospec=ssh.SSH)
+ ssh_mock.execute = \
+ mock.Mock(return_value=(0, "", ""))
+ ssh.from_node.return_value = ssh_mock
+ ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(
+ NAME, vnfd, resource_helper_type=mock.Mock())
+ ixnet_traffic_gen._terminated = mock.MagicMock()
+ ixnet_traffic_gen._terminated.value = 0
+ ixnet_traffic_gen._ixia_traffic_gen = mock.MagicMock()
+ ixnet_traffic_gen._ixia_traffic_gen.ix_stop_traffic = mock.Mock()
+ ixnet_traffic_gen._traffic_process = mock.MagicMock()
+ ixnet_traffic_gen._traffic_process.terminate = mock.Mock()
+ self.assertIsNone(ixnet_traffic_gen.terminate())
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ def test__check_status(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd)
+ sut._check_status()
+
+ @mock.patch("yardstick.ssh.SSH")
+ def test_traffic_runner(self, mock_ssh, *args):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ # traffic_profile.ports is standardized on port_num
+ mock_traffic_profile.ports = [0, 1]
+
+ mock_ssh_instance = mock.Mock(autospec=mock_ssh.SSH)
+ mock_ssh_instance.execute.return_value = 0, "", ""
+ mock_ssh_instance.run.return_value = 0, "", ""
+
+ mock_ssh.from_node.return_value = mock_ssh_instance
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vnfd["mgmt-interface"].update({
+ 'tg-config': {
+ "ixchassis": "1.1.1.1",
+ "py_bin_path": "/root",
+ }
+ })
+
+ samples = {}
+ name = ''
+ for ifname in range(1):
+ name = "xe{}".format(ifname)
+ samples[name] = {
+ "Rx_Rate_Kbps": 20,
+ "Tx_Rate_Kbps": 20,
+ "Rx_Rate_Mbps": 10,
+ "Tx_Rate_Mbps": 10,
+ "RxThroughput": 10,
+ "TxThroughput": 10,
+ "Valid_Frames_Rx": 1000,
+ "Frames_Tx": 1000,
+ "in_packets": 1000,
+ "out_packets": 1000,
+ }
+
+ samples.update({"CurrentDropPercentage": 0.0})
+
+ last_res = [
+ 0,
+ {
+ "Rx_Rate_Kbps": [20, 20],
+ "Tx_Rate_Kbps": [20, 20],
+ "Rx_Rate_Mbps": [10, 10],
+ "Tx_Rate_Mbps": [10, 10],
+ "CurrentDropPercentage": [0, 0],
+ "RxThroughput": [10, 10],
+ "TxThroughput": [10, 10],
+ "Frames_Tx": [1000, 1000],
+ "in_packets": [1000, 1000],
+ "Valid_Frames_Rx": [1000, 1000],
+ "out_packets": [1000, 1000],
+ },
+ ]
+
+ mock_traffic_profile.execute_traffic.return_value = [
+ 'Completed', samples]
+ mock_traffic_profile.get_drop_percentage.return_value = [
+ 'Completed', samples]
+
+ sut = tg_rfc2544_ixia.IxiaTrafficGen(name, vnfd)
+ sut.vnf_port_pairs = [[[0], [1]]]
+ sut.tc_file_name = self._get_file_abspath(TEST_FILE_YAML)
+ sut.topology = ""
+
+ sut.ssh_helper = mock.Mock()
+ sut._traffic_process = mock.MagicMock()
+ sut.generate_port_pairs = mock.Mock()
+
+ sut._ixia_traffic_gen = mock.MagicMock()
+ sut._ixia_traffic_gen.ix_get_statistics.return_value = last_res
+
+ sut.resource_helper.client = mock.MagicMock()
+ sut.resource_helper.client_started = mock.MagicMock()
+ sut.resource_helper.client_started.value = 1
+ sut.resource_helper.rfc_helper.iteration.value = 11
+ sut.resource_helper._ix_scenario = mock.Mock()
+
+ sut.scenario_helper.scenario_cfg = {
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ 'latency': True
+ },
+ 'vnf__1': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1,
+ },
+ },
+ },
+ 'task_path': '/path/to/task'
+ }
+
+ @mock.patch.object(six.moves.builtins, 'open', create=True)
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.open',
+ mock.mock_open(), create=True)
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.LOG.exception')
+ def _traffic_runner(*args):
+ result = sut._traffic_runner(mock_traffic_profile)
+ self.assertIsNone(result)
+
+ _traffic_runner()
+
+ def test_run_traffic_once(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd)
+ sut._init_traffic_process = mock.Mock()
+ sut._tasks_queue.put = mock.Mock()
+ sut.resource_helper.client_started.value = 0
+ sut.run_traffic_once(self.TRAFFIC_PROFILE)
+ sut._tasks_queue.put.assert_called_once_with("RUN_TRAFFIC")
+ sut._init_traffic_process.assert_called_once_with(self.TRAFFIC_PROFILE)
+
+ def test__test_runner(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd)
+ tasks = 'tasks'
+ results = 'results'
+ sut.resource_helper = mock.Mock()
+ sut._test_runner(self.TRAFFIC_PROFILE, tasks, results)
+ sut.resource_helper.run_test.assert_called_once_with(self.TRAFFIC_PROFILE,
+ tasks, results)
+
+ @mock.patch.object(time, 'sleep', return_value=0)
+ def test__init_traffic_process(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd)
+ sut._test_runner = mock.Mock(return_value=0)
+ sut.resource_helper = mock.Mock()
+ sut.resource_helper.client_started.value = 0
+ sut._init_traffic_process(self.TRAFFIC_PROFILE)
+
+ def test_wait_on_traffic(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd)
+ sut._tasks_queue.join = mock.Mock(return_value=0)
+ sut._result_queue.get = mock.Mock(return_value='COMPLETE')
+ result = sut.wait_on_traffic()
+ sut._tasks_queue.join.assert_called_once()
+ sut._result_queue.get.assert_called_once()
+ self.assertEqual(result, 'COMPLETE')
+
+
+class TestIxiaBasicScenario(unittest.TestCase):
+
+ STATS = {'stat_name': ['Card01/Port01',
+ 'Card02/Port02'],
+ 'port_name': ['Ethernet - 001', 'Ethernet - 002'],
+ 'Frames_Tx': ['150', '150'],
+ 'Valid_Frames_Rx': ['150', '150'],
+ 'Frames_Tx_Rate': ['0.0', '0.0'],
+ 'Valid_Frames_Rx_Rate': ['0.0', '0.0'],
+ 'Bytes_Rx': ['9600', '9600'],
+ 'Bytes_Tx': ['9600', '9600'],
+ 'Tx_Rate_Kbps': ['0.0', '0.0'],
+ 'Rx_Rate_Mbps': ['0.0', '0.0'],
+ 'Tx_Rate_Mbps': ['0.0', '0.0'],
+ 'Rx_Rate_Kbps': ['0.0', '0.0'],
+ 'Store-Forward_Max_latency_ns': ['100', '200'],
+ 'Store-Forward_Min_latency_ns': ['100', '200'],
+ 'Store-Forward_Avg_latency_ns': ['100', '200']}
+
+ def setUp(self):
+ self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen')
+ self.mock_IxNextgen = self._mock_IxNextgen.start()
+ self.context_cfg = mock.Mock()
+ self.ixia_cfg = mock.Mock()
+ self.scenario = tg_rfc2544_ixia.IxiaBasicScenario(self.mock_IxNextgen,
+ self.context_cfg,
+ self.ixia_cfg)
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_IxNextgen.stop()
+
+ def test___init___(self):
+ self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaBasicScenario)
+ self.assertEqual(self.scenario.client, self.mock_IxNextgen)
+
+ def test_create_traffic_model(self):
+ self.mock_IxNextgen.get_vports.return_value = [1, 2, 3, 4]
+ yaml_data = {'traffic_profile': {}
+ }
+ traffic_profile = ixia_rfc2544.IXIARFC2544Profile(yaml_data)
+ self.scenario.create_traffic_model(traffic_profile)
+ self.scenario.client.get_vports.assert_called_once()
+ self.scenario.client.create_traffic_model.assert_called_once_with(
+ [1, 3], [2, 4], traffic_profile)
+
+ def test_apply_config(self):
+ self.assertIsNone(self.scenario.apply_config())
+
+ def test_run_protocols(self):
+ self.assertIsNone(self.scenario.run_protocols())
+
+ def test_stop_protocols(self):
+ self.assertIsNone(self.scenario.stop_protocols())
+
+ def test__get_stats(self):
+ self.scenario._get_stats()
+ self.scenario.client.get_statistics.assert_called_once()
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaBasicScenario, '_get_stats')
+ def test_generate_samples(self, mock_get_stats):
+
+ expected_samples = {'xe0': {
+ 'InPackets': 150,
+ 'OutPackets': 150,
+ 'InBytes': 9600,
+ 'OutBytes': 9600,
+ 'RxThroughput': 5.0,
+ 'TxThroughput': 5.0,
+ 'RxThroughputBps': 320.0,
+ 'TxThroughputBps': 320.0,
+ 'LatencyMax': 100,
+ 'LatencyMin': 100,
+ 'LatencyAvg': 100},
+ 'xe1': {
+ 'InPackets': 150,
+ 'OutPackets': 150,
+ 'InBytes': 9600,
+ 'OutBytes': 9600,
+ 'RxThroughput': 5.0,
+ 'TxThroughput': 5.0,
+ 'RxThroughputBps': 320.0,
+ 'TxThroughputBps': 320.0,
+ 'LatencyMax': 200,
+ 'LatencyMin': 200,
+ 'LatencyAvg': 200}}
+
+ res_helper = mock.Mock()
+ res_helper.vnfd_helper.find_interface_by_port.side_effect = \
+ [{'name': 'xe0'}, {'name': 'xe1'}]
+ ports = [0, 1]
+ duration = 30
+ mock_get_stats.return_value = self.STATS
+ samples = self.scenario.generate_samples(res_helper, ports, duration)
+ mock_get_stats.assert_called_once()
+ self.assertEqual(samples, expected_samples)
+
+
+class TestIxiaL3Scenario(TestIxiaBasicScenario):
+ IXIA_CFG = {
+ 'flow': {
+ 'src_ip': ['192.168.0.1-192.168.0.50'],
+ 'dst_ip': ['192.168.1.1-192.168.1.150']
+ }
+ }
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__0': {
+ 'role': 'IxNet',
+ 'interfaces': {
+ 'xe0': {
+ 'vld_id': 'uplink_0',
+ 'local_ip': '10.1.1.1',
+ 'local_mac': 'aa:bb:cc:dd:ee:ff',
+ 'ifname': 'xe0'
+ },
+ 'xe1': {
+ 'vld_id': 'downlink_0',
+ 'local_ip': '20.2.2.2',
+ 'local_mac': 'bb:bb:cc:dd:ee:ee',
+ 'ifname': 'xe1'
+ }
+ },
+ 'routing_table': [{
+ 'network': "152.16.100.20",
+ 'netmask': '255.255.0.0',
+ 'gateway': '152.16.100.21',
+ 'if': 'xe0'
+ }]
+ }
+ }
+ }
+
+ def setUp(self):
+ super(TestIxiaL3Scenario, self).setUp()
+ self.ixia_cfg = self.IXIA_CFG
+ self.context_cfg = self.CONTEXT_CFG
+ self.scenario = tg_rfc2544_ixia.IxiaL3Scenario(self.mock_IxNextgen,
+ self.context_cfg,
+ self.ixia_cfg)
+
+ def test___init___(self):
+ self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaL3Scenario)
+ self.assertEqual(self.scenario.client, self.mock_IxNextgen)
+
+ def test_create_traffic_model(self):
+ self.mock_IxNextgen.get_vports.return_value = ['1', '2']
+ traffic_profile = 'fake_profile'
+ self.scenario.create_traffic_model(traffic_profile)
+ self.scenario.client.get_vports.assert_called_once()
+ self.scenario.client.create_ipv4_traffic_model.\
+ assert_called_once_with(['1/protocols/static'],
+ ['2/protocols/static'],
+ 'fake_profile')
+
+ def test_apply_config(self):
+ self.scenario._add_interfaces = mock.Mock()
+ self.scenario._add_static_ips = mock.Mock()
+ self.assertIsNone(self.scenario.apply_config())
+
+ def test__add_static(self):
+ self.mock_IxNextgen.get_vports.return_value = ['1', '2']
+ self.mock_IxNextgen.get_static_interface.side_effect = ['intf1',
+ 'intf2']
+
+ self.scenario._add_static_ips()
+
+ self.mock_IxNextgen.get_static_interface.assert_any_call('1')
+ self.mock_IxNextgen.get_static_interface.assert_any_call('2')
+
+ self.scenario.client.add_static_ipv4.assert_any_call(
+ 'intf1', '1', '192.168.0.1', 49, '32')
+ self.scenario.client.add_static_ipv4.assert_any_call(
+ 'intf2', '2', '192.168.1.1', 149, '32')
+
+ def test__add_interfaces(self):
+ self.mock_IxNextgen.get_vports.return_value = ['1', '2']
+
+ self.scenario._add_interfaces()
+
+ self.mock_IxNextgen.add_interface.assert_any_call('1',
+ '10.1.1.1',
+ 'aa:bb:cc:dd:ee:ff',
+ '152.16.100.21')
+ self.mock_IxNextgen.add_interface.assert_any_call('2',
+ '20.2.2.2',
+ 'bb:bb:cc:dd:ee:ee',
+ None)
+
+
+class TestIxiaPppoeClientScenario(unittest.TestCase):
+
+ IXIA_CFG = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1,
+ 's_vlan': 10,
+ 'c_vlan': 20,
+ 'ip': ['10.3.3.1', '10.4.4.1']
+ },
+ 'ipv4_client': {
+ 'sessions_per_port': 1,
+ 'sessions_per_vlan': 1,
+ 'vlan': 101,
+ 'gateway_ip': ['10.1.1.1', '10.2.2.1'],
+ 'ip': ['10.1.1.1', '10.2.2.1'],
+ 'prefix': ['24', '24']
+ },
+ 'priority': {
+ 'tos': {'precedence': [0, 4]}
+ }
+ }
+
+ CONTEXT_CFG = {
+ 'nodes': {'tg__0': {
+ 'interfaces': {'xe0': {
+ 'local_ip': '10.1.1.1',
+ 'netmask': '255.255.255.0'
+ }}}}}
+
+ def setUp(self):
+ self._mock_IxNextgen = mock.patch.object(ixnet_api, 'IxNextgen')
+ self.mock_IxNextgen = self._mock_IxNextgen.start()
+ self.scenario = tg_rfc2544_ixia.IxiaPppoeClientScenario(
+ self.mock_IxNextgen, self.CONTEXT_CFG, self.IXIA_CFG)
+ tg_rfc2544_ixia.WAIT_PROTOCOLS_STARTED = 2
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_IxNextgen.stop()
+
+ def test___init___(self):
+ self.assertIsInstance(self.scenario, tg_rfc2544_ixia.IxiaPppoeClientScenario)
+ self.assertEqual(self.scenario.client, self.mock_IxNextgen)
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_fill_ixia_config')
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_apply_access_network_config')
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_apply_core_network_config')
+ def test_apply_config(self, mock_apply_core_net_cfg,
+ mock_apply_access_net_cfg,
+ mock_fill_ixia_config):
+ self.mock_IxNextgen.get_vports.return_value = [1, 2, 3, 4]
+ self.scenario.apply_config()
+ self.scenario.client.get_vports.assert_called_once()
+ self.assertEqual(self.scenario._uplink_vports, [1, 3])
+ self.assertEqual(self.scenario._downlink_vports, [2, 4])
+ mock_fill_ixia_config.assert_called_once()
+ mock_apply_core_net_cfg.assert_called_once()
+ mock_apply_access_net_cfg.assert_called_once()
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_get_endpoints_src_dst_id_pairs')
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_get_endpoints_src_dst_obj_pairs')
+ def test_create_traffic_model(self, mock_obj_pairs, mock_id_pairs):
+ uplink_endpoints = ['group1', 'group2']
+ downlink_endpoints = ['group3', 'group3']
+ mock_id_pairs.return_value = ['xe0', 'xe1', 'xe0', 'xe1']
+ mock_obj_pairs.return_value = ['group1', 'group3', 'group2', 'group3']
+ mock_tp = mock.Mock()
+ mock_tp.full_profile = {'uplink_0': 'data',
+ 'downlink_0': 'data',
+ 'uplink_1': 'data',
+ 'downlink_1': 'data'
+ }
+ self.scenario.create_traffic_model(mock_tp)
+ mock_id_pairs.assert_called_once_with(mock_tp.full_profile)
+ mock_obj_pairs.assert_called_once_with(['xe0', 'xe1', 'xe0', 'xe1'])
+ self.scenario.client.create_ipv4_traffic_model.assert_called_once_with(
+ uplink_endpoints, downlink_endpoints, mock_tp)
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_get_endpoints_src_dst_id_pairs')
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ '_get_endpoints_src_dst_obj_pairs')
+ def test_create_traffic_model_topology_based_flows(self, mock_obj_pairs,
+ mock_id_pairs):
+ uplink_topologies = ['topology1', 'topology3']
+ downlink_topologies = ['topology2', 'topology4']
+ mock_id_pairs.return_value = []
+ mock_obj_pairs.return_value = []
+ mock_tp = mock.Mock()
+ mock_tp.full_profile = {'uplink_0': 'data',
+ 'downlink_0': 'data',
+ 'uplink_1': 'data',
+ 'downlink_1': 'data'
+ }
+ self.scenario._access_topologies = ['topology1', 'topology3']
+ self.scenario._core_topologies = ['topology2', 'topology4']
+ self.scenario.create_traffic_model(mock_tp)
+ mock_id_pairs.assert_called_once_with(mock_tp.full_profile)
+ mock_obj_pairs.assert_called_once_with([])
+ self.scenario.client.create_ipv4_traffic_model.assert_called_once_with(
+ uplink_topologies, downlink_topologies, mock_tp)
+
+ def test__get_endpoints_src_dst_id_pairs(self):
+ full_tp = OrderedDict([
+ ('uplink_0', {'ipv4': {'port': 'xe0'}}),
+ ('downlink_0', {'ipv4': {'port': 'xe1'}}),
+ ('uplink_1', {'ipv4': {'port': 'xe0'}}),
+ ('downlink_1', {'ipv4': {'port': 'xe3'}})])
+ endpoints_src_dst_pairs = ['xe0', 'xe1', 'xe0', 'xe3']
+ res = self.scenario._get_endpoints_src_dst_id_pairs(full_tp)
+ self.assertEqual(res, endpoints_src_dst_pairs)
+
+ def test__get_endpoints_src_dst_id_pairs_wrong_flows_number(self):
+ full_tp = OrderedDict([
+ ('uplink_0', {'ipv4': {'port': 'xe0'}}),
+ ('downlink_0', {'ipv4': {'port': 'xe1'}}),
+ ('uplink_1', {'ipv4': {'port': 'xe0'}})])
+ with self.assertRaises(RuntimeError):
+ self.scenario._get_endpoints_src_dst_id_pairs(full_tp)
+
+ def test__get_endpoints_src_dst_id_pairs_no_port_key(self):
+ full_tp = OrderedDict([
+ ('uplink_0', {'ipv4': {'id': 1}}),
+ ('downlink_0', {'ipv4': {'id': 2}})])
+ self.assertEqual(
+ self.scenario._get_endpoints_src_dst_id_pairs(full_tp), [])
+
+ def test__get_endpoints_src_dst_obj_pairs_tp_with_port_key(self):
+ endpoints_id_pairs = ['xe0', 'xe1',
+ 'xe0', 'xe1',
+ 'xe0', 'xe3',
+ 'xe0', 'xe3']
+ ixia_cfg = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1
+ },
+ 'flow': {
+ 'src_ip': [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}],
+ 'dst_ip': [{'tg__0': 'xe1'}, {'tg__0': 'xe3'}]
+ }
+ }
+
+ expected_result = ['tp1_dg1', 'tp3_dg1', 'tp1_dg2', 'tp3_dg1',
+ 'tp1_dg3', 'tp4_dg1', 'tp1_dg4', 'tp4_dg1']
+
+ self.scenario._ixia_cfg = ixia_cfg
+ self.scenario._access_topologies = ['topology1', 'topology2']
+ self.scenario._core_topologies = ['topology3', 'topology4']
+ self.mock_IxNextgen.get_topology_device_groups.side_effect = \
+ [['tp1_dg1', 'tp1_dg2', 'tp1_dg3', 'tp1_dg4'],
+ ['tp2_dg1', 'tp2_dg2', 'tp2_dg3', 'tp2_dg4'],
+ ['tp3_dg1'],
+ ['tp4_dg1']]
+ res = self.scenario._get_endpoints_src_dst_obj_pairs(
+ endpoints_id_pairs)
+ self.assertEqual(res, expected_result)
+
+ def test__get_endpoints_src_dst_obj_pairs_default_flows_mapping(self):
+ endpoints_id_pairs = []
+ ixia_cfg = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1
+ },
+ 'flow': {
+ 'src_ip': [{'tg__0': 'xe0'}, {'tg__0': 'xe2'}],
+ 'dst_ip': [{'tg__0': 'xe1'}, {'tg__0': 'xe3'}]
+ }
+ }
+
+ self.scenario._ixia_cfg = ixia_cfg
+ res = self.scenario._get_endpoints_src_dst_obj_pairs(
+ endpoints_id_pairs)
+ self.assertEqual(res, [])
+
+ def test_run_protocols(self):
+ self.scenario.client.is_protocols_running.return_value = True
+ self.scenario.run_protocols()
+ self.scenario.client.start_protocols.assert_called_once()
+
+ def test_run_protocols_timeout_exception(self):
+ self.scenario.client.is_protocols_running.return_value = False
+ with self.assertRaises(exceptions.WaitTimeout):
+ self.scenario.run_protocols()
+ self.scenario.client.start_protocols.assert_called_once()
+
+ def test_stop_protocols(self):
+ self.scenario.stop_protocols()
+ self.scenario.client.stop_protocols.assert_called_once()
+
+ def test__get_intf_addr_str_type_input(self):
+ intf = '192.168.10.2/24'
+ ip, mask = self.scenario._get_intf_addr(intf)
+ self.assertEqual(ip, '192.168.10.2')
+ self.assertEqual(mask, 24)
+
+ def test__get_intf_addr_dict_type_input(self):
+ intf = {'tg__0': 'xe0'}
+ ip, mask = self.scenario._get_intf_addr(intf)
+ self.assertEqual(ip, '10.1.1.1')
+ self.assertEqual(mask, 24)
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, '_get_intf_addr')
+ def test__fill_ixia_config(self, mock_get_intf_addr):
+
+ ixia_cfg = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1,
+ 's_vlan': 10,
+ 'c_vlan': 20,
+ 'ip': ['10.3.3.1/24', '10.4.4.1/24']
+ },
+ 'ipv4_client': {
+ 'sessions_per_port': 1,
+ 'sessions_per_vlan': 1,
+ 'vlan': 101,
+ 'gateway_ip': ['10.1.1.1/24', '10.2.2.1/24'],
+ 'ip': ['10.1.1.1/24', '10.2.2.1/24']
+ }
+ }
+
+ mock_get_intf_addr.side_effect = [
+ ('10.3.3.1', '24'),
+ ('10.4.4.1', '24'),
+ ('10.1.1.1', '24'),
+ ('10.2.2.1', '24'),
+ ('10.1.1.1', '24'),
+ ('10.2.2.1', '24')
+ ]
+ self.scenario._ixia_cfg = ixia_cfg
+ self.scenario._fill_ixia_config()
+ self.assertEqual(mock_get_intf_addr.call_count, 6)
+ self.assertEqual(self.scenario._ixia_cfg['pppoe_client']['ip'],
+ ['10.3.3.1', '10.4.4.1'])
+ self.assertEqual(self.scenario._ixia_cfg['ipv4_client']['ip'],
+ ['10.1.1.1', '10.2.2.1'])
+ self.assertEqual(self.scenario._ixia_cfg['ipv4_client']['prefix'],
+ ['24', '24'])
+
+ @mock.patch('yardstick.network_services.libs.ixia_libs.ixnet.ixnet_api.Vlan')
+ def test__apply_access_network_config_pap_auth(self, mock_vlan):
+ _ixia_cfg = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1,
+ 's_vlan': 10,
+ 'c_vlan': 20,
+ 'pap_user': 'test_pap',
+ 'pap_password': 'pap'
+ }}
+ pap_user = _ixia_cfg['pppoe_client']['pap_user']
+ pap_passwd = _ixia_cfg['pppoe_client']['pap_password']
+ self.scenario._ixia_cfg = _ixia_cfg
+ self.scenario._uplink_vports = [0, 2]
+ self.scenario.client.add_topology.side_effect = ['Topology 1', 'Topology 2']
+ self.scenario.client.add_device_group.side_effect = ['Dg1', 'Dg2', 'Dg3',
+ 'Dg4', 'Dg5', 'Dg6',
+ 'Dg7', 'Dg8']
+ self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2', 'Eth3',
+ 'Eth4', 'Eth5', 'Eth6',
+ 'Eth7', 'Eth8']
+ self.scenario._apply_access_network_config()
+ self.assertEqual(self.scenario.client.add_topology.call_count, 2)
+ self.assertEqual(self.scenario.client.add_device_group.call_count, 8)
+ self.assertEqual(self.scenario.client.add_ethernet.call_count, 8)
+ self.assertEqual(mock_vlan.call_count, 16)
+ self.assertEqual(self.scenario.client.add_vlans.call_count, 8)
+ self.assertEqual(self.scenario.client.add_pppox_client.call_count, 8)
+ self.scenario.client.add_topology.assert_has_calls([
+ mock.call('Topology access 0', 0),
+ mock.call('Topology access 1', 2)
+ ])
+ self.scenario.client.add_device_group.assert_has_calls([
+ mock.call('Topology 1', 'SVLAN 10', 1),
+ mock.call('Topology 1', 'SVLAN 11', 1),
+ mock.call('Topology 1', 'SVLAN 12', 1),
+ mock.call('Topology 1', 'SVLAN 13', 1),
+ mock.call('Topology 2', 'SVLAN 14', 1),
+ mock.call('Topology 2', 'SVLAN 15', 1),
+ mock.call('Topology 2', 'SVLAN 16', 1),
+ mock.call('Topology 2', 'SVLAN 17', 1)
+ ])
+ self.scenario.client.add_ethernet.assert_has_calls([
+ mock.call('Dg1', 'Ethernet'),
+ mock.call('Dg2', 'Ethernet'),
+ mock.call('Dg3', 'Ethernet'),
+ mock.call('Dg4', 'Ethernet'),
+ mock.call('Dg5', 'Ethernet'),
+ mock.call('Dg6', 'Ethernet'),
+ mock.call('Dg7', 'Ethernet'),
+ mock.call('Dg8', 'Ethernet')
+ ])
+ mock_vlan.assert_has_calls([
+ mock.call(vlan_id=10),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=11),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=12),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=13),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=14),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=15),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=16),
+ mock.call(vlan_id=20, vlan_id_step=1),
+ mock.call(vlan_id=17),
+ mock.call(vlan_id=20, vlan_id_step=1)
+ ])
+ self.scenario.client.add_pppox_client.assert_has_calls([
+ mock.call('Eth1', 'pap', pap_user, pap_passwd),
+ mock.call('Eth2', 'pap', pap_user, pap_passwd),
+ mock.call('Eth3', 'pap', pap_user, pap_passwd),
+ mock.call('Eth4', 'pap', pap_user, pap_passwd),
+ mock.call('Eth5', 'pap', pap_user, pap_passwd),
+ mock.call('Eth6', 'pap', pap_user, pap_passwd),
+ mock.call('Eth7', 'pap', pap_user, pap_passwd),
+ mock.call('Eth8', 'pap', pap_user, pap_passwd)
+ ])
+
+ def test__apply_access_network_config_chap_auth(self):
+ _ixia_cfg = {
+ 'pppoe_client': {
+ 'sessions_per_port': 4,
+ 'sessions_per_svlan': 1,
+ 's_vlan': 10,
+ 'c_vlan': 20,
+ 'chap_user': 'test_chap',
+ 'chap_password': 'chap'
+ }}
+ chap_user = _ixia_cfg['pppoe_client']['chap_user']
+ chap_passwd = _ixia_cfg['pppoe_client']['chap_password']
+ self.scenario._ixia_cfg = _ixia_cfg
+ self.scenario._uplink_vports = [0, 2]
+ self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2', 'Eth3',
+ 'Eth4', 'Eth5', 'Eth6',
+ 'Eth7', 'Eth8']
+ self.scenario._apply_access_network_config()
+ self.assertEqual(self.scenario.client.add_pppox_client.call_count, 8)
+ self.scenario.client.add_pppox_client.assert_has_calls([
+ mock.call('Eth1', 'chap', chap_user, chap_passwd),
+ mock.call('Eth2', 'chap', chap_user, chap_passwd),
+ mock.call('Eth3', 'chap', chap_user, chap_passwd),
+ mock.call('Eth4', 'chap', chap_user, chap_passwd),
+ mock.call('Eth5', 'chap', chap_user, chap_passwd),
+ mock.call('Eth6', 'chap', chap_user, chap_passwd),
+ mock.call('Eth7', 'chap', chap_user, chap_passwd),
+ mock.call('Eth8', 'chap', chap_user, chap_passwd)
+ ])
+
+ @mock.patch('yardstick.network_services.libs.ixia_libs.ixnet.ixnet_api.Vlan')
+ def test__apply_core_network_config_no_bgp_proto(self, mock_vlan):
+ self.scenario._downlink_vports = [1, 3]
+ self.scenario.client.add_topology.side_effect = ['Topology 1', 'Topology 2']
+ self.scenario.client.add_device_group.side_effect = ['Dg1', 'Dg2']
+ self.scenario.client.add_ethernet.side_effect = ['Eth1', 'Eth2']
+ self.scenario._apply_core_network_config()
+ self.assertEqual(self.scenario.client.add_topology.call_count, 2)
+ self.assertEqual(self.scenario.client.add_device_group.call_count, 2)
+ self.assertEqual(self.scenario.client.add_ethernet.call_count, 2)
+ self.assertEqual(mock_vlan.call_count, 2)
+ self.assertEqual(self.scenario.client.add_vlans.call_count, 2)
+ self.assertEqual(self.scenario.client.add_ipv4.call_count, 2)
+ self.scenario.client.add_topology.assert_has_calls([
+ mock.call('Topology core 0', 1),
+ mock.call('Topology core 1', 3)
+ ])
+ self.scenario.client.add_device_group.assert_has_calls([
+ mock.call('Topology 1', 'Core port 0', 1),
+ mock.call('Topology 2', 'Core port 1', 1)
+ ])
+ self.scenario.client.add_ethernet.assert_has_calls([
+ mock.call('Dg1', 'Ethernet'),
+ mock.call('Dg2', 'Ethernet')
+ ])
+ mock_vlan.assert_has_calls([
+ mock.call(vlan_id=101),
+ mock.call(vlan_id=102)
+ ])
+ self.scenario.client.add_ipv4.assert_has_calls([
+ mock.call('Eth1', name='ipv4', addr=ipaddress.IPv4Address('10.1.1.2'),
+ addr_step='0.0.0.1', prefix='24', gateway='10.1.1.1'),
+ mock.call('Eth2', name='ipv4', addr=ipaddress.IPv4Address('10.2.2.2'),
+ addr_step='0.0.0.1', prefix='24', gateway='10.2.2.1')
+ ])
+ self.scenario.client.add_bgp.assert_not_called()
+
+ def test__apply_core_network_config_with_bgp_proto(self):
+ bgp_params = {
+ 'bgp': {
+ 'bgp_type': 'external',
+ 'dut_ip': '10.0.0.1',
+ 'as_number': 65000
+ }
+ }
+ self.scenario._ixia_cfg['ipv4_client'].update(bgp_params)
+ self.scenario._downlink_vports = [1, 3]
+ self.scenario.client.add_ipv4.side_effect = ['ipv4_1', 'ipv4_2']
+ self.scenario._apply_core_network_config()
+ self.assertEqual(self.scenario.client.add_bgp.call_count, 2)
+ self.scenario.client.add_bgp.assert_has_calls([
+ mock.call('ipv4_1', dut_ip=bgp_params["bgp"]["dut_ip"],
+ local_as=bgp_params["bgp"]["as_number"],
+ bgp_type=bgp_params["bgp"]["bgp_type"]),
+ mock.call('ipv4_2', dut_ip=bgp_params["bgp"]["dut_ip"],
+ local_as=bgp_params["bgp"]["as_number"],
+ bgp_type=bgp_params["bgp"]["bgp_type"])
+ ])
+
+ def test_update_tracking_options_raw_priority(self):
+ raw_priority = {'raw': 4}
+ self.scenario._ixia_cfg['priority'] = raw_priority
+ self.scenario.update_tracking_options()
+ self.scenario.client.set_flow_tracking.assert_called_once_with(
+ ['flowGroup0', 'vlanVlanId0', 'ipv4Raw0'])
+
+ def test_update_tracking_options_tos_priority(self):
+ tos_priority = {'tos': {'precedence': [4, 7]}}
+ self.scenario._ixia_cfg['priority'] = tos_priority
+ self.scenario.update_tracking_options()
+ self.scenario.client.set_flow_tracking.assert_called_once_with(
+ ['flowGroup0', 'vlanVlanId0', 'ipv4Precedence0'])
+
+ def test_update_tracking_options_dscp_priority(self):
+ dscp_priority = {'dscp': {'defaultPHB': [4, 7]}}
+ self.scenario._ixia_cfg['priority'] = dscp_priority
+ self.scenario.update_tracking_options()
+ self.scenario.client.set_flow_tracking.assert_called_once_with(
+ ['flowGroup0', 'vlanVlanId0', 'ipv4DefaultPhb0'])
+
+ def test_update_tracking_options_invalid_priority_data(self):
+ invalid_priority = {'tos': {'inet-precedence': [4, 7]}}
+ self.scenario._ixia_cfg['priority'] = invalid_priority
+ self.scenario.update_tracking_options()
+ self.scenario.client.set_flow_tracking.assert_called_once_with(
+ ['flowGroup0', 'vlanVlanId0', 'ipv4Precedence0'])
+
+ def test_get_tc_rfc2544_options(self):
+ rfc2544_tc_opts = {'allowed_drop_rate': '0.0001 - 0.0001'}
+ self.scenario._ixia_cfg['rfc2544'] = rfc2544_tc_opts
+ res = self.scenario.get_tc_rfc2544_options()
+ self.assertEqual(res, rfc2544_tc_opts)
+
+ def test__get_stats(self):
+ self.scenario._get_stats()
+ self.scenario.client.get_pppoe_scenario_statistics.assert_called_once()
+
+ def test_get_flow_id_data(self):
+ stats = [{'id': 1, 'in_packets': 10, 'out_packets': 20}]
+ key = "in_packets"
+ flow_id = 1
+ res = self.scenario.get_flow_id_data(stats, flow_id, key)
+ self.assertEqual(res, 10)
+
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario, '_get_stats')
+ @mock.patch.object(tg_rfc2544_ixia.IxiaPppoeClientScenario,
+ 'get_priority_flows_stats')
+ def test_generate_samples(self, mock_prio_flow_statistics,
+ mock_get_stats):
+ ixia_stats = {
+ 'flow_statistic': [
+ {'Flow_Group': 'RFC2544-1 - Flow Group 0001',
+ 'Frames_Delta': '0',
+ 'IP_Priority': '0',
+ 'Rx_Frames': '3000',
+ 'Tx_Frames': '3000',
+ 'VLAN-ID': '100',
+ 'Tx_Port': 'Ethernet - 001',
+ 'Store-Forward_Avg_latency_ns': '2',
+ 'Store-Forward_Min_latency_ns': '2',
+ 'Store-Forward_Max_latency_ns': '2'},
+ {'Flow_Group': 'RFC2544-2 - Flow Group 0001',
+ 'Frames_Delta': '0',
+ 'IP_Priority': '0',
+ 'Rx_Frames': '3000',
+ 'Tx_Frames': '3000',
+ 'VLAN-ID': '101',
+ 'Tx_Port': 'Ethernet - 002',
+ 'Store-Forward_Avg_latency_ns': '2',
+ 'Store-Forward_Min_latency_ns': '2',
+ 'Store-Forward_Max_latency_ns': '2'
+ }],
+ 'port_statistics': [
+ {'Frames_Tx': '3000',
+ 'Valid_Frames_Rx': '3000',
+ 'Bytes_Rx': '192000',
+ 'Bytes_Tx': '192000',
+ 'Rx_Rate_Kbps': '0.0',
+ 'Tx_Rate_Kbps': '0.0',
+ 'Rx_Rate_Mbps': '0.0',
+ 'Tx_Rate_Mbps': '0.0',
+ 'port_name': 'Ethernet - 001'},
+ {'Frames_Tx': '3000',
+ 'Valid_Frames_Rx': '3000',
+ 'Bytes_Rx': '192000',
+ 'Bytes_Tx': '192000',
+ 'Rx_Rate_Kbps': '0.0',
+ 'Tx_Rate_Kbps': '0.0',
+ 'Rx_Rate_Mbps': '0.0',
+ 'Tx_Rate_Mbps': '0.0',
+ 'port_name': 'Ethernet - 002'}],
+ 'pppox_client_per_port': [
+ {'Sessions_Down': '0',
+ 'Sessions_Not_Started': '0',
+ 'Sessions_Total': '1',
+ 'Sessions_Up': '1',
+ 'subs_port': 'Ethernet - 001'}]}
+
+ prio_flows_stats = {
+ '0': {
+ 'InPackets': 6000,
+ 'OutPackets': 6000,
+ 'RxThroughput': 200.0,
+ 'TxThroughput': 200.0,
+ 'LatencyAvg': 2,
+ 'LatencyMax': 2,
+ 'LatencyMin': 2
+ }
+ }
+
+ expected_result = {'priority_stats': {
+ '0': {'RxThroughput': 200.0,
+ 'TxThroughput': 200.0,
+ 'LatencyAvg': 2,
+ 'LatencyMax': 2,
+ 'LatencyMin': 2,
+ 'InPackets': 6000,
+ 'OutPackets': 6000}},
+ 'xe0': {'RxThroughput': 100.0,
+ 'LatencyAvg': 2,
+ 'LatencyMax': 2,
+ 'LatencyMin': 2,
+ 'TxThroughput': 100.0,
+ 'InPackets': 3000,
+ 'OutPackets': 3000,
+ 'InBytes': 192000,
+ 'OutBytes': 192000,
+ 'RxThroughputBps': 6400.0,
+ 'TxThroughputBps': 6400.0,
+ 'SessionsDown': 0,
+ 'SessionsNotStarted': 0,
+ 'SessionsTotal': 1,
+ 'SessionsUp': 1},
+ 'xe1': {'RxThroughput': 100.0,
+ 'LatencyAvg': 2,
+ 'LatencyMax': 2,
+ 'LatencyMin': 2,
+ 'TxThroughput': 100.0,
+ 'InPackets': 3000,
+ 'OutPackets': 3000,
+ 'InBytes': 192000,
+ 'OutBytes': 192000,
+ 'RxThroughputBps': 6400.0,
+ 'TxThroughputBps': 6400.0}}
+
+ mock_get_stats.return_value = ixia_stats
+ mock_prio_flow_statistics.return_value = prio_flows_stats
+ ports = [0, 1]
+ port_names = [{'name': 'xe0'}, {'name': 'xe1'}]
+ duration = 30
+ res_helper = mock.Mock()
+ res_helper.vnfd_helper.find_interface_by_port.side_effect = \
+ port_names
+ samples = self.scenario.generate_samples(res_helper, ports, duration)
+ self.assertIsNotNone(samples)
+ self.assertIsNotNone(samples.get('xe0'))
+ self.assertIsNotNone(samples.get('xe1'))
+ self.assertEqual(samples, expected_result)
+ mock_get_stats.assert_called_once()
+ mock_prio_flow_statistics.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
new file mode 100644
index 000000000..51b1b0d33
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_trex.py
@@ -0,0 +1,312 @@
+# Copyright (c) 2016-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.
+import time
+
+import mock
+import unittest
+
+from yardstick.benchmark import contexts
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_trex
+
+
+class TestTrexRfcResouceHelper(unittest.TestCase):
+
+ @mock.patch.object(time, 'sleep')
+ def test__run_traffic_once(self, *args):
+ mock_setup_helper = mock.Mock()
+ mock_traffic_profile = mock.Mock()
+ mock_traffic_profile.config.duration = 3
+ mock_traffic_profile.execute_traffic.return_value = ('fake_ports',
+ 'port_pg_id_map')
+ mock_traffic_profile.get_drop_percentage.return_value = (True,
+ 'percentage')
+ rfc_rh = tg_rfc2544_trex.TrexRfcResourceHelper(mock_setup_helper)
+ rfc_rh.TRANSIENT_PERIOD = 0
+ rfc_rh.rfc2544_helper = mock.Mock()
+
+ with mock.patch.object(rfc_rh, '_get_samples') as mock_get_samples:
+ self.assertTrue(rfc_rh._run_traffic_once(mock_traffic_profile))
+
+ mock_traffic_profile.execute_traffic.assert_called_once_with(rfc_rh)
+ mock_traffic_profile.stop_traffic.assert_called_once_with(rfc_rh)
+ mock_traffic_profile.stop_traffic.assert_called_once()
+ mock_get_samples.assert_has_calls([
+ mock.call('fake_ports', port_pg_id='port_pg_id_map'),
+ mock.call('fake_ports', port_pg_id='port_pg_id_map')])
+
+
+class TestTrexTrafficGenRFC(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'ifname': 'xe0',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'vld_id': 'uplink_0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:01',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'ifname': 'xe1',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'vld_id': 'downlink_0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:02'
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf',
+ 'name': 'VPEVnfSsh',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64,
+ },
+ }
+
+ TC_YAML = {
+ 'scenarios': [
+ {
+ 'tc_options': {
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ },
+ 'runner': {
+ 'duration': 400,
+ 'interval': 35,
+ 'type': 'Duration',
+ },
+ 'traffic_options': {
+ 'flow': 'ipv4_1flow_Packets_vpe.yaml',
+ 'imix': 'imix_voice.yaml',
+ },
+ 'vnf_options': {
+ 'vpe': {
+ 'cfg': 'vpe_config',
+ },
+ },
+ 'traffic_profile': 'ipv4_throughput_vpe.yaml',
+ 'type': 'NSPerf',
+ 'nodes': {
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick',
+ },
+ 'topology': 'vpe_vnf_topology.yaml',
+ },
+ ],
+ 'context': {
+ 'nfvi_type': 'baremetal',
+ 'type': contexts.CONTEXT_NODE,
+ 'name': 'yardstick',
+ 'file': '/etc/yardstick/nodes/pod.yaml',
+ },
+ 'schema': 'yardstick:task:0.1',
+ }
+
+ def setUp(self):
+ self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper = self._mock_ssh_helper.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh_helper.stop()
+
+ def test___init__(self):
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ self.assertIsNotNone(trex_traffic_gen.resource_helper._terminated.value)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ trex_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {trex_traffic_gen.name: "mock"}
+ }
+ expected = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {},
+ }
+ self.assertEqual(trex_traffic_gen.collect_kpi(), expected)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+ def test_instantiate(self, *args):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ trex_traffic_gen._start_server = mock.Mock(return_value=0)
+ trex_traffic_gen.resource_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+
+ scenario_cfg = {
+ "tc": "tc_baremetal_rfc2544_ipv4_1flow_64B",
+ "topology": 'nsb_test_case.yaml',
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__1': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1
+ },
+ },
+ },
+ }
+ tg_rfc2544_trex.WAIT_TIME = 3
+ scenario_cfg.update({"nodes": {"tg_1": {}, "vnf1": {}}})
+ self.assertIsNone(trex_traffic_gen.instantiate(scenario_cfg, {}))
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+ def test_instantiate_error(self, *args):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ trex_traffic_gen = tg_rfc2544_trex.TrexTrafficGenRFC('vnf1', self.VNFD_0)
+ trex_traffic_gen.resource_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+ scenario_cfg = {
+ "tc": "tc_baremetal_rfc2544_ipv4_1flow_64B",
+ "nodes": {
+ "tg_1": {},
+ "vnf1": {}
+ },
+ "topology": 'nsb_test_case.yaml',
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__1': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1,
+ },
+ },
+ },
+ }
+ trex_traffic_gen.instantiate(scenario_cfg, {})
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
new file mode 100644
index 000000000..0a441c8ce
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex.py
@@ -0,0 +1,516 @@
+# Copyright (c) 2016-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.
+
+import copy
+
+import mock
+import unittest
+
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import tg_trex
+from yardstick.benchmark.contexts import base as ctx_base
+
+
+NAME = 'vnf__1'
+
+
+class TestTrexTrafficGen(unittest.TestCase):
+
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd',
+ 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64
+ },
+ }
+
+ SCENARIO_CFG = {
+ "options": {
+ "packetsize": 64,
+ "traffic_type": 4,
+ "rfc2544": {
+ "allowed_drop_rate": "0.8 - 1",
+ },
+ "vnf__1": {
+ "rules": "acl_1rule.yaml",
+ "vnf_config": {
+ "lb_config": "SW",
+ "lb_count": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 1,
+ }
+ }
+ },
+ "task_id": "a70bdf4a-8e67-47a3-9dc1-273c14506eb7",
+ "tc": "tc_ipv4_1Mflow_64B_packetsize",
+ "runner": {
+ "object": "NetworkServiceTestCase",
+ "interval": 35,
+ "output_filename": "/tmp/yardstick.out",
+ "runner_id": 74476, "duration": 400,
+ "type": "Duration"
+ },
+ "traffic_profile": "ipv4_throughput_acl.yaml",
+ "traffic_options": {
+ "flow": "ipv4_Packets_acl.yaml",
+ "imix": "imix_voice.yaml"
+ },
+ "type": "ISB",
+ "nodes": {
+ "tg__2": "trafficgen_2.yardstick",
+ "tg__1": "trafficgen_1.yardstick",
+ "vnf__1": "vnf.yardstick"
+ },
+ "topology": "udpreplay-tg-topology-baremetal.yaml"
+ }
+
+ CONTEXT_CFG = {
+ "nodes": {
+ "vnf__1": {
+ "vnfd-id-ref": "vnf__1",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens786f0",
+ "vld_id": tp_base.TrafficProfile.UPLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.0",
+ "local_ip": "152.16.100.19",
+ "driver": "i40e",
+ "dst_ip": "152.16.100.20",
+ "local_mac": "00:00:00:00:00:02",
+ "dst_mac": "00:00:00:00:00:04",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_iface_name": "ens786f1",
+ "vld_id": tp_base.TrafficProfile.DOWNLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.1",
+ "local_ip": "152.16.40.19",
+ "driver": "i40e",
+ "dst_ip": "152.16.40.20",
+ "local_mac": "00:00:00:00:00:01",
+ "dst_mac": "00:00:00:00:00:03",
+ "dpdk_port_num": 1
+ }
+ },
+ "host": "1.2.1.1",
+ "user": "root",
+ "nd_route_tbl": [
+ {
+ "netmask": "112",
+ "if": "xe0",
+ "gateway": "0064:ff9b:0:0:0:0:9810:6414",
+ "network": "0064:ff9b:0:0:0:0:9810:6414"
+ },
+ {
+ "netmask": "112",
+ "if": "xe1",
+ "gateway": "0064:ff9b:0:0:0:0:9810:2814",
+ "network": "0064:ff9b:0:0:0:0:9810:2814"
+ }
+ ],
+ "password": "r00t",
+ "VNF model": "udp_replay.yaml",
+ "name": "vnf.yardstick",
+ "member-vnf-index": "2",
+ "routing_table": [
+ {
+ "netmask": "255.255.255.0",
+ "if": "xe0",
+ "gateway": "152.16.100.20",
+ "network": "152.16.100.20"
+ },
+ {
+ "netmask": "255.255.255.0",
+ "if": "xe1",
+ "gateway": "152.16.40.20",
+ "network": "152.16.40.20"
+ }
+ ],
+ "role": "vnf"
+ },
+ "trafficgen_2.yardstick": {
+ "member-vnf-index": "3",
+ "role": "TrafficGen",
+ "name": "trafficgen_2.yardstick",
+ "vnfd-id-ref": "tg__2",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens513f0",
+ "vld_id": tp_base.TrafficProfile.DOWNLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:02:00.0",
+ "local_ip": "152.16.40.20",
+ "driver": "ixgbe",
+ "dst_ip": "152.16.40.19",
+ "local_mac": "00:00:00:00:00:03",
+ "dst_mac": "00:00:00:00:00:01",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_iface_name": "ens513f1",
+ "netmask": "255.255.255.0",
+ "network": "202.16.100.0",
+ "local_ip": "202.16.100.20",
+ "driver": "ixgbe",
+ "local_mac": "00:1e:67:d0:60:5d",
+ "vpci": "0000:02:00.1",
+ "dpdk_port_num": 1
+ }
+ },
+ "password": "r00t",
+ "VNF model": "l3fwd_vnf.yaml",
+ "user": "root"
+ },
+ "trafficgen_1.yardstick": {
+ "member-vnf-index": "1",
+ "role": "TrafficGen",
+ "name": "trafficgen_1.yardstick",
+ "vnfd-id-ref": "tg__1",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens785f0",
+ "vld_id": tp_base.TrafficProfile.UPLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.0",
+ "local_ip": "152.16.100.20",
+ "driver": "i40e",
+ "dst_ip": "152.16.100.19",
+ "local_mac": "00:00:00:00:00:04",
+ "dst_mac": "00:00:00:00:00:02",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_ip": "152.16.100.21",
+ "driver": "i40e",
+ "vpci": "0000:05:00.1",
+ "dpdk_port_num": 1,
+ "local_iface_name": "ens785f1",
+ "netmask": "255.255.255.0",
+ "local_mac": "00:00:00:00:00:01"
+ }
+ },
+ "password": "r00t",
+ "VNF model": "tg_rfc2544_tpl.yaml",
+ "user": "root"
+ }
+ }
+ }
+
+ def setUp(self):
+ self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper = self._mock_ssh_helper.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh_helper.stop()
+
+ def test___init__(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ self.assertIsInstance(trex_traffic_gen.resource_helper,
+ tg_trex.TrexResourceHelper)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {trex_traffic_gen.name: "mock"}
+ }
+ trex_traffic_gen.resource_helper._queue.put({})
+ result = trex_traffic_gen.collect_kpi()
+ expected = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {}
+ }
+ self.assertEqual(expected, result)
+
+ def test_listen_traffic(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ self.assertIsNone(trex_traffic_gen.listen_traffic({}))
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+ def test_instantiate(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen._start_server = mock.Mock(return_value=0)
+ trex_traffic_gen._tg_process = mock.MagicMock()
+ trex_traffic_gen._tg_process.start = mock.Mock()
+ trex_traffic_gen._tg_process.exitcode = 0
+ trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=1)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+ self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server', return_value='fake_context')
+ def test_instantiate_error(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen._start_server = mock.Mock(return_value=0)
+ trex_traffic_gen._tg_process = mock.MagicMock()
+ trex_traffic_gen._tg_process.start = mock.Mock()
+ trex_traffic_gen._tg_process._is_alive = mock.Mock(return_value=0)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+ self.assertIsNone(trex_traffic_gen.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
+
+ def test__start_server(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.scenario_helper.scenario_cfg = {}
+ self.assertIsNone(trex_traffic_gen._start_server())
+
+ def test__start_server_multiple_queues(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.scenario_helper.scenario_cfg = {
+ "options": {NAME: {"queues_per_port": 2}}}
+ self.assertIsNone(trex_traffic_gen._start_server())
+
+ def test__traffic_runner(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.execute_traffic.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
+ self.sut.ssh_helper = mock.Mock()
+ self.sut.ssh_helper.run = mock.Mock()
+ self.sut._connect_client = mock.Mock()
+ self.sut._connect_client.get_stats = mock.Mock(return_value="0")
+ self.sut.resource_helper.RUN_DURATION = 0
+ self.sut.resource_helper.QUEUE_WAIT_TIME = 0
+ # must generate cfg before we can run traffic so Trex port mapping is
+ # created
+ self.sut.resource_helper.generate_cfg()
+ with mock.patch.object(self.sut.resource_helper, 'run_traffic'):
+ self.sut._traffic_runner(mock_traffic_profile)
+
+ def test__generate_trex_cfg(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ self.assertIsNone(trex_traffic_gen.resource_helper.generate_cfg())
+
+ def test_build_ports_reversed_pci_ordering(self):
+ vnfd = copy.deepcopy(self.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ vnfd['vdu'][0]['external-interface'] = [
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 2,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:04:00.0',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.generate_cfg()
+ trex_traffic_gen.resource_helper._build_ports()
+ self.assertEqual(sorted(trex_traffic_gen.resource_helper.all_ports),
+ [0, 1])
+ # there is a gap in ordering
+ self.assertEqual(
+ {0: 0, 2: 1},
+ dict(trex_traffic_gen.resource_helper.dpdk_to_trex_port_map))
+
+ def test_run_traffic(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.sut = tg_trex.TrexTrafficGen(NAME, vnfd)
+ self.sut.ssh_helper = mock.Mock()
+ self.sut.ssh_helper.run = mock.Mock()
+ self.sut._traffic_runner = mock.Mock(return_value=0)
+ self.sut.resource_helper.client_started.value = 1
+ result = self.sut.run_traffic(mock_traffic_profile)
+ self.sut._traffic_process.terminate()
+ self.assertIsNotNone(result)
+
+ def test_terminate(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ self.assertIsNone(trex_traffic_gen.terminate())
+
+ def test__connect_client(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex.TrexTrafficGen(NAME, vnfd)
+ client = mock.Mock()
+ client.connect = mock.Mock(return_value=0)
+ self.assertIsNotNone(trex_traffic_gen.resource_helper._connect(client))
+
+
+class TrexResourceHelperTestCase(unittest.TestCase):
+
+ def test__get_samples(self):
+ mock_setup_helper = mock.Mock()
+ trex_rh = tg_trex.TrexResourceHelper(mock_setup_helper)
+ trex_rh.vnfd_helper.interfaces = [
+ {'name': 'interface1'},
+ {'name': 'interface2'}]
+ stats = {
+ 10: {'rx_pps': 5, 'ipackets': 200},
+ 20: {'rx_pps': 10, 'ipackets': 300},
+ 'latency': {1: {'latency': 'latency_port_10_pg_id_1'},
+ 2: {'latency': 'latency_port_10_pg_id_2'},
+ 3: {'latency': 'latency_port_20_pg_id_3'},
+ 4: {'latency': 'latency_port_20_pg_id_4'}}
+ }
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(10)
+ port_pg_id.increase_pg_id()
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(20)
+ port_pg_id.increase_pg_id()
+ port_pg_id.increase_pg_id()
+
+ with mock.patch.object(trex_rh, 'get_stats') as mock_get_stats, \
+ mock.patch.object(trex_rh.vnfd_helper, 'port_num') as \
+ mock_port_num:
+ mock_get_stats.return_value = stats
+ mock_port_num.side_effect = [10, 20]
+ output = trex_rh._get_samples([10, 20], port_pg_id=port_pg_id)
+
+ interface = output['interface1']
+ self.assertEqual(5.0, interface['rx_throughput_fps'])
+ self.assertEqual(200, interface['in_packets'])
+ self.assertEqual('latency_port_10_pg_id_1', interface['latency'][1])
+ self.assertEqual('latency_port_10_pg_id_2', interface['latency'][2])
+
+ interface = output['interface2']
+ self.assertEqual(10.0, interface['rx_throughput_fps'])
+ self.assertEqual(300, interface['in_packets'])
+ self.assertEqual('latency_port_20_pg_id_3', interface['latency'][3])
+ self.assertEqual('latency_port_20_pg_id_4', interface['latency'][4])
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex_vpp.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex_vpp.py
new file mode 100644
index 000000000..ef1ae1182
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_trex_vpp.py
@@ -0,0 +1,1130 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+from multiprocessing import Process
+
+import mock
+from trex_stl_lib.trex_stl_exceptions import STLError
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.traffic_profile import base as tp_base
+from yardstick.network_services.traffic_profile import rfc2544
+from yardstick.network_services.vnf_generic.vnf import base, sample_vnf, \
+ tg_trex_vpp
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import \
+ mock_ssh
+
+
+class TestTrexVppResourceHelper(unittest.TestCase):
+ TRAFFIC_PROFILE = {
+ "schema": "isb:traffic_profile:0.1",
+ "name": "fixed",
+ "description": "Fixed traffic profile to run UDP traffic",
+ "traffic_profile": {
+ "traffic_type": "FixedTraffic",
+ "frame_rate": 100, # pps
+ "flow_number": 10,
+ "frame_size": 64
+ },
+ }
+
+ def test_fmt_latency(self):
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ self.assertEqual('10/90/489', vpp_rfc.fmt_latency(10, 90, 489))
+
+ def test_fmt_latency_error(self):
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ self.assertEqual('-1/-1/-1', vpp_rfc.fmt_latency('err', 'err', 'err'))
+
+ def test_generate_samples(self):
+ stats = {
+ 0: {
+ "ibytes": 55549120,
+ "ierrors": 0,
+ "ipackets": 867955,
+ "obytes": 55549696,
+ "oerrors": 0,
+ "opackets": 867964,
+ "rx_bps": 104339032.0,
+ "rx_bps_L1": 136944984.0,
+ "rx_pps": 203787.2,
+ "rx_util": 1.36944984,
+ "tx_bps": 134126008.0,
+ "tx_bps_L1": 176040392.0,
+ "tx_pps": 261964.9,
+ "tx_util": 1.7604039200000001
+ },
+ 1: {
+ "ibytes": 55549696,
+ "ierrors": 0,
+ "ipackets": 867964,
+ "obytes": 55549120,
+ "oerrors": 0,
+ "opackets": 867955,
+ "rx_bps": 134119648.0,
+ "rx_bps_L1": 176032032.0,
+ "rx_pps": 261952.4,
+ "rx_util": 1.76032032,
+ "tx_bps": 104338192.0,
+ "tx_bps_L1": 136943872.0,
+ "tx_pps": 203785.5,
+ "tx_util": 1.36943872
+ },
+ "flow_stats": {
+ 1: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 6400,
+ "1": 0,
+ "total": 6400
+ },
+ "rx_pkts": {
+ "0": 100,
+ "1": 0,
+ "total": 100
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 0,
+ "1": 6400,
+ "total": 6400
+ },
+ "tx_pkts": {
+ "0": 0,
+ "1": 100,
+ "total": 100
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ 2: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 0,
+ "1": 6464,
+ "total": 6464
+ },
+ "rx_pkts": {
+ "0": 0,
+ "1": 101,
+ "total": 101
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 6464,
+ "1": 0,
+ "total": 6464
+ },
+ "tx_pkts": {
+ "0": 101,
+ "1": 0,
+ "total": 101
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ "global": {
+ "rx_err": {
+ "0": 0,
+ "1": 0
+ },
+ "tx_err": {
+ "0": 0,
+ "1": 0
+ }
+ }
+ },
+ "global": {
+ "bw_per_core": 45.6,
+ "cpu_util": 0.1494,
+ "queue_full": 0,
+ "rx_bps": 238458672.0,
+ "rx_cpu_util": 4.751e-05,
+ "rx_drop_bps": 0.0,
+ "rx_pps": 465739.6,
+ "tx_bps": 238464208.0,
+ "tx_pps": 465750.4
+ },
+ "latency": {
+ 1: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 63.375,
+ "histogram": {
+ "20": 1,
+ "30": 18,
+ "40": 12,
+ "50": 10,
+ "60": 12,
+ "70": 11,
+ "80": 6,
+ "90": 10,
+ "100": 20
+ },
+ "jitter": 23,
+ "last_max": 122,
+ "total_max": 123,
+ "total_min": 20
+ }
+ },
+ 2: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 74,
+ "histogram": {
+ "60": 20,
+ "70": 10,
+ "80": 3,
+ "90": 4,
+ "100": 64
+ },
+ "jitter": 6,
+ "last_max": 83,
+ "total_max": 135,
+ "total_min": 60
+ }
+ },
+ "global": {
+ "bad_hdr": 0,
+ "old_flow": 0
+ }
+ },
+ "total": {
+ "ibytes": 111098816,
+ "ierrors": 0,
+ "ipackets": 1735919,
+ "obytes": 111098816,
+ "oerrors": 0,
+ "opackets": 1735919,
+ "rx_bps": 238458680.0,
+ "rx_bps_L1": 312977016.0,
+ "rx_pps": 465739.6,
+ "rx_util": 3.1297701599999996,
+ "tx_bps": 238464200.0,
+ "tx_bps_L1": 312984264.0,
+ "tx_pps": 465750.4,
+ "tx_util": 3.12984264
+ }
+ }
+ expected = {
+ "xe0": {
+ "in_packets": 867955,
+ "latency": {
+ 2: {
+ "avg_latency": 74.0,
+ "max_latency": 135.0,
+ "min_latency": 60.0
+ }
+ },
+ "out_packets": 867964,
+ "rx_throughput_bps": 104339032.0,
+ "rx_throughput_fps": 203787.2,
+ "tx_throughput_bps": 134126008.0,
+ "tx_throughput_fps": 261964.9
+ },
+ "xe1": {
+ "in_packets": 867964,
+ "latency": {
+ 1: {
+ "avg_latency": 63.375,
+ "max_latency": 123.0,
+ "min_latency": 20.0
+ }
+ },
+ "out_packets": 867955,
+ "rx_throughput_bps": 134119648.0,
+ "rx_throughput_fps": 261952.4,
+ "tx_throughput_bps": 104338192.0,
+ "tx_throughput_fps": 203785.5
+ }
+ }
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.vnfd_helper = base.VnfdHelper(TestTrexTrafficGenVpp.VNFD_0)
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(1)
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(0)
+ port_pg_id.increase_pg_id()
+ self.assertEqual(expected,
+ vpp_rfc.generate_samples(stats, [0, 1], port_pg_id,
+ True))
+
+ def test_generate_samples_error(self):
+ stats = {
+ 0: {
+ "ibytes": 55549120,
+ "ierrors": 0,
+ "ipackets": 867955,
+ "obytes": 55549696,
+ "oerrors": 0,
+ "opackets": 867964,
+ "rx_bps": 104339032.0,
+ "rx_bps_L1": 136944984.0,
+ "rx_pps": 203787.2,
+ "rx_util": 1.36944984,
+ "tx_bps": 134126008.0,
+ "tx_bps_L1": 176040392.0,
+ "tx_pps": 261964.9,
+ "tx_util": 1.7604039200000001
+ },
+ 1: {
+ "ibytes": 55549696,
+ "ierrors": 0,
+ "ipackets": 867964,
+ "obytes": 55549120,
+ "oerrors": 0,
+ "opackets": 867955,
+ "rx_bps": 134119648.0,
+ "rx_bps_L1": 176032032.0,
+ "rx_pps": 261952.4,
+ "rx_util": 1.76032032,
+ "tx_bps": 104338192.0,
+ "tx_bps_L1": 136943872.0,
+ "tx_pps": 203785.5,
+ "tx_util": 1.36943872
+ },
+ "flow_stats": {
+ 1: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 6400,
+ "1": 0,
+ "total": 6400
+ },
+ "rx_pkts": {
+ "0": 100,
+ "1": 0,
+ "total": 100
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 0,
+ "1": 6400,
+ "total": 6400
+ },
+ "tx_pkts": {
+ "0": 0,
+ "1": 100,
+ "total": 100
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ 2: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 0,
+ "1": 6464,
+ "total": 6464
+ },
+ "rx_pkts": {
+ "0": 0,
+ "1": 101,
+ "total": 101
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 6464,
+ "1": 0,
+ "total": 6464
+ },
+ "tx_pkts": {
+ "0": 101,
+ "1": 0,
+ "total": 101
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ "global": {
+ "rx_err": {
+ "0": 0,
+ "1": 0
+ },
+ "tx_err": {
+ "0": 0,
+ "1": 0
+ }
+ }
+ },
+ "global": {
+ "bw_per_core": 45.6,
+ "cpu_util": 0.1494,
+ "queue_full": 0,
+ "rx_bps": 238458672.0,
+ "rx_cpu_util": 4.751e-05,
+ "rx_drop_bps": 0.0,
+ "rx_pps": 465739.6,
+ "tx_bps": 238464208.0,
+ "tx_pps": 465750.4
+ },
+ "latency": {
+ 1: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": "err",
+ "histogram": {
+ "20": 1,
+ "30": 18,
+ "40": 12,
+ "50": 10,
+ "60": 12,
+ "70": 11,
+ "80": 6,
+ "90": 10,
+ "100": 20
+ },
+ "jitter": 23,
+ "last_max": 122,
+ "total_max": "err",
+ "total_min": "err"
+ }
+ },
+ 2: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 74,
+ "histogram": {
+ "60": 20,
+ "70": 10,
+ "80": 3,
+ "90": 4,
+ "100": 64
+ },
+ "jitter": 6,
+ "last_max": 83,
+ "total_max": 135,
+ "total_min": 60
+ }
+ },
+ "global": {
+ "bad_hdr": 0,
+ "old_flow": 0
+ }
+ },
+ "total": {
+ "ibytes": 111098816,
+ "ierrors": 0,
+ "ipackets": 1735919,
+ "obytes": 111098816,
+ "oerrors": 0,
+ "opackets": 1735919,
+ "rx_bps": 238458680.0,
+ "rx_bps_L1": 312977016.0,
+ "rx_pps": 465739.6,
+ "rx_util": 3.1297701599999996,
+ "tx_bps": 238464200.0,
+ "tx_bps_L1": 312984264.0,
+ "tx_pps": 465750.4,
+ "tx_util": 3.12984264
+ }
+ }
+ expected = {'xe0': {'in_packets': 867955,
+ 'latency': {2: {'avg_latency': 74.0,
+ 'max_latency': 135.0,
+ 'min_latency': 60.0}},
+ 'out_packets': 867964,
+ 'rx_throughput_bps': 104339032.0,
+ 'rx_throughput_fps': 203787.2,
+ 'tx_throughput_bps': 134126008.0,
+ 'tx_throughput_fps': 261964.9},
+ 'xe1': {'in_packets': 867964,
+ 'latency': {1: {'avg_latency': -1.0,
+ 'max_latency': -1.0,
+ 'min_latency': -1.0}},
+ 'out_packets': 867955,
+ 'rx_throughput_bps': 134119648.0,
+ 'rx_throughput_fps': 261952.4,
+ 'tx_throughput_bps': 104338192.0,
+ 'tx_throughput_fps': 203785.5}}
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.vnfd_helper = base.VnfdHelper(TestTrexTrafficGenVpp.VNFD_0)
+ vpp_rfc.get_stats = mock.Mock()
+ vpp_rfc.get_stats.return_value = stats
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(1)
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(0)
+ port_pg_id.increase_pg_id()
+ self.assertEqual(expected,
+ vpp_rfc.generate_samples(stats=None, ports=[0, 1],
+ port_pg_id=port_pg_id,
+ latency=True))
+
+ def test__run_traffic_once(self):
+ mock_setup_helper = mock.Mock()
+ mock_traffic_profile = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.TRANSIENT_PERIOD = 0
+ vpp_rfc.rfc2544_helper = mock.Mock()
+
+ self.assertTrue(vpp_rfc._run_traffic_once(mock_traffic_profile))
+ mock_traffic_profile.execute_traffic.assert_called_once_with(vpp_rfc)
+
+ def test_run_traffic(self):
+ mock_traffic_profile = mock.Mock(autospec=tp_base.TrafficProfile)
+ mock_traffic_profile.get_traffic_definition.return_value = "64"
+ mock_traffic_profile.params = self.TRAFFIC_PROFILE
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.ssh_helper = mock.Mock()
+ vpp_rfc.ssh_helper.run = mock.Mock()
+ vpp_rfc._traffic_runner = mock.Mock(return_value=0)
+ vpp_rfc._build_ports = mock.Mock()
+ vpp_rfc._connect = mock.Mock()
+ vpp_rfc.run_traffic(mock_traffic_profile)
+
+ def test_send_traffic_on_tg(self):
+ stats = {
+ 0: {
+ "ibytes": 55549120,
+ "ierrors": 0,
+ "ipackets": 867955,
+ "obytes": 55549696,
+ "oerrors": 0,
+ "opackets": 867964,
+ "rx_bps": 104339032.0,
+ "rx_bps_L1": 136944984.0,
+ "rx_pps": 203787.2,
+ "rx_util": 1.36944984,
+ "tx_bps": 134126008.0,
+ "tx_bps_L1": 176040392.0,
+ "tx_pps": 261964.9,
+ "tx_util": 1.7604039200000001
+ },
+ 1: {
+ "ibytes": 55549696,
+ "ierrors": 0,
+ "ipackets": 867964,
+ "obytes": 55549120,
+ "oerrors": 0,
+ "opackets": 867955,
+ "rx_bps": 134119648.0,
+ "rx_bps_L1": 176032032.0,
+ "rx_pps": 261952.4,
+ "rx_util": 1.76032032,
+ "tx_bps": 104338192.0,
+ "tx_bps_L1": 136943872.0,
+ "tx_pps": 203785.5,
+ "tx_util": 1.36943872
+ },
+ "flow_stats": {
+ 1: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 6400,
+ "1": 0,
+ "total": 6400
+ },
+ "rx_pkts": {
+ "0": 100,
+ "1": 0,
+ "total": 100
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 0,
+ "1": 6400,
+ "total": 6400
+ },
+ "tx_pkts": {
+ "0": 0,
+ "1": 100,
+ "total": 100
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ 2: {
+ "rx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "rx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "rx_bytes": {
+ "0": 0,
+ "1": 6464,
+ "total": 6464
+ },
+ "rx_pkts": {
+ "0": 0,
+ "1": 101,
+ "total": 101
+ },
+ "rx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ },
+ "tx_bps_l1": {
+ "0": 0.0,
+ "1": 0.0,
+ "total": 0.0
+ },
+ "tx_bytes": {
+ "0": 6464,
+ "1": 0,
+ "total": 6464
+ },
+ "tx_pkts": {
+ "0": 101,
+ "1": 0,
+ "total": 101
+ },
+ "tx_pps": {
+ "0": 0,
+ "1": 0,
+ "total": 0
+ }
+ },
+ "global": {
+ "rx_err": {
+ "0": 0,
+ "1": 0
+ },
+ "tx_err": {
+ "0": 0,
+ "1": 0
+ }
+ }
+ },
+ "global": {
+ "bw_per_core": 45.6,
+ "cpu_util": 0.1494,
+ "queue_full": 0,
+ "rx_bps": 238458672.0,
+ "rx_cpu_util": 4.751e-05,
+ "rx_drop_bps": 0.0,
+ "rx_pps": 465739.6,
+ "tx_bps": 238464208.0,
+ "tx_pps": 465750.4
+ },
+ "latency": {
+ 1: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 63.375,
+ "histogram": {
+ "20": 1,
+ "30": 18,
+ "40": 12,
+ "50": 10,
+ "60": 12,
+ "70": 11,
+ "80": 6,
+ "90": 10,
+ "100": 20
+ },
+ "jitter": 23,
+ "last_max": 122,
+ "total_max": 123,
+ "total_min": 20
+ }
+ },
+ 2: {
+ "err_cntrs": {
+ "dropped": 0,
+ "dup": 0,
+ "out_of_order": 0,
+ "seq_too_high": 0,
+ "seq_too_low": 0
+ },
+ "latency": {
+ "average": 74,
+ "histogram": {
+ "60": 20,
+ "70": 10,
+ "80": 3,
+ "90": 4,
+ "100": 64
+ },
+ "jitter": 6,
+ "last_max": 83,
+ "total_max": 135,
+ "total_min": 60
+ }
+ },
+ "global": {
+ "bad_hdr": 0,
+ "old_flow": 0
+ }
+ },
+ "total": {
+ "ibytes": 111098816,
+ "ierrors": 0,
+ "ipackets": 1735919,
+ "obytes": 111098816,
+ "oerrors": 0,
+ "opackets": 1735919,
+ "rx_bps": 238458680.0,
+ "rx_bps_L1": 312977016.0,
+ "rx_pps": 465739.6,
+ "rx_util": 3.1297701599999996,
+ "tx_bps": 238464200.0,
+ "tx_bps_L1": 312984264.0,
+ "tx_pps": 465750.4,
+ "tx_util": 3.12984264
+ }
+ }
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.vnfd_helper = base.VnfdHelper(TestTrexTrafficGenVpp.VNFD_0)
+ vpp_rfc.client = mock.Mock()
+ vpp_rfc.client.get_warnings.return_value = 'get_warnings'
+ vpp_rfc.client.get_stats.return_value = stats
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(1)
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(0)
+ port_pg_id.increase_pg_id()
+ self.assertEqual(stats,
+ vpp_rfc.send_traffic_on_tg([0, 1], port_pg_id, 30,
+ 10000, True))
+
+ def test_send_traffic_on_tg_error(self):
+ mock_setup_helper = mock.Mock()
+ vpp_rfc = tg_trex_vpp.TrexVppResourceHelper(mock_setup_helper)
+ vpp_rfc.vnfd_helper = base.VnfdHelper(TestTrexTrafficGenVpp.VNFD_0)
+ vpp_rfc.client = mock.Mock()
+ vpp_rfc.client.get_warnings.return_value = 'get_warnings'
+ vpp_rfc.client.get_stats.side_effect = STLError('get_stats')
+ vpp_rfc.client.wait_on_traffic.side_effect = STLError(
+ 'wait_on_traffic')
+ port_pg_id = rfc2544.PortPgIDMap()
+ port_pg_id.add_port(1)
+ port_pg_id.increase_pg_id()
+ port_pg_id.add_port(0)
+ port_pg_id.increase_pg_id()
+ # with self.assertRaises(RuntimeError) as raised:
+ vpp_rfc.send_traffic_on_tg([0, 1], port_pg_id, 30, 10000, True)
+ # self.assertIn('TRex stateless runtime error', str(raised.exception))
+
+
+class TestTrexTrafficGenVpp(unittest.TestCase):
+ VNFD_0 = {
+ "benchmark": {
+ "kpi": [
+ "rx_throughput_fps",
+ "tx_throughput_fps",
+ "tx_throughput_mbps",
+ "rx_throughput_mbps",
+ "in_packets",
+ "out_packets",
+ "min_latency",
+ "max_latency",
+ "avg_latency"
+ ]
+ },
+ "description": "TRex stateless traffic verifier",
+ "id": "TrexTrafficGenVpp",
+ "mgmt-interface": {
+ "ip": "10.10.10.10",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "trexgen-baremetal"
+ },
+ "name": "trexverifier",
+ "short-name": "trexverifier",
+ "vdu": [
+ {
+ "description": "TRex stateless traffic verifier",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "dpdk_port_num": 1,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.2",
+ "dst_mac": "90:e2:ba:7c:41:a9",
+ "ifname": "xe1",
+ "local_ip": "192.168.101.1",
+ "local_mac": "90:e2:ba:7c:30:e9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "192.168.101.1",
+ "dst_mac": "90:e2:ba:7c:30:e9",
+ "ifname": "xe0",
+ "local_ip": "192.168.101.2",
+ "local_mac": "90:e2:ba:7c:41:a9",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "tg__0",
+ "vld_id": "downlink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "downlink_0",
+ "vpci": "0000:81:00.1"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "trexgen-baremetal",
+ "name": "trexgen-baremetal"
+ }
+ ]
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ def setUp(self):
+ self._mock_ssh_helper = mock.patch.object(sample_vnf, 'VnfSshHelper')
+ self.mock_ssh_helper = self._mock_ssh_helper.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_ssh_helper.stop()
+
+ def test___init__(self):
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp(
+ 'tg0', self.VNFD_0)
+ self.assertIsNotNone(
+ trex_traffic_gen.resource_helper._terminated.value)
+
+ def test__check_status(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp('tg0', vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper.execute.return_value = 0, '', ''
+ trex_traffic_gen.scenario_helper.scenario_cfg = {}
+ self.assertEqual(0, trex_traffic_gen._check_status())
+
+ def test__start_server(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp('tg0', vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.scenario_helper.scenario_cfg = {}
+ self.assertIsNone(trex_traffic_gen._start_server())
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ def test_collect_kpi(self, *args):
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp(
+ 'tg0', self.VNFD_0)
+ trex_traffic_gen.scenario_helper.scenario_cfg = {
+ 'nodes': {trex_traffic_gen.name: "mock"}
+ }
+ expected = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {},
+ }
+ self.assertEqual(trex_traffic_gen.collect_kpi(), expected)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate(self, *args):
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp(
+ 'tg0', self.VNFD_0)
+ trex_traffic_gen._start_server = mock.Mock(return_value=0)
+ trex_traffic_gen.resource_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+
+ scenario_cfg = {
+ "tc": "tc_baremetal_rfc2544_ipv4_1flow_64B",
+ "topology": 'nsb_test_case.yaml',
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__0': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1
+ },
+ },
+ },
+ }
+ tg_trex_vpp.WAIT_TIME = 3
+ scenario_cfg.update({"nodes": {"tg0": {}, "vnf0": {}}})
+ self.assertIsNone(trex_traffic_gen.instantiate(scenario_cfg, {}))
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_error(self, *args):
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp(
+ 'tg0', self.VNFD_0)
+ trex_traffic_gen.resource_helper = mock.MagicMock()
+ trex_traffic_gen.setup_helper.setup_vnf_environment = mock.MagicMock()
+ scenario_cfg = {
+ "tc": "tc_baremetal_rfc2544_ipv4_1flow_64B",
+ "nodes": {
+ "tg0": {},
+ "vnf0": {}
+ },
+ "topology": 'nsb_test_case.yaml',
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__0': {
+ 'rules': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1,
+ },
+ },
+ },
+ }
+ trex_traffic_gen.instantiate(scenario_cfg, {})
+
+ @mock.patch(
+ 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper')
+ def test_wait_for_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ trex_traffic_gen = tg_trex_vpp.TrexTrafficGenVpp('tg0', vnfd)
+ trex_traffic_gen.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper = mock.MagicMock()
+ trex_traffic_gen.resource_helper.ssh_helper.execute.return_value = 0, '', ''
+ trex_traffic_gen.scenario_helper.scenario_cfg = {}
+ trex_traffic_gen._tg_process = mock_process
+ self.assertEqual(432, trex_traffic_gen.wait_for_instantiate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py
new file mode 100755
index 000000000..3b226d3f1
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_tg_vcmts_pktgen.py
@@ -0,0 +1,652 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import mock
+import socket
+import threading
+import time
+import os
+import copy
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+from yardstick.network_services.vnf_generic.vnf import tg_vcmts_pktgen
+from yardstick.common import exceptions
+
+
+NAME = "tg__0"
+
+
+class TestPktgenHelper(unittest.TestCase):
+
+ def test___init__(self):
+ pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000)
+ self.assertEqual(pktgen_helper.host, "localhost")
+ self.assertEqual(pktgen_helper.port, 23000)
+ self.assertFalse(pktgen_helper.connected)
+
+ def _run_fake_server(self):
+ server_sock = socket.socket()
+ server_sock.bind(('localhost', 23000))
+ server_sock.listen(0)
+ client_socket, _ = server_sock.accept()
+ client_socket.close()
+ server_sock.close()
+
+ def test__connect(self):
+ pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000)
+ self.assertFalse(pktgen_helper._connect())
+ server_thread = threading.Thread(target=self._run_fake_server)
+ server_thread.start()
+ time.sleep(0.5)
+ self.assertTrue(pktgen_helper._connect())
+ pktgen_helper._sock.close()
+ server_thread.join()
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.tg_vcmts_pktgen.time')
+ def test_connect(self, *args):
+ pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000)
+ pktgen_helper.connected = True
+ self.assertTrue(pktgen_helper.connect())
+ pktgen_helper.connected = False
+
+ pktgen_helper._connect = mock.MagicMock(return_value=True)
+ self.assertTrue(pktgen_helper.connect())
+ self.assertTrue(pktgen_helper.connected)
+
+ pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000)
+ pktgen_helper._connect = mock.MagicMock(return_value=False)
+ self.assertFalse(pktgen_helper.connect())
+ self.assertFalse(pktgen_helper.connected)
+
+ def test_send_command(self):
+ pktgen_helper = tg_vcmts_pktgen.PktgenHelper("localhost", 23000)
+ self.assertFalse(pktgen_helper.send_command(""))
+
+ pktgen_helper.connected = True
+ pktgen_helper._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.assertFalse(pktgen_helper.send_command(""))
+
+ pktgen_helper._sock = mock.MagicMock()
+ self.assertTrue(pktgen_helper.send_command(""))
+
+
+class TestVcmtsPktgenSetupEnvHelper(unittest.TestCase):
+
+ PKTGEN_PARAMETERS = "export LUA_PATH=/vcmts/Pktgen.lua;"\
+ "export CMK_PROC_FS=/host/proc;"\
+ " /pktgen-config/setup.sh 0 4 18:02.0 "\
+ "18:02.1 18:02.2 18:02.3 00:00.0 00:00.0 "\
+ "00:00.0 00:00.0 imix1_100cms_1ofdm.pcap "\
+ "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\
+ "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\
+ "imix1_100cms_1ofdm.pcap imix1_100cms_1ofdm.pcap "\
+ "imix1_100cms_1ofdm.pcap"
+
+ OPTIONS = {
+ "pktgen_values": "/tmp/pktgen_values.yaml",
+ "tg__0": {
+ "pktgen_id": 0
+ },
+ "vcmts_influxdb_ip": "10.80.5.150",
+ "vcmts_influxdb_port": 8086,
+ "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
+ "vnf__0": {
+ "sg_id": 0,
+ "stream_dir": "us"
+ },
+ "vnf__1": {
+ "sg_id": 0,
+ "stream_dir": "ds"
+ }
+ }
+
+ def setUp(self):
+ vnfd_helper = VnfdHelper(
+ TestVcmtsPktgen.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+
+ self.setup_helper = tg_vcmts_pktgen.VcmtsPktgenSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+
+ def test_generate_pcap_filename(self):
+ pcap_file_name = self.setup_helper.generate_pcap_filename(\
+ TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'][0])
+ self.assertEquals(pcap_file_name, "imix1_100cms_1ofdm.pcap")
+
+ def test_find_port_cfg(self):
+ port_cfg = self.setup_helper.find_port_cfg(\
+ TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'], "port_0")
+ self.assertIsNotNone(port_cfg)
+
+ port_cfg = self.setup_helper.find_port_cfg(\
+ TestVcmtsPktgen.PKTGEN_POD_VALUES[0]['ports'], "port_8")
+ self.assertIsNone(port_cfg)
+
+ def test_build_pktgen_parameters(self):
+ parameters = self.setup_helper.build_pktgen_parameters(
+ TestVcmtsPktgen.PKTGEN_POD_VALUES[0])
+ self.assertEquals(parameters, self.PKTGEN_PARAMETERS)
+
+ def test_start_pktgen(self):
+ self.setup_helper.ssh_helper = mock.MagicMock()
+ self.setup_helper.start_pktgen(TestVcmtsPktgen.PKTGEN_POD_VALUES[0])
+ self.setup_helper.ssh_helper.send_command.assert_called_with(
+ self.PKTGEN_PARAMETERS)
+
+ def test_setup_vnf_environment(self):
+ self.assertIsNone(self.setup_helper.setup_vnf_environment())
+
+class TestVcmtsPktgen(unittest.TestCase):
+
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{
+ "benchmark": {
+ "kpi": [
+ "upstream/bits_per_second"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "vCMTS Pktgen Kubernetes",
+ "id": "VcmtsPktgen",
+ "mgmt-interface": {
+ "ip": "192.168.24.150",
+ "key_filename": "/tmp/yardstick_key-a3b663c2",
+ "user": "root",
+ "vdu-id": "vcmtspktgen-kubernetes"
+ },
+ "name": "vcmtspktgen",
+ "short-name": "vcmtspktgen",
+ "vdu": [
+ {
+ "description": "vCMTS Pktgen Kubernetes",
+ "external-interface": [],
+ "id": "vcmtspktgen-kubernetes",
+ "name": "vcmtspktgen-kubernetes"
+ }
+ ],
+ "vm-flavor": {
+ "memory-mb": "4096",
+ "vcpu-count": "4"
+ }
+ }]
+ }}
+
+ PKTGEN_POD_VALUES = [
+ {
+ "num_ports": "4",
+ "pktgen_id": "0",
+ "ports": [
+ {
+ "net_pktgen": "18:02.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_0": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:02.1",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_1": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:02.2",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_2": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:02.3",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_3": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_4": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_5": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_6": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_7": "",
+ "traffic_type": "imix1"
+ }
+ ]
+ },
+ {
+ "num_ports": 4,
+ "pktgen_id": 1,
+ "ports": [
+ {
+ "net_pktgen": "18:0a.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_0": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:0a.1",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_1": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:0a.2",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_2": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "18:0a.3",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_3": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_4": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_5": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_6": "",
+ "traffic_type": "imix1"
+ },
+ {
+ "net_pktgen": "00:00.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "port_7": "",
+ "traffic_type": "imix1"
+ }
+ ]
+ }
+ ]
+
+ SCENARIO_CFG = {
+ "nodes": {
+ "tg__0": "pktgen0-k8syardstick-a3b663c2",
+ "vnf__0": "vnf0us-k8syardstick-a3b663c2",
+ "vnf__1": "vnf0ds-k8syardstick-a3b663c2"
+ },
+ "options": {
+ "pktgen_values": "/tmp/pktgen_values.yaml",
+ "tg__0": {
+ "pktgen_id": 0
+ },
+ "vcmts_influxdb_ip": "10.80.5.150",
+ "vcmts_influxdb_port": 8086,
+ "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
+ "vnf__0": {
+ "sg_id": 0,
+ "stream_dir": "us"
+ },
+ "vnf__1": {
+ "sg_id": 0,
+ "stream_dir": "ds"
+ }
+ },
+ "task_id": "a3b663c2-e616-4777-b6d0-ec2ea7a06f42",
+ "task_path": "samples/vnf_samples/nsut/cmts",
+ "tc": "tc_vcmts_k8s_pktgen",
+ "topology": "k8s_vcmts_topology.yaml",
+ "traffic_profile": "../../traffic_profiles/fixed.yaml",
+ "type": "NSPerf"
+ }
+
+ CONTEXT_CFG = {
+ "networks": {
+ "flannel": {
+ "name": "flannel"
+ },
+ "xe0": {
+ "name": "xe0"
+ },
+ "xe1": {
+ "name": "xe1"
+ }
+ },
+ "nodes": {
+ "tg__0": {
+ "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.24.150",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.24.150",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.24.150",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.24.150",
+ "key_filename": "/tmp/yardstick_key-a3b663c2",
+ "member-vnf-index": "1",
+ "name": "pktgen0-k8syardstick-a3b663c2",
+ "private_ip": "192.168.24.150",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 60270,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 43619,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 60270,
+ "user": "root",
+ "vnfd-id-ref": "tg__0"
+ },
+ "vnf__0": {
+ "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.100.132",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.100.132",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.100.132",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.100.132",
+ "key_filename": "/tmp/yardstick_key-a3b663c2",
+ "member-vnf-index": "3",
+ "name": "vnf0us-k8syardstick-a3b663c2",
+ "private_ip": "192.168.100.132",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 57057,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 29700,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 57057,
+ "user": "root",
+ "vnfd-id-ref": "vnf__0"
+ },
+ "vnf__1": {
+ "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.100.134",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.100.134",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.100.134",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.100.134",
+ "key_filename": "/tmp/yardstick_key-a3b663c2",
+ "member-vnf-index": "4",
+ "name": "vnf0ds-k8syardstick-a3b663c2",
+ "private_ip": "192.168.100.134",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 18581,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 18469,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 18581,
+ "user": "root",
+ "vnfd-id-ref": "vnf__1"
+ }
+ }
+ }
+
+ PKTGEN_VALUES_PATH = "/tmp/pktgen_values.yaml"
+
+ PKTGEN_VALUES = \
+ "serviceAccount: cmk-serviceaccount\n" \
+ "images:\n" \
+ " vcmts_pktgen: vcmts-pktgen:v18.10\n" \
+ "topology:\n" \
+ " pktgen_replicas: 8\n" \
+ " pktgen_pods:\n" \
+ " - pktgen_id: 0\n" \
+ " num_ports: 4\n" \
+ " ports:\n" \
+ " - port_0:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.0\n" \
+ " - port_1:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.1\n" \
+ " - port_2:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.2\n" \
+ " - port_3:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.3\n" \
+ " - port_4:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.4\n" \
+ " - port_5:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.5\n" \
+ " - port_6:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.6\n" \
+ " - port_7:\n" \
+ " traffic_type: 'imix2'\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " net_pktgen: 8a:02.7\n"
+
+ def setUp(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.vcmts_pktgen = tg_vcmts_pktgen.VcmtsPktgen(NAME, vnfd)
+ self.vcmts_pktgen._start_server = mock.Mock(return_value=0)
+ self.vcmts_pktgen.resource_helper = mock.MagicMock()
+ self.vcmts_pktgen.setup_helper = mock.MagicMock()
+
+ def test___init__(self):
+ self.assertFalse(self.vcmts_pktgen.traffic_finished)
+ self.assertIsNotNone(self.vcmts_pktgen.setup_helper)
+ self.assertIsNotNone(self.vcmts_pktgen.resource_helper)
+
+ def test_extract_pod_cfg(self):
+ pod_cfg = self.vcmts_pktgen.extract_pod_cfg(self.PKTGEN_POD_VALUES, "0")
+ self.assertIsNotNone(pod_cfg)
+ self.assertEqual(pod_cfg["pktgen_id"], "0")
+ pod_cfg = self.vcmts_pktgen.extract_pod_cfg(self.PKTGEN_POD_VALUES, "4")
+ self.assertIsNone(pod_cfg)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_missing_pktgen_values_key(self, *args):
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options'].pop('pktgen_values', None)
+ with self.assertRaises(KeyError):
+ self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_missing_pktgen_values_file(self, *args):
+ if os.path.isfile(self.PKTGEN_VALUES_PATH):
+ os.remove(self.PKTGEN_VALUES_PATH)
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options']['pktgen_values'] = self.PKTGEN_VALUES_PATH
+ with self.assertRaises(RuntimeError):
+ self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_empty_pktgen_values_file(self, *args):
+ yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w')
+ yaml_sample.write("")
+ yaml_sample.close()
+
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options']['pktgen_values'] = self.PKTGEN_VALUES_PATH
+ with self.assertRaises(RuntimeError):
+ self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ if os.path.isfile(self.PKTGEN_VALUES_PATH):
+ os.remove(self.PKTGEN_VALUES_PATH)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_invalid_pktgen_id(self, *args):
+ yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w')
+ yaml_sample.write(self.PKTGEN_VALUES)
+ yaml_sample.close()
+
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options'][NAME]['pktgen_id'] = 12
+ with self.assertRaises(KeyError):
+ self.vcmts_pktgen.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ if os.path.isfile(self.PKTGEN_VALUES_PATH):
+ os.remove(self.PKTGEN_VALUES_PATH)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server',
+ return_value='fake_context')
+ def test_instantiate_all_valid(self, *args):
+ yaml_sample = open(self.PKTGEN_VALUES_PATH, 'w')
+ yaml_sample.write(self.PKTGEN_VALUES)
+ yaml_sample.close()
+
+ self.vcmts_pktgen.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG)
+ self.assertIsNotNone(self.vcmts_pktgen.pod_cfg)
+ self.assertEqual(self.vcmts_pktgen.pod_cfg["pktgen_id"], "0")
+
+ if os.path.isfile(self.PKTGEN_VALUES_PATH):
+ os.remove(self.PKTGEN_VALUES_PATH)
+
+ def test_run_traffic_failed_connect(self):
+ self.vcmts_pktgen.pktgen_helper = mock.MagicMock()
+ self.vcmts_pktgen.pktgen_helper.connect.return_value = False
+ with self.assertRaises(exceptions.PktgenActionError):
+ self.vcmts_pktgen.run_traffic({})
+
+ def test_run_traffic_successful_connect(self):
+ self.vcmts_pktgen.pktgen_helper = mock.MagicMock()
+ self.vcmts_pktgen.pktgen_helper.connect.return_value = True
+ self.vcmts_pktgen.pktgen_rate = 8.0
+ self.assertTrue(self.vcmts_pktgen.run_traffic({}))
+ self.vcmts_pktgen.pktgen_helper.connect.assert_called_once()
+ self.vcmts_pktgen.pktgen_helper.send_command.assert_called_with(
+ 'pktgen.start("all");')
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py
new file mode 100644
index 000000000..aabd402a6
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_udp_replay.py
@@ -0,0 +1,470 @@
+# Copyright (c) 2016-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.
+
+import unittest
+import mock
+import os
+
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.udp_replay import UdpReplayApproxVnf
+from yardstick.network_services.vnf_generic.vnf.sample_vnf import ScenarioHelper
+
+
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+
+NAME = "vnf__1"
+
+
+@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+class TestUdpReplayApproxVnf(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'UdpReplayVnf',
+ 'vdu': [
+ {
+ 'description': 'UDPReplay approximation using DPDK',
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'if': 'xe0',
+ 'network': '152.16.100.20',
+ 'gateway': '152.16.100.20',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'if': 'xe1',
+ 'network': '152.16.40.20',
+ 'gateway': '152.16.40.20',
+ }
+ ],
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'driver': 'i40e',
+ 'local_iface_name': 'xe0',
+ 'bandwidth': '10 Gbps',
+ 'local_ip': '152.16.100.19',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ 'netmask': '255.255.255.0',
+ 'dst_ip': '152.16.100.20',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'driver': 'i40e',
+ 'local_iface_name': 'xe1',
+ 'bandwidth': '10 Gbps',
+ 'local_ip': '152.16.40.19',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ 'netmask': '255.255.255.0',
+ 'dst_ip': '152.16.40.20',
+ 'type': 'PCI-PASSTHROUGH',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ }
+ ],
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'if': 'xe0',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ },
+ {
+ 'netmask': '112',
+ 'if': 'xe1',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ }
+ ],
+ 'id': 'udpreplayvnf-baremetal',
+ 'name': 'udpreplayvnf-baremetal',
+ }
+ ],
+ 'description': 'UDPReplay approximation using DPDK',
+ 'name': 'VPEVnfSsh',
+ 'mgmt-interface': {
+ 'vdu-id': 'udpreplay-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ]
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ }
+ ],
+ 'id': 'UdpReplayApproxVnf',
+ }
+
+ SCENARIO_CFG = {
+ "options": {
+ "packetsize": 64,
+ "traffic_type": 4,
+ "rfc2544": {
+ "allowed_drop_rate": "0.8 - 1",
+ },
+ "vnf__1": {
+ "rules": "acl_1rule.yaml",
+ "vnf_config": {
+ "lb_config": "SW",
+ "lb_count": 1,
+ "worker_config": "1C/1T",
+ "worker_threads": 1,
+ },
+ "hw_csum": "false",
+ }
+ },
+ "task_id": "a70bdf4a-8e67-47a3-9dc1-273c14506eb7",
+ "tc": "tc_ipv4_1Mflow_64B_packetsize",
+ "runner": {
+ "object": "NetworkServiceTestCase",
+ "interval": 35,
+ "output_filename": "/tmp/yardstick.out",
+ "runner_id": 74476, "duration": 400,
+ "type": "Duration"
+ },
+ "traffic_profile": "ipv4_throughput_acl.yaml",
+ "traffic_options": {
+ "flow": "ipv4_Packets_acl.yaml",
+ "imix": "imix_voice.yaml"
+ },
+ "type": "ISB",
+ "nodes": {
+ "tg__2": "trafficgen_2.yardstick",
+ "tg__1": "trafficgen_1.yardstick",
+ "vnf__1": "vnf.yardstick"
+ },
+ "topology": "udpreplay-tg-topology-baremetal.yaml"
+ }
+
+ CONTEXT_CFG = {
+ "nodes": {
+ "vnf__1": {
+ "vnfd-id-ref": "vnf__1",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens786f0",
+ "vld_id": UdpReplayApproxVnf.UPLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.0",
+ "local_ip": "152.16.100.19",
+ "driver": "i40e",
+ "dst_ip": "152.16.100.20",
+ "local_mac": "00:00:00:00:00:02",
+ "dst_mac": "00:00:00:00:00:04",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_iface_name": "ens786f1",
+ "vld_id": UdpReplayApproxVnf.DOWNLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.1",
+ "local_ip": "152.16.40.19",
+ "driver": "i40e",
+ "dst_ip": "152.16.40.20",
+ "local_mac": "00:00:00:00:00:01",
+ "dst_mac": "00:00:00:00:00:03",
+ "dpdk_port_num": 1
+ }
+ },
+ "host": "1.2.1.1",
+ "user": "root",
+ "nd_route_tbl": [
+ {
+ "netmask": "112",
+ "if": "xe0",
+ "gateway": "0064:ff9b:0:0:0:0:9810:6414",
+ "network": "0064:ff9b:0:0:0:0:9810:6414"
+ },
+ {
+ "netmask": "112",
+ "if": "xe1",
+ "gateway": "0064:ff9b:0:0:0:0:9810:2814",
+ "network": "0064:ff9b:0:0:0:0:9810:2814"
+ }
+ ],
+ "password": "r00t",
+ "VNF model": "udp_replay.yaml",
+ "name": "vnf.yardstick",
+ "member-vnf-index": "2",
+ "routing_table": [
+ {
+ "netmask": "255.255.255.0",
+ "if": "xe0",
+ "gateway": "152.16.100.20",
+ "network": "152.16.100.20"
+ },
+ {
+ "netmask": "255.255.255.0",
+ "if": "xe1",
+ "gateway": "152.16.40.20",
+ "network": "152.16.40.20"
+ }
+ ],
+ "role": "vnf"
+ },
+ "trafficgen_2.yardstick": {
+ "member-vnf-index": "3",
+ "role": "TrafficGen",
+ "name": "trafficgen_2.yardstick",
+ "vnfd-id-ref": "tg__2",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens513f0",
+ "vld_id": UdpReplayApproxVnf.DOWNLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:02:00.0",
+ "local_ip": "152.16.40.20",
+ "driver": "ixgbe",
+ "dst_ip": "152.16.40.19",
+ "local_mac": "00:00:00:00:00:03",
+ "dst_mac": "00:00:00:00:00:01",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_iface_name": "ens513f1",
+ "netmask": "255.255.255.0",
+ "network": "202.16.100.0",
+ "local_ip": "202.16.100.20",
+ "driver": "ixgbe",
+ "local_mac": "00:1e:67:d0:60:5d",
+ "vpci": "0000:02:00.1",
+ "dpdk_port_num": 1
+ }
+ },
+ "password": "r00t",
+ "VNF model": "l3fwd_vnf.yaml",
+ "user": "root"
+ },
+ "trafficgen_1.yardstick": {
+ "member-vnf-index": "1",
+ "role": "TrafficGen",
+ "name": "trafficgen_1.yardstick",
+ "vnfd-id-ref": "tg__1",
+ "ip": "1.2.1.1",
+ "interfaces": {
+ "xe0": {
+ "local_iface_name": "ens785f0",
+ "vld_id": UdpReplayApproxVnf.UPLINK,
+ "netmask": "255.255.255.0",
+ "vpci": "0000:05:00.0",
+ "local_ip": "152.16.100.20",
+ "driver": "i40e",
+ "dst_ip": "152.16.100.19",
+ "local_mac": "00:00:00:00:00:04",
+ "dst_mac": "00:00:00:00:00:02",
+ "dpdk_port_num": 0
+ },
+ "xe1": {
+ "local_ip": "152.16.100.21",
+ "driver": "i40e",
+ "vpci": "0000:05:00.1",
+ "dpdk_port_num": 1,
+ "local_iface_name": "ens785f1",
+ "netmask": "255.255.255.0",
+ "local_mac": "00:00:00:00:00:01"
+ }
+ },
+ "password": "r00t",
+ "VNF model": "tg_rfc2544_tpl.yaml",
+ "user": "root"
+ }
+ }
+ }
+
+ def test___init__(self, *args):
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ self.assertIsNone(udp_replay_approx_vnf._vnf_process)
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD_0
+ get_stats_ret_val = \
+ "stats\r\r\n\r\nUDP_Replay stats:\r\n--------------\r\n" \
+ "Port\t\tRx Packet\t\tTx Packet\t\tRx Pkt Drop\t\tTx Pkt Drop\t\tarp_pkts \r\n"\
+ "0\t\t7374156\t\t7374136\t\t\t0\t\t\t0\t\t\t0\r\n" \
+ "1\t\t7374316\t\t7374315\t\t\t0\t\t\t0\t\t\t0\r\n\r\nReplay>\r\r\nReplay>"
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, vnfd)
+ udp_replay_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {udp_replay_approx_vnf.name: "mock"}
+ }
+ udp_replay_approx_vnf.q_in = mock.MagicMock()
+ udp_replay_approx_vnf.q_out = mock.MagicMock()
+ udp_replay_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
+ udp_replay_approx_vnf.get_stats = mock.Mock(return_value=get_stats_ret_val)
+ result = {
+ 'physical_node': 'mock_node',
+ 'collect_stats': {},
+ 'packets_dropped': 0,
+ 'packets_fwd': 14748451,
+ 'packets_in': 14748472
+ }
+ self.assertEqual(result, udp_replay_approx_vnf.collect_kpi())
+
+ @mock.patch(SSH_HELPER)
+ def test_get_stats(self, ssh, *args):
+ mock_ssh(ssh)
+
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf.q_in = mock.MagicMock()
+ udp_replay_approx_vnf.q_out = mock.MagicMock()
+ udp_replay_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ mock_result = \
+ "CG-NAPT(.*\n)*Received 100, Missed 0, Dropped 0,Translated 100,ingress"
+
+ udp_replay_approx_vnf.vnf_execute = mock.Mock(return_value=mock_result)
+
+ self.assertEqual(mock_result,
+ udp_replay_approx_vnf.get_stats())
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch(SSH_HELPER)
+ def test__build_config(self, ssh, mock_get_ctx, *args):
+ mock_ssh(ssh)
+
+ nfvi_context = mock.Mock()
+ nfvi_context.attrs = {'nfvi_type': 'baremetal'}
+ mock_get_ctx.return_value = nfvi_context
+
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf.queue_wrapper = mock.MagicMock()
+ udp_replay_approx_vnf.nfvi_context = mock_get_ctx
+ udp_replay_approx_vnf.nfvi_context.attrs = {'nfvi_type': 'baremetal'}
+ udp_replay_approx_vnf.setup_helper.bound_pci = []
+ udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
+ udp_replay_approx_vnf.scenario_helper = ScenarioHelper(name='vnf__1')
+ udp_replay_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+
+ cmd_line = udp_replay_approx_vnf._build_config()
+
+ expected = \
+ "sudo tool_path --log-level=5 -c 0x7 -n 4 -w -- -p 0x3 --config='(0,0,1),(1,0,2)'"
+ self.assertEqual(cmd_line, expected)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.udp_replay.open')
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch(SSH_HELPER)
+ def test__build_pipeline_kwargs(self, ssh, mock_get_ctx, *args):
+ mock_ssh(ssh)
+
+ nfvi_context = mock.Mock()
+ nfvi_context.attrs = {'nfvi_type': "baremetal"}
+ mock_get_ctx.return_value = nfvi_context
+
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf.setup_helper.bound_pci = ['0000:00:0.1', '0000:00:0.3']
+ udp_replay_approx_vnf.all_ports = ["xe0", "xe1"]
+ udp_replay_approx_vnf.ssh_helper.provision_tool = mock.MagicMock(return_value="tool_path")
+ udp_replay_approx_vnf.scenario_helper = ScenarioHelper(name='vnf__1')
+ udp_replay_approx_vnf.scenario_helper.scenario_cfg = self.SCENARIO_CFG
+
+ udp_replay_approx_vnf._build_pipeline_kwargs()
+
+ self.assertEqual(udp_replay_approx_vnf.pipeline_kwargs, {
+ 'config': '(0,0,1),(1,0,2)',
+ 'cpu_mask_hex': '0x7',
+ 'hw_csum': '',
+ 'port_mask_hex': '0x3',
+ 'tool_path': 'tool_path',
+ 'whitelist': '0000:00:0.1 -w 0000:00:0.3'
+ })
+
+ @mock.patch(SSH_HELPER)
+ def test_run_udp_replay(self, ssh, *args):
+ mock_ssh(ssh)
+
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf._build_config = mock.MagicMock()
+ udp_replay_approx_vnf.queue_wrapper = mock.MagicMock()
+ udp_replay_approx_vnf.scenario_helper = mock.MagicMock()
+
+ udp_replay_approx_vnf._run()
+
+ udp_replay_approx_vnf.ssh_helper.run.assert_called_once()
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf.q_out.put("Replay>")
+ udp_replay_approx_vnf.WAIT_TIME = 0
+ udp_replay_approx_vnf.setup_helper.setup_vnf_environment = mock.Mock()
+
+ udp_replay_approx_vnf.deploy_helper = mock.MagicMock()
+ udp_replay_approx_vnf.deploy_vnfs = mock.MagicMock()
+ self.assertIsNone(udp_replay_approx_vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
+
+ udp_replay_approx_vnf._vnf_process.is_alive = mock.Mock(return_value=1)
+ udp_replay_approx_vnf._vnf_process.exitcode = 0
+
+ self.assertEqual(udp_replay_approx_vnf.wait_for_instantiate(), 0)
+
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch('yardstick.ssh.SSH')
+ @mock.patch(SSH_HELPER)
+ def test_instantiate_panic(self, *args):
+ udp_replay_approx_vnf = UdpReplayApproxVnf(NAME, self.VNFD_0)
+ udp_replay_approx_vnf.WAIT_TIME = 0
+ udp_replay_approx_vnf.q_out.put("some text PANIC some text")
+ udp_replay_approx_vnf.setup_helper.setup_vnf_environment = mock.Mock()
+
+ udp_replay_approx_vnf.deploy_helper = mock.MagicMock()
+ self.assertIsNone(udp_replay_approx_vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG))
+ with self.assertRaises(RuntimeError):
+ udp_replay_approx_vnf.wait_for_instantiate()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py
new file mode 100755
index 000000000..11e3d6e17
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vcmts_vnf.py
@@ -0,0 +1,651 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import mock
+import copy
+import os
+
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+from yardstick.network_services.vnf_generic.vnf import vcmts_vnf
+from yardstick.common import exceptions
+
+from influxdb.resultset import ResultSet
+
+NAME = "vnf__0"
+
+
+class TestInfluxDBHelper(unittest.TestCase):
+
+ def test___init__(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ self.assertEqual(influxdb_helper._vcmts_influxdb_ip, "localhost")
+ self.assertEqual(influxdb_helper._vcmts_influxdb_port, 8086)
+ self.assertIsNotNone(influxdb_helper._last_upstream_rx)
+ self.assertIsNotNone(influxdb_helper._last_values_time)
+
+ def test_start(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ influxdb_helper.start()
+ self.assertIsNotNone(influxdb_helper._read_client)
+ self.assertIsNotNone(influxdb_helper._write_client)
+
+ def test__get_last_value_time(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'),
+ vcmts_vnf.InfluxDBHelper.INITIAL_VALUE)
+
+ influxdb_helper._last_values_time['cpu_value'] = "RANDOM"
+ self.assertEqual(influxdb_helper._get_last_value_time('cpu_value'),
+ "RANDOM")
+
+ def test__set_last_value_time(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ influxdb_helper._set_last_value_time('cpu_value', '00:00')
+ self.assertEqual(influxdb_helper._last_values_time['cpu_value'],
+ "'00:00'")
+
+ def test__query_measurement(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ influxdb_helper._read_client = mock.MagicMock()
+
+ resulted_generator = mock.MagicMock()
+ resulted_generator.keys.return_value = []
+ influxdb_helper._read_client.query.return_value = resulted_generator
+ query_result = influxdb_helper._query_measurement('cpu_value')
+ self.assertIsNone(query_result)
+
+ resulted_generator = mock.MagicMock()
+ resulted_generator.keys.return_value = ["", ""]
+ resulted_generator.get_points.return_value = ResultSet({"":""})
+ influxdb_helper._read_client.query.return_value = resulted_generator
+ query_result = influxdb_helper._query_measurement('cpu_value')
+ self.assertIsNotNone(query_result)
+
+ def test__rw_measurment(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ influxdb_helper._query_measurement = mock.MagicMock()
+ influxdb_helper._query_measurement.return_value = None
+ influxdb_helper._rw_measurment('cpu_value', [])
+ self.assertEqual(len(influxdb_helper._last_values_time), 0)
+
+ entry = {
+ "type":"type",
+ "host":"host",
+ "time":"time",
+ "id": "1",
+ "value": "1.0"
+ }
+ influxdb_helper._query_measurement.return_value = [entry]
+ influxdb_helper._write_client = mock.MagicMock()
+ influxdb_helper._rw_measurment('cpu_value', ["id", "value"])
+ self.assertEqual(len(influxdb_helper._last_values_time), 1)
+ influxdb_helper._write_client.write_points.assert_called_once()
+
+ def test_copy_kpi(self):
+ influxdb_helper = vcmts_vnf.InfluxDBHelper("localhost", 8086)
+ influxdb_helper._rw_measurment = mock.MagicMock()
+ influxdb_helper.copy_kpi()
+ influxdb_helper._rw_measurment.assert_called()
+
+
+class TestVcmtsdSetupEnvHelper(unittest.TestCase):
+ POD_CFG = {
+ "cm_crypto": "aes",
+ "cpu_socket_id": "0",
+ "ds_core_pool_index": "2",
+ "ds_core_type": "exclusive",
+ "net_ds": "1a:02.1",
+ "net_us": "1a:02.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "power_mgmt": "pm_on",
+ "qat": "qat_off",
+ "service_group_config": "",
+ "sg_id": "0",
+ "vcmtsd_image": "vcmts-d:perf"
+ }
+
+ OPTIONS = {
+ "pktgen_values": "/tmp/pktgen_values.yaml",
+ "tg__0": {
+ "pktgen_id": 0
+ },
+ "vcmts_influxdb_ip": "10.80.5.150",
+ "vcmts_influxdb_port": 8086,
+ "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
+ "vnf__0": {
+ "sg_id": 0,
+ "stream_dir": "us"
+ },
+ "vnf__1": {
+ "sg_id": 0,
+ "stream_dir": "ds"
+ }
+ }
+
+ def setUp(self):
+ vnfd_helper = VnfdHelper(
+ TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+
+ self.setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+
+ def _build_us_parameters(self):
+ return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \
+ + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \
+ + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \
+ + " --pool=shared" \
+ + " /vcmts-config/run_upstream.sh " + self.POD_CFG['sg_id'] \
+ + " " + self.POD_CFG['ds_core_type'] \
+ + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \
+ + " " + str(self.POD_CFG['num_subs']) + "cm" \
+ + " " + self.POD_CFG['cm_crypto'] \
+ + " " + self.POD_CFG['qat'] \
+ + " " + self.POD_CFG['net_us'] \
+ + " " + self.POD_CFG['power_mgmt']
+
+ def test_build_us_parameters(self):
+ constructed = self._build_us_parameters()
+ result = self.setup_helper.build_us_parameters(self.POD_CFG)
+ self.assertEqual(constructed, result)
+
+ def _build_ds_parameters(self):
+ return vcmts_vnf.VcmtsdSetupEnvHelper.BASE_PARAMETERS + " " \
+ + " /opt/bin/cmk isolate --conf-dir=/etc/cmk" \
+ + " --socket-id=" + str(self.POD_CFG['cpu_socket_id']) \
+ + " --pool=" + self.POD_CFG['ds_core_type'] \
+ + " /vcmts-config/run_downstream.sh " + self.POD_CFG['sg_id'] \
+ + " " + self.POD_CFG['ds_core_type'] \
+ + " " + str(self.POD_CFG['ds_core_pool_index']) \
+ + " " + str(self.POD_CFG['num_ofdm']) + "ofdm" \
+ + " " + str(self.POD_CFG['num_subs']) + "cm" \
+ + " " + self.POD_CFG['cm_crypto'] \
+ + " " + self.POD_CFG['qat'] \
+ + " " + self.POD_CFG['net_ds'] \
+ + " " + self.POD_CFG['power_mgmt']
+
+ def test_build_ds_parameters(self):
+ constructed = self._build_ds_parameters()
+ result = self.setup_helper.build_ds_parameters(self.POD_CFG)
+ self.assertEqual(constructed, result)
+
+ def test_build_cmd(self):
+ us_constructed = self._build_us_parameters()
+ us_result = self.setup_helper.build_cmd('us', self.POD_CFG)
+ self.assertEqual(us_constructed, us_result)
+ ds_constructed = self._build_ds_parameters()
+ ds_result = self.setup_helper.build_cmd('ds', self.POD_CFG)
+ self.assertEqual(ds_constructed, ds_result)
+
+ def test_run_vcmtsd(self):
+ us_constructed = self._build_us_parameters()
+
+ vnfd_helper = VnfdHelper(
+ TestVcmtsVNF.VNFD['vnfd:vnfd-catalog']['vnfd'][0])
+ ssh_helper = mock.MagicMock()
+ scenario_helper = mock.Mock()
+ scenario_helper.options = self.OPTIONS
+
+ setup_helper = vcmts_vnf.VcmtsdSetupEnvHelper(
+ vnfd_helper, ssh_helper, scenario_helper)
+
+ setup_helper.run_vcmtsd('us', self.POD_CFG)
+ ssh_helper.send_command.assert_called_with(us_constructed)
+
+ def test_setup_vnf_environment(self):
+ self.assertIsNone(self.setup_helper.setup_vnf_environment())
+
+class TestVcmtsVNF(unittest.TestCase):
+
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{
+ "benchmark": {
+ "kpi": [
+ "upstream/bits_per_second"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "vCMTS Upstream-Downstream Kubernetes",
+ "id": "VcmtsVNF",
+ "mgmt-interface": {
+ "ip": "192.168.100.35",
+ "key_filename": "/tmp/yardstick_key-81dcca91",
+ "user": "root",
+ "vdu-id": "vcmtsvnf-kubernetes"
+ },
+ "name": "vcmtsvnf",
+ "short-name": "vcmtsvnf",
+ "vdu": [
+ {
+ "description": "vCMTS Upstream-Downstream Kubernetes",
+ "external-interface": [],
+ "id": "vcmtsvnf-kubernetes",
+ "name": "vcmtsvnf-kubernetes"
+ }
+ ],
+ "vm-flavor": {
+ "memory-mb": "4096",
+ "vcpu-count": "4"
+ }
+ }]
+ }
+ }
+
+ POD_CFG = [
+ {
+ "cm_crypto": "aes",
+ "cpu_socket_id": "0",
+ "ds_core_pool_index": "2",
+ "ds_core_type": "exclusive",
+ "net_ds": "1a:02.1",
+ "net_us": "1a:02.0",
+ "num_ofdm": "1",
+ "num_subs": "100",
+ "power_mgmt": "pm_on",
+ "qat": "qat_off",
+ "service_group_config": "",
+ "sg_id": "0",
+ "vcmtsd_image": "vcmts-d:perf"
+ },
+ ]
+
+ SCENARIO_CFG = {
+ "nodes": {
+ "tg__0": "pktgen0-k8syardstick-afae18b2",
+ "vnf__0": "vnf0us-k8syardstick-afae18b2",
+ "vnf__1": "vnf0ds-k8syardstick-afae18b2"
+ },
+ "options": {
+ "pktgen_values": "/tmp/pktgen_values.yaml",
+ "tg__0": {
+ "pktgen_id": 0
+ },
+ "vcmts_influxdb_ip": "10.80.5.150",
+ "vcmts_influxdb_port": 8086,
+ "vcmtsd_values": "/tmp/vcmtsd_values.yaml",
+ "vnf__0": {
+ "sg_id": 0,
+ "stream_dir": "us"
+ },
+ "vnf__1": {
+ "sg_id": 0,
+ "stream_dir": "ds"
+ }
+ },
+ "task_id": "afae18b2-9902-477f-8128-49afde7c3040",
+ "task_path": "samples/vnf_samples/nsut/cmts",
+ "tc": "tc_vcmts_k8s_pktgen",
+ "topology": "k8s_vcmts_topology.yaml",
+ "traffic_profile": "../../traffic_profiles/fixed.yaml",
+ "type": "NSPerf"
+ }
+
+ CONTEXT_CFG = {
+ "networks": {
+ "flannel": {
+ "name": "flannel"
+ },
+ "xe0": {
+ "name": "xe0"
+ },
+ "xe1": {
+ "name": "xe1"
+ }
+ },
+ "nodes": {
+ "tg__0": {
+ "VNF model": "../../vnf_descriptors/tg_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.24.110",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.24.110",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.24.110",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.24.110",
+ "key_filename": "/tmp/yardstick_key-afae18b2",
+ "member-vnf-index": "1",
+ "name": "pktgen0-k8syardstick-afae18b2",
+ "private_ip": "192.168.24.110",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 17153,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 51250,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 17153,
+ "user": "root",
+ "vnfd-id-ref": "tg__0"
+ },
+ "vnf__0": {
+ "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.100.53",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.100.53",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.100.53",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.100.53",
+ "key_filename": "/tmp/yardstick_key-afae18b2",
+ "member-vnf-index": "3",
+ "name": "vnf0us-k8syardstick-afae18b2",
+ "private_ip": "192.168.100.53",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 34027,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 32580,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 34027,
+ "user": "root",
+ "vnfd-id-ref": "vnf__0"
+ },
+ "vnf__1": {
+ "VNF model": "../../vnf_descriptors/vnf_vcmts_tpl.yaml",
+ "interfaces": {
+ "flannel": {
+ "local_ip": "192.168.100.52",
+ "local_mac": None,
+ "network_name": "flannel"
+ },
+ "xe0": {
+ "local_ip": "192.168.100.52",
+ "local_mac": None,
+ "network_name": "xe0"
+ },
+ "xe1": {
+ "local_ip": "192.168.100.52",
+ "local_mac": None,
+ "network_name": "xe1"
+ }
+ },
+ "ip": "192.168.100.52",
+ "key_filename": "/tmp/yardstick_key-afae18b2",
+ "member-vnf-index": "4",
+ "name": "vnf0ds-k8syardstick-afae18b2",
+ "private_ip": "192.168.100.52",
+ "service_ports": [
+ {
+ "name": "ssh",
+ "node_port": 58661,
+ "port": 22,
+ "protocol": "TCP",
+ "target_port": 22
+ },
+ {
+ "name": "lua",
+ "node_port": 58233,
+ "port": 22022,
+ "protocol": "TCP",
+ "target_port": 22022
+ }
+ ],
+ "ssh_port": 58661,
+ "user": "root",
+ "vnfd-id-ref": "vnf__1"
+ },
+ }
+ }
+
+ VCMTSD_VALUES_PATH = "/tmp/vcmtsd_values.yaml"
+
+ VCMTSD_VALUES = \
+ "serviceAccount: cmk-serviceaccount\n" \
+ "topology:\n" \
+ " vcmts_replicas: 16\n" \
+ " vcmts_pods:\n" \
+ " - service_group_config:\n" \
+ " sg_id: 0\n" \
+ " net_us: 18:02.0\n" \
+ " net_ds: 18:02.1\n" \
+ " num_ofdm: 4\n" \
+ " num_subs: 300\n" \
+ " cm_crypto: aes\n" \
+ " qat: qat_off\n" \
+ " power_mgmt: pm_on\n" \
+ " cpu_socket_id: 0\n" \
+ " ds_core_type: exclusive\n" \
+ " ds_core_pool_index: 0\n" \
+ " vcmtsd_image: vcmts-d:feat"
+
+ VCMTSD_VALUES_INCOMPLETE = \
+ "serviceAccount: cmk-serviceaccount\n" \
+ "topology:\n" \
+ " vcmts_replicas: 16"
+
+ def setUp(self):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ self.vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
+
+ def test___init__(self, *args):
+ self.assertIsNotNone(self.vnf.setup_helper)
+
+ def test_extract_pod_cfg(self):
+ pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "0")
+ self.assertIsNotNone(pod_cfg)
+ self.assertEqual(pod_cfg['sg_id'], '0')
+ pod_cfg = self.vnf.extract_pod_cfg(self.POD_CFG, "1")
+ self.assertIsNone(pod_cfg)
+
+ def test_instantiate_missing_influxdb_info(self):
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options'].pop('vcmts_influxdb_ip', None)
+ with self.assertRaises(KeyError):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ def test_instantiate_missing_vcmtsd_values_file(self):
+ if os.path.isfile(self.VCMTSD_VALUES_PATH):
+ os.remove(self.VCMTSD_VALUES_PATH)
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH
+ with self.assertRaises(RuntimeError):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ def test_instantiate_empty_vcmtsd_values_file(self):
+ yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
+ yaml_sample.write("")
+ yaml_sample.close()
+
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options']['vcmtsd_values'] = self.VCMTSD_VALUES_PATH
+ with self.assertRaises(RuntimeError):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ if os.path.isfile(self.VCMTSD_VALUES_PATH):
+ os.remove(self.VCMTSD_VALUES_PATH)
+
+ def test_instantiate_missing_vcmtsd_values_key(self):
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options'].pop('vcmtsd_values', None)
+ with self.assertRaises(KeyError):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ def test_instantiate_invalid_vcmtsd_values(self):
+ yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
+ yaml_sample.write(self.VCMTSD_VALUES_INCOMPLETE)
+ yaml_sample.close()
+
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ with self.assertRaises(KeyError):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ if os.path.isfile(self.VCMTSD_VALUES_PATH):
+ os.remove(self.VCMTSD_VALUES_PATH)
+
+ def test_instantiate_invalid_sg_id(self):
+ yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
+ yaml_sample.write(self.VCMTSD_VALUES)
+ yaml_sample.close()
+
+ err_scenario_cfg = copy.deepcopy(self.SCENARIO_CFG)
+ err_scenario_cfg['options'][NAME]['sg_id'] = 8
+ with self.assertRaises(exceptions.IncorrectConfig):
+ self.vnf.instantiate(err_scenario_cfg, self.CONTEXT_CFG)
+
+ if os.path.isfile(self.VCMTSD_VALUES_PATH):
+ os.remove(self.VCMTSD_VALUES_PATH)
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.vcmts_vnf.VnfSshHelper')
+ def test_instantiate_all_valid(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vnf = vcmts_vnf.VcmtsVNF(NAME, vnfd)
+
+ yaml_sample = open(self.VCMTSD_VALUES_PATH, 'w')
+ yaml_sample.write(self.VCMTSD_VALUES)
+ yaml_sample.close()
+
+ vnf.instantiate(self.SCENARIO_CFG, self.CONTEXT_CFG)
+ self.assertEqual(vnf.vcmts_influxdb_ip, "10.80.5.150")
+ self.assertEqual(vnf.vcmts_influxdb_port, 8086)
+
+ if os.path.isfile(self.VCMTSD_VALUES_PATH):
+ os.remove(self.VCMTSD_VALUES_PATH)
+
+ def test__update_collectd_options(self):
+ scenario_cfg = {'options':
+ {'collectd':
+ {'interval': 3,
+ 'plugins':
+ {'plugin3': {'param': 3}}},
+ 'vnf__0':
+ {'collectd':
+ {'interval': 2,
+ 'plugins':
+ {'plugin3': {'param': 2},
+ 'plugin2': {'param': 2}}}}}}
+ context_cfg = {'nodes':
+ {'vnf__0':
+ {'collectd':
+ {'interval': 1,
+ 'plugins':
+ {'plugin3': {'param': 1},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}}}}
+ expected = {'interval': 1,
+ 'plugins':
+ {'plugin3': {'param': 1},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+
+ self.vnf._update_collectd_options(scenario_cfg, context_cfg)
+ self.assertEqual(self.vnf.setup_helper.collectd_options, expected)
+
+ def test__update_options(self):
+ options1 = {'interval': 1,
+ 'param1': 'value1',
+ 'plugins':
+ {'plugin3': {'param': 3},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+ options2 = {'interval': 2,
+ 'param2': 'value2',
+ 'plugins':
+ {'plugin4': {'param': 4},
+ 'plugin2': {'param': 2},
+ 'plugin1': {'param': 2}}}
+ expected = {'interval': 1,
+ 'param1': 'value1',
+ 'param2': 'value2',
+ 'plugins':
+ {'plugin4': {'param': 4},
+ 'plugin3': {'param': 3},
+ 'plugin2': {'param': 1},
+ 'plugin1': {'param': 1}}}
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vnf = vcmts_vnf.VcmtsVNF('vnf1', vnfd)
+ vnf._update_options(options2, options1)
+ self.assertEqual(options2, expected)
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.vnf.wait_for_instantiate())
+
+ def test_terminate(self):
+ self.assertIsNone(self.vnf.terminate())
+
+ def test_scale(self):
+ self.assertIsNone(self.vnf.scale())
+
+ def test_collect_kpi(self):
+ self.vnf.influxdb_helper = mock.MagicMock()
+ self.vnf.collect_kpi()
+ self.vnf.influxdb_helper.copy_kpi.assert_called_once()
+
+ def test_start_collect(self):
+ self.vnf.vcmts_influxdb_ip = "localhost"
+ self.vnf.vcmts_influxdb_port = 8800
+
+ self.assertIsNone(self.vnf.start_collect())
+ self.assertIsNotNone(self.vnf.influxdb_helper)
+
+ def test_stop_collect(self):
+ self.assertIsNone(self.vnf.stop_collect())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
new file mode 100644
index 000000000..5334ce18c
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vfw_vnf.py
@@ -0,0 +1,371 @@
+# Copyright (c) 2016-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.
+
+import unittest
+import mock
+import os
+
+from yardstick.common import utils
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.vnf_generic.vnf.vfw_vnf import FWApproxVnf
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.vnf_generic.vnf.vfw_vnf import FWApproxSetupEnvHelper
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+SSH_HELPER = 'yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper'
+
+name = 'vnf__1'
+
+
+@mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.Process")
+class TestFWApproxVnf(unittest.TestCase):
+ VNFD = {'vnfd:vnfd-catalog':
+ {'vnfd':
+ [{'short-name': 'VpeVnf',
+ 'vdu':
+ [{'routing_table':
+ [{'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'},
+ {'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl':
+ [{'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface':
+ [{'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02'},
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'},
+ {'virtual-interface':
+ {'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01'},
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'}]}],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface':
+ {'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1'},
+ 'benchmark':
+ {'kpi': ['packets_in', 'packets_fwd', 'packets_dropped']},
+ 'connection-point': [{'type': 'VPORT', 'name': 'xe0'},
+ {'type': 'VPORT', 'name': 'xe1'}],
+ 'id': 'FWApproxVnf', 'name': 'VPEVnfSsh'}]}}
+
+ scenario_cfg = {'options': {'packetsize': 64, 'traffic_type': 4,
+ 'rfc2544': {'allowed_drop_rate': '0.8 - 1'},
+ 'vnf__1': {'rules': 'acl_1rule.yaml',
+ 'vnf_config': {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config':
+ '1C/1T',
+ 'worker_threads': 1}}
+ },
+ 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+ 'task_path': '/tmp',
+ 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+ 'runner': {'object': 'NetworkServiceTestCase',
+ 'interval': 35,
+ 'output_filename': '/tmp/yardstick.out',
+ 'runner_id': 74476, 'duration': 400,
+ 'type': 'Duration'},
+ 'traffic_profile': 'ipv4_throughput_vfw.yaml',
+ 'traffic_options': {'flow': 'ipv4_Packets_vfw.yaml',
+ 'imix': 'imix_voice.yaml'},
+ 'type': 'ISB',
+ 'nodes': {'tg__2': 'trafficgen_2.yardstick',
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick'},
+ 'topology': 'vpe-tg-topology-baremetal.yaml'}
+
+ context_cfg = {'nodes': {'tg__2':
+ {'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens513f0',
+ 'vld_id': FWApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root'},
+ 'tg__1':
+ {'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens785f0',
+ 'vld_id': FWApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root'},
+ 'vnf__1':
+ {'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces':
+ {'xe0': {'local_iface_name': 'ens786f0',
+ 'vld_id': FWApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0},
+ 'xe1': {'local_iface_name': 'ens786f1',
+ 'vld_id': FWApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1}},
+ 'routing_table':
+ [{'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0'},
+ {'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1'}],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl':
+ [{'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'},
+ {'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'}],
+ 'password': 'r00t',
+ 'VNF model': 'vfw_vnf.yaml'}}}
+
+ def test___init__(self, *args):
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ self.assertIsNone(vfw_approx_vnf._vnf_process)
+
+ STATS = """\
+p vfw stats
+
+VFW Stats
+{"VFW_counters" : {"id" : "PIPELINE4", " pkts_received": 6007180, " pkts_fw_forwarded": 6007180, " pkts_drop_fw": 0, " pkts_acl_forwarded": 6007180, "pkts_drop_without_rule" : 0, "average_pkts_in_batch" : 31, "average_internal_time_in_clocks" : 17427, "average_external_time_in_clocks" : 261120, "total_time_measures" : 189829, "ct_packets_forwarded" : 6007148, "ct_packets_dropped" : 0, "bytes_processed ": 360430800, "ct_sessions" : {"active" : 130050, "open_attempt" : 130050, "re-open_attempt" : 0, "established" : 0, "closed" : 0, "timeout" : 0}, "ct_drops" : {"out_of_window" : 0, "invalid_conn" : 0, "invalid_state_transition" : 0 "RST" : 0}}
+VFW TOTAL: pkts_received: 6007180, "pkts_fw_forwarded": 6007180, "pkts_drop_fw": 0, "fw_drops" : {"TTL_zero" : 0, "bad_size" : 0, "fragmented_packet" : 0, "unsupported_packet_types" : 0, "no_arp_entry" : 6007180}, "pkts_acl_forwarded": 6007180, "pkts_drop_without_rule": 0, "packets_last_sec" : 0, "average_packets_per_sec" : 0, "bytes_last_sec" : 0, "average_bytes_per_sec" : 0, "bytes_processed ": 360430800
+"CT TOTAL: ct_packets_forwarded" : 6007180, " ct_packets_dropped" : 0, "ct_sessions" : {"active" : 130050, "open_attempt" : 130050, "re-open_attempt" : 0, "established" : 0, "closed" : 0, "timeout" : 0}, "ct_drops" : {"out_of_window" : 0, "invalid_conn" : 0, "invalid_state_transition" : 0 "RST" : 0}
+Action ID: 00, packetCount: 2954633, byteCount: 177277980
+Action ID: 01, packetCount: 3052547, byteCount: 183152820
+pipeline>
+
+pipeline>
+""" # noqa
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server', return_value='mock_node')
+ @mock.patch(SSH_HELPER)
+ def test_collect_kpi(self, ssh, *args):
+ mock_ssh(ssh)
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ vfw_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {vfw_approx_vnf.name: "mock"}
+ }
+ vfw_approx_vnf.q_in = mock.MagicMock()
+ vfw_approx_vnf.q_out = mock.MagicMock()
+ vfw_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ vfw_approx_vnf.resource = mock.Mock(autospec=ResourceProfile)
+ vfw_approx_vnf.resource_helper = mock.MagicMock(
+ **{'collect_kpi.return_value': {"core": {}}})
+ vfw_approx_vnf.vnf_execute = mock.Mock(return_value=self.STATS)
+ result = {
+ 'physical_node': 'mock_node',
+ 'packets_dropped': 0,
+ 'packets_fwd': 6007180,
+ 'packets_in': 6007180,
+ 'collect_stats': {'core': {}},
+ }
+ self.assertEqual(result, vfw_approx_vnf.collect_kpi())
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.time")
+ @mock.patch(SSH_HELPER)
+ def test_vnf_execute_command(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ vfw_approx_vnf.q_in = mock.MagicMock()
+ vfw_approx_vnf.q_out = mock.MagicMock()
+ vfw_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ cmd = "quit"
+ self.assertEqual(vfw_approx_vnf.vnf_execute(cmd), "")
+
+ @mock.patch(SSH_HELPER)
+ def test_get_stats(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ vfw_approx_vnf.q_in = mock.MagicMock()
+ vfw_approx_vnf.q_out = mock.MagicMock()
+ vfw_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ vfw_approx_vnf.vnf_execute = mock.Mock(return_value=self.STATS)
+ self.assertEqual(self.STATS, vfw_approx_vnf.get_stats())
+
+ def _get_file_abspath(self, filename):
+ curr_path = os.path.dirname(os.path.abspath(__file__))
+ file_path = os.path.join(curr_path, filename)
+ return file_path
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.vfw_vnf.hex")
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.vfw_vnf.eval")
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.vfw_vnf.open")
+ @mock.patch(SSH_HELPER)
+ def test_run_vfw(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ vfw_approx_vnf._build_config = mock.MagicMock()
+ vfw_approx_vnf.queue_wrapper = mock.MagicMock()
+ vfw_approx_vnf.ssh_helper = mock.MagicMock()
+ vfw_approx_vnf.ssh_helper.run = mock.MagicMock()
+ vfw_approx_vnf.scenario_helper.scenario_cfg = self.scenario_cfg
+ vfw_approx_vnf.vnf_cfg = {'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1}
+ vfw_approx_vnf.all_options = {'traffic_type': '4',
+ 'topology': 'nsb_test_case.yaml'}
+ vfw_approx_vnf._run()
+ vfw_approx_vnf.ssh_helper.run.assert_called_once()
+
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch.object(ctx_base.Context, 'get_context_from_server')
+ @mock.patch(SSH_HELPER)
+ def test_instantiate(self, ssh, *args):
+ mock_ssh(ssh)
+
+ vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0]
+ vfw_approx_vnf = FWApproxVnf(name, vnfd)
+ vfw_approx_vnf.ssh_helper = ssh
+ vfw_approx_vnf.deploy_helper = mock.MagicMock()
+ vfw_approx_vnf.resource_helper = mock.MagicMock()
+ vfw_approx_vnf._build_config = mock.MagicMock()
+ self.scenario_cfg['vnf_options'] = {'acl': {'cfg': "",
+ 'rules': ""}}
+ self.scenario_cfg.update({"nodes": {"vnf__1": ""}})
+ self.assertIsNone(vfw_approx_vnf.instantiate(self.scenario_cfg, self.context_cfg))
+
+
+class TestFWApproxSetupEnvHelper(unittest.TestCase):
+
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.open')
+ @mock.patch.object(utils, 'find_relative_file')
+ @mock.patch('yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig')
+ @mock.patch.object(utils, 'open_relative_file')
+ def test_build_config(self, *args):
+ vnfd_helper = mock.Mock()
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+ scenario_helper.options = {}
+ scenario_helper.all_options = {}
+
+ vfw_approx_setup_helper = FWApproxSetupEnvHelper(vnfd_helper, ssh_helper, scenario_helper)
+ vfw_approx_setup_helper.get_flows_config = mock.Mock()
+
+ vfw_approx_setup_helper.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
+ vfw_approx_setup_helper.ssh_helper.all_ports = mock.Mock()
+ vfw_approx_setup_helper.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
+ expected = 'sudo tool_path -p 0x3 -f /tmp/vfw_config -s /tmp/vfw_script --hwlb 3'
+ self.assertEqual(vfw_approx_setup_helper.build_config(), expected)
+ vfw_approx_setup_helper.get_flows_config.assert_called_once()
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py
new file mode 100644
index 000000000..d86dab8ad
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vims_vnf.py
@@ -0,0 +1,713 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License,Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import unittest
+import mock
+
+from yardstick.network_services.vnf_generic.vnf import vims_vnf
+from yardstick.tests.unit.network_services.vnf_generic.vnf.test_base import mock_ssh
+
+
+class TestVimsPcscfVnf(unittest.TestCase):
+
+ VNFD_0 = {
+ "short-name": "SippVnf",
+ "vdu": [
+ {
+ "id": "sippvnf-baremetal",
+ "routing_table": "",
+ "external-interface": [
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe0",
+ "name": "xe0"
+ },
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe1",
+ "name": "xe1"
+ }
+ ],
+ "name": "sippvnf-baremetal",
+ "description": "Sipp"
+ }
+ ],
+ "description": "ImsbenchSipp",
+ "mgmt-interface": {
+ "vdu-id": "sipp-baremetal",
+ "password": "r00t",
+ "user": "root",
+ "ip": "10.80.3.11"
+ },
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "id": "SippVnf",
+ "name": "SippVnf"
+ }
+
+ def setUp(self):
+ self.pcscf_vnf = vims_vnf.VimsPcscfVnf('vnf__0', self.VNFD_0)
+
+ def test___init__(self):
+ self.assertEqual(self.pcscf_vnf.name, 'vnf__0')
+ self.assertIsInstance(self.pcscf_vnf.resource_helper,
+ vims_vnf.VimsResourceHelper)
+ self.assertIsNone(self.pcscf_vnf._vnf_process)
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.pcscf_vnf.wait_for_instantiate())
+
+ def test__run(self):
+ self.assertIsNone(self.pcscf_vnf._run())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.pcscf_vnf.start_collect())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.pcscf_vnf.collect_kpi())
+
+
+class TestVimsHssVnf(unittest.TestCase):
+
+ VNFD_1 = {
+ "short-name": "SippVnf",
+ "vdu": [
+ {
+ "id": "sippvnf-baremetal",
+ "routing_table": "",
+ "external-interface": [
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe0",
+ "name": "xe0"
+ },
+ {
+ "virtual-interface": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "vnfd-connection-point-ref": "xe1",
+ "name": "xe1"
+ }
+ ],
+ "name": "sippvnf-baremetal",
+ "description": "Sipp"
+ }
+ ],
+ "description": "ImsbenchSipp",
+ "mgmt-interface": {
+ "vdu-id": "sipp-baremetal",
+ "password": "r00t",
+ "user": "root",
+ "ip": "10.80.3.11"
+ },
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "id": "SippVnf",
+ "name": "SippVnf"
+ }
+
+ SCENARIO_CFG = {
+ "task_id": "86414e11-5ef5-4426-b175-71baaa00fbd7",
+ "tc": "tc_vims_baremetal_sipp",
+ "runner": {
+ "interval": 1,
+ "output_config": {
+ "DEFAULT": {
+ "debug": "False",
+ "dispatcher": [
+ "influxdb"
+ ]
+ },
+ "nsb": {
+ "debug": "False",
+ "trex_client_lib": "/opt/nsb_bin/trex_client/stl",
+ "bin_path": "/opt/nsb_bin",
+ "trex_path": "/opt/nsb_bin/trex/scripts",
+ "dispatcher": "influxdb"
+ },
+ "dispatcher_influxdb": {
+ "username": "root",
+ "target": "http://10.80.3.11:8086",
+ "db_name": "yardstick",
+ "timeout": "5",
+ "debug": "False",
+ "password": "root",
+ "dispatcher": "influxdb"
+ },
+ "dispatcher_http": {
+ "debug": "False",
+ "dispatcher": "influxdb",
+ "timeout": "5",
+ "target": "http://127.0.0.1:8000/results"
+ },
+ "dispatcher_file": {
+ "debug": "False",
+ "backup_count": "0",
+ "max_bytes": "0",
+ "dispatcher": "influxdb",
+ "file_path": "/tmp/yardstick.out"
+ }
+ },
+ "runner_id": 22610,
+ "duration": 60,
+ "type": "Vims"
+ },
+ "nodes": {
+ "vnf__0": "pcscf.yardstick-86414e11",
+ "vnf__1": "hss.yardstick-86414e11",
+ "tg__0": "sipp.yardstick-86414e11"
+ },
+ "topology": "vims-topology.yaml",
+ "type": "NSPerf",
+ "traffic_profile": "../../traffic_profiles/ipv4_throughput.yaml",
+ "task_path": "samples/vnf_samples/nsut/vims",
+ "options": {
+ "init_reg_max": 5000,
+ "end_user": 10000,
+ "reg_cps": 20,
+ "rereg_cps": 20,
+ "rereg_step": 10,
+ "wait_time": 5,
+ "start_user": 1,
+ "msgc_cps": 10,
+ "dereg_step": 10,
+ "call_cps": 10,
+ "reg_step": 10,
+ "init_reg_cps": 50,
+ "dereg_cps": 20,
+ "msgc_step": 5,
+ "call_step": 5,
+ "hold_time": 15,
+ "port": 5060,
+ "run_mode": "nortp"
+ }
+ }
+
+ CONTEXT_CFG = {
+ "nodes": {
+ "tg__0": {
+ "ip": "10.80.3.11",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "xe1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vnf__0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "vnf__1": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/tg_sipp_vnfd.yaml",
+ "name": "sipp.yardstick-86414e11",
+ "vnfd-id-ref": "tg__0",
+ "member-vnf-index": "1",
+ "role": "TrafficGen",
+ "ctx_type": "Node"
+ },
+ "vnf__0": {
+ "ip": "10.80.3.7",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "tg__0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/vims_pcscf_vnfd.yaml",
+ "name": "pcscf.yardstick-86414e11",
+ "vnfd-id-ref": "vnf__0",
+ "member-vnf-index": "2",
+ "role": "VirtualNetworkFunction",
+ "ctx_type": "Node"
+ },
+ "vnf__1": {
+ "ip": "10.80.3.7",
+ "interfaces": {
+ "xe0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "tg__0": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "peer_intf": {
+ "vld_id": "data_network",
+ "peer_ifname": "xe1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "network": {},
+ "local_ip": "10.80.3.7",
+ "peer_intf": {
+ "vld_id": "ims_network",
+ "peer_ifname": "xe0",
+ "dst_mac": "90:e2:ba:7c:41:e8",
+ "network": {},
+ "local_ip": "10.80.3.11",
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ },
+ "node_name": "vnf__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:a8"
+ },
+ "node_name": "tg__0",
+ "netmask": "255.255.255.0",
+ "peer_name": "vnf__1",
+ "dst_ip": "10.80.3.7",
+ "ifname": "xe1",
+ "local_mac": "90:e2:ba:7c:30:e8"
+ }
+ },
+ "node_name": "vnf__1",
+ "netmask": "255.255.255.0",
+ "peer_name": "tg__0",
+ "dst_ip": "10.80.3.11",
+ "ifname": "xe0",
+ "local_mac": "90:e2:ba:7c:41:e8"
+ }
+ },
+ "user": "root",
+ "password": "r00t",
+ "VNF model": "../../vnf_descriptors/vims_hss_vnfd.yaml",
+ "name": "hss.yardstick-86414e11",
+ "vnfd-id-ref": "vnf__1",
+ "member-vnf-index": "3",
+ "role": "VirtualNetworkFunction",
+ "ctx_type": "Node"
+ }
+ },
+ "networks": {}
+ }
+
+ def setUp(self):
+ self.hss_vnf = vims_vnf.VimsHssVnf('vnf__1', self.VNFD_1)
+
+ def test___init__(self):
+ self.assertIsInstance(self.hss_vnf.resource_helper,
+ vims_vnf.VimsResourceHelper)
+ self.assertIsNone(self.hss_vnf._vnf_process)
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.VnfSshHelper")
+ def test_instantiate(self, ssh):
+ mock_ssh(ssh)
+ hss_vnf = vims_vnf.VimsHssVnf('vnf__1', self.VNFD_1)
+ self.assertIsNone(hss_vnf.instantiate(self.SCENARIO_CFG,
+ self.CONTEXT_CFG))
+
+ def test_wait_for_instantiate(self):
+ self.assertIsNone(self.hss_vnf.wait_for_instantiate())
+
+ def test_start_collect(self):
+ self.assertIsNone(self.hss_vnf.start_collect())
+
+ def test_collect_kpi(self):
+ self.assertIsNone(self.hss_vnf.collect_kpi())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py
new file mode 100644
index 000000000..8342f5faa
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpe_vnf.py
@@ -0,0 +1,744 @@
+# Copyright (c) 2016-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.
+
+from multiprocessing import Process, Queue
+import time
+
+import mock
+import unittest
+
+from yardstick.benchmark.contexts import base as ctx_base
+from yardstick.network_services.nfvi.resource import ResourceProfile
+from yardstick.network_services.vnf_generic.vnf import base as vnf_base
+from yardstick.network_services.vnf_generic.vnf import sample_vnf
+from yardstick.network_services.vnf_generic.vnf import vpe_vnf
+from yardstick.tests.unit.network_services.vnf_generic.vnf import test_base
+
+
+TEST_FILE_YAML = 'nsb_test_case.yaml'
+
+NAME = 'vnf_1'
+
+PING_OUTPUT_1 = "Pkts in: 101\r\n\tPkts dropped by AH: 100\r\n\tPkts dropped by other: 100"
+
+MODULE_PATH = test_base.FileAbsPath(__file__)
+get_file_abspath = MODULE_PATH.get_path
+
+
+class TestConfigCreate(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1'
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0'
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1'
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.100.20',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0'
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1'
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.1.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.1.1.1'
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf', 'name': 'VPEVnfSsh'
+ }
+
+ def test___init__(self):
+ vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+ config_create = vpe_vnf.ConfigCreate(vnfd_helper, 2)
+ self.assertEqual(config_create.uplink_ports, ['xe0'])
+ self.assertEqual(config_create.downlink_ports, ['xe1'])
+ self.assertEqual(config_create.socket, 2)
+
+ def test_generate_vpe_script(self):
+ vnfd_helper = vnf_base.VnfdHelper(self.VNFD_0)
+ vpe_config_vnf = vpe_vnf.ConfigCreate(vnfd_helper, 2)
+ intf = [
+ {
+ "name": 'xe1',
+ "virtual-interface": {
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "00:00:00:00:00:00:02",
+ },
+ },
+ {
+ "name": 'xe2',
+ "virtual-interface": {
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "00:00:00:00:00:00:02",
+ },
+ },
+ ]
+ vpe_config_vnf.downlink_ports = ['xe1']
+ vpe_config_vnf.uplink_ports = ['xe2']
+ result = vpe_config_vnf.generate_vpe_script(intf)
+ self.assertIsInstance(result, str)
+ self.assertNotEqual(result, '')
+
+
+class TestVpeApproxVnf(unittest.TestCase):
+
+ VNFD_0 = {
+ 'short-name': 'VpeVnf',
+ 'vdu': [
+ {
+ 'routing_table': [
+ {
+ 'network': '152.16.100.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '152.16.40.20',
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'description': 'VPE approximation using DPDK',
+ 'name': 'vpevnf-baremetal',
+ 'nd_route_tbl': [
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'id': 'vpevnf-baremetal',
+ 'external-interface': [
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:04',
+ 'vpci': '0000:05:00.0',
+ 'local_ip': '152.16.100.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 0,
+ 'bandwidth': '10 Gbps',
+ 'driver': "i40e",
+ 'dst_ip': '152.16.100.20',
+ 'local_iface_name': 'xe0',
+ 'local_mac': '00:00:00:00:00:02',
+ 'vld_id': 'uplink_0',
+ 'ifname': 'xe0',
+ },
+ 'vnfd-connection-point-ref': 'xe0',
+ 'name': 'xe0',
+ },
+ {
+ 'virtual-interface': {
+ 'dst_mac': '00:00:00:00:00:03',
+ 'vpci': '0000:05:00.1',
+ 'local_ip': '152.16.40.19',
+ 'type': 'PCI-PASSTHROUGH',
+ 'driver': "i40e",
+ 'netmask': '255.255.255.0',
+ 'dpdk_port_num': 1,
+ 'bandwidth': '10 Gbps',
+ 'dst_ip': '152.16.40.20',
+ 'local_iface_name': 'xe1',
+ 'local_mac': '00:00:00:00:00:01',
+ 'vld_id': 'downlink_0',
+ 'ifname': 'xe1',
+ },
+ 'vnfd-connection-point-ref': 'xe1',
+ 'name': 'xe1',
+ },
+ ],
+ },
+ ],
+ 'description': 'Vpe approximation using DPDK',
+ 'mgmt-interface': {
+ 'vdu-id': 'vpevnf-baremetal',
+ 'host': '1.2.1.1',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'ip': '1.2.1.1',
+ },
+ 'benchmark': {
+ 'kpi': [
+ 'packets_in',
+ 'packets_fwd',
+ 'packets_dropped',
+ ],
+ },
+ 'connection-point': [
+ {
+ 'type': 'VPORT',
+ 'name': 'xe0',
+ },
+ {
+ 'type': 'VPORT',
+ 'name': 'xe1',
+ },
+ ],
+ 'id': 'VpeApproxVnf',
+ 'name': 'VPEVnfSsh',
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ SCENARIO_CFG = {
+ 'options': {
+ 'packetsize': 64,
+ 'traffic_type': 4,
+ 'rfc2544': {
+ 'allowed_drop_rate': '0.8 - 1',
+ },
+ 'vnf__1': {
+ 'cfg': 'acl_1rule.yaml',
+ 'vnf_config': {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config':
+ '1C/1T',
+ 'worker_threads': 1,
+ },
+ }
+ },
+ 'task_id': 'a70bdf4a-8e67-47a3-9dc1-273c14506eb7',
+ 'tc': 'tc_ipv4_1Mflow_64B_packetsize',
+ 'runner': {
+ 'object': 'NetworkServiceTestCase',
+ 'interval': 35,
+ 'output_filename': '/tmp/yardstick.out',
+ 'runner_id': 74476,
+ 'duration': 400,
+ 'type': 'Duration',
+ },
+ 'traffic_profile': 'ipv4_throughput_vpe.yaml',
+ 'traffic_options': {
+ 'flow': 'ipv4_Packets_vpe.yaml',
+ 'imix': 'imix_voice.yaml',
+ },
+ 'type': 'ISB',
+ 'nodes': {
+ 'tg__2': 'trafficgen_2.yardstick',
+ 'tg__1': 'trafficgen_1.yardstick',
+ 'vnf__1': 'vnf.yardstick',
+ },
+ 'topology': 'vpe-tg-topology-baremetal.yaml',
+ }
+
+ CONTEXT_CFG = {
+ 'nodes': {
+ 'tg__2': {
+ 'member-vnf-index': '3',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_2.yardstick',
+ 'vnfd-id-ref': 'tg__2',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens513f0',
+ 'vld_id': vpe_vnf.VpeApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.20',
+ 'dst_mac': '00:00:00:00:00:01',
+ 'local_mac': '00:00:00:00:00:03',
+ 'dst_ip': '152.16.40.19',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens513f1',
+ 'netmask': '255.255.255.0',
+ 'network': '202.16.100.0',
+ 'local_ip': '202.16.100.20',
+ 'local_mac': '00:1e:67:d0:60:5d',
+ 'driver': 'ixgbe',
+ 'vpci': '0000:02:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'l3fwd_vnf.yaml',
+ 'user': 'root',
+ },
+ 'tg__1': {
+ 'member-vnf-index': '1',
+ 'role': 'TrafficGen',
+ 'name': 'trafficgen_1.yardstick',
+ 'vnfd-id-ref': 'tg__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens785f0',
+ 'vld_id': vpe_vnf.VpeApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.20',
+ 'dst_mac': '00:00:00:00:00:02',
+ 'local_mac': '00:00:00:00:00:04',
+ 'dst_ip': '152.16.100.19',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens785f1',
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.21',
+ 'local_mac': '00:00:00:00:00:01',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'password': 'r00t',
+ 'VNF model': 'tg_rfc2544_tpl.yaml',
+ 'user': 'root',
+ },
+ 'vnf__1': {
+ 'name': 'vnf.yardstick',
+ 'vnfd-id-ref': 'vnf__1',
+ 'ip': '1.2.1.1',
+ 'interfaces': {
+ 'xe0': {
+ 'local_iface_name': 'ens786f0',
+ 'vld_id': vpe_vnf.VpeApproxVnf.UPLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.100.19',
+ 'dst_mac': '00:00:00:00:00:04',
+ 'local_mac': '00:00:00:00:00:02',
+ 'dst_ip': '152.16.100.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.0',
+ 'dpdk_port_num': 0,
+ },
+ 'xe1': {
+ 'local_iface_name': 'ens786f1',
+ 'vld_id': vpe_vnf.VpeApproxVnf.DOWNLINK,
+ 'netmask': '255.255.255.0',
+ 'local_ip': '152.16.40.19',
+ 'dst_mac': '00:00:00:00:00:03',
+ 'local_mac': '00:00:00:00:00:01',
+ 'dst_ip': '152.16.40.20',
+ 'driver': 'i40e',
+ 'vpci': '0000:05:00.1',
+ 'dpdk_port_num': 1,
+ },
+ },
+ 'routing_table': [
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.100.20',
+ 'network': '152.16.100.20',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '255.255.255.0',
+ 'gateway': '152.16.40.20',
+ 'network': '152.16.40.20',
+ 'if': 'xe1',
+ },
+ ],
+ 'member-vnf-index': '2',
+ 'host': '1.2.1.1',
+ 'role': 'vnf',
+ 'user': 'root',
+ 'nd_route_tbl': [
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:6414',
+ 'network': '0064:ff9b:0:0:0:0:9810:6414',
+ 'if': 'xe0',
+ },
+ {
+ 'netmask': '112',
+ 'gateway': '0064:ff9b:0:0:0:0:9810:2814',
+ 'network': '0064:ff9b:0:0:0:0:9810:2814',
+ 'if': 'xe1',
+ },
+ ],
+ 'password': 'r00t',
+ 'VNF model': 'vpe_vnf.yaml',
+ },
+ },
+ }
+
+ def setUp(self):
+ self._mock_time_sleep = mock.patch.object(time, 'sleep')
+ self.mock_time_sleep = self._mock_time_sleep.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_time_sleep.stop()
+
+ def test___init__(self):
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ self.assertIsNone(vpe_approx_vnf._vnf_process)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_collect_kpi_sa_not_running(self, ssh, *args):
+ test_base.mock_ssh(ssh)
+
+ resource = mock.Mock(autospec=ResourceProfile)
+ resource.check_if_system_agent_running.return_value = 1, ''
+ resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
+ resource.check_if_system_agent_running.return_value = (1, None)
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {vpe_approx_vnf.name: "mock"}
+ }
+ vpe_approx_vnf.q_in = mock.MagicMock()
+ vpe_approx_vnf.q_out = mock.MagicMock()
+ vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ vpe_approx_vnf.resource_helper.resource = resource
+
+ expected = {
+ 'physical_node': 'mock_node',
+ 'pkt_in_down_stream': 0,
+ 'pkt_in_up_stream': 0,
+ 'pkt_drop_down_stream': 0,
+ 'pkt_drop_up_stream': 0,
+ 'collect_stats': {'core': {}},
+ }
+ self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
+
+ @mock.patch.object(ctx_base.Context, 'get_physical_node_from_server',
+ return_value='mock_node')
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_collect_kpi_sa_running(self, ssh, *args):
+ test_base.mock_ssh(ssh)
+
+ resource = mock.Mock(autospec=ResourceProfile)
+ resource.check_if_system_agent_running.return_value = 0, '1234'
+ resource.amqp_collect_nfvi_kpi.return_value = {'foo': 234}
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf.scenario_helper.scenario_cfg = {
+ 'nodes': {vpe_approx_vnf.name: "mock"}
+ }
+ vpe_approx_vnf.q_in = mock.MagicMock()
+ vpe_approx_vnf.q_out = mock.MagicMock()
+ vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ vpe_approx_vnf.resource_helper.resource = resource
+
+ expected = {
+ 'physical_node': 'mock_node',
+ 'pkt_in_down_stream': 0,
+ 'pkt_in_up_stream': 0,
+ 'pkt_drop_down_stream': 0,
+ 'pkt_drop_up_stream': 0,
+ 'collect_stats': {'core': {'foo': 234}},
+ }
+ self.assertEqual(vpe_approx_vnf.collect_kpi(), expected)
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_vnf_execute(self, ssh):
+ test_base.mock_ssh(ssh)
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf.q_in = mock.MagicMock()
+ vpe_approx_vnf.q_out = mock.MagicMock()
+ vpe_approx_vnf.q_out.qsize = mock.Mock(return_value=0)
+ self.assertEqual(vpe_approx_vnf.vnf_execute("quit", 0), '')
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_run_vpe(self, ssh):
+ test_base.mock_ssh(ssh)
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
+ vpe_approx_vnf.vnf_cfg = {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1,
+ }
+ vpe_approx_vnf.scenario_helper.scenario_cfg = {
+ 'options': {
+ NAME: {
+ 'traffic_type': '4',
+ 'topology': 'nsb_test_case.yaml',
+ 'vnf_config': 'vpe_config',
+ }
+ }
+ }
+ vpe_approx_vnf.topology = "nsb_test_case.yaml"
+ vpe_approx_vnf.nfvi_type = "baremetal"
+ vpe_approx_vnf._provide_config_file = mock.Mock()
+ vpe_approx_vnf._build_config = mock.MagicMock()
+
+ self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
+ self.assertIsInstance(vpe_approx_vnf.ssh_helper, mock.Mock)
+ self.assertIsNone(vpe_approx_vnf._run())
+
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.sample_vnf.MultiPortConfig")
+ @mock.patch("yardstick.network_services.vnf_generic.vnf.vpe_vnf.ConfigCreate")
+ @mock.patch("six.moves.builtins.open")
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_build_config(self, ssh, *args):
+ test_base.mock_ssh(ssh)
+ vpe_approx_vnf = vpe_vnf.VpeApproxSetupEnvHelper(
+ mock.MagicMock(), mock.MagicMock(), mock.MagicMock())
+ vpe_approx_vnf.tc_file_name = get_file_abspath(TEST_FILE_YAML)
+ vpe_approx_vnf.generate_port_pairs = mock.Mock()
+ vpe_approx_vnf.vnf_cfg = {
+ 'lb_config': 'SW',
+ 'lb_count': 1,
+ 'worker_config': '1C/1T',
+ 'worker_threads': 1,
+ }
+ vpe_approx_vnf.scenario_helper.scenario_cfg = {
+ 'options': {
+ NAME: {
+ 'traffic_type': '4',
+ 'topology': 'nsb_test_case.yaml',
+ 'vnf_config': 'vpe_config',
+ }
+ }
+ }
+ vpe_approx_vnf.topology = "nsb_test_case.yaml"
+ vpe_approx_vnf.nfvi_type = "baremetal"
+ vpe_approx_vnf._provide_config_file = mock.Mock()
+
+ vpe_approx_vnf.ssh_helper = mock.MagicMock()
+ vpe_approx_vnf.scenario_helper = mock.MagicMock()
+ vpe_approx_vnf.ssh_helper.bin_path = mock.Mock()
+ vpe_approx_vnf.ssh_helper.upload_config_file = mock.MagicMock()
+ self.assertIsNone(vpe_approx_vnf._build_vnf_ports())
+
+ vpe_approx_vnf.ssh_helper.provision_tool = mock.Mock(return_value='tool_path')
+ vpe_approx_vnf.ssh_helper.all_ports = mock.Mock()
+ vpe_approx_vnf.vnfd_helper.port_nums = mock.Mock(return_value=[0, 1])
+ vpe_approx_vnf.scenario_helper.vnf_cfg = {'lb_config': 'HW'}
+
+ expected = 'sudo tool_path -p 0x3 -f /tmp/vpe_config -s /tmp/vpe_script --hwlb 3'
+ self.assertEqual(vpe_approx_vnf.build_config(), expected)
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_wait_for_instantiate(self, ssh):
+ test_base.mock_ssh(ssh)
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ mock_q_out = mock.Mock(autospec=Queue)
+ mock_q_out.get.side_effect = iter(["pipeline>"])
+ mock_q_out.qsize.side_effect = range(1, -1, -1)
+
+ mock_resource = mock.MagicMock()
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock_process
+ vpe_approx_vnf.q_out = mock_q_out
+ vpe_approx_vnf.queue_wrapper = mock.Mock(
+ autospec=vnf_base.QueueFileWrapper)
+ vpe_approx_vnf.resource_helper.resource = mock_resource
+
+ vpe_approx_vnf.q_out.put("pipeline>")
+ self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_wait_for_instantiate_fragmented(self, ssh):
+ test_base.mock_ssh(ssh)
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ # test that fragmented pipeline prompt is recognized
+ mock_q_out = mock.Mock(autospec=Queue)
+ mock_q_out.get.side_effect = iter(["wow pipel", "ine>"])
+ mock_q_out.qsize.side_effect = range(2, -1, -1)
+
+ mock_resource = mock.MagicMock()
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock_process
+ vpe_approx_vnf.q_out = mock_q_out
+ vpe_approx_vnf.queue_wrapper = mock.Mock(
+ autospec=vnf_base.QueueFileWrapper)
+ vpe_approx_vnf.resource_helper.resource = mock_resource
+
+ self.assertEqual(vpe_approx_vnf.wait_for_instantiate(), 432)
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_wait_for_instantiate_crash(self, ssh):
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = False
+ mock_process.exitcode = 432
+
+ mock_resource = mock.MagicMock()
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock_process
+ vpe_approx_vnf.resource_helper.resource = mock_resource
+
+ with self.assertRaises(RuntimeError) as raised:
+ vpe_approx_vnf.wait_for_instantiate()
+
+ self.assertIn('VNF process died', str(raised.exception))
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_wait_for_instantiate_panic(self, ssh):
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ mock_resource = mock.MagicMock()
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock_process
+ vpe_approx_vnf.resource_helper.resource = mock_resource
+
+ vpe_approx_vnf.q_out.put("PANIC")
+ with self.assertRaises(RuntimeError) as raised:
+ vpe_approx_vnf.wait_for_instantiate()
+
+ self.assertIn('Error starting', str(raised.exception))
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_wait_for_instantiate_panic_fragmented(self, ssh):
+ test_base.mock_ssh(ssh, exec_result=(1, "", ""))
+
+ mock_process = mock.Mock(autospec=Process)
+ mock_process.is_alive.return_value = True
+ mock_process.exitcode = 432
+
+ # test that fragmented PANIC is recognized
+ mock_q_out = mock.Mock(autospec=Queue)
+ mock_q_out.get.side_effect = iter(["omg PA", "NIC this is bad"])
+ mock_q_out.qsize.side_effect = range(2, -1, -1)
+
+ mock_resource = mock.MagicMock()
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock_process
+ vpe_approx_vnf.q_out = mock_q_out
+ vpe_approx_vnf.resource_helper.resource = mock_resource
+
+ with self.assertRaises(RuntimeError) as raised:
+ vpe_approx_vnf.wait_for_instantiate()
+
+ self.assertIn('Error starting', str(raised.exception))
+
+ @mock.patch.object(sample_vnf, 'VnfSshHelper')
+ def test_terminate(self, ssh):
+ test_base.mock_ssh(ssh)
+
+ vpe_approx_vnf = vpe_vnf.VpeApproxVnf(NAME, self.VNFD_0)
+ vpe_approx_vnf._vnf_process = mock.MagicMock()
+ vpe_approx_vnf._resource_collect_stop = mock.Mock()
+ vpe_approx_vnf.resource_helper = mock.MagicMock()
+
+ self.assertIsNone(vpe_approx_vnf.terminate())
diff --git a/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py
new file mode 100644
index 000000000..cca604f43
--- /dev/null
+++ b/yardstick/tests/unit/network_services/vnf_generic/vnf/test_vpp_helpers.py
@@ -0,0 +1,1723 @@
+# Copyright (c) 2019 Viosoft Corporation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+import ipaddress
+import unittest
+
+import mock
+
+from yardstick.common import exceptions
+from yardstick.network_services.helpers import cpu
+from yardstick.network_services.vnf_generic.vnf import vpp_helpers
+from yardstick.network_services.vnf_generic.vnf.base import VnfdHelper
+from yardstick.network_services.vnf_generic.vnf.vpp_helpers import \
+ VppSetupEnvHelper, VppConfigGenerator, VatTerminal
+
+
+class TestVppConfigGenerator(unittest.TestCase):
+
+ def test_add_config_item(self):
+ test_item = {}
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log',
+ ['unix', 'log'])
+ self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item)
+
+ def test_add_config_item_str(self):
+ test_item = {'unix': ''}
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_config_item(test_item, '/tmp/vpe.log',
+ ['unix', 'log'])
+ self.assertEqual({'unix': {'log': '/tmp/vpe.log'}}, test_item)
+
+ def test_add_unix_log(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_unix_log()
+ self.assertEqual('unix\n{\n log /tmp/vpe.log\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_unix_cli_listen(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_unix_cli_listen()
+ self.assertEqual('unix\n{\n cli-listen /run/vpp/cli.sock\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_unix_nodaemon(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_unix_nodaemon()
+ self.assertEqual('unix\n{\n nodaemon \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_unix_coredump(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_unix_coredump()
+ self.assertEqual('unix\n{\n full-coredump \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_dev(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_dev('0000:00:00.0')
+ self.assertEqual('dpdk\n{\n dev 0000:00:00.0 \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_cryptodev(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_cryptodev(2, '0000:00:00.0')
+ self.assertEqual(
+ 'dpdk\n{\n dev 0000:00:01.0 \n dev 0000:00:01.1 \n uio-driver igb_uio\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_sw_cryptodev(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_sw_cryptodev('aesni_gcm', 0, 2)
+ self.assertEqual(
+ 'dpdk\n{\n vdev cryptodev_aesni_gcm_pmd,socket_id=0 \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_dev_default_rxq(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_dev_default_rxq(1)
+ self.assertEqual(
+ 'dpdk\n{\n dev default\n {\n num-rx-queues 1\n }\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_dev_default_rxd(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_dev_default_rxd(2048)
+ self.assertEqual(
+ 'dpdk\n{\n dev default\n {\n num-rx-desc 2048\n }\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_dev_default_txd(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_dev_default_txd(2048)
+ self.assertEqual(
+ 'dpdk\n{\n dev default\n {\n num-tx-desc 2048\n }\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_log_level(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_log_level('debug')
+ self.assertEqual('dpdk\n{\n log-level debug\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_socketmem(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_socketmem('1024,1024')
+ self.assertEqual('dpdk\n{\n socket-mem 1024,1024\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_num_mbufs(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_num_mbufs(32768)
+ self.assertEqual('dpdk\n{\n num-mbufs 32768\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_uio_driver(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_uio_driver('igb_uio')
+ self.assertEqual('dpdk\n{\n uio-driver igb_uio\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_cpu_main_core(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_cpu_main_core('1,2')
+ self.assertEqual('cpu\n{\n main-core 1,2\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_cpu_corelist_workers(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_cpu_corelist_workers('1,2')
+ self.assertEqual('cpu\n{\n corelist-workers 1,2\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_heapsize(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_heapsize('4G')
+ self.assertEqual('heapsize 4G\n', vpp_config_generator.dump_config())
+
+ def test_add_ip6_hash_buckets(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_ip6_hash_buckets(2000000)
+ self.assertEqual('ip6\n{\n hash-buckets 2000000\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_ip6_heap_size(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_ip6_heap_size('4G')
+ self.assertEqual('ip6\n{\n heap-size 4G\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_ip_heap_size(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_ip_heap_size('4G')
+ self.assertEqual('ip\n{\n heap-size 4G\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_statseg_size(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_statseg_size('4G')
+ self.assertEqual('statseg\n{\n size 4G\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_plugin(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_plugin('enable', ['dpdk_plugin.so'])
+ self.assertEqual(
+ 'plugins\n{\n plugin [\'dpdk_plugin.so\']\n {\n enable \n }\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_no_multi_seg(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_no_multi_seg()
+ self.assertEqual('dpdk\n{\n no-multi-seg \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_add_dpdk_no_tx_checksum_offload(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_dpdk_no_tx_checksum_offload()
+ self.assertEqual('dpdk\n{\n no-tx-checksum-offload \n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_dump_config(self):
+ vpp_config_generator = VppConfigGenerator()
+ vpp_config_generator.add_unix_log()
+ self.assertEqual('unix\n{\n log /tmp/vpe.log\n}\n',
+ vpp_config_generator.dump_config())
+
+ def test_pci_dev_check(self):
+ self.assertTrue(VppConfigGenerator.pci_dev_check('0000:00:00.0'))
+
+ def test_pci_dev_check_error(self):
+ with self.assertRaises(ValueError) as raised:
+ VppConfigGenerator.pci_dev_check('0000:00:0.0')
+ self.assertIn(
+ 'PCI address 0000:00:0.0 is not in valid format xxxx:xx:xx.x',
+ str(raised.exception))
+
+
+class TestVppSetupEnvHelper(unittest.TestCase):
+ VNFD_0 = {
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "VPP IPsec",
+ "id": "VipsecApproxVnf",
+ "mgmt-interface": {
+ "ip": "10.10.10.101",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "ipsecvnf-baremetal"
+ },
+ "name": "IpsecVnf",
+ "short-name": "IpsecVnf",
+ "vdu": [
+ {
+ "description": "VPP Ipsec",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:ff:07.0"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "ipsecvnf-baremetal",
+ "name": "ipsecvnf-baremetal",
+ "routing_table": []
+ }
+ ]
+ }
+
+ VNFD_1 = {
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "VPP IPsec",
+ "id": "VipsecApproxVnf",
+ "mgmt-interface": {
+ "ip": "10.10.10.101",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "ipsecvnf-baremetal"
+ },
+ "name": "IpsecVnf",
+ "short-name": "IpsecVnf",
+ "vdu": [
+ {
+ "description": "VPP Ipsec",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:ff:07.0"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "ipsecvnf-baremetal",
+ "name": "ipsecvnf-baremetal",
+ "routing_table": []
+ }
+ ]
+ }
+
+ VNFD_2 = {
+ "benchmark": {
+ "kpi": [
+ "packets_in",
+ "packets_fwd",
+ "packets_dropped"
+ ]
+ },
+ "connection-point": [
+ {
+ "name": "xe0",
+ "type": "VPORT"
+ },
+ {
+ "name": "xe1",
+ "type": "VPORT"
+ }
+ ],
+ "description": "VPP IPsec",
+ "id": "VipsecApproxVnf",
+ "mgmt-interface": {
+ "ip": "10.10.10.101",
+ "password": "r00t",
+ "user": "root",
+ "vdu-id": "ipsecvnf-baremetal"
+ },
+ "name": "IpsecVnf",
+ "short-name": "IpsecVnf",
+ "vdu": [
+ {
+ "description": "VPP Ipsec",
+ "external-interface": [
+ {
+ "name": "xe0",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.1",
+ "dst_mac": "90:e2:ba:7c:30:e8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.2",
+ "local_mac": "90:e2:ba:7c:41:a8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe0",
+ "peer_intf": {
+ "dpdk_port_num": 0,
+ "driver": "igb_uio",
+ "dst_ip": "192.168.100.2",
+ "dst_mac": "90:e2:ba:7c:41:a8",
+ "ifname": "xe0",
+ "local_ip": "192.168.100.1",
+ "local_mac": "90:e2:ba:7c:30:e8",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "tg__0",
+ "peer_ifname": "xe0",
+ "peer_name": "vnf__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:81:00.0"
+ },
+ "peer_name": "tg__0",
+ "vld_id": "uplink_0",
+ "vpci": "0000:ff:06.0"
+ },
+ "vnfd-connection-point-ref": "xe0"
+ },
+ {
+ "name": "xe1",
+ "virtual-interface": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.2",
+ "dst_mac": "0a:b1:ec:fd:a2:66",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.1",
+ "local_mac": "4e:90:85:d3:c5:13",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__0",
+ "peer_ifname": "xe1",
+ "peer_intf": {
+ "driver": "igb_uio",
+ "dst_ip": "1.1.1.1",
+ "dst_mac": "4e:90:85:d3:c5:13",
+ "ifname": "xe1",
+ "local_ip": "1.1.1.2",
+ "local_mac": "0a:b1:ec:fd:a2:66",
+ "netmask": "255.255.255.0",
+ "network": {},
+ "node_name": "vnf__1",
+ "peer_ifname": "xe1",
+ "peer_name": "vnf__0",
+ "vld_id": "ciphertext",
+ "vpci": "0000:00:07.0"
+ },
+ "peer_name": "vnf__1",
+ "vld_id": "ciphertext",
+ "vpci": "0000:ff:07.0"
+ },
+ "vnfd-connection-point-ref": "xe1"
+ }
+ ],
+ "id": "ipsecvnf-baremetal",
+ "name": "ipsecvnf-baremetal",
+ "routing_table": []
+ }
+ ]
+ }
+
+ VNFD = {
+ 'vnfd:vnfd-catalog': {
+ 'vnfd': [
+ VNFD_0,
+ ],
+ },
+ }
+
+ VPP_INTERFACES_DUMP = [
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0,
+ "l2_address_length": 0,
+ "l2_address": [0, 0, 0, 0, 0, 0, 0, 0],
+ "interface_name": "local0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 0,
+ "link_speed": 0,
+ "mtu": 0,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length": 6,
+ "l2_address": [144, 226, 186, 124, 65, 168, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 2,
+ "sup_sw_if_index": 2,
+ "l2_address_length": 6,
+ "l2_address": [78, 144, 133, 211, 197, 19, 0, 0],
+ "interface_name": "VirtualFunctionEthernetff/7/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9206,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }
+ ]
+
+ VPP_INTERFACES_DUMP_MAC_ERR = [
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0,
+ "l2_address_length": 0,
+ "l2_address": [0, 0, 0, 0, 0, 0, 0, 0],
+ "interface_name": "local0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 0,
+ "link_speed": 0,
+ "mtu": 0,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length": 6,
+ "l2_address": [144, 226, 186, 124, 65, 169, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ },
+ {
+ "sw_if_index": 2,
+ "sup_sw_if_index": 2,
+ "l2_address_length": 6,
+ "l2_address": [78, 144, 133, 211, 197, 20, 0, 0],
+ "interface_name": "VirtualFunctionEthernetff/7/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9206,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }
+ ]
+
+ CPU_LAYOUT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 0, 1, 1, 0]]}
+ CPU_SMT = {'cpuinfo': [[0, 0, 0, 0, 0, 0, 0, 0],
+ [1, 0, 0, 0, 0, 1, 1, 0],
+ [2, 1, 0, 0, 0, 2, 2, 1],
+ [3, 1, 0, 0, 0, 3, 3, 1],
+ [4, 2, 0, 0, 0, 4, 4, 2],
+ [5, 2, 0, 0, 0, 5, 5, 2],
+ [6, 3, 0, 0, 0, 6, 6, 3],
+ [7, 3, 0, 0, 0, 7, 7, 3],
+ [8, 4, 0, 0, 0, 8, 8, 4],
+ [9, 5, 0, 1, 0, 0, 0, 0],
+ [10, 6, 0, 1, 0, 1, 1, 0],
+ [11, 6, 0, 1, 0, 2, 2, 1],
+ [12, 7, 0, 1, 0, 3, 3, 1],
+ [13, 7, 0, 1, 0, 4, 4, 2],
+ [14, 8, 0, 1, 0, 5, 5, 2],
+ [15, 8, 0, 1, 0, 6, 6, 3],
+ [16, 9, 0, 1, 0, 7, 7, 3],
+ [17, 9, 0, 1, 0, 8, 8, 4]]}
+
+ def test_kill_vnf(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, 0, 0
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.kill_vnf()
+
+ def test_kill_vnf_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 1, 0, 0
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with self.assertRaises(RuntimeError) as raised:
+ vpp_setup_env_helper.kill_vnf()
+
+ self.assertIn('Failed to stop service vpp', str(raised.exception))
+
+ def test_tear_down(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.tear_down()
+
+ def test_start_vpp_service(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, 0, 0
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.start_vpp_service()
+
+ def test_start_vpp_service_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 1, 0, 0
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with self.assertRaises(RuntimeError) as raised:
+ vpp_setup_env_helper.start_vpp_service()
+
+ self.assertIn('Failed to start service vpp', str(raised.exception))
+
+ def test__update_vnfd_helper(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ {'vpp-data': {'vpp-key': 'vpp-value'}})
+
+ self.assertEqual({'vpp-key': 'vpp-value'},
+ vpp_setup_env_helper.vnfd_helper.get('vpp-data', {}))
+
+ def test__update_vnfd_helper_with_key(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper._update_vnfd_helper({'driver': 'qat'}, 'xe0')
+
+ self.assertEqual('qat',
+ vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'driver'))
+
+ def test__update_vnfd_helper_dict_without_key(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ {'mgmt-interface': {'name': 'net'}})
+
+ self.assertEqual({'ip': '10.10.10.101',
+ 'name': 'net',
+ 'password': 'r00t',
+ 'user': 'root',
+ 'vdu-id': 'ipsecvnf-baremetal'},
+ vpp_setup_env_helper.vnfd_helper.get('mgmt-interface',
+ {}))
+
+ def test_get_value_by_interface_key(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ {'vpp-data': {'vpp-key': 'vpp-value'}}, 'xe0')
+
+ self.assertEqual({'vpp-key': 'vpp-value'},
+ vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'vpp-data'))
+
+ def test_get_value_by_interface_key_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ {'vpp-data': {'vpp-key': 'vpp-value'}}, 'xe0')
+
+ self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe2', 'vpp-err'))
+
+ def test_crypto_device_init(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.dpdk_bind_helper.load_dpdk_driver = mock.Mock()
+ vpp_setup_env_helper.dpdk_bind_helper.bind = mock.Mock()
+
+ vpp_setup_env_helper.kill_vnf = mock.Mock()
+ vpp_setup_env_helper.pci_driver_unbind = mock.Mock()
+
+ with mock.patch.object(vpp_setup_env_helper, 'get_pci_dev_driver') as \
+ mock_get_pci_dev_driver, \
+ mock.patch.object(vpp_setup_env_helper, 'set_sriov_numvfs') as \
+ mock_set_sriov_numvfs:
+ mock_get_pci_dev_driver.return_value = 'igb_uio'
+ self.assertIsNone(
+ vpp_setup_env_helper.crypto_device_init('0000:ff:06.0', 32))
+ mock_set_sriov_numvfs.assert_called()
+
+ def test_get_sriov_numvfs(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '32', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertEqual(32,
+ vpp_setup_env_helper.get_sriov_numvfs('0000:ff:06.0'))
+
+ def test_get_sriov_numvfs_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, 'err', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertEqual(0,
+ vpp_setup_env_helper.get_sriov_numvfs('0000:ff:06.0'))
+
+ def test_set_sriov_numvfs(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.set_sriov_numvfs('0000:ff:06.0')
+ self.assertEqual(ssh_helper.execute.call_count, 1)
+
+ def test_pci_driver_unbind(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.pci_driver_unbind('0000:ff:06.0')
+ self.assertEqual(ssh_helper.execute.call_count, 1)
+
+ def test_get_pci_dev_driver(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = \
+ 0, 'Slot: ff:07.0\n' \
+ 'Class: Ethernet controller\n' \
+ 'Vendor: Intel Corporation\n' \
+ 'Device: 82599 Ethernet Controller Virtual Function\n' \
+ 'SVendor: Intel Corporation\n' \
+ 'SDevice: 82599 Ethernet Controller Virtual Function\n' \
+ 'Rev: 01\n' \
+ 'Driver: igb_uio\n' \
+ 'Module: ixgbevf', ''
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertEqual('igb_uio', vpp_setup_env_helper.get_pci_dev_driver(
+ '0000:ff:06.0'))
+
+ def test_get_pci_dev_driver_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 1, 'err', ''
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with self.assertRaises(RuntimeError) as raised:
+ vpp_setup_env_helper.get_pci_dev_driver(
+ '0000:ff:06.0')
+
+ self.assertIn("'lspci -vmmks 0000:ff:06.0' failed",
+ str(raised.exception))
+
+ def test_get_pci_dev_driver_output_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = \
+ 0, 'Slot: ff:07.0\n' \
+ '\n\t' \
+ 'Vendor: Intel Corporation\n' \
+ 'Device: 82599 Ethernet Controller Virtual Function\n' \
+ 'SVendor: Intel Corporation\n' \
+ 'SDevice: 82599 Ethernet Controller Virtual Function\n' \
+ 'Rev: 01\n' \
+ 'Driver_err: igb_uio\n' \
+ 'Module: ixgbevf', ''
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertIsNone(
+ vpp_setup_env_helper.get_pci_dev_driver('0000:ff:06.0'))
+
+ def test_vpp_create_ipsec_tunnels(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ self.assertIsNone(
+ vpp_setup_env_helper.vpp_create_ipsec_tunnels('10.10.10.2',
+ '10.10.10.1', 'xe0',
+ 1, 1, mock.Mock(),
+ 'crypto_key',
+ mock.Mock(),
+ 'integ_key',
+ '20.20.20.0'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+
+ def test_vpp_create_ipsec_1000_tunnels(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ self.assertIsNone(
+ vpp_setup_env_helper.vpp_create_ipsec_tunnels('10.10.10.2',
+ '10.10.10.1', 'xe0',
+ 1000, 128000,
+ mock.Mock(),
+ 'crypto_key',
+ mock.Mock(),
+ 'integ_key',
+ '20.20.20.0'))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+
+ def test_apply_config(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertIsNone(vpp_setup_env_helper.apply_config(mock.Mock()))
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+
+ def test_apply_config_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 1, '', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with self.assertRaises(RuntimeError) as raised:
+ vpp_setup_env_helper.apply_config(mock.Mock())
+
+ self.assertIn('Writing config file failed', str(raised.exception))
+
+ def test_vpp_route_add(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertIsNone(
+ vpp_setup_env_helper.vpp_route_add('xe0', '10.10.10.1', 24))
+
+ def test_vpp_route_add_without_index(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertIsNone(
+ vpp_setup_env_helper.vpp_route_add('xe0', '10.10.10.1', 24,
+ interface='xe0',
+ use_sw_index=False))
+
+ def test_add_arp_on_dut(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertEqual('', vpp_setup_env_helper.add_arp_on_dut('xe0',
+ '10.10.10.1',
+ '00:00:00:00:00:00'))
+
+ def test_set_ip(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertEqual('',
+ vpp_setup_env_helper.set_ip('xe0', '10.10.10.1',
+ 24))
+
+ def test_set_interface_state(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertEqual('',
+ vpp_setup_env_helper.set_interface_state('xe0',
+ 'up'))
+
+ def test_set_interface_state_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ with self.assertRaises(ValueError) as raised:
+ vpp_setup_env_helper.set_interface_state('xe0', 'error')
+ self.assertIn('Unexpected interface state: error',
+ str(raised.exception))
+
+ def test_set_interface_down_state(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertEqual('',
+ vpp_setup_env_helper.set_interface_state('xe0',
+ 'down'))
+
+ def test_vpp_set_interface_mtu(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = ''
+ self.assertIsNone(
+ vpp_setup_env_helper.vpp_set_interface_mtu('xe0', 9200))
+
+ def test_vpp_interfaces_ready_wait(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ self.assertIsNone(vpp_setup_env_helper.vpp_interfaces_ready_wait())
+
+ def test_vpp_interfaces_ready_wait_timeout(self):
+ json_output = [[
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0,
+ "l2_address_length": 0,
+ "l2_address": [0, 0, 0, 0, 0, 0, 0, 0],
+ "interface_name": "xe0",
+ "admin_up_down": 1,
+ "link_up_down": 0,
+ "link_duplex": 0,
+ "link_speed": 0,
+ "mtu": 0,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }]]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ with self.assertRaises(RuntimeError) as raised:
+ vpp_setup_env_helper.vpp_interfaces_ready_wait(5)
+ self.assertIn('timeout, not up [\'xe0\']', str(raised.exception))
+
+ def test_vpp_get_interface_data(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ self.assertEqual(json_output[0],
+ vpp_setup_env_helper.vpp_get_interface_data())
+
+ def test_vpp_get_interface_data_ifname(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ self.assertEqual(json_output[0][2],
+ vpp_setup_env_helper.vpp_get_interface_data(
+ 'VirtualFunctionEthernetff/7/0'))
+
+ def test_vpp_get_interface_data_ifname_error(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ self.assertEqual({}, vpp_setup_env_helper.vpp_get_interface_data(
+ 'error'))
+
+ def test_vpp_get_interface_data_ifindex(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ self.assertEqual(json_output[0][1],
+ vpp_setup_env_helper.vpp_get_interface_data(1))
+
+ def test_vpp_get_interface_data_error(self):
+ json_output = [self.VPP_INTERFACES_DUMP]
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+
+ with mock.patch.object(vpp_helpers.VatTerminal,
+ 'vat_terminal_exec_cmd_from_template') as \
+ mock_vat_terminal_exec_cmd_from_template:
+ mock_vat_terminal_exec_cmd_from_template.return_value = json_output
+ with self.assertRaises(TypeError) as raised:
+ vpp_setup_env_helper.vpp_get_interface_data(1.0)
+ self.assertEqual('', str(raised.exception))
+
+ def test_update_vpp_interface_data(self):
+ output = '{}\n{}'.format(self.VPP_INTERFACES_DUMP,
+ 'dump_interface_table:6019: JSON output ' \
+ 'supported only for VPE API calls and dump_stats_table\n' \
+ '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \
+ 'dump_interface_table error: Misc')
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, output.replace("\'", "\""), ''
+ ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates'
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertIsNone(vpp_setup_env_helper.update_vpp_interface_data())
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 1)
+ self.assertEqual('TenGigabitEthernetff/6/0',
+ vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_name'))
+ self.assertEqual(1, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'vpp_sw_index'))
+ self.assertEqual('VirtualFunctionEthernetff/7/0',
+ vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_name'))
+ self.assertEqual(2, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe1', 'vpp_sw_index'))
+
+ def test_update_vpp_interface_data_error(self):
+ output = '{}\n{}'.format(self.VPP_INTERFACES_DUMP_MAC_ERR,
+ 'dump_interface_table:6019: JSON output ' \
+ 'supported only for VPE API calls and dump_stats_table\n' \
+ '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \
+ 'dump_interface_table error: Misc')
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, output.replace("\'", "\""), ''
+ ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates'
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertIsNone(vpp_setup_env_helper.update_vpp_interface_data())
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 1)
+
+ def test_iface_update_numa(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '0', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertIsNone(vpp_setup_env_helper.iface_update_numa())
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+ self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+
+ def test_iface_update_numa_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_1)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '-1', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout:
+ mock_get_cpu_layout.return_value = self.CPU_LAYOUT
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ self.assertIsNone(vpp_setup_env_helper.iface_update_numa())
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+ self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertEqual(0, vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+
+ def test_iface_update_without_numa(self):
+ vnfd_helper = VnfdHelper(self.VNFD_2)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, '-1', ''
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with mock.patch.object(cpu.CpuSysCores, 'get_cpu_layout') as \
+ mock_get_cpu_layout:
+ mock_get_cpu_layout.return_value = self.CPU_SMT
+ sys_cores = cpu.CpuSysCores(ssh_helper)
+ vpp_setup_env_helper._update_vnfd_helper(
+ sys_cores.get_cpu_layout())
+ self.assertIsNone(vpp_setup_env_helper.iface_update_numa())
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 2)
+ self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe0', 'numa_node'))
+ self.assertIsNone(vpp_setup_env_helper.get_value_by_interface_key(
+ 'xe1', 'numa_node'))
+
+ def test_execute_script(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ vpp_setup_env_helper.execute_script('dump_interfaces.vat', True, True)
+ self.assertGreaterEqual(ssh_helper.put_file.call_count, 1)
+ self.assertGreaterEqual(ssh_helper.execute.call_count, 1)
+
+ def test_execute_script_error(self):
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.side_effect = Exception
+
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ with self.assertRaises(Exception) as raised:
+ vpp_setup_env_helper.execute_script('dump_interfaces.vat', True,
+ True)
+ self.assertIn(
+ 'VAT script execution failed: vpp_api_test json in dump_interfaces.vat script',
+ str(raised.exception))
+ self.assertGreaterEqual(ssh_helper.put_file.call_count, 1)
+
+ def test_execute_script_json_out(self):
+ json_output = [
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0
+ },
+ {
+ "l2_address_length": 6,
+ "l2_address": [144, 226, 186, 124, 65, 168, 0, 0]
+ },
+ {
+ "interface_name": "VirtualFunctionEthernetff/7/0",
+ "admin_up_down": 0
+ }
+ ]
+ output = '{}\n{}'.format(json_output,
+ 'dump_interface_table:6019: JSON output ' \
+ 'supported only for VPE API calls and dump_stats_table\n' \
+ '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \
+ 'dump_interface_table error: Misc')
+ vnfd_helper = VnfdHelper(self.VNFD_0)
+ ssh_helper = mock.Mock()
+ ssh_helper.execute.return_value = 0, output, ''
+ ssh_helper.join_bin_path.return_value = '/opt/nsb_bin/vpp/templates'
+ scenario_helper = mock.Mock()
+ vpp_setup_env_helper = VppSetupEnvHelper(vnfd_helper, ssh_helper,
+ scenario_helper)
+ self.assertEqual(str(json_output),
+ vpp_setup_env_helper.execute_script_json_out(
+ 'dump_interfaces.vat'))
+
+ def test_self_cleanup_vat_json_output(self):
+ json_output = [
+ {
+ "sw_if_index": 0,
+ "sup_sw_if_index": 0
+ },
+ {
+ "l2_address_length": 6,
+ "l2_address": [144, 226, 186, 124, 65, 168, 0, 0]
+ },
+ {
+ "interface_name": "VirtualFunctionEthernetff/7/0",
+ "admin_up_down": 0
+ }
+ ]
+
+ output = '{}\n{}'.format(json_output,
+ 'dump_interface_table:6019: JSON output ' \
+ 'supported only for VPE API calls and dump_stats_table\n' \
+ '/opt/nsb_bin/vpp/templates/dump_interfaces.vat(2): \n' \
+ 'dump_interface_table error: Misc')
+ self.assertEqual(str(json_output),
+ VppSetupEnvHelper.cleanup_vat_json_output(output,
+ '/opt/nsb_bin/vpp/templates/dump_interfaces.vat'))
+
+ def test__convert_mac_to_number_list(self):
+ self.assertEqual([144, 226, 186, 124, 65, 168],
+ VppSetupEnvHelper._convert_mac_to_number_list(
+ '90:e2:ba:7c:41:a8'))
+
+ def test_get_vpp_interface_by_mac(self):
+ mac_address = '90:e2:ba:7c:41:a8'
+ self.assertEqual({'admin_up_down': 0,
+ 'interface_name': 'TenGigabitEthernetff/6/0',
+ 'l2_address': [144, 226, 186, 124, 65, 168, 0, 0],
+ 'l2_address_length': 6,
+ 'link_duplex': 2,
+ 'link_speed': 32,
+ 'link_up_down': 0,
+ 'mtu': 9202,
+ 'sub_default': 0,
+ 'sub_dot1ad': 0,
+ 'sub_exact_match': 0,
+ 'sub_id': 0,
+ 'sub_inner_vlan_id': 0,
+ 'sub_inner_vlan_id_any': 0,
+ 'sub_number_of_tags': 0,
+ 'sub_outer_vlan_id': 0,
+ 'sub_outer_vlan_id_any': 0,
+ 'sup_sw_if_index': 1,
+ 'sw_if_index': 1,
+ 'vtr_op': 0,
+ 'vtr_push_dot1q': 0,
+ 'vtr_tag1': 0,
+ 'vtr_tag2': 0},
+ VppSetupEnvHelper.get_vpp_interface_by_mac(
+ self.VPP_INTERFACES_DUMP, mac_address))
+
+ def test_get_vpp_interface_by_mac_error(self):
+ mac_address = '90:e2:ba:7c:41:a9'
+ with self.assertRaises(ValueError) as raised:
+ VppSetupEnvHelper.get_vpp_interface_by_mac(
+ [{
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length": 7,
+ "l2_address": [144, 226, 186, 124, 65, 169, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }], mac_address)
+
+ self.assertIn('l2_address_length value is not 6.',
+ str(raised.exception))
+
+ def test_get_vpp_interface_by_mac_l2_error(self):
+ mac_address = '90:e2:ba:7c:41:a7'
+ with self.assertRaises(KeyError) as raised:
+ VppSetupEnvHelper.get_vpp_interface_by_mac(
+ [{
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length": 6,
+ "l2_address_err": [144, 226, 186, 124, 65, 167, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }], mac_address)
+
+ self.assertIn(
+ 'key l2_address not found in interface dict.Probably input list ' \
+ 'is not parsed from correct VAT json output.',
+ str(raised.exception))
+
+ def test_get_vpp_interface_by_mac_l2_length_error(self):
+ mac_address = '90:e2:ba:7c:41:a6'
+ with self.assertRaises(KeyError) as raised:
+ VppSetupEnvHelper.get_vpp_interface_by_mac(
+ [{
+ "sw_if_index": 1,
+ "sup_sw_if_index": 1,
+ "l2_address_length_err": 6,
+ "l2_address": [144, 226, 186, 124, 65, 166, 0, 0],
+ "interface_name": "TenGigabitEthernetff/6/0",
+ "admin_up_down": 0,
+ "link_up_down": 0,
+ "link_duplex": 2,
+ "link_speed": 32,
+ "mtu": 9202,
+ "sub_id": 0,
+ "sub_dot1ad": 0,
+ "sub_number_of_tags": 0,
+ "sub_outer_vlan_id": 0,
+ "sub_inner_vlan_id": 0,
+ "sub_exact_match": 0,
+ "sub_default": 0,
+ "sub_outer_vlan_id_any": 0,
+ "sub_inner_vlan_id_any": 0,
+ "vtr_op": 0,
+ "vtr_push_dot1q": 0,
+ "vtr_tag1": 0,
+ "vtr_tag2": 0
+ }], mac_address)
+
+ self.assertIn(
+ 'key l2_address_length not found in interface dict. Probably ' \
+ 'input list is not parsed from correct VAT json output.',
+ str(raised.exception))
+
+ def test_get_prefix_length(self):
+ start_ip = '10.10.10.0'
+ end_ip = '10.10.10.127'
+ ips = [ipaddress.ip_address(ip) for ip in
+ [str(ipaddress.ip_address(start_ip)), str(end_ip)]]
+ lowest_ip, highest_ip = min(ips), max(ips)
+
+ self.assertEqual(25,
+ VppSetupEnvHelper.get_prefix_length(int(lowest_ip),
+ int(highest_ip),
+ lowest_ip.max_prefixlen))
+
+ def test_get_prefix_length_zero_prefix(self):
+ start_ip = '10.0.0.0'
+ end_ip = '10.0.0.0'
+ ips = [ipaddress.ip_address(ip) for ip in
+ [str(ipaddress.ip_address(start_ip)), str(end_ip)]]
+ lowest_ip, highest_ip = min(ips), max(ips)
+
+ self.assertEqual(0,
+ VppSetupEnvHelper.get_prefix_length(int(lowest_ip),
+ int(highest_ip),
+ 0))
+
+
+class TestVatTerminal(unittest.TestCase):
+
+ def test___init___error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_open.side_effect = exceptions.SSHTimeout
+
+ with self.assertRaises(RuntimeError) as raised:
+ VatTerminal(ssh_helper, json_param=True)
+ self.assertIn('Cannot open interactive terminal',
+ str(raised.exception))
+
+ def test___init___exec_error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout
+ VatTerminal(ssh_helper, json_param=True)
+
+ def test_vat_terminal_exec_cmd(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.return_value = str(
+ {'empty': 'value'}).replace("\'", "\"")
+ vat_terminal = VatTerminal(ssh_helper, json_param=True)
+
+ self.assertEqual({'empty': 'value'},
+ vat_terminal.vat_terminal_exec_cmd(
+ "hw_interface_set_mtu sw_if_index 1 mtu 9200"))
+
+ def test_vat_terminal_exec_cmd_array(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.return_value = str(
+ [{'empty': 'value'}]).replace("\'", "\"")
+ vat_terminal = VatTerminal(ssh_helper, json_param=True)
+
+ self.assertEqual([{'empty': 'value'}],
+ vat_terminal.vat_terminal_exec_cmd(
+ "hw_interface_set_mtu sw_if_index 1 mtu 9200"))
+
+ def test_vat_terminal_exec_cmd_without_output(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.return_value = str(
+ {'empty': 'value'}).replace("\'", "\"")
+ vat_terminal = VatTerminal(ssh_helper, json_param=False)
+
+ self.assertIsNone(vat_terminal.vat_terminal_exec_cmd(
+ "hw_interface_set_mtu sw_if_index 1 mtu 9200"))
+
+ def test_vat_terminal_exec_cmd_error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.return_value = str(
+ {'empty': 'value'}).replace("\'", "\"")
+ ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout
+
+ vat_terminal = VatTerminal(ssh_helper, json_param=True)
+
+ with self.assertRaises(RuntimeError) as raised:
+ vat_terminal.vat_terminal_exec_cmd(
+ "hw_interface_set_mtu sw_if_index 1 mtu 9200")
+ self.assertIn(
+ 'VPP is not running on node. VAT command hw_interface_set_mtu ' \
+ 'sw_if_index 1 mtu 9200 execution failed',
+ str(raised.exception))
+
+ def test_vat_terminal_exec_cmd_output_error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.return_value = str(
+ 'empty: value').replace("\'", "\"")
+
+ vat_terminal = VatTerminal(ssh_helper, json_param=True)
+
+ with self.assertRaises(RuntimeError) as raised:
+ vat_terminal.vat_terminal_exec_cmd(
+ "hw_interface_set_mtu sw_if_index 1 mtu 9200")
+ self.assertIn(
+ 'VAT command hw_interface_set_mtu sw_if_index 1 mtu 9200: no JSON data.',
+ str(raised.exception))
+
+ def test_vat_terminal_close(self):
+ ssh_helper = mock.Mock()
+ vat_terminal = VatTerminal(ssh_helper, json_param=False)
+ self.assertIsNone(vat_terminal.vat_terminal_close())
+
+ def test_vat_terminal_close_error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_exec_command.side_effect = exceptions.SSHTimeout
+ vat_terminal = VatTerminal(ssh_helper, json_param=False)
+ with self.assertRaises(RuntimeError) as raised:
+ vat_terminal.vat_terminal_close()
+ self.assertIn('Failed to close VAT console', str(raised.exception))
+
+ def test_vat_terminal_close_vat_error(self):
+ ssh_helper = mock.Mock()
+ ssh_helper.interactive_terminal_close.side_effect = exceptions.SSHTimeout
+ vat_terminal = VatTerminal(ssh_helper, json_param=False)
+ with self.assertRaises(RuntimeError) as raised:
+ vat_terminal.vat_terminal_close()
+ self.assertIn('Cannot close interactive terminal',
+ str(raised.exception))
+
+ def test_vat_terminal_exec_cmd_from_template(self):
+ ssh_helper = mock.Mock()
+ vat_terminal = VatTerminal(ssh_helper, json_param=False)
+
+ with mock.patch.object(vat_terminal, 'vat_terminal_exec_cmd') as \
+ mock_vat_terminal_exec_cmd:
+ mock_vat_terminal_exec_cmd.return_value = 'empty'
+ self.assertEqual(['empty'],
+ vat_terminal.vat_terminal_exec_cmd_from_template(
+ "hw_interface_set_mtu.vat", sw_if_index=1,
+ mtu=9200))
diff --git a/yardstick/tests/unit/orchestrator/__init__.py b/yardstick/tests/unit/orchestrator/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/orchestrator/__init__.py
diff --git a/yardstick/tests/unit/orchestrator/test_heat.py b/yardstick/tests/unit/orchestrator/test_heat.py
new file mode 100644
index 000000000..2e60a72cb
--- /dev/null
+++ b/yardstick/tests/unit/orchestrator/test_heat.py
@@ -0,0 +1,417 @@
+##############################################################################
+# Copyright (c) 2017 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 tempfile
+
+import munch
+import mock
+from oslo_serialization import jsonutils
+from oslo_utils import uuidutils
+import shade
+import unittest
+
+from yardstick.benchmark.contexts import node
+from yardstick.common import constants
+from yardstick.common import exceptions
+from yardstick.orchestrator import heat
+
+
+class FakeStack(object):
+
+ def __init__(self, outputs=None, status=None, id=None):
+ self.outputs = outputs
+ self.status = status
+ self.id = id
+
+
+class HeatStackTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self.stack_name = 'STACK NAME'
+ with mock.patch.object(shade, 'openstack_cloud'):
+ self.heatstack = heat.HeatStack(self.stack_name)
+ self._mock_stack_create = mock.patch.object(self.heatstack._cloud,
+ 'create_stack')
+ self.mock_stack_create = self._mock_stack_create.start()
+ self._mock_stack_delete = mock.patch.object(self.heatstack._cloud,
+ 'delete_stack')
+ self.mock_stack_delete = self._mock_stack_delete.start()
+ self._mock_stack_get = mock.patch.object(self.heatstack._cloud,
+ 'get_stack')
+ self.mock_stack_get = self._mock_stack_get.start()
+
+ self.addCleanup(self._cleanup)
+
+ def _cleanup(self):
+ self._mock_stack_create.stop()
+ self._mock_stack_delete.stop()
+ self._mock_stack_get.stop()
+ heat._DEPLOYED_STACKS = {}
+
+ @mock.patch.object(shade, 'openstack_cloud')
+ def test__init(self, mock_openstack_cloud):
+ os_cloud_config = {'key': 'value'}
+ heatstack = heat.HeatStack('name', os_cloud_config=os_cloud_config)
+ self.assertEqual('name', heatstack.name)
+ os_cloud_config.update(constants.OS_CLOUD_DEFAULT_CONFIG)
+ mock_openstack_cloud.assert_called_once_with(**os_cloud_config)
+
+ def test_create(self):
+ template = {'tkey': 'tval'}
+ heat_parameters = {'pkey': 'pval'}
+ outputs = [{'output_key': 'okey', 'output_value': 'oval'}]
+ id = uuidutils.generate_uuid()
+ self.mock_stack_create.return_value = FakeStack(
+ outputs=outputs, status=mock.Mock(), id=id)
+ mock_tfile = mock.Mock()
+ with mock.patch.object(tempfile._TemporaryFileWrapper, '__enter__',
+ return_value=mock_tfile):
+ self.heatstack.create(template, heat_parameters, True, 100)
+ mock_tfile.write.assert_called_once_with(jsonutils.dump_as_bytes(template))
+ mock_tfile.close.assert_called_once()
+
+ self.mock_stack_create.assert_called_once_with(
+ self.stack_name, template_file=mock_tfile.name, wait=True,
+ timeout=100, pkey='pval')
+ self.assertEqual({'okey': 'oval'}, self.heatstack.outputs)
+ self.assertEqual(heat._DEPLOYED_STACKS[id], self.heatstack._stack)
+
+ def test_stacks_exist(self):
+ self.assertEqual(0, self.heatstack.stacks_exist())
+ heat._DEPLOYED_STACKS['id'] = 'stack'
+ self.assertEqual(1, self.heatstack.stacks_exist())
+
+ def test_delete_not_uuid(self):
+ self.assertIsNone(self.heatstack.delete())
+
+ def test_delete_existing_uuid(self):
+ id = uuidutils.generate_uuid()
+ self.heatstack._stack = FakeStack(
+ outputs=mock.Mock(), status=mock.Mock(), id=id)
+ heat._DEPLOYED_STACKS[id] = self.heatstack._stack
+ delete_return = mock.Mock()
+ self.mock_stack_delete.return_value = delete_return
+
+ ret = self.heatstack.delete(wait=True)
+ self.assertEqual(delete_return, ret)
+ self.assertFalse(heat._DEPLOYED_STACKS)
+ self.mock_stack_delete.assert_called_once_with(id, wait=True)
+
+ def test_delete_bug_in_shade(self):
+ id = uuidutils.generate_uuid()
+ self.heatstack._stack = FakeStack(
+ outputs=mock.Mock(), status=mock.Mock(), id=id)
+ heat._DEPLOYED_STACKS[id] = self.heatstack._stack
+ self.mock_stack_delete.side_effect = TypeError()
+
+ ret = self.heatstack.delete(wait=True)
+ self.assertTrue(ret)
+ self.assertFalse(heat._DEPLOYED_STACKS)
+ self.mock_stack_delete.assert_called_once_with(id, wait=True)
+
+ def test_get(self):
+ # make sure shade/get_stack is called with the appropriate vars
+ self.mock_stack_get.return_value = munch.Munch(
+ id="my-existing-stack-id",
+ outputs=[
+ {
+ u'output_value': u'b734d06a-dec7-...',
+ u'output_key': u'ares.demo-test-port-network_id',
+ u'description': u''
+ },
+ {u'output_value': u'b08da78c-2218-...',
+ u'output_key': u'ares.demo-test-port-subnet_id',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.0/24',
+ u'output_key': u'demo-test-subnet-cidr',
+ u'description': u''
+ },
+ {u'output_value': u'b08da78c-2218-...',
+ u'output_key': u'demo-test-subnet',
+ u'description': u''
+ },
+ {u'output_value': u'b1a03624-aefc-...',
+ u'output_key': u'ares.demo',
+ u'description': u''
+ },
+ {u'output_value': u'266a8088-c630-...',
+ u'output_key': u'demo-secgroup',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.5',
+ u'output_key': u'ares.demo-test-port',
+ u'description': u''
+ },
+ {u'output_value': u'10.0.1.1',
+ u'output_key': u'demo-test-subnet-gateway_ip',
+ u'description': u''
+ },
+ {u'output_value': u'',
+ u'output_key': u'ares.demo-test-port-device_id',
+ u'description': u''
+ },
+ {u'output_value': u'172.24.4.7',
+ u'output_key': u'ares.demo-fip',
+ u'description': u''
+ },
+ {u'output_value': u'fa:16:3e:6c:c3:0f',
+ u'output_key': u'ares.demo-test-port-mac_address',
+ u'description': u''}
+ ]
+ )
+ expected_outputs = {
+ 'ares.demo-test-port-network_id': 'b734d06a-dec7-...',
+ 'ares.demo-test-port-subnet_id': 'b08da78c-2218-...',
+ 'demo-test-subnet-cidr': '10.0.1.0/24',
+ 'demo-test-subnet': 'b08da78c-2218-...',
+ 'ares.demo': 'b1a03624-aefc-...',
+ 'demo-secgroup': '266a8088-c630-...',
+ 'ares.demo-test-port': '10.0.1.5',
+ 'demo-test-subnet-gateway_ip': '10.0.1.1',
+ 'ares.demo-test-port-device_id': '',
+ 'ares.demo-fip': '172.24.4.7',
+ 'ares.demo-test-port-mac_address': 'fa:16:3e:6c:c3:0f',
+ }
+
+ stack_id = "my-existing-stack-id"
+ self.heatstack.name = "my-existing-stack"
+ self.heatstack.get()
+
+ self.mock_stack_get.assert_called_once_with(self.heatstack.name)
+ self.assertEqual(expected_outputs, self.heatstack.outputs)
+ self.assertEqual(1, len(heat._DEPLOYED_STACKS))
+ self.assertEqual(self.heatstack._stack,
+ heat._DEPLOYED_STACKS[stack_id])
+
+ def test_get_invalid_name(self):
+ # No context matching this name exists
+ self.mock_stack_get.return_value = []
+ self.heatstack.name = 'not-a-stack'
+ self.heatstack.get()
+ self.assertEqual(0, len(heat._DEPLOYED_STACKS))
+
+
+class HeatTemplateTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._os_cloud_config = {'key1': 'value1'}
+ self.template = heat.HeatTemplate(
+ 'test', os_cloud_config=self._os_cloud_config)
+
+ def test_add_tenant_network(self):
+ self.template.add_network('some-network')
+
+ self.assertEqual('OS::Neutron::Net',
+ self.template.resources['some-network']['type'])
+
+ def test_add_provider_network(self):
+ self.template.add_network('some-network', 'physnet2', 'sriov')
+
+ self.assertEqual(self.template.resources['some-network']['type'],
+ 'OS::Neutron::ProviderNet')
+ self.assertEqual(self.template.resources['some-network'][
+ 'properties']['physical_network'], 'physnet2')
+
+ def test_add_subnet(self):
+ netattrs = {'cidr': '10.0.0.0/24',
+ 'provider': None,
+ 'external_network': 'ext_net'}
+ self.template.add_subnet('some-subnet', "some-network",
+ netattrs['cidr'])
+
+ self.assertEqual(self.template.resources['some-subnet']['type'],
+ 'OS::Neutron::Subnet')
+ self.assertEqual(self.template.resources['some-subnet']['properties'][
+ 'cidr'], '10.0.0.0/24')
+
+ def test_add_router(self):
+ self.template.add_router('some-router', 'ext-net', 'some-subnet')
+
+ self.assertEqual(self.template.resources['some-router']['type'],
+ 'OS::Neutron::Router')
+ self.assertIn('some-subnet',
+ self.template.resources['some-router']['depends_on'])
+
+ def test_add_router_interface(self):
+ self.template.add_router_interface('some-router-if', 'some-router',
+ 'some-subnet')
+
+ self.assertEqual(self.template.resources['some-router-if']['type'],
+ 'OS::Neutron::RouterInterface')
+ self.assertIn('some-subnet',
+ self.template.resources['some-router-if']['depends_on'])
+
+ def test_add_servergroup(self):
+ self.template.add_servergroup('some-server-group', 'anti-affinity')
+
+ self.assertEqual(self.template.resources['some-server-group']['type'],
+ 'OS::Nova::ServerGroup')
+ self.assertEqual(self.template.resources['some-server-group'][
+ 'properties']['policies'], ['anti-affinity'])
+
+ def test_add_security_group(self):
+ security_group = {
+ 'rules': [
+ {'remote_ip_prefix': '0.0.0.0/0',
+ 'port_range_max': 65535,
+ 'port_range_min': 1,
+ 'protocol': 'custom'},
+ ]
+ }
+ self.template.add_security_group('some-security-group', security_group)
+
+ secgroup_rsc = self.template.resources['some-security-group']
+
+ self.assertEqual(secgroup_rsc['type'], "OS::Neutron::SecurityGroup")
+ self.assertEqual(secgroup_rsc['properties']['description'],
+ "Custom security group rules defined by the user")
+ self.assertEqual(secgroup_rsc['properties']['rules'][0]['protocol'],
+ 'custom')
+
+ def test__add_resources_to_template_raw(self):
+ test_context = node.NodeContext()
+ self.addCleanup(test_context._delete_context)
+ test_context._name = 'foo'
+ test_context.template_file = '/tmp/some-heat-file'
+ test_context.heat_parameters = {'image': 'cirros'}
+ test_context.key_filename = "/tmp/1234"
+ test_context.keypair_name = "foo-key"
+ test_context.secgroup_name = "foo-secgroup"
+ test_context.key_uuid = "2f2e4997-0a8e-4eb7-9fa4-f3f8fbbc393b"
+
+ test_context.tmpfile = tempfile.NamedTemporaryFile(
+ delete=True, mode='w+t')
+ test_context.tmpfile.write("heat_template_version: 2015-04-30")
+ test_context.tmpfile.flush()
+ test_context.tmpfile.seek(0)
+ heat_template = heat.HeatTemplate('template name')
+ heat_template.resources = {}
+
+ heat_template.add_network("network1")
+ heat_template.add_network("network2")
+ heat_template.add_security_group("sec_group1")
+ heat_template.add_security_group("sec_group2")
+ heat_template.add_subnet("subnet1", "network1", "cidr1")
+ heat_template.add_subnet("subnet2", "network2", "cidr2")
+ heat_template.add_router("router1", "gw1", "subnet1")
+ heat_template.add_router_interface("router_if1", "router1", "subnet1")
+ network1 = mock.MagicMock()
+ network1.stack_name = "network1"
+ network1.subnet_stack_name = "subnet1"
+ network1.vnic_type = "normal"
+ network2 = mock.MagicMock()
+ network2.stack_name = "network2"
+ network2.subnet_stack_name = "subnet2"
+ network2.vnic_type = "normal"
+ heat_template.add_port("port1", network1)
+ heat_template.add_port("port2", network2,
+ sec_group_id="sec_group1", provider="not-sriov")
+ heat_template.add_port("port3", network2,
+ sec_group_id="sec_group1", provider="sriov")
+ heat_template.add_floating_ip("floating_ip1", "network1", "port1",
+ "router_if1")
+ heat_template.add_floating_ip("floating_ip2", "network2", "port2",
+ "router_if2", "foo-secgroup")
+ heat_template.add_floating_ip_association("floating_ip1_association",
+ "floating_ip1", "port1")
+ heat_template.add_servergroup("server_grp2", "affinity")
+ heat_template.add_servergroup("server_grp3", "anti-affinity")
+ heat_template.add_security_group("security_group")
+ heat_template.add_server(name="server1", image="image1",
+ flavor="flavor1", flavors=[])
+ heat_template.add_server_group(name="servergroup",
+ policies=["policy1", "policy2"])
+ heat_template.add_server_group(name="servergroup",
+ policies="policy1")
+ heat_template.add_server(
+ name="server2", image="image1", flavor="flavor1", flavors=[],
+ ports=["port1", "port2"], networks=["network1", "network2"],
+ scheduler_hints="hints1", user="user1", key_name="foo-key",
+ user_data="user", metadata={"cat": 1, "doc": 2},
+ additional_properties={"prop1": 1, "prop2": 2})
+ heat_template.add_server(
+ name="server2", image="image1", flavor="flavor1",
+ flavors=["flavor1", "flavor2"], ports=["port1", "port2"],
+ networks=["network1", "network2"], scheduler_hints="hints1",
+ user="user1", key_name="foo-key", user_data="user",
+ metadata={"cat": 1, "doc": 2},
+ additional_properties={"prop1": 1, "prop2": 2})
+ heat_template.add_server(
+ name="server2", image="image1", flavor="flavor1",
+ flavors=["flavor3", "flavor4"], ports=["port1", "port2"],
+ networks=["network1", "network2"], scheduler_hints="hints1",
+ user="user1", key_name="foo-key", user_data="user",
+ metadata={"cat": 1, "doc": 2},
+ additional_properties={"prop1": 1, "prop2": 2})
+ heat_template.add_flavor(name="flavor1", vcpus=1, ram=2048, disk=1,
+ extra_specs={"cat": 1, "dog": 2})
+ heat_template.add_flavor(name=None, vcpus=1, ram=2048)
+ heat_template.add_server(
+ name="server1", image="image1", flavor="flavor1", flavors=[],
+ ports=["port1", "port2"], networks=["network1", "network2"],
+ scheduler_hints="hints1", user="user1", key_name="foo-key",
+ user_data="user", metadata={"cat": 1, "doc": 2},
+ additional_properties={"prop1": 1, "prop2": 2})
+ heat_template.add_network("network1")
+
+ heat_template.add_flavor("test")
+ self.assertEqual(heat_template.resources['test']['type'],
+ 'OS::Nova::Flavor')
+
+ def test_create_not_block(self):
+ heat_stack = mock.Mock()
+ with mock.patch.object(heat, 'HeatStack', return_value=heat_stack) \
+ as mock_heatstack:
+ ret = self.template.create(block=False)
+
+ mock_heatstack.assert_called_once_with(
+ self.template.name, os_cloud_config=self.template._os_cloud_config)
+ heat_stack.create.assert_called_once_with(
+ self.template._template, self.template.heat_parameters, False,
+ 3600)
+ self.assertEqual(heat_stack, ret)
+
+ def test_create_block(self):
+ heat_stack = mock.Mock()
+ heat_stack.status = self.template.HEAT_STATUS_COMPLETE
+ with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
+ ret = self.template.create(block=False)
+ heat_stack.create.assert_called_once_with(
+ self.template._template, self.template.heat_parameters, False,
+ 3600)
+ self.assertEqual(heat_stack, ret)
+
+ def test_create_block_status_no_complete(self):
+ heat_stack = mock.Mock()
+ heat_stack.status = 'other status'
+ heat_stack.get_failures.return_value = []
+ with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
+ self.assertRaises(exceptions.HeatTemplateError,
+ self.template.create, block=True)
+ heat_stack.create.assert_called_once_with(
+ self.template._template, self.template.heat_parameters, True,
+ 3600)
+
+ def test_create_block_status_no_complete_with_reasons(self):
+ heat_stack = mock.Mock()
+ heat_stack.status = 'other status'
+ heat_stack.get_failures.return_value = [
+ mock.Mock(resource_status_reason="A reason"),
+ mock.Mock(resource_status_reason="Something else")
+ ]
+ with mock.patch.object(heat, 'HeatStack', return_value=heat_stack):
+ with mock.patch.object(heat, 'log') as mock_log:
+ self.assertRaises(exceptions.HeatTemplateError,
+ self.template.create, block=True)
+ mock_log.error.assert_any_call("%s", "A reason")
+ mock_log.error.assert_any_call("%s", "Something else")
+ heat_stack.create.assert_called_once_with(
+ self.template._template, self.template.heat_parameters, True,
+ 3600)
diff --git a/yardstick/tests/unit/orchestrator/test_kubernetes.py b/yardstick/tests/unit/orchestrator/test_kubernetes.py
new file mode 100644
index 000000000..2d5c4a26f
--- /dev/null
+++ b/yardstick/tests/unit/orchestrator/test_kubernetes.py
@@ -0,0 +1,643 @@
+##############################################################################
+# Copyright (c) 2017 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 copy
+
+import mock
+
+from yardstick.common import exceptions
+from yardstick.common import kubernetes_utils
+from yardstick.orchestrator import kubernetes
+from yardstick.tests.unit import base
+
+
+class GetTemplateTestCase(base.BaseUnitTestCase):
+
+ def test_get_template(self):
+ output_t = {
+ "apiVersion": "v1",
+ "kind": "ReplicationController",
+ "metadata": {
+ "name": "host-k8s-86096c30"
+ },
+ "spec": {
+ "replicas": 1,
+ "template": {
+ "metadata": {
+ "labels": {
+ "app": "host-k8s-86096c30"
+ }
+ },
+ "spec": {
+ "containers": [
+ {
+ "args": [
+ "-c",
+ "chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
+service ssh restart;while true ; do sleep 10000; done"
+ ],
+ "command": [
+ "/bin/bash"
+ ],
+ "image": "openretriever/yardstick",
+ "name": "host-k8s-86096c30-container",
+ "volumeMounts": [
+ {
+ "mountPath": "/tmp/.ssh/",
+ "name": "k8s-86096c30-key",
+ "readOnly": False
+ }
+ ]
+ }
+ ],
+ "volumes": [
+ {
+ "configMap": {
+ "name": "k8s-86096c30-key"
+ },
+ "name": "k8s-86096c30-key"
+ }
+ ],
+ "nodeSelector": {
+ "kubernetes.io/hostname": "node-01"
+ },
+ "restartPolicy": "Always",
+ "tolerations": [
+ {"operator": "Exists"}
+ ]
+ }
+ }
+ }
+ }
+ input_s = {
+ 'command': '/bin/bash',
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
+service ssh restart;while true ; do sleep 10000; done'],
+ 'ssh_key': 'k8s-86096c30-key',
+ 'nodeSelector': {'kubernetes.io/hostname': 'node-01'},
+ 'volumes': [],
+ 'restartPolicy': 'Always'
+ }
+ name = 'host-k8s-86096c30'
+ output_r = kubernetes.ReplicationControllerObject(
+ name, **input_s).get_template()
+ self.assertEqual(output_r, output_t)
+
+ def test_get_template_invalid_restart_policy(self):
+ input_s = {'restartPolicy': 'invalid_option'}
+ name = 'host-k8s-86096c30'
+ with self.assertRaises(exceptions.KubernetesWrongRestartPolicy):
+ kubernetes.ReplicationControllerObject(
+ name, **input_s).get_template()
+
+
+class GetRcPodsTestCase(base.BaseUnitTestCase):
+
+ @mock.patch('yardstick.orchestrator.kubernetes.k8s_utils.get_pod_list')
+ def test_get_rc_pods(self, mock_get_pod_list):
+ servers = {
+ 'host': {
+ 'image': 'openretriever/yardstick',
+ 'command': '/bin/bash',
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
+service ssh restart;while true ; do sleep 10000; done']
+ },
+ 'target': {
+ 'image': 'openretriever/yardstick',
+ 'command': '/bin/bash',
+ 'args': ['-c', 'chmod 700 ~/.ssh; chmod 600 ~/.ssh/*; \
+service ssh restart;while true ; do sleep 10000; done']
+ }
+ }
+ k8s_template = kubernetes.KubernetesTemplate('k8s-86096c30', servers)
+ mock_get_pod_list.return_value.items = []
+ pods = k8s_template.get_rc_pods()
+ self.assertEqual(pods, [])
+
+
+class ReplicationControllerObjectTestCase(base.BaseUnitTestCase):
+
+ def test__init_one_container(self):
+ pod_name = 'pod_name'
+ _kwargs = {'args': ['arg1', 'arg2'],
+ 'image': 'fake_image',
+ 'command': 'fake_command'}
+ k8s_obj = kubernetes.ReplicationControllerObject(pod_name, **_kwargs)
+ self.assertEqual(1, len(k8s_obj._containers))
+ container = k8s_obj._containers[0]
+ self.assertEqual(['arg1', 'arg2'], container._args)
+ self.assertEqual('fake_image', container._image)
+ self.assertEqual(['fake_command'], container._command)
+ self.assertEqual([], container._volume_mounts)
+
+ def test__init_multipe_containers(self):
+ pod_name = 'pod_name'
+ containers = []
+ for i in range(5):
+ containers.append({'args': ['arg1', 'arg2'],
+ 'image': 'fake_image_%s' % i,
+ 'command': 'fake_command_%s' % i})
+ _kwargs = {'containers': containers}
+ k8s_obj = kubernetes.ReplicationControllerObject(pod_name, **_kwargs)
+ self.assertEqual(5, len(k8s_obj._containers))
+ for i in range(5):
+ container = k8s_obj._containers[i]
+ self.assertEqual(['arg1', 'arg2'], container._args)
+ self.assertEqual('fake_image_%s' % i, container._image)
+ self.assertEqual(['fake_command_%s' % i], container._command)
+ self.assertEqual([], container._volume_mounts)
+
+ def test__add_volumes(self):
+ volume1 = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ volume2 = {'name': 'volume2',
+ 'configMap': 'data'}
+ k8s_obj = kubernetes.ReplicationControllerObject(
+ 'name', ssh_key='fake_sshkey', volumes=[volume2])
+ k8s_obj._add_volumes()
+ volumes = k8s_obj.template['spec']['template']['spec']['volumes']
+ self.assertEqual(sorted([volume1, volume2], key=lambda k: k['name']),
+ sorted(volumes, key=lambda k: k['name']))
+
+ def test__add_volumes_no_volumes(self):
+ volume1 = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ k8s_obj = kubernetes.ReplicationControllerObject(
+ 'name', ssh_key='fake_sshkey')
+ k8s_obj._add_volumes()
+ volumes = k8s_obj.template['spec']['template']['spec']['volumes']
+ self.assertEqual([volume1], volumes)
+
+ def test__create_ssh_key_volume(self):
+ expected = {'name': 'fake_sshkey',
+ 'configMap': {'name': 'fake_sshkey'}}
+ k8s_obj = kubernetes.ReplicationControllerObject(
+ 'name', ssh_key='fake_sshkey')
+ self.assertEqual(expected, k8s_obj._create_ssh_key_volume())
+
+ def test__create_volume_item(self):
+ for vol_type in kubernetes_utils.get_volume_types():
+ volume = {'name': 'vol_name',
+ vol_type: 'data'}
+ self.assertEqual(
+ volume,
+ kubernetes.ReplicationControllerObject.
+ _create_volume_item(volume))
+
+ def test__create_volume_item_invalid_type(self):
+ volume = {'name': 'vol_name',
+ 'invalid_type': 'data'}
+ with self.assertRaises(exceptions.KubernetesTemplateInvalidVolumeType):
+ kubernetes.ReplicationControllerObject._create_volume_item(volume)
+
+ def test__add_security_context(self):
+ k8s_obj = kubernetes.ReplicationControllerObject('pod_name')
+ self.assertNotIn('securityContext',
+ k8s_obj.template['spec']['template']['spec'])
+
+ k8s_obj._security_context = {'key_pod': 'value_pod'}
+ k8s_obj._add_security_context()
+ self.assertEqual(
+ {'key_pod': 'value_pod'},
+ k8s_obj.template['spec']['template']['spec']['securityContext'])
+
+ def test__add_security_context_by_init(self):
+ containers = []
+ for i in range(5):
+ containers.append(
+ {'securityContext': {'key%s' % i: 'value%s' % i}})
+ _kwargs = {'containers': containers,
+ 'securityContext': {'key_pod': 'value_pod'}}
+ k8s_obj = kubernetes.ReplicationControllerObject('pod_name', **_kwargs)
+ self.assertEqual(
+ {'key_pod': 'value_pod'},
+ k8s_obj.template['spec']['template']['spec']['securityContext'])
+ for i in range(5):
+ container = (
+ k8s_obj.template['spec']['template']['spec']['containers'][i])
+ self.assertEqual({'key%s' % i: 'value%s' % i},
+ container['securityContext'])
+
+ def test__add_networks(self):
+ k8s_obj = kubernetes.ReplicationControllerObject(
+ 'name', networks=['network1', 'network2', 'network3'])
+ k8s_obj._add_networks()
+ networks = k8s_obj.\
+ template['spec']['template']['metadata']['annotations']['networks']
+ expected = ('[{"name": "network1"}, {"name": "network2"}, '
+ '{"name": "network3"}]')
+ self.assertEqual(expected, networks)
+
+ def test__add_tolerations(self):
+ _kwargs = {'tolerations': [{'key': 'key1',
+ 'value': 'value2',
+ 'effect': 'effect3',
+ 'operator': 'operator4',
+ 'wrong_key': 'error_key'}]
+ }
+ k8s_obj = kubernetes.ReplicationControllerObject('pod_name', **_kwargs)
+ k8s_obj._add_tolerations()
+ _tol = k8s_obj.template['spec']['template']['spec']['tolerations']
+ self.assertEqual(1, len(_tol))
+ self.assertEqual({'key': 'key1',
+ 'value': 'value2',
+ 'effect': 'effect3',
+ 'operator': 'operator4'},
+ _tol[0])
+
+ def test__add_tolerations_default(self):
+ k8s_obj = kubernetes.ReplicationControllerObject('pod_name')
+ k8s_obj._add_tolerations()
+ _tol = k8s_obj.template['spec']['template']['spec']['tolerations']
+ self.assertEqual(1, len(_tol))
+ self.assertEqual({'operator': 'Exists'}, _tol[0])
+
+
+class ContainerObjectTestCase(base.BaseUnitTestCase):
+
+ def test__create_volume_mounts(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ ssh_vol = {'name': 'fake_ssh_key',
+ 'mountPath': kubernetes.ContainerObject.SSH_MOUNT_PATH,
+ 'readOnly': False}
+ expected = copy.deepcopy(volume_mount)
+ expected['readOnly'] = False
+ expected = [expected, ssh_vol]
+ container_obj = kubernetes.ContainerObject(
+ 'cname', 'fake_ssh_key', volumeMounts=[volume_mount])
+ output = container_obj._create_volume_mounts()
+ self.assertEqual(expected, output)
+
+ def test__create_volume_mounts_no_volume_mounts(self):
+ ssh_vol = {'name': 'fake_ssh_key2',
+ 'mountPath': kubernetes.ContainerObject.SSH_MOUNT_PATH,
+ 'readOnly': False}
+ container_obj = kubernetes.ContainerObject('name', 'fake_ssh_key2')
+ output = container_obj._create_volume_mounts()
+ self.assertEqual([ssh_vol], output)
+
+ def test__create_volume_mounts_item(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ expected = copy.deepcopy(volume_mount)
+ expected['readOnly'] = False
+ output = kubernetes.ContainerObject._create_volume_mounts_item(
+ volume_mount)
+ self.assertEqual(expected, output)
+
+ def test_get_container_item(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args)
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts()}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_with_security_context(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args, securityContext={'key': 'value'})
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'securityContext': {'key': 'value'}}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_with_env(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args, env=[{'name': 'fake_var_name',
+ 'value': 'fake_var_value'}])
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'env': [{'name': 'fake_var_name',
+ 'value': 'fake_var_value'}]}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_with_ports_multi_parameter(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args, ports=[{'containerPort': 'fake_port_name',
+ 'hostPort': 'fake_host_port',
+ 'name': 'fake_name',
+ 'protocol': 'fake_protocol',
+ 'invalid_varible': 'fakeinvalid_varible',
+ 'hostIP': 'fake_port_number'}])
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'ports': [{'containerPort': 'fake_port_name',
+ 'hostPort': 'fake_host_port',
+ 'name': 'fake_name',
+ 'protocol': 'fake_protocol',
+ 'hostIP': 'fake_port_number'}]}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_with_ports_no_container_port(self):
+ with self.assertRaises(exceptions.KubernetesContainerPortNotDefined):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args, ports=[{'hostPort': 'fake_host_port',
+ 'name': 'fake_name',
+ 'protocol': 'fake_protocol',
+ 'hostIP': 'fake_port_number'}])
+ container_obj.get_container_item()
+
+ def test_get_container_item_with_resources(self):
+ volume_mount = {'name': 'fake_name',
+ 'mountPath': 'fake_path'}
+ args = ['arg1', 'arg2']
+ resources = {'requests': {'key1': 'val1'},
+ 'limits': {'key2': 'val2'},
+ 'other_key': {'key3': 'val3'}}
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', volumeMount=[volume_mount],
+ args=args, resources=resources)
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'resources': {'requests': {'key1': 'val1'},
+ 'limits': {'key2': 'val2'}}}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_image_pull_policy(self):
+ container_obj = kubernetes.ContainerObject(
+ 'cname', ssh_key='fake_sshkey', imagePullPolicy='Always')
+ expected = {'args': [],
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'imagePullPolicy':'Always'}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test_get_container_item_with_tty_stdin(self):
+ args = ['arg1', 'arg2']
+ container_obj = kubernetes.ContainerObject(
+ 'cname', 'fake_sshkey', args=args, tty=False, stdin=True)
+ expected = {'args': args,
+ 'command': kubernetes.ContainerObject.COMMAND_DEFAULT,
+ 'image': kubernetes.ContainerObject.IMAGE_DEFAULT,
+ 'name': 'cname-container',
+ 'volumeMounts': container_obj._create_volume_mounts(),
+ 'tty': False,
+ 'stdin': True}
+ self.assertEqual(expected, container_obj.get_container_item())
+
+ def test__parse_commands_string(self):
+ container_obj = kubernetes.ContainerObject('cname', 'fake_sshkey')
+ self.assertEqual(['fake command'],
+ container_obj._parse_commands('fake command'))
+
+ def test__parse_commands_list(self):
+ container_obj = kubernetes.ContainerObject('cname', 'fake_sshkey')
+ self.assertEqual(['cmd1', 'cmd2'],
+ container_obj._parse_commands(['cmd1', 'cmd2']))
+
+ def test__parse_commands_exception(self):
+ container_obj = kubernetes.ContainerObject('cname', 'fake_sshkey')
+ with self.assertRaises(exceptions.KubernetesContainerCommandType):
+ container_obj._parse_commands({})
+
+
+class CustomResourceDefinitionObjectTestCase(base.BaseUnitTestCase):
+
+ def test__init(self):
+ template = {
+ 'metadata': {
+ 'name': 'newcrds.ctx_name.com'
+ },
+ 'spec': {
+ 'group': 'ctx_name.com',
+ 'version': 'v2',
+ 'scope': 'scope',
+ 'names': {'plural': 'newcrds',
+ 'singular': 'newcrd',
+ 'kind': 'Newcrd'}
+ }
+ }
+ crd_obj = kubernetes.CustomResourceDefinitionObject(
+ 'ctx_name', name='newcrd', version='v2', scope='scope')
+ self.assertEqual('newcrds.ctx_name.com', crd_obj._name)
+ self.assertEqual(template, crd_obj._template)
+
+ def test__init_missing_parameter(self):
+ with self.assertRaises(exceptions.KubernetesCRDObjectDefinitionError):
+ kubernetes.CustomResourceDefinitionObject('ctx_name',
+ noname='name')
+
+
+class NetworkObjectTestCase(base.BaseUnitTestCase):
+
+ def setUp(self):
+ self.net_obj = kubernetes.NetworkObject(name='fake_name',
+ plugin='fake_plugin',
+ args='fake_args')
+
+ def test__init_missing_parameter(self):
+ with self.assertRaises(
+ exceptions.KubernetesNetworkObjectDefinitionError):
+ kubernetes.NetworkObject('network_name', plugin='plugin')
+ with self.assertRaises(
+ exceptions.KubernetesNetworkObjectDefinitionError):
+ kubernetes.NetworkObject('network_name', args='args')
+
+ @mock.patch.object(kubernetes_utils, 'get_custom_resource_definition')
+ def test_crd(self, mock_get_crd):
+ mock_crd = mock.Mock()
+ mock_get_crd.return_value = mock_crd
+ net_obj = copy.deepcopy(self.net_obj)
+ self.assertEqual(mock_crd, net_obj.crd)
+
+ def test_template(self):
+ net_obj = copy.deepcopy(self.net_obj)
+ expected = {'apiVersion': 'group.com/v2',
+ 'kind': kubernetes.NetworkObject.KIND,
+ 'metadata': {
+ 'name': 'fake_name'},
+ 'plugin': 'fake_plugin',
+ 'args': 'fake_args'}
+ crd = mock.Mock()
+ crd.spec.group = 'group.com'
+ crd.spec.version = 'v2'
+ net_obj._crd = crd
+ self.assertEqual(expected, net_obj.template)
+
+ def test_group(self):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._crd = mock.Mock()
+ net_obj._crd.spec.group = 'fake_group'
+ self.assertEqual('fake_group', net_obj.group)
+
+ def test_version(self):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._crd = mock.Mock()
+ net_obj._crd.spec.version = 'version_4'
+ self.assertEqual('version_4', net_obj.version)
+
+ def test_plural(self):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._crd = mock.Mock()
+ net_obj._crd.spec.names.plural = 'name_ending_in_s'
+ self.assertEqual('name_ending_in_s', net_obj.plural)
+
+ def test_scope(self):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._crd = mock.Mock()
+ net_obj._crd.spec.scope = 'Cluster'
+ self.assertEqual('Cluster', net_obj.scope)
+
+ @mock.patch.object(kubernetes_utils, 'create_network')
+ def test_create(self, mock_create_network):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._scope = 'scope'
+ net_obj._group = 'group'
+ net_obj._version = 'version'
+ net_obj._plural = 'plural'
+ net_obj._template = 'template'
+ net_obj._name = 'fake_name'
+ net_obj.create()
+ mock_create_network.assert_called_once_with(
+ 'scope', 'group', 'version', 'plural', 'template', 'fake_name')
+
+ @mock.patch.object(kubernetes_utils, 'delete_network')
+ def test_delete(self, mock_delete_network):
+ net_obj = copy.deepcopy(self.net_obj)
+ net_obj._scope = 'scope'
+ net_obj._group = 'group'
+ net_obj._version = 'version'
+ net_obj._plural = 'plural'
+ net_obj._name = 'name'
+ net_obj.delete()
+ mock_delete_network.assert_called_once_with(
+ 'scope', 'group', 'version', 'plural', 'name', skip_codes=[404])
+
+
+class ServiceNodePortObjectTestCase(base.BaseUnitTestCase):
+
+ def test__init(self):
+ with mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port') \
+ as mock_add_port:
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'port': 80, 'name': 'web'}])
+
+ mock_add_port.assert_has_calls([mock.call(22, 'ssh', protocol='TCP'),
+ mock.call(80, 'web')])
+
+ @mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port')
+ def test__init_missing_mandatory_parameters(self, *args):
+ with self.assertRaises(
+ exceptions.KubernetesServiceObjectDefinitionError):
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'port': 80}])
+ with self.assertRaises(
+ exceptions.KubernetesServiceObjectDefinitionError):
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'name': 'web'}])
+
+ @mock.patch.object(kubernetes.ServiceNodePortObject, '_add_port')
+ def test__init_missing_bad_name(self, *args):
+ with self.assertRaises(
+ exceptions.KubernetesServiceObjectNameError):
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'port': 80, 'name': '-web'}])
+ with self.assertRaises(
+ exceptions.KubernetesServiceObjectNameError):
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'port': 80, 'name': 'Web'}])
+ with self.assertRaises(
+ exceptions.KubernetesServiceObjectNameError):
+ kubernetes.ServiceNodePortObject(
+ 'fake_name', node_ports=[{'port': 80, 'name': 'web-'}])
+
+ def test__add_port(self):
+ nodeport_object = kubernetes.ServiceNodePortObject('fake_name')
+ port_ssh = {'name': 'ssh',
+ 'port': 22,
+ 'protocol': 'TCP'}
+ port_definition = {'port': 80,
+ 'protocol': 'TCP',
+ 'name': 'web',
+ 'targetPort': 10080,
+ 'nodePort': 30080}
+ port = copy.deepcopy(port_definition)
+ _port = port.pop('port')
+ name = port.pop('name')
+ nodeport_object._add_port(_port, name, **port)
+ self.assertEqual([port_ssh, port_definition],
+ nodeport_object.template['spec']['ports'])
+
+ @mock.patch.object(kubernetes_utils, 'create_service')
+ def test_create(self, mock_create_service):
+ nodeport_object = kubernetes.ServiceNodePortObject('fake_name')
+ nodeport_object.template = 'fake_template'
+ nodeport_object.create()
+ mock_create_service.assert_called_once_with('fake_template')
+
+ @mock.patch.object(kubernetes_utils, 'delete_service')
+ def test_delete(self, mock_delete_service):
+ nodeport_object = kubernetes.ServiceNodePortObject('fake_name')
+ nodeport_object.delete()
+ mock_delete_service.assert_called_once_with('fake_name-service',
+ skip_codes=[404])
+
+
+class KubernetesTemplate(base.BaseUnitTestCase):
+
+ def test_get_rc_by_name(self):
+ ctx_cfg = {
+ 'servers': {
+ 'host1': {'args': 'some data'}
+ }
+ }
+ k_template = kubernetes.KubernetesTemplate('k8s_name', ctx_cfg)
+ rc = k_template.get_rc_by_name('host1-k8s_name')
+ self.assertTrue(isinstance(rc, kubernetes.ReplicationControllerObject))
+
+ def test_get_rc_by_name_wrong_name(self):
+ ctx_cfg = {
+ 'servers': {
+ 'host1': {'args': 'some data'}
+ }
+ }
+ k_template = kubernetes.KubernetesTemplate('k8s_name', ctx_cfg)
+ self.assertIsNone(k_template.get_rc_by_name('wrong_host_name'))
+
+ def test_get_rc_by_name_no_rcs(self):
+ ctx_cfg = {'servers': {}}
+ k_template = kubernetes.KubernetesTemplate('k8s_name', ctx_cfg)
+ self.assertIsNone(k_template.get_rc_by_name('any_host_name'))
diff --git a/yardstick/tests/unit/service/__init__.py b/yardstick/tests/unit/service/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/service/__init__.py
diff --git a/yardstick/tests/unit/service/test_environment.py b/yardstick/tests/unit/service/test_environment.py
new file mode 100644
index 000000000..779e6eaa0
--- /dev/null
+++ b/yardstick/tests/unit/service/test_environment.py
@@ -0,0 +1,46 @@
+##############################################################################
+# 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 mock
+
+from yardstick.common import exceptions
+from yardstick.service import environment
+from yardstick.tests.unit import base as ut_base
+
+
+class EnvironmentTestCase(ut_base.BaseUnitTestCase):
+
+ 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'
+ }
+ ]
+ }
+
+ with mock.patch.object(environment.AnsibleCommon,
+ 'gen_inventory_ini_dict'), \
+ mock.patch.object(environment.AnsibleCommon, 'get_sut_info',
+ return_value={'node1': {}}), \
+ mock.patch.object(environment.Environment, '_format_sut_info'):
+ env = environment.Environment(pod=pod_info)
+ env.get_sut_info()
+
+ def test_get_sut_info_pod_str(self):
+ pod_info = 'nodes'
+
+ env = environment.Environment(pod=pod_info)
+ with self.assertRaises(exceptions.UnsupportedPodFormatError):
+ env.get_sut_info()
diff --git a/yardstick/tests/unit/test_cmd/__init__.py b/yardstick/tests/unit/test_cmd/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/test_cmd/__init__.py
diff --git a/yardstick/tests/unit/test_cmd/commands/__init__.py b/yardstick/tests/unit/test_cmd/commands/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/yardstick/tests/unit/test_cmd/commands/__init__.py
diff --git a/yardstick/tests/unit/test_cmd/commands/test_env.py b/yardstick/tests/unit/test_cmd/commands/test_env.py
new file mode 100644
index 000000000..5d3520986
--- /dev/null
+++ b/yardstick/tests/unit/test_cmd/commands/test_env.py
@@ -0,0 +1,69 @@
+##############################################################################
+# 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 os
+import sys
+
+import mock
+import uuid
+
+from yardstick.cmd.commands import env
+from yardstick.tests.unit import base
+
+
+class EnvCommandTestCase(base.BaseUnitTestCase):
+
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
+ def test_do_influxdb(self, check_status_mock, start_async_task_mock):
+ _env = env.EnvCommand()
+ _env.do_influxdb({})
+ start_async_task_mock.assert_called_once()
+ check_status_mock.assert_called_once()
+
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
+ def test_do_grafana(self, check_status_mock, start_async_task_mock):
+ _env = env.EnvCommand()
+ _env.do_grafana({})
+ start_async_task_mock.assert_called_once()
+ check_status_mock.assert_called_once()
+
+ @mock.patch.object(env.EnvCommand, '_start_async_task')
+ @mock.patch.object(env.EnvCommand, '_check_status')
+ def test_do_prepare(self, check_status_mock, start_async_task_mock):
+ _env = env.EnvCommand()
+ _env.do_prepare({})
+ start_async_task_mock.assert_called_once()
+ check_status_mock.assert_called_once()
+
+ @mock.patch.object(env.HttpClient, 'post')
+ def test_start_async_task(self, post_mock):
+ data = {'action': 'create_grafana'}
+ env.EnvCommand()._start_async_task(data)
+ post_mock.assert_called_once()
+
+ @mock.patch.object(env.HttpClient, 'get')
+ @mock.patch.object(env.EnvCommand, '_print_status')
+ def test_check_status(self, mock_print, mock_get):
+ task_id = str(uuid.uuid4())
+ mock_get.return_value = {'status': 2, 'result': 'error'}
+ self.assertEqual(
+ 2, env.EnvCommand()._check_status(task_id, 'hello world'))
+ self.assertEqual(2, mock_print.call_count)
+
+ @mock.patch.object(sys, 'stdout')
+ @mock.patch.object(os, 'popen')
+ def test_print_status(self, mock_popen, mock_stdout):
+ mock_popen_obj = mock.Mock()
+ mock_popen_obj.read.return_value = ''
+ mock_popen.return_value = mock_popen_obj
+ env.EnvCommand()._print_status('hello', 'word')
+ mock_stdout.write.assert_not_called()
+ mock_stdout.flush.assert_not_called()
diff --git a/yardstick/tests/unit/test_cmd/commands/test_testcase.py b/yardstick/tests/unit/test_cmd/commands/test_testcase.py
new file mode 100644
index 000000000..922167614
--- /dev/null
+++ b/yardstick/tests/unit/test_cmd/commands/test_testcase.py
@@ -0,0 +1,21 @@
+##############################################################################
+# Copyright (c) 2017 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
+from mock import patch
+
+from yardstick.cmd.commands.testcase import TestcaseCommands
+
+
+class TestcaseCommandsUT(unittest.TestCase):
+ @patch('yardstick.cmd.commands.testcase.TestcaseCommands._format_print')
+ @patch('yardstick.cmd.commands.client')
+ def test_do_list(self, mock_client, mock_print):
+ mock_client.get.return_value = {'result': []}
+ TestcaseCommands().do_list({})
+ mock_print.assert_called_once()
diff --git a/yardstick/tests/unit/test_cmd/test_NSBperf.py b/yardstick/tests/unit/test_cmd/test_NSBperf.py
new file mode 100644
index 000000000..5de892212
--- /dev/null
+++ b/yardstick/tests/unit/test_cmd/test_NSBperf.py
@@ -0,0 +1,132 @@
+# 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.
+
+import argparse
+import os
+import subprocess
+
+import mock
+from six.moves import builtins
+import unittest
+
+from yardstick.cmd import NSBperf
+
+
+@mock.patch('six.moves.input', return_value='0')
+class TestHandler(unittest.TestCase):
+
+ def test_handler(self, *args):
+ subprocess.call = mock.Mock(return_value=0)
+ self.assertRaises(SystemExit, NSBperf.sigint_handler)
+
+
+class TestYardstickNSCli(unittest.TestCase):
+
+ def setUp(self):
+ self._mock_print = mock.patch.object(builtins, 'print')
+ self.mock_print = self._mock_print.start()
+ self.addCleanup(self._stop_mocks)
+
+ def _stop_mocks(self):
+ self._mock_print.stop()
+
+ def test___init__(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ self.assertIsNotNone(yardstick_ns_cli)
+
+ def test_generate_final_report(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ test_case = "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml"
+ if os.path.isfile("/tmp/yardstick.out"):
+ os.remove('/tmp/yardstick.out')
+ self.assertIsNone(yardstick_ns_cli.generate_final_report(test_case))
+
+ def test_generate_kpi_results(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ tkey = "cpu"
+ tgen = {"cpu": {"ipc": 0}}
+ self.assertIsNone(yardstick_ns_cli.generate_kpi_results(tkey, tgen))
+
+ def test_generate_nfvi_results(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ nfvi = {"collect_stats": {"cpu": {"ipc": 0, "Hz": 2.6}}}
+ self.assertIsNone(yardstick_ns_cli.generate_nfvi_results(nfvi))
+
+ def test_handle_list_options(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ CLI_PATH = os.path.dirname(os.path.realpath(__file__))
+ repo_dir = CLI_PATH + "/../../../"
+ test_path = os.path.join(repo_dir, "../samples/vnf_samples/nsut/")
+ args = {"list_vnfs": True, "list": False}
+ self.assertRaises(SystemExit, yardstick_ns_cli.handle_list_options,
+ args, test_path)
+ args = {"list_vnfs": False, "list": True}
+ self.assertRaises(SystemExit,
+ yardstick_ns_cli.handle_list_options,
+ args, test_path)
+
+ def test_main(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ yardstick_ns_cli.parse_arguments = mock.Mock(return_value=0)
+ yardstick_ns_cli.handle_list_options = mock.Mock(return_value=0)
+ yardstick_ns_cli.terminate_if_less_options = mock.Mock(return_value=0)
+ yardstick_ns_cli.run_test = mock.Mock(return_value=0)
+ self.assertIsNone(yardstick_ns_cli.main())
+
+ @mock.patch.object(argparse.ArgumentParser, 'parse_args')
+ def test_parse_arguments(self, mock_parse):
+ class DummyArgs(object):
+ var1 = 'value1'
+
+ mock_parse.return_value = DummyArgs
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ self.assertIn('var1', yardstick_ns_cli.parse_arguments())
+
+ def test_run_test(self):
+ cur_dir = os.getcwd()
+ CLI_PATH = os.path.dirname(os.path.realpath(__file__))
+ YARDSTICK_REPOS_DIR = os.path.join(CLI_PATH + "/../../")
+ test_path = os.path.join(YARDSTICK_REPOS_DIR,
+ "../samples/vnf_samples/nsut/")
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ subprocess.check_output = mock.Mock(return_value=0)
+ args = {"vnf": "vpe",
+ "test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml"}
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
+ os.chdir(cur_dir)
+ args = {"vnf": "vpe1"}
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
+ os.chdir(cur_dir)
+ args = {"vnf": "vpe",
+ "test": "tc_baremetal_rfc2544_ipv4_1flow_1518B.yaml."}
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
+ os.chdir(cur_dir)
+ args = []
+ self.assertIsNone(yardstick_ns_cli.run_test(args, test_path))
+ os.chdir(cur_dir)
+
+ def test_terminate_if_less_options(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ args = {"vnf": False}
+ self.assertRaises(SystemExit,
+ yardstick_ns_cli.terminate_if_less_options, args)
+
+ def test_validate_input(self):
+ yardstick_ns_cli = NSBperf.YardstickNSCli()
+ self.assertEqual(1, yardstick_ns_cli.validate_input("", 4))
+ NSBperf.input = lambda _: 'yes'
+ self.assertEqual(1, yardstick_ns_cli.validate_input(5, 4))
+ subprocess.call = mock.Mock(return_value=0)
+ self.assertEqual(0, yardstick_ns_cli.validate_input(2, 4))
+ subprocess.call = mock.Mock(return_value=0)
diff --git a/yardstick/tests/unit/test_ssh.py b/yardstick/tests/unit/test_ssh.py
new file mode 100644
index 000000000..374fb6644
--- /dev/null
+++ b/yardstick/tests/unit/test_ssh.py
@@ -0,0 +1,684 @@
+# Copyright 2013: Mirantis Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import os
+import socket
+import unittest
+from io import StringIO
+from itertools import count
+
+import mock
+from oslo_utils import encodeutils
+
+from yardstick.common import exceptions
+from yardstick import ssh
+from yardstick.ssh import SSH
+from yardstick.ssh import AutoConnectSSH
+
+
+class FakeParamikoException(Exception):
+ pass
+
+
+class SSHTestCase(unittest.TestCase):
+ """Test all small SSH methods."""
+
+ def setUp(self):
+ super(SSHTestCase, self).setUp()
+ self.test_client = ssh.SSH("root", "example.net")
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ def test_construct(self, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ test_ssh = ssh.SSH("root", "example.net", port=33, pkey="key",
+ key_filename="kf", password="secret")
+ mock_ssh__get_pkey.assert_called_once_with("key")
+ self.assertEqual("root", test_ssh.user)
+ self.assertEqual("example.net", test_ssh.host)
+ self.assertEqual(33, test_ssh.port)
+ self.assertEqual("pkey", test_ssh.pkey)
+ self.assertEqual("kf", test_ssh.key_filename)
+ self.assertEqual("secret", test_ssh.password)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ def test_ssh_from_node(self, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ node = {
+ "user": "root", "ip": "example.net", "ssh_port": 33,
+ "key_filename": "kf", "password": "secret"
+ }
+ test_ssh = ssh.SSH.from_node(node)
+ self.assertEqual("root", test_ssh.user)
+ self.assertEqual("example.net", test_ssh.host)
+ self.assertEqual(33, test_ssh.port)
+ self.assertEqual("kf", test_ssh.key_filename)
+ self.assertEqual("secret", test_ssh.password)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ def test_ssh_from_node_password_default(self, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ node = {
+ "user": "root", "ip": "example.net", "ssh_port": 33,
+ "key_filename": "kf"
+ }
+ test_ssh = ssh.SSH.from_node(node)
+ self.assertEqual("root", test_ssh.user)
+ self.assertEqual("example.net", test_ssh.host)
+ self.assertEqual(33, test_ssh.port)
+ self.assertEqual("kf", test_ssh.key_filename)
+ self.assertIsNone(test_ssh.password)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ def test_ssh_from_node_ssh_port_default(self, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ node = {
+ "user": "root", "ip": "example.net",
+ "key_filename": "kf", "password": "secret"
+ }
+ test_ssh = ssh.SSH.from_node(node)
+ self.assertEqual("root", test_ssh.user)
+ self.assertEqual("example.net", test_ssh.host)
+ self.assertEqual(ssh.SSH.SSH_PORT, test_ssh.port)
+ self.assertEqual("kf", test_ssh.key_filename)
+ self.assertEqual("secret", test_ssh.password)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ def test_ssh_from_node_key_filename_default(self, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ node = {
+ "user": "root", "ip": "example.net", "ssh_port": 33,
+ "password": "secret"
+ }
+ test_ssh = ssh.SSH.from_node(node)
+ self.assertEqual("root", test_ssh.user)
+ self.assertEqual("example.net", test_ssh.host)
+ self.assertEqual(33, test_ssh.port)
+ self.assertIsNone(test_ssh.key_filename)
+ self.assertEqual("secret", test_ssh.password)
+
+ def test_construct_default(self):
+ self.assertEqual("root", self.test_client.user)
+ self.assertEqual("example.net", self.test_client.host)
+ self.assertEqual(22, self.test_client.port)
+ self.assertIsNone(self.test_client.pkey)
+ self.assertIsNone(self.test_client.key_filename)
+ self.assertIsNone(self.test_client.password)
+
+ @mock.patch("yardstick.ssh.paramiko")
+ def test__get_pkey_invalid(self, mock_paramiko):
+ mock_paramiko.SSHException = FakeParamikoException
+ rsa = mock_paramiko.rsakey.RSAKey
+ dss = mock_paramiko.dsskey.DSSKey
+ rsa.from_private_key.side_effect = mock_paramiko.SSHException
+ dss.from_private_key.side_effect = mock_paramiko.SSHException
+ self.assertRaises(exceptions.SSHError, self.test_client._get_pkey, "key")
+
+ @mock.patch("yardstick.ssh.six.moves.StringIO")
+ @mock.patch("yardstick.ssh.paramiko")
+ def test__get_pkey_dss(self, mock_paramiko, mock_string_io):
+ mock_paramiko.SSHException = FakeParamikoException
+ mock_string_io.return_value = "string_key"
+ mock_paramiko.dsskey.DSSKey.from_private_key.return_value = "dss_key"
+ rsa = mock_paramiko.rsakey.RSAKey
+ rsa.from_private_key.side_effect = mock_paramiko.SSHException
+ key = self.test_client._get_pkey("key")
+ dss_calls = mock_paramiko.dsskey.DSSKey.from_private_key.mock_calls
+ self.assertEqual([mock.call("string_key")], dss_calls)
+ self.assertEqual(key, "dss_key")
+ mock_string_io.assert_called_once_with("key")
+
+ @mock.patch("yardstick.ssh.six.moves.StringIO")
+ @mock.patch("yardstick.ssh.paramiko")
+ def test__get_pkey_rsa(self, mock_paramiko, mock_string_io):
+ mock_paramiko.SSHException = FakeParamikoException
+ mock_string_io.return_value = "string_key"
+ mock_paramiko.rsakey.RSAKey.from_private_key.return_value = "rsa_key"
+ dss = mock_paramiko.dsskey.DSSKey
+ dss.from_private_key.side_effect = mock_paramiko.SSHException
+ key = self.test_client._get_pkey("key")
+ rsa_calls = mock_paramiko.rsakey.RSAKey.from_private_key.mock_calls
+ self.assertEqual([mock.call("string_key")], rsa_calls)
+ self.assertEqual(key, "rsa_key")
+ mock_string_io.assert_called_once_with("key")
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ @mock.patch("yardstick.ssh.paramiko")
+ def test__get_client(self, mock_paramiko, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "key"
+ fake_client = mock.Mock()
+ mock_paramiko.SSHClient.return_value = fake_client
+ mock_paramiko.AutoAddPolicy.return_value = "autoadd"
+
+ test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+ client = test_ssh._get_client()
+
+ self.assertEqual(fake_client, client)
+ client_calls = [
+ mock.call.set_missing_host_key_policy("autoadd"),
+ mock.call.connect("example.net", username="admin",
+ port=22, pkey="key", key_filename=None,
+ password=None,
+ allow_agent=False, look_for_keys=False,
+ timeout=1),
+ ]
+ self.assertEqual(client_calls, client.mock_calls)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ @mock.patch("yardstick.ssh.paramiko")
+ def test__get_client_with_exception(self, mock_paramiko, mock_ssh__get_pkey):
+ class MyError(Exception):
+ pass
+
+ mock_ssh__get_pkey.return_value = "pkey"
+ fake_client = mock.Mock()
+ fake_client.connect.side_effect = MyError
+ fake_client.set_missing_host_key_policy.return_value = None
+ mock_paramiko.SSHClient.return_value = fake_client
+ mock_paramiko.AutoAddPolicy.return_value = "autoadd"
+
+ test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+
+ with self.assertRaises(exceptions.SSHError) as raised:
+ test_ssh._get_client()
+
+ mock_paramiko.SSHClient.assert_called_once()
+ mock_paramiko.AutoAddPolicy.assert_called_once()
+ fake_client.set_missing_host_key_policy.assert_called_once()
+ fake_client.connect.assert_called_once()
+ exc_str = str(raised.exception)
+ self.assertIn('raised during connect', exc_str)
+ self.assertIn('MyError', exc_str)
+
+ @mock.patch("yardstick.ssh.SSH._get_pkey")
+ @mock.patch("yardstick.ssh.paramiko")
+ def test_copy(self, mock_paramiko, mock_ssh__get_pkey):
+ mock_ssh__get_pkey.return_value = "pkey"
+ fake_client = mock.Mock()
+ fake_client.connect.side_effect = IOError
+ mock_paramiko.SSHClient.return_value = fake_client
+ mock_paramiko.AutoAddPolicy.return_value = "autoadd"
+
+ test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+ result = test_ssh.copy()
+ self.assertIsNot(test_ssh, result)
+
+ def test_close(self):
+ with mock.patch.object(self.test_client, "_client") as m_client:
+ self.test_client.close()
+ m_client.close.assert_called_once_with()
+ self.assertFalse(self.test_client._client)
+
+ @mock.patch("yardstick.ssh.six.moves.StringIO")
+ def test_execute(self, mock_string_io):
+ mock_string_io.side_effect = stdio = [mock.Mock(), mock.Mock()]
+ stdio[0].read.return_value = "stdout fake data"
+ stdio[1].read.return_value = "stderr fake data"
+ with mock.patch.object(self.test_client, "run", return_value=0)\
+ as mock_run:
+ status, stdout, stderr = self.test_client.execute(
+ "cmd",
+ stdin="fake_stdin",
+ timeout=43)
+ mock_run.assert_called_once_with(
+ "cmd", stdin="fake_stdin", stdout=stdio[0],
+ stderr=stdio[1], timeout=43, raise_on_error=False)
+ self.assertEqual(0, status)
+ self.assertEqual("stdout fake data", stdout)
+ self.assertEqual("stderr fake data", stderr)
+
+ @mock.patch("yardstick.ssh.six.moves.StringIO")
+ def test_execute_raise_on_error_passed(self, mock_string_io):
+ mock_string_io.side_effect = stdio = [mock.Mock(), mock.Mock()]
+ stdio[0].read.return_value = "stdout fake data"
+ stdio[1].read.return_value = "stderr fake data"
+ with mock.patch.object(self.test_client, "run", return_value=0) \
+ as mock_run:
+ status, stdout, stderr = self.test_client.execute(
+ "cmd",
+ stdin="fake_stdin",
+ timeout=43,
+ raise_on_error=True)
+ mock_run.assert_called_once_with(
+ "cmd", stdin="fake_stdin", stdout=stdio[0],
+ stderr=stdio[1], timeout=43, raise_on_error=True)
+ self.assertEqual(0, status)
+ self.assertEqual("stdout fake data", stdout)
+ self.assertEqual("stderr fake data", stderr)
+
+ @mock.patch("yardstick.ssh.time")
+ def test_wait_timeout(self, mock_time):
+ mock_time.time.side_effect = [1, 50, 150]
+ self.test_client.execute = mock.Mock(side_effect=[exceptions.SSHError,
+ exceptions.SSHError,
+ 0])
+ self.assertRaises(exceptions.SSHTimeout, self.test_client.wait)
+ self.assertEqual([mock.call("uname")] * 2,
+ self.test_client.execute.mock_calls)
+
+ @mock.patch("yardstick.ssh.time")
+ def test_wait(self, mock_time):
+ mock_time.time.side_effect = [1, 50, 100]
+ self.test_client.execute = mock.Mock(side_effect=[exceptions.SSHError,
+ exceptions.SSHError,
+ 0])
+ self.test_client.wait()
+ self.assertEqual([mock.call("uname")] * 3,
+ self.test_client.execute.mock_calls)
+
+ @mock.patch("yardstick.ssh.paramiko")
+ def test_send_command(self, _):
+ paramiko_sshclient = self.test_client._get_client()
+ with mock.patch.object(paramiko_sshclient, "exec_command") \
+ as mock_paramiko_exec_command:
+ self.test_client.send_command('cmd')
+ mock_paramiko_exec_command.assert_called_once_with('cmd',
+ get_pty=True)
+
+ @mock.patch("yardstick.ssh.paramiko")
+ def test_interactive_terminal_open(self, mock_paramiko):
+ fake_client = mock.Mock()
+ fake_session = mock.Mock()
+ fake_session.recv.return_value = ":~# "
+ fake_transport = mock.Mock()
+ fake_transport.open_session.return_value = fake_session
+ fake_client.get_transport.return_value = fake_transport
+ mock_paramiko.SSHClient.return_value = fake_client
+
+ test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+ result = test_ssh.interactive_terminal_open()
+ self.assertEqual(fake_session, result)
+
+ @mock.patch("yardstick.ssh.paramiko")
+ def test_interactive_terminal_exec_command(self, mock_paramiko):
+ fake_client = mock.Mock()
+ fake_session = mock.Mock()
+ fake_session.recv.return_value = "stdout fake data"
+ fake_transport = mock.Mock()
+ fake_transport.open_session.return_value = fake_session
+ fake_client.get_transport.return_value = fake_transport
+ mock_paramiko.SSHClient.return_value = fake_client
+
+ test_ssh = ssh.SSH("admin", "example.net", pkey="key")
+ with mock.patch.object(fake_session, "sendall") \
+ as mock_paramiko_send_command:
+ result = test_ssh.interactive_terminal_exec_command(fake_session,
+ 'cmd', "vat# ")
+ self.assertEqual("stdout fake data", result)
+ mock_paramiko_send_command.assert_called_once_with('cmd\n')
+
+ @mock.patch("yardstick.ssh.paramiko")
+ def test_interactive_terminal_close(self, _):
+ fake_session = mock.Mock()
+ paramiko_sshclient = self.test_client._get_client()
+ paramiko_sshclient.get_transport.open_session.return_value = fake_session
+ with mock.patch.object(fake_session, "close") \
+ as mock_paramiko_terminal_close:
+ self.test_client.interactive_terminal_close(fake_session)
+ mock_paramiko_terminal_close.assert_called_once_with()
+
+
+class SSHRunTestCase(unittest.TestCase):
+ """Test SSH.run method in different aspects.
+
+ Also tested method "execute".
+ """
+
+ def setUp(self):
+ super(SSHRunTestCase, self).setUp()
+
+ self.fake_client = mock.Mock()
+ self.fake_session = mock.Mock()
+ self.fake_transport = mock.Mock()
+
+ self.fake_transport.open_session.return_value = self.fake_session
+ self.fake_client.get_transport.return_value = self.fake_transport
+
+ self.fake_session.recv_ready.return_value = False
+ self.fake_session.recv_stderr_ready.return_value = False
+ self.fake_session.send_ready.return_value = False
+ self.fake_session.exit_status_ready.return_value = True
+ self.fake_session.recv_exit_status.return_value = 0
+
+ self.test_client = ssh.SSH("admin", "example.net")
+ self.test_client._get_client = mock.Mock(return_value=self.fake_client)
+
+ @mock.patch("yardstick.ssh.select")
+ def test_execute(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.recv_ready.side_effect = [1, 0, 0]
+ self.fake_session.recv_stderr_ready.side_effect = [1, 0]
+ self.fake_session.recv.return_value = "ok"
+ self.fake_session.recv_stderr.return_value = "error"
+ self.fake_session.exit_status_ready.return_value = 1
+ self.fake_session.recv_exit_status.return_value = 127
+ self.assertEqual((127, "ok", "error"), self.test_client.execute("cmd"))
+ self.fake_session.exec_command.assert_called_once_with("cmd")
+
+ @mock.patch("yardstick.ssh.select")
+ def test_execute_args(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.recv_ready.side_effect = [1, 0, 0]
+ self.fake_session.recv_stderr_ready.side_effect = [1, 0]
+ self.fake_session.recv.return_value = "ok"
+ self.fake_session.recv_stderr.return_value = "error"
+ self.fake_session.exit_status_ready.return_value = 1
+ self.fake_session.recv_exit_status.return_value = 127
+
+ result = self.test_client.execute("cmd arg1 'arg2 with space'")
+ self.assertEqual((127, "ok", "error"), result)
+ self.fake_session.exec_command.assert_called_once_with(
+ "cmd arg1 'arg2 with space'")
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.assertEqual(0, self.test_client.run("cmd"))
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_nonzero_status(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.recv_exit_status.return_value = 1
+ self.assertRaises(exceptions.SSHError, self.test_client.run, "cmd")
+ self.assertEqual(1, self.test_client.run("cmd", raise_on_error=False))
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_stdout(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.recv_ready.side_effect = [True, True, False]
+ self.fake_session.recv.side_effect = ["ok1", "ok2"]
+ stdout = mock.Mock()
+ self.test_client.run("cmd", stdout=stdout)
+ self.assertEqual([mock.call("ok1"), mock.call("ok2")],
+ stdout.write.mock_calls)
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_stderr(self, mock_select):
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.recv_stderr_ready.side_effect = [True, False]
+ self.fake_session.recv_stderr.return_value = "error"
+ stderr = mock.Mock()
+ self.test_client.run("cmd", stderr=stderr)
+ stderr.write.assert_called_once_with("error")
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_stdin(self, mock_select):
+ """Test run method with stdin.
+
+ Third send call was called with "e2" because only 3 bytes was sent
+ by second call. So remainig 2 bytes of "line2" was sent by third call.
+ """
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.exit_status_ready.side_effect = [0, 0, 0, True]
+ self.fake_session.send_ready.return_value = True
+ self.fake_session.send.side_effect = [5, 3, 2]
+ fake_stdin = mock.Mock()
+ fake_stdin.read.side_effect = ["line1", "line2", ""]
+ fake_stdin.closed = False
+
+ def close():
+ fake_stdin.closed = True
+ fake_stdin.close = mock.Mock(side_effect=close)
+ self.test_client.run("cmd", stdin=fake_stdin)
+ call = mock.call
+ send_calls = [call(encodeutils.safe_encode("line1", "utf-8")),
+ call(encodeutils.safe_encode("line2", "utf-8")),
+ call(encodeutils.safe_encode("e2", "utf-8"))]
+ self.assertEqual(send_calls, self.fake_session.send.mock_calls)
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_stdin_keep_open(self, mock_select):
+ """Test run method with stdin.
+
+ Third send call was called with "e2" because only 3 bytes was sent
+ by second call. So remainig 2 bytes of "line2" was sent by third call.
+ """
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.exit_status_ready.side_effect = [0, 0, 0, True]
+ self.fake_session.send_ready.return_value = True
+ self.fake_session.send.side_effect = len
+ fake_stdin = StringIO(u"line1\nline2\n")
+ self.test_client.run("cmd", stdin=fake_stdin, keep_stdin_open=True)
+ call = mock.call
+ send_calls = [call(encodeutils.safe_encode("line1\nline2\n", "utf-8"))]
+ self.assertEqual(send_calls, self.fake_session.send.mock_calls)
+
+ @mock.patch("yardstick.ssh.select")
+ def test_run_select_error(self, mock_select):
+ self.fake_session.exit_status_ready.return_value = False
+ mock_select.select.return_value = ([], [], [True])
+ self.assertRaises(exceptions.SSHError, self.test_client.run, "cmd")
+
+ @mock.patch("yardstick.ssh.time")
+ @mock.patch("yardstick.ssh.select")
+ def test_run_timemout(self, mock_select, mock_time):
+ mock_time.time.side_effect = [1, 3700]
+ mock_select.select.return_value = ([], [], [])
+ self.fake_session.exit_status_ready.return_value = False
+ self.assertRaises(exceptions.SSHTimeout, self.test_client.run, "cmd")
+
+ @mock.patch("yardstick.ssh.open", create=True)
+ def test__put_file_shell(self, mock_open):
+ with mock.patch.object(self.test_client, "run") as run_mock:
+ self.test_client._put_file_shell("localfile", "remotefile", 0o42)
+ run_mock.assert_called_once_with(
+ 'cat > "remotefile"&& chmod -- 042 "remotefile"',
+ stdin=mock_open.return_value.__enter__.return_value)
+
+ @mock.patch("yardstick.ssh.open", create=True)
+ def test__put_file_shell_space(self, mock_open):
+ with mock.patch.object(self.test_client, "run") as run_mock:
+ self.test_client._put_file_shell("localfile",
+ "filename with space", 0o42)
+ run_mock.assert_called_once_with(
+ 'cat > "filename with space"&& chmod -- 042 "filename with '
+ 'space"',
+ stdin=mock_open.return_value.__enter__.return_value)
+
+ @mock.patch("yardstick.ssh.open", create=True)
+ def test__put_file_shell_tilde(self, mock_open):
+ with mock.patch.object(self.test_client, "run") as run_mock:
+ self.test_client._put_file_shell("localfile", "~/remotefile", 0o42)
+ run_mock.assert_called_once_with(
+ 'cat > ~/"remotefile"&& chmod -- 042 ~/"remotefile"',
+ stdin=mock_open.return_value.__enter__.return_value)
+
+ @mock.patch("yardstick.ssh.open", create=True)
+ def test__put_file_shell_tilde_spaces(self, mock_open):
+ with mock.patch.object(self.test_client, "run") as run_mock:
+ self.test_client._put_file_shell("localfile", "~/file with space",
+ 0o42)
+ run_mock.assert_called_once_with(
+ 'cat > ~/"file with space"&& chmod -- 042 ~/"file with space"',
+ stdin=mock_open.return_value.__enter__.return_value)
+
+ @mock.patch("yardstick.ssh.os.stat")
+ def test__put_file_sftp(self, mock_stat):
+ sftp = self.fake_client.open_sftp.return_value = mock.MagicMock()
+ sftp.__enter__.return_value = sftp
+
+ mock_stat.return_value = os.stat_result([0o753] + [0] * 9)
+
+ self.test_client._put_file_sftp("localfile", "remotefile")
+
+ sftp.put.assert_called_once_with("localfile", "remotefile")
+ mock_stat.assert_any_call("localfile")
+ sftp.chmod.assert_any_call("remotefile", 0o753)
+ sftp.__exit__.assert_called_once_with(None, None, None)
+
+ def test__put_file_sftp_mode(self):
+ sftp = self.fake_client.open_sftp.return_value = mock.MagicMock()
+ sftp.__enter__.return_value = sftp
+
+ self.test_client._put_file_sftp("localfile", "remotefile", mode=0o753)
+
+ sftp.put.assert_called_once_with("localfile", "remotefile")
+ sftp.chmod.assert_called_once_with("remotefile", 0o753)
+ sftp.__exit__.assert_called_once_with(None, None, None)
+
+ def test_put_file_SSHException(self):
+ exc = ssh.paramiko.SSHException
+ self.test_client._put_file_sftp = mock.Mock(side_effect=exc())
+ self.test_client._put_file_shell = mock.Mock()
+
+ self.test_client.put_file("foo", "bar", 42)
+ self.test_client._put_file_sftp.assert_called_once_with("foo", "bar",
+ mode=42)
+ self.test_client._put_file_shell.assert_called_once_with("foo", "bar",
+ mode=42)
+
+ def test_put_file_socket_error(self):
+ exc = socket.error
+ self.test_client._put_file_sftp = mock.Mock(side_effect=exc())
+ self.test_client._put_file_shell = mock.Mock()
+
+ self.test_client.put_file("foo", "bar", 42)
+ self.test_client._put_file_sftp.assert_called_once_with("foo", "bar",
+ mode=42)
+ self.test_client._put_file_shell.assert_called_once_with("foo", "bar",
+ mode=42)
+
+ @mock.patch("yardstick.ssh.os.stat")
+ def test_put_file_obj_with_mode(self, mock_stat):
+ sftp = self.fake_client.open_sftp.return_value = mock.MagicMock()
+ sftp.__enter__.return_value = sftp
+
+ mock_stat.return_value = os.stat_result([0o753] + [0] * 9)
+
+ self.test_client.put_file_obj("localfile", "remotefile", 'my_mode')
+
+ sftp.__enter__.assert_called_once()
+ sftp.putfo.assert_called_once_with("localfile", "remotefile")
+ sftp.chmod.assert_called_once_with("remotefile", 'my_mode')
+ sftp.__exit__.assert_called_once_with(None, None, None)
+
+
+class TestAutoConnectSSH(unittest.TestCase):
+
+ def test__connect_loop(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=0)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
+
+ auto_connect_ssh._connect()
+ mock__get_client.assert_called_once()
+
+ def test___init___negative(self):
+ with self.assertRaises(TypeError):
+ AutoConnectSSH('user1', 'host1', wait=['wait'])
+
+ with self.assertRaises(ValueError):
+ AutoConnectSSH('user1', 'host1', wait='wait')
+
+ @mock.patch('yardstick.ssh.time')
+ def test__connect_loop_ssh_error(self, mock_time):
+ mock_time.time.side_effect = count()
+
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=10)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
+ mock__get_client.side_effect = exceptions.SSHError
+
+ with self.assertRaises(exceptions.SSHTimeout):
+ auto_connect_ssh._connect()
+
+ self.assertEqual(mock_time.time.call_count, 12)
+
+ def test_get_file_obj(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1', wait=10)
+ auto_connect_ssh._get_client = mock__get_client = mock.Mock()
+ mock_client = mock__get_client()
+ mock_open_sftp = mock_client.open_sftp()
+ mock_sftp = mock.Mock()
+ mock_open_sftp.__enter__ = mock.Mock(return_value=mock_sftp)
+ mock_open_sftp.__exit__ = mock.Mock()
+
+ auto_connect_ssh.get_file_obj('remote/path', mock.Mock())
+
+ mock_sftp.getfo.assert_called_once()
+
+ def test__make_dict(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+
+ expected = {
+ 'user': 'user1',
+ 'host': 'host1',
+ 'port': SSH.SSH_PORT,
+ 'pkey': None,
+ 'key_filename': None,
+ 'password': None,
+ 'name': None,
+ 'wait': AutoConnectSSH.DEFAULT_WAIT_TIMEOUT,
+ }
+ result = auto_connect_ssh._make_dict()
+ self.assertDictEqual(result, expected)
+
+ def test_get_class(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+
+ self.assertEqual(auto_connect_ssh.get_class(), AutoConnectSSH)
+
+ def test_drop_connection(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ self.assertFalse(auto_connect_ssh._client)
+ auto_connect_ssh._client = True
+ auto_connect_ssh.drop_connection()
+ self.assertFalse(auto_connect_ssh._client)
+
+ @mock.patch('yardstick.ssh.SCPClient')
+ def test_put(self, mock_scp_client_type):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ auto_connect_ssh._client = mock.Mock()
+
+ auto_connect_ssh.put('a', 'z')
+ with mock_scp_client_type() as mock_scp_client:
+ mock_scp_client.put.assert_called_once()
+
+ @mock.patch('yardstick.ssh.SCPClient')
+ def test_get(self, mock_scp_client_type):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ auto_connect_ssh._client = mock.Mock()
+
+ auto_connect_ssh.get('a', 'z')
+ with mock_scp_client_type() as mock_scp_client:
+ mock_scp_client.get.assert_called_once()
+
+ def test_put_file(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ auto_connect_ssh._client = mock.Mock()
+ auto_connect_ssh._put_file_sftp = mock_put_sftp = mock.Mock()
+
+ auto_connect_ssh.put_file('a', 'b')
+ mock_put_sftp.assert_called_once()
+
+ def test_execute(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ auto_connect_ssh._client = mock.Mock()
+ auto_connect_ssh.run = mock.Mock(return_value=0)
+ exit_code, _, _ = auto_connect_ssh.execute('')
+ self.assertEqual(exit_code, 0)
+
+ def _mock_run(self, *args, **kwargs):
+ if args[0] == 'ls':
+ if kwargs.get('raise_on_error'):
+ raise exceptions.SSHError(error_msg='Command error')
+ return 1
+ return 0
+
+ def test_execute_command_error(self):
+ auto_connect_ssh = AutoConnectSSH('user1', 'host1')
+ auto_connect_ssh._client = mock.Mock()
+ auto_connect_ssh.run = mock.Mock(side_effect=self._mock_run)
+ self.assertRaises(exceptions.SSHError, auto_connect_ssh.execute, 'ls',
+ raise_on_error=True)
+ exit_code, _, _ = auto_connect_ssh.execute('ls')
+ self.assertNotEqual(exit_code, 0)