aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/database/v2/handlers.py3
-rw-r--r--api/resources/v1/env.py52
-rw-r--r--api/resources/v2/containers.py2
-rw-r--r--api/resources/v2/environments.py8
-rw-r--r--api/resources/v2/images.py8
-rw-r--r--api/resources/v2/openrcs.py8
-rw-r--r--api/resources/v2/pods.py8
-rw-r--r--api/resources/v2/projects.py8
-rw-r--r--api/resources/v2/tasks.py18
-rw-r--r--api/resources/v2/testcases.py8
-rw-r--r--api/resources/v2/testsuites.py8
-rw-r--r--api/utils/thread.py8
-rw-r--r--plugin/CI/storperf.yaml4
-rw-r--r--samples/storperf.yaml1
-rwxr-xr-xtests/ci/prepare_env.sh8
-rw-r--r--tests/ci/scp_storperf_files.sh21
-rwxr-xr-xtests/ci/yardstick-verify4
-rw-r--r--tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml9
-rw-r--r--tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml3
-rw-r--r--tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml6
-rw-r--r--tests/unit/benchmark/contexts/test_model.py35
-rw-r--r--tests/unit/benchmark/scenarios/networking/test_pktgen.py534
-rw-r--r--yardstick/benchmark/contexts/heat.py7
-rw-r--r--yardstick/benchmark/contexts/model.py29
-rw-r--r--yardstick/benchmark/core/plugin.py4
-rw-r--r--yardstick/benchmark/core/task.py7
-rw-r--r--yardstick/benchmark/scenarios/availability/attacker_conf.yaml7
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash42
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash65
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash2
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash2
-rw-r--r--yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash2
-rwxr-xr-xyardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash70
-rw-r--r--yardstick/benchmark/scenarios/availability/monitor_conf.yaml2
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen.py242
-rw-r--r--yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash139
-rw-r--r--yardstick/benchmark/scenarios/storage/fio.py32
-rw-r--r--yardstick/benchmark/scenarios/storage/storperf.py7
-rw-r--r--yardstick/common/constants.py2
-rw-r--r--yardstick/common/utils.py10
-rw-r--r--yardstick/network_services/vnf_generic/vnf/base.py1
-rw-r--r--yardstick/orchestrator/heat.py36
42 files changed, 1349 insertions, 123 deletions
diff --git a/api/database/v2/handlers.py b/api/database/v2/handlers.py
index 44c14df61..1bc32bf0e 100644
--- a/api/database/v2/handlers.py
+++ b/api/database/v2/handlers.py
@@ -173,6 +173,9 @@ class V2ProjectHandler(object):
class V2TaskHandler(object):
+ def list_all(self):
+ return V2Task.query.all()
+
def insert(self, kwargs):
task = V2Task(**kwargs)
db_session.add(task)
diff --git a/api/resources/v1/env.py b/api/resources/v1/env.py
index 4632f15fe..8943db3d1 100644
--- a/api/resources/v1/env.py
+++ b/api/resources/v1/env.py
@@ -65,16 +65,20 @@ class V1Env(ApiResource):
client.pull(consts.GRAFANA_IMAGE, consts.GRAFANA_TAG)
LOG.info('Createing grafana container')
- self._create_grafana_container(client)
+ container = self._create_grafana_container(client)
LOG.info('Grafana container is created')
time.sleep(5)
+ container = client.inspect_container(container['Id'])
+ ip = container['NetworkSettings']['Networks']['bridge']['IPAddress']
+ LOG.debug('container ip is: %s', ip)
+
LOG.info('Creating data source for grafana')
- self._create_data_source()
+ self._create_data_source(ip)
LOG.info('Creating dashboard for grafana')
- self._create_dashboard()
+ self._create_dashboard(ip)
self._update_task_status(task_id)
LOG.info('Finished')
@@ -82,8 +86,8 @@ class V1Env(ApiResource):
self._update_task_error(task_id, str(e))
LOG.exception('Create grafana failed')
- def _create_dashboard(self):
- url = 'http://admin:admin@%s:3000/api/dashboards/db' % consts.GRAFANA_IP
+ def _create_dashboard(self, ip):
+ url = 'http://admin:admin@{}:{}/api/dashboards/db'.format(ip, consts.GRAFANA_PORT)
path = os.path.join(consts.REPOS_DIR, 'dashboard', '*dashboard.json')
for i in sorted(glob.iglob(path)):
@@ -95,13 +99,21 @@ class V1Env(ApiResource):
LOG.exception('Create dashboard %s failed', i)
raise
- def _create_data_source(self):
- url = 'http://admin:admin@%s:3000/api/datasources' % consts.GRAFANA_IP
+ def _create_data_source(self, ip):
+ url = 'http://admin:admin@{}:{}/api/datasources'.format(ip, consts.GRAFANA_PORT)
+ influx_conf = utils.parse_ini_file(consts.CONF_FILE)
+
+ try:
+ influx_url = influx_conf['dispatcher_influxdb']['target']
+ except KeyError:
+ LOG.exception('influxdb url not set in yardstick.conf')
+ raise
+
data = {
"name": "yardstick",
"type": "influxdb",
"access": "proxy",
- "url": "http://%s:8086" % consts.INFLUXDB_IP,
+ "url": influx_url,
"password": "root",
"user": "root",
"database": "yardstick",
@@ -117,8 +129,8 @@ class V1Env(ApiResource):
raise
def _create_grafana_container(self, client):
- ports = [3000]
- port_bindings = {k: k for k in ports}
+ ports = [consts.GRAFANA_PORT]
+ port_bindings = {consts.GRAFANA_PORT: consts.GRAFANA_MAPPING_PORT}
restart_policy = {"MaximumRetryCount": 0, "Name": "always"}
host_config = client.create_host_config(port_bindings=port_bindings,
restart_policy=restart_policy)
@@ -133,6 +145,7 @@ class V1Env(ApiResource):
host_config=host_config)
LOG.info('Starting container')
client.start(container)
+ return container
def _check_image_exist(self, client, t):
return any(t in a['RepoTags'][0]
@@ -152,9 +165,6 @@ class V1Env(ApiResource):
client = Client(base_url=consts.DOCKER_URL)
try:
- LOG.info('Changing output to influxdb')
- self._change_output_to_influxdb()
-
LOG.info('Checking if influxdb image exist')
if not self._check_image_exist(client, '%s:%s' %
(consts.INFLUXDB_IMAGE,
@@ -163,11 +173,18 @@ class V1Env(ApiResource):
client.pull(consts.INFLUXDB_IMAGE, tag=consts.INFLUXDB_TAG)
LOG.info('Createing influxdb container')
- self._create_influxdb_container(client)
+ container = self._create_influxdb_container(client)
LOG.info('Influxdb container is created')
time.sleep(5)
+ container = client.inspect_container(container['Id'])
+ ip = container['NetworkSettings']['Networks']['bridge']['IPAddress']
+ LOG.debug('container ip is: %s', ip)
+
+ LOG.info('Changing output to influxdb')
+ self._change_output_to_influxdb(ip)
+
LOG.info('Config influxdb')
self._config_influxdb()
@@ -180,7 +197,7 @@ class V1Env(ApiResource):
def _create_influxdb_container(self, client):
- ports = [8083, 8086]
+ ports = [consts.INFLUXDB_DASHBOARD_PORT, consts.INFLUXDB_PORT]
port_bindings = {k: k for k in ports}
restart_policy = {"MaximumRetryCount": 0, "Name": "always"}
host_config = client.create_host_config(port_bindings=port_bindings,
@@ -196,6 +213,7 @@ class V1Env(ApiResource):
host_config=host_config)
LOG.info('Starting container')
client.start(container)
+ return container
def _config_influxdb(self):
try:
@@ -208,7 +226,7 @@ class V1Env(ApiResource):
except Exception:
LOG.exception('Config influxdb failed')
- def _change_output_to_influxdb(self):
+ def _change_output_to_influxdb(self, ip):
utils.makedirs(consts.CONF_DIR)
parser = configparser.ConfigParser()
@@ -218,7 +236,7 @@ class V1Env(ApiResource):
LOG.info('Set dispatcher to influxdb')
parser.set('DEFAULT', 'dispatcher', 'influxdb')
parser.set('dispatcher_influxdb', 'target',
- 'http://%s:8086' % consts.INFLUXDB_IP)
+ 'http://{}:{}'.format(ip, consts.INFLUXDB_PORT))
LOG.info('Writing to %s', consts.CONF_FILE)
with open(consts.CONF_FILE, 'w') as f:
diff --git a/api/resources/v2/containers.py b/api/resources/v2/containers.py
index ce7130376..66dc94120 100644
--- a/api/resources/v2/containers.py
+++ b/api/resources/v2/containers.py
@@ -1,5 +1,5 @@
##############################################################################
-# Copyright (c) 2016 Huawei Technologies Co.,Ltd and others.
+# 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
diff --git a/api/resources/v2/environments.py b/api/resources/v2/environments.py
index e4679b0d6..f021a3c5a 100644
--- a/api/resources/v2/environments.py
+++ b/api/resources/v2/environments.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 uuid
import logging
diff --git a/api/resources/v2/images.py b/api/resources/v2/images.py
index 701818493..8755e5265 100644
--- a/api/resources/v2/images.py
+++ b/api/resources/v2/images.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 logging
import subprocess
import threading
diff --git a/api/resources/v2/openrcs.py b/api/resources/v2/openrcs.py
index 5f3b9382f..cb506d0e8 100644
--- a/api/resources/v2/openrcs.py
+++ b/api/resources/v2/openrcs.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 uuid
import logging
import re
diff --git a/api/resources/v2/pods.py b/api/resources/v2/pods.py
index ebc1312da..f2316d353 100644
--- a/api/resources/v2/pods.py
+++ b/api/resources/v2/pods.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 uuid
import yaml
import logging
diff --git a/api/resources/v2/projects.py b/api/resources/v2/projects.py
index 376cf1a37..2ff61d0fe 100644
--- a/api/resources/v2/projects.py
+++ b/api/resources/v2/projects.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 uuid
import logging
diff --git a/api/resources/v2/tasks.py b/api/resources/v2/tasks.py
index 0eb95773a..b64f5ef24 100644
--- a/api/resources/v2/tasks.py
+++ b/api/resources/v2/tasks.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 uuid
import logging
from datetime import datetime
@@ -21,6 +29,16 @@ LOG.setLevel(logging.DEBUG)
class V2Tasks(ApiResource):
+ def get(self):
+ task_handler = V2TaskHandler()
+ tasks = [change_obj_to_dict(t) for t in task_handler.list_all()]
+
+ for t in tasks:
+ result = t['result']
+ t['result'] = jsonutils.loads(result) if result else None
+
+ return result_handler(consts.API_SUCCESS, {'tasks': tasks})
+
def post(self):
return self._dispatch_post()
diff --git a/api/resources/v2/testcases.py b/api/resources/v2/testcases.py
index 81b4aa88c..ca88e9856 100644
--- a/api/resources/v2/testcases.py
+++ b/api/resources/v2/testcases.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 logging
import errno
import os
diff --git a/api/resources/v2/testsuites.py b/api/resources/v2/testsuites.py
index ee942eff9..56ad47375 100644
--- a/api/resources/v2/testsuites.py
+++ b/api/resources/v2/testsuites.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 os
import errno
import logging
diff --git a/api/utils/thread.py b/api/utils/thread.py
index 5f4ec7e94..20bd07a12 100644
--- a/api/utils/thread.py
+++ b/api/utils/thread.py
@@ -1,3 +1,11 @@
+##############################################################################
+# 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 threading
import os
import logging
diff --git a/plugin/CI/storperf.yaml b/plugin/CI/storperf.yaml
index e144dd150..70915f661 100644
--- a/plugin/CI/storperf.yaml
+++ b/plugin/CI/storperf.yaml
@@ -7,7 +7,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
---
-# StorPerf plugin configration file for huawei-pod1
+# StorPerf plugin configration file for compass pod in CI
# Used for integration StorPerf into Yardstick as a plugin
schema: "yardstick:plugin:0.1"
@@ -16,6 +16,6 @@ plugins:
name: storperf
deployment:
- ip: 192.168.10.6
+ ip: local
user: root
password: root
diff --git a/samples/storperf.yaml b/samples/storperf.yaml
index 5000759e0..2ea022173 100644
--- a/samples/storperf.yaml
+++ b/samples/storperf.yaml
@@ -18,6 +18,7 @@ scenarios:
options:
agent_count: 1
agent_image: "Ubuntu-16.04"
+ agent_flavor: "storperf"
public_network: "ext-net"
volume_size: 2
# target:
diff --git a/tests/ci/prepare_env.sh b/tests/ci/prepare_env.sh
index 3d9cc298f..c3ee4c76b 100755
--- a/tests/ci/prepare_env.sh
+++ b/tests/ci/prepare_env.sh
@@ -11,7 +11,7 @@
# Perepare the environment to run yardstick ci
: ${DEPLOY_TYPE:='bm'} # Can be any of 'bm' (Bare Metal) or 'virt' (Virtual)
-
+: ${INSTALLER_TYPE:='unknown'}
: ${NODE_NAME:='unknown'}
: ${EXTERNAL_NETWORK:='admin_floating_net'}
@@ -61,9 +61,9 @@ export EXTERNAL_NETWORK INSTALLER_TYPE DEPLOY_TYPE NODE_NAME
# Prepare a admin-rc file for StorPerf integration
$YARDSTICK_REPO_DIR/tests/ci/prepare_storperf_admin-rc.sh
-# copy a admin-rc file for StorPerf integration to the deployment location
-if [ "$NODE_NAME" == "huawei-pod1" ]; then
- bash $YARDSTICK_REPO_DIR/tests/ci/scp_storperf_files.sh
+# copy Storperf related files to the deployment location
+if [ "$INSTALLER_TYPE" == "compass" ]; then
+ source $YARDSTICK_REPO_DIR/tests/ci/scp_storperf_files.sh
fi
# Fetching id_rsa file from jump_server..."
diff --git a/tests/ci/scp_storperf_files.sh b/tests/ci/scp_storperf_files.sh
index 234032cf1..ffcc710cb 100644
--- a/tests/ci/scp_storperf_files.sh
+++ b/tests/ci/scp_storperf_files.sh
@@ -12,9 +12,24 @@
# Copy storperf_admin-rc to deployment location.
ssh_options="-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"
+
+case "$NODE_NAME" in
+ "huawei-pod1")
+ JUMP_HOST_IP='192.168.10.6'
+ ;;
+ "huawei-pod2")
+ JUMP_HOST_IP='192.168.11.2'
+ ;;
+ *)
+ # no node name, exit
+ exit 1
+ ;;
+esac
+export JUMP_HOST_IP
+
sshpass -p root scp 2>/dev/null $ssh_options ~/storperf_admin-rc \
- root@192.168.10.6:/root/ &> /dev/null
+ root@${JUMP_HOST_IP}:/root/ &> /dev/null
sshpass -p root scp 2>/dev/null $ssh_options /home/opnfv/repos/storperf/docker-compose/docker-compose.yaml \
- root@192.168.10.6:/root/ &> /dev/null
+ root@${JUMP_HOST_IP}:/root/ &> /dev/null
sshpass -p root scp 2>/dev/null $ssh_options /home/opnfv/repos/storperf/docker-compose/nginx.conf \
- root@192.168.10.6:/root/ &> /dev/null
+ root@${JUMP_HOST_IP}:/root/ &> /dev/null
diff --git a/tests/ci/yardstick-verify b/tests/ci/yardstick-verify
index 096ea534f..751cf65f3 100755
--- a/tests/ci/yardstick-verify
+++ b/tests/ci/yardstick-verify
@@ -100,7 +100,7 @@ set -o pipefail
install_storperf()
{
# Install Storper on huawei-pod1
- if [ "$NODE_NAME" == "huawei-pod1" ]; then
+ if [ "$INSTALLER_TYPE" == "compass" ]; then
echo
echo "========== Installing storperf =========="
@@ -115,7 +115,7 @@ install_storperf()
remove_storperf()
{
# remove Storper from huawei-pod1
- if [ "$NODE_NAME" == "huawei-pod1" ]; then
+ if [ "$INSTALLER_TYPE" == "compass" ]; then
echo
echo "========== Removing storperf =========="
diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml
index 4c7fdab90..f5ccb255a 100644
--- a/tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml
+++ b/tests/opnfv/test_cases/opnfv_yardstick_tc008.yaml
@@ -29,12 +29,21 @@ scenarios:
packetsize: {{pkt_size}}
number_of_ports: {{num_ports}}
duration: 20
+ # choose vnic name: default to eth0
+ # vnic_name: 'ens3'
+ # turn on multiqueue inside VM
+ # multiqueue: True
+ # choose starting pps: default 1M;
+ # works with binary search runner Dynamictp to find max throughput per sla
+ # pps: 3000000
host: demeter.yardstick-TC008
target: poseidon.yardstick-TC008
runner:
type: Iteration
+ # binary search runner
+ # type: Dynamictp
iterations: 10
interval: 1
diff --git a/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml b/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
index 5bd3f676f..ef4f02c9e 100644
--- a/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
+++ b/tests/opnfv/test_cases/opnfv_yardstick_tc074.yaml
@@ -14,13 +14,14 @@ description: >
StorPerf is a tool to measure block and object storage performance in an NFVI.
{% set public_network = public_network or "ext-net" %}
-{% set StorPerf_ip = StorPerf_ip or "192.168.10.6" %}
+{% set StorPerf_ip = StorPerf_ip or "192.168.200.1" %}
scenarios:
-
type: StorPerf
options:
agent_count: 1
agent_image: "Ubuntu-16.04"
+ agent_flavor: "storperf"
public_network: {{public_network}}
volume_size: 4
block_sizes: "4096"
diff --git a/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml b/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml
index ba1a93cec..dea44c8b3 100644
--- a/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml
+++ b/tests/opnfv/test_suites/opnfv_os-nosdn-nofeature-ha_daily.yaml
@@ -134,10 +134,12 @@ test_cases:
file_name: opnfv_yardstick_tc074.yaml
constraint:
installer: compass
- pod: huawei-pod1
+ pod: huawei-pod1, huawei-pod2
task_args:
huawei-pod1: '{"public_network": "ext-net",
- "StorPerf_ip": "192.168.200.1"}'
+ "StorPerf_ip": "192.168.10.6"}'
+ huawei-pod2: '{"public_network": "ext-net",
+ "StorPerf_ip": "192.168.11.2"}'
-
file_name: opnfv_yardstick_tc075.yaml
constraint:
diff --git a/tests/unit/benchmark/contexts/test_model.py b/tests/unit/benchmark/contexts/test_model.py
index 3fb186b9b..1ce550306 100644
--- a/tests/unit/benchmark/contexts/test_model.py
+++ b/tests/unit/benchmark/contexts/test_model.py
@@ -161,6 +161,23 @@ class NetworkTestCase(unittest.TestCase):
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):
@@ -214,11 +231,12 @@ class ServerTestCase(unittest.TestCase):
attrs = {'image': 'some-image', 'flavor': 'some-flavor', 'floating_ip': '192.168.1.10', 'floating_ip_assoc': 'some-vm'}
test_server = model.Server('foo', self.mock_context, attrs)
- self.mock_context.flavors = ['flavor1', 'flavor2', 'some-flavor']
+ 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.subnet_stack_name = 'some-network-stack-subnet'
mock_network.provider = 'sriov'
mock_network.external_network = 'ext_net'
@@ -232,7 +250,8 @@ class ServerTestCase(unittest.TestCase):
mock_network.stack_name,
mock_network.subnet_stack_name,
sec_group_id=self.mock_context.secgroup_name,
- provider=mock_network.provider)
+ provider=mock_network.provider,
+ allowed_address_pairs=mock_network.allowed_address_pairs)
mock_template.add_floating_ip.assert_called_with(
'some-server-fip',
@@ -290,11 +309,12 @@ class ServerTestCase(unittest.TestCase):
}
test_server = model.Server('ServerFlavor-2', self.mock_context, attrs)
- self.mock_context.flavors = ['flavor2']
+ self.mock_context.flavors = ['flavor2']
mock_network = mock.Mock()
- mock_network.configure_mock(name='some-network', stack_name= 'some-network-stack',
- subnet_stack_name = 'some-network-stack-subnet',
- provider = 'some-provider')
+ mock_network.allowed_address_pairs = ["1", "2"]
+ 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')
@@ -304,7 +324,8 @@ class ServerTestCase(unittest.TestCase):
mock_network.stack_name,
mock_network.subnet_stack_name,
provider=mock_network.provider,
- sec_group_id=self.mock_context.secgroup_name)
+ 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',
diff --git a/tests/unit/benchmark/scenarios/networking/test_pktgen.py b/tests/unit/benchmark/scenarios/networking/test_pktgen.py
index d4eb1246f..2914c8e02 100644
--- a/tests/unit/benchmark/scenarios/networking/test_pktgen.py
+++ b/tests/unit/benchmark/scenarios/networking/test_pktgen.py
@@ -138,6 +138,7 @@ class PktgenTestCase(unittest.TestCase):
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_successful_sla(self, mock_ssh):
@@ -164,6 +165,7 @@ class PktgenTestCase(unittest.TestCase):
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_unsuccessful_sla(self, mock_ssh):
@@ -204,6 +206,538 @@ class PktgenTestCase(unittest.TestCase):
mock_ssh.SSH.from_node().execute.return_value = (1, '', 'FOOBAR')
self.assertRaises(RuntimeError, p.run, result)
+ def test_pktgen_get_vnic_driver_name(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, 'ixgbevf', '')
+
+ vnic_driver_name = p._get_vnic_driver_name()
+ self.assertEqual(vnic_driver_name, 'ixgbevf')
+
+ def test_pktgen_unsuccessful_get_vnic_driver_name(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._get_vnic_driver_name)
+
+ def test_pktgen_get_sriov_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '2', '')
+
+ p.queue_number = p._get_sriov_queue_number()
+ self.assertEqual(p.queue_number, 2)
+
+ def test_pktgen_unsuccessful_get_sriov_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._get_sriov_queue_number)
+
+ def test_pktgen_get_available_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '4', '')
+
+ p._get_available_queue_number()
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "sudo ethtool -l eth0 | grep Combined | head -1 |" \
+ "awk '{printf $2}'")
+
+ def test_pktgen_unsuccessful_get_available_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._get_available_queue_number)
+
+ def test_pktgen_get_usable_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '1', '')
+
+ p._get_usable_queue_number()
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "sudo ethtool -l eth0 | grep Combined | tail -1 |" \
+ "awk '{printf $2}'")
+
+ def test_pktgen_unsuccessful_get_usable_queue_number(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._get_usable_queue_number)
+
+ def test_pktgen_enable_ovs_multiqueue(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '4', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = 1
+ p._get_usable_queue_number = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = 4
+ p._get_available_queue_number = mock_result2
+
+ p.queue_number = p._enable_ovs_multiqueue()
+ self.assertEqual(p.queue_number, 4)
+
+ def test_pktgen_enable_ovs_multiqueue_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '1', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = 1
+ p._get_usable_queue_number = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = 1
+ p._get_available_queue_number = mock_result2
+
+ p.queue_number = p._enable_ovs_multiqueue()
+ self.assertEqual(p.queue_number, 1)
+
+ def test_pktgen_unsuccessful_enable_ovs_multiqueue(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = 1
+ p._get_usable_queue_number = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = 4
+ p._get_available_queue_number = mock_result2
+
+ self.assertRaises(RuntimeError, p._enable_ovs_multiqueue)
+
+ def test_pktgen_setup_irqmapping_ovs(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '10', '')
+
+ p._setup_irqmapping_ovs(4)
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "echo 8 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_pktgen_setup_irqmapping_ovs_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '10', '')
+
+ p._setup_irqmapping_ovs(1)
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "echo 1 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_pktgen_unsuccessful_setup_irqmapping_ovs(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._setup_irqmapping_ovs, 4)
+
+ def test_pktgen_unsuccessful_setup_irqmapping_ovs_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._setup_irqmapping_ovs, 1)
+
+ def test_pktgen_setup_irqmapping_sriov(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '10', '')
+
+ p._setup_irqmapping_sriov(2)
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "echo 2 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_pktgen_setup_irqmapping_sriov_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '10', '')
+
+ p._setup_irqmapping_sriov(1)
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "echo 1 | sudo tee /proc/irq/10/smp_affinity")
+
+ def test_pktgen_unsuccessful_setup_irqmapping_sriov(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._setup_irqmapping_sriov, 2)
+
+ def test_pktgen_unsuccessful_setup_irqmapping_sriov_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._setup_irqmapping_sriov, 1)
+
+ def test_pktgen_is_irqbalance_disabled(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p._is_irqbalance_disabled()
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "grep ENABLED /etc/default/irqbalance")
+
+ def test_pktgen_unsuccessful_is_irqbalance_disabled(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._is_irqbalance_disabled)
+
+ def test_pktgen_disable_irqbalance(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '', '')
+
+ p._disable_irqbalance()
+
+ mock_ssh.SSH.from_node().execute.assert_called_with(
+ "sudo service irqbalance disable")
+
+ def test_pktgen_unsuccessful_disable_irqbalance(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (1, '', '')
+
+ self.assertRaises(RuntimeError, p._disable_irqbalance)
+
+ def test_pktgen_multiqueue_setup_ovs(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'multiqueue': True},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '4', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = False
+ p._is_irqbalance_disabled = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = "virtio_net"
+ p._get_vnic_driver_name = mock_result2
+
+ mock_result3 = mock.Mock()
+ mock_result3.return_value = 1
+ p._get_usable_queue_number = mock_result3
+
+ mock_result4 = mock.Mock()
+ mock_result4.return_value = 4
+ p._get_available_queue_number = mock_result4
+
+ p.multiqueue_setup()
+
+ self.assertEqual(p.queue_number, 4)
+
+ def test_pktgen_multiqueue_setup_ovs_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'multiqueue': True},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '1', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = False
+ p._is_irqbalance_disabled = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = "virtio_net"
+ p._get_vnic_driver_name = mock_result2
+
+ mock_result3 = mock.Mock()
+ mock_result3.return_value = 1
+ p._get_usable_queue_number = mock_result3
+
+ mock_result4 = mock.Mock()
+ mock_result4.return_value = 1
+ p._get_available_queue_number = mock_result4
+
+ p.multiqueue_setup()
+
+ self.assertEqual(p.queue_number, 1)
+
+ def test_pktgen_multiqueue_setup_sriov(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'multiqueue': True},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '2', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = False
+ p._is_irqbalance_disabled = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = "ixgbevf"
+ p._get_vnic_driver_name = mock_result2
+
+ p.multiqueue_setup()
+
+ self.assertEqual(p.queue_number, 2)
+
+ def test_pktgen_multiqueue_setup_sriov_1q(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'multiqueue': True},
+ }
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_ssh.SSH.from_node().execute.return_value = (0, '1', '')
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = False
+ p._is_irqbalance_disabled = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = "ixgbevf"
+ p._get_vnic_driver_name = mock_result2
+
+ p.multiqueue_setup()
+
+ self.assertEqual(p.queue_number, 1)
+
+ def test_pktgen_run_with_setup_done(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10, 'duration': 20, 'multiqueue': True},
+ 'sla': {'max_ppm': 1}
+ }
+ result = {}
+ p = pktgen.Pktgen(args, self.ctx)
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ p.setup_done = True
+ p.multiqueue_setup_done = True
+
+ mock_iptables_result = mock.Mock()
+ mock_iptables_result.return_value = 149300
+ p._iptables_get_result = mock_iptables_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149300, "flows": 110}'
+ mock_ssh.SSH.from_node().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_run_with_ovs_multiqueque(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10, 'duration': 20, 'multiqueue': True},
+ 'sla': {'max_ppm': 1}
+ }
+ result = {}
+
+ p = pktgen.Pktgen(args, self.ctx)
+
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_result = mock.Mock()
+ mock_result.return_value = "virtio_net"
+ p._get_vnic_driver_name = mock_result
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = 1
+ p._get_usable_queue_number = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = 4
+ p._get_available_queue_number = mock_result2
+
+ mock_result3 = mock.Mock()
+ mock_result3.return_value = 4
+ p._enable_ovs_multiqueue = mock_result3
+
+ mock_result4 = mock.Mock()
+ p._setup_irqmapping_ovs = mock_result4
+
+ mock_iptables_result = mock.Mock()
+ mock_iptables_result.return_value = 149300
+ p._iptables_get_result = mock_iptables_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149300, "flows": 110}'
+ mock_ssh.SSH.from_node().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_run_with_sriov_multiqueque(self, mock_ssh):
+ args = {
+ 'options': {'packetsize': 60, 'number_of_ports': 10, 'duration': 20, 'multiqueue': True},
+ 'sla': {'max_ppm': 1}
+ }
+ result = {}
+
+ p = pktgen.Pktgen(args, self.ctx)
+
+ p.server = mock_ssh.SSH.from_node()
+ p.client = mock_ssh.SSH.from_node()
+
+ mock_result1 = mock.Mock()
+ mock_result1.return_value = "ixgbevf"
+ p._get_vnic_driver_name = mock_result1
+
+ mock_result2 = mock.Mock()
+ mock_result2.return_value = 2
+ p._get_sriov_queue_number = mock_result2
+
+ mock_result3 = mock.Mock()
+ p._setup_irqmapping_sriov = mock_result3
+
+ mock_iptables_result = mock.Mock()
+ mock_iptables_result.return_value = 149300
+ p._iptables_get_result = mock_iptables_result
+
+ sample_output = '{"packets_per_second": 9753, "errors": 0, \
+ "packets_sent": 149300, "flows": 110}'
+ mock_ssh.SSH.from_node().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 main():
unittest.main()
diff --git a/yardstick/benchmark/contexts/heat.py b/yardstick/benchmark/contexts/heat.py
index 0a94dd976..d5349eab5 100644
--- a/yardstick/benchmark/contexts/heat.py
+++ b/yardstick/benchmark/contexts/heat.py
@@ -152,9 +152,12 @@ class HeatContext(Context):
template.add_network(network.stack_name,
network.physical_network,
network.provider,
- network.segmentation_id)
+ network.segmentation_id,
+ network.port_security_enabled)
template.add_subnet(network.subnet_stack_name, network.stack_name,
- network.subnet_cidr)
+ network.subnet_cidr,
+ network.enable_dhcp,
+ network.gateway_ip)
if network.router:
template.add_router(network.router.stack_name,
diff --git a/yardstick/benchmark/contexts/model.py b/yardstick/benchmark/contexts/model.py
index 06538d8a9..6601ecf3b 100644
--- a/yardstick/benchmark/contexts/model.py
+++ b/yardstick/benchmark/contexts/model.py
@@ -104,11 +104,24 @@ class Network(Object):
self.stack_name = context.name + "-" + self.name
self.subnet_stack_name = self.stack_name + "-subnet"
self.subnet_cidr = attrs.get('cidr', '10.0.1.0/24')
+ self.enable_dhcp = attrs.get('enable_dhcp', 'true')
self.router = None
self.physical_network = attrs.get('physical_network', 'physnet1')
self.provider = attrs.get('provider')
self.segmentation_id = attrs.get('segmentation_id')
self.network_type = attrs.get('network_type')
+ self.port_security_enabled = attrs.get('port_security_enabled', True)
+ self.allowed_address_pairs = attrs.get('allowed_address_pairs', [])
+ try:
+ # we require 'null' or '' to disable setting gateway_ip
+ self.gateway_ip = attrs['gateway_ip']
+ except KeyError:
+ # default to explicit None
+ self.gateway_ip = None
+ else:
+ # null is None in YAML, so we have to convert back to string
+ if self.gateway_ip is None:
+ self.gateway_ip = "null"
if "external_network" in attrs:
self.router = Router("router", self.name,
@@ -234,10 +247,16 @@ class Server(Object): # pragma: no cover
for network in networks:
port_name = server_name + "-" + network.name + "-port"
self.ports[network.name] = {"stack_name": port_name}
- template.add_port(port_name, network.stack_name,
- network.subnet_stack_name,
- sec_group_id=self.secgroup_name,
- provider=network.provider)
+ # we can't use secgroups if port_security_enabled is False
+ if network.port_security_enabled:
+ sec_group_id = self.secgroup_name
+ else:
+ sec_group_id = None
+ # don't refactor to pass in network object, that causes JSON
+ # circular ref encode errors
+ template.add_port(port_name, network.stack_name, network.subnet_stack_name,
+ sec_group_id=sec_group_id, provider=network.provider,
+ allowed_address_pairs=network.allowed_address_pairs)
port_name_list.append(port_name)
if self.floating_ip:
@@ -248,7 +267,7 @@ class Server(Object): # pragma: no cover
external_network,
port_name,
network.router.stack_if_name,
- self.secgroup_name)
+ sec_group_id)
self.floating_ip_assoc["stack_name"] = \
server_name + "-fip-assoc"
template.add_floating_ip_association(
diff --git a/yardstick/benchmark/core/plugin.py b/yardstick/benchmark/core/plugin.py
index 7f67a04b3..6c06767d5 100644
--- a/yardstick/benchmark/core/plugin.py
+++ b/yardstick/benchmark/core/plugin.py
@@ -84,8 +84,8 @@ class Plugin(object):
if deployment_ip == "local":
self.client = ssh.SSH.from_node(deployment, overrides={
- # host can't be None, fail if no INSTALLER_IP
- 'ip': os.environ["INSTALLER_IP"],
+ # host can't be None, fail if no JUMP_HOST_IP
+ 'ip': os.environ["JUMP_HOST_IP"],
})
else:
self.client = ssh.SSH.from_node(deployment)
diff --git a/yardstick/benchmark/core/task.py b/yardstick/benchmark/core/task.py
index b53d6446e..ede14b1c0 100644
--- a/yardstick/benchmark/core/task.py
+++ b/yardstick/benchmark/core/task.py
@@ -58,7 +58,12 @@ class Task(object): # pragma: no cover
check_environment()
- output_config = utils.parse_ini_file(config_file)
+ try:
+ output_config = utils.parse_ini_file(config_file)
+ except Exception:
+ # all error will be ignore, the default value is {}
+ output_config = {}
+
self._init_output_config(output_config)
self._set_output_config(output_config, args.output_file)
LOG.debug('Output configuration is: %s', output_config)
diff --git a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
index b8c34ad44..aa144ab50 100644
--- a/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/attacker_conf.yaml
@@ -16,6 +16,11 @@ kill-process:
inject_script: ha_tools/fault_process_kill.bash
recovery_script: ha_tools/start_service.bash
+kill-lxc-process:
+ check_script: ha_tools/check_lxc_process_python.bash
+ inject_script: ha_tools/fault_lxc_process_kill.bash
+ recovery_script: ha_tools/start_lxc_service.bash
+
bare-metal-down:
check_script: ha_tools/check_host_ping.bash
recovery_script: ha_tools/ipmi_power.bash
@@ -34,4 +39,4 @@ stress-cpu:
block-io:
inject_script: ha_tools/disk/block_io.bash
- recovery_script: ha_tools/disk/recovery_disk_io.bash \ No newline at end of file
+ recovery_script: ha_tools/disk/recovery_disk_io.bash
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash b/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash
new file mode 100755
index 000000000..6d2f4dd51
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/check_lxc_process_python.bash
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+##############################################################################
+# 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
+##############################################################################
+
+# check the status of a service
+
+set -e
+
+NOVA_API_PROCESS_1="nova-api-os-compute"
+NOVA_API_PROCESS_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+process_name=$1
+
+lxc_filter=$(echo "${process_name}" | sed 's/-/_/g')
+
+if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+fi
+
+if [ "${process_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ echo $(($(lxc-attach -n "${container_1}" -- ps aux | grep -e "${NOVA_API_PROCESS_1}" | grep -v grep | grep -cv /bin/sh) + $(lxc-attach -n "${container_2}" -- ps aux | grep -e "${NOVA_API_PROCESS_2}" | grep -v grep | grep -cv /bin/sh)))
+else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ if [ "${process_name}" = "haproxy" ]; then
+ ps aux | grep -e "/usr/.*/${process_name}" | grep -v grep | grep -cv /bin/sh
+ else
+ lxc-attach -n "${container}" -- ps aux | grep -e "${process_name}" | grep -v grep | grep -cv /bin/sh
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash b/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash
new file mode 100755
index 000000000..b0b86ab65
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/fault_lxc_process_kill.bash
@@ -0,0 +1,65 @@
+#!/bin/sh
+
+##############################################################################
+# 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
+##############################################################################
+
+# Stop process by process name
+
+set -e
+
+NOVA_API_PROCESS_1="nova-api-os-compute"
+NOVA_API_PROCESS_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+process_name=$1
+
+lxc_filter=$(echo "${process_name}" | sed 's/-/_/g')
+
+if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+fi
+
+if [ "${process_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ pids_1=$(lxc-attach -n "${container_1}" -- pgrep -f "/openstack/.*/${NOVA_API_PROCESS_1}")
+ for pid in ${pids_1};
+ do
+ lxc-attach -n "${container_1}" -- kill -9 "${pid}"
+ done
+
+ pids_2=$(lxc-attach -n "${container_2}" -- pgrep -f "/openstack/.*/${NOVA_API_PROCESS_2}")
+ for pid in ${pids_2};
+ do
+ lxc-attach -n "${container_2}" -- kill -9 "${pid}"
+ done
+else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ if [ "${process_name}" = "haproxy" ]; then
+ for pid in $(pgrep -cf "/usr/.*/${process_name}");
+ do
+ kill -9 "${pid}"
+ done
+ elif [ "${process_name}" = "keystone" ]; then
+ pids=$(lxc-attach -n "${container}" -- ps aux | grep "keystone" | grep -iv heartbeat | grep -iv monitor | grep -v grep | grep -v /bin/sh | awk '{print $2}')
+ for pid in ${pids};
+ do
+ lxc-attach -n "${container}" -- kill -9 "${pid}"
+ done
+ else
+ pids=$(lxc-attach -n "${container}" -- pgrep -f "/openstack/.*/${process_name}")
+ for pid in ${pids};
+ do
+ lxc-attach -n "${container}" -- kill -9 "${pid}"
+ done
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
index aee516ea9..7408409a9 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/create_flavor.bash
@@ -20,4 +20,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor create $1 --id $2 --ram $3 --disk $4 --vcpus $5
+openstack ${SECURE} flavor create $1 --id $2 --ram $3 --disk $4 --vcpus $5
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
index d39926fc5..7240476f7 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/delete_flavor.bash
@@ -20,4 +20,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor delete $1
+openstack ${SECURE} flavor delete $1
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash b/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
index bd61ba9bb..e679fdb9e 100644
--- a/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/nova/show_flavors.bash
@@ -19,4 +19,4 @@ else
SECURE=""
fi
-openstack "${SECURE}" flavor list
+openstack ${SECURE} flavor list
diff --git a/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash b/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash
new file mode 100755
index 000000000..36a673977
--- /dev/null
+++ b/yardstick/benchmark/scenarios/availability/ha_tools/start_lxc_service.bash
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+##############################################################################
+# 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
+##############################################################################
+
+# Start a service and check the service is started
+
+set -e
+
+NOVA_API_SERVICE_1="nova-api-os-compute"
+NOVA_API_SERVICE_2="nova-api-metadata"
+NOVA_API_LXC_FILTER_1="nova_api_os_compute"
+NOVA_API_LXC_FILTER_2="nova_api_metadata"
+
+service_name=$1
+
+if [ "${service_name}" = "haproxy" ]; then
+ if which systemctl 2>/dev/null; then
+ systemctl start $service_name
+ else
+ service $service_name start
+ fi
+else
+ lxc_filter=${service_name//-/_}
+
+ if [ "${lxc_filter}" = "glance_api" ]; then
+ lxc_filter="glance"
+ fi
+
+ if [ "${service_name}" = "nova-api" ]; then
+ container_1=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_1}")
+ container_2=$(lxc-ls -1 --filter="${NOVA_API_LXC_FILTER_2}")
+
+ if lxc-attach -n "${container_1}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container_1}" -- systemctl start "${NOVA_API_SERVICE_1}"
+ else
+ lxc-attach -n "${container_1}" -- service "${NOVA_API_SERVICE_1}" start
+ fi
+
+ if lxc-attach -n "${container_2}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container_2}" -- systemctl start "${NOVA_API_SERVICE_2}"
+ else
+ lxc-attach -n "${container_2}" -- service "${NOVA_API_SERVICE_2}" start
+ fi
+ else
+ container=$(lxc-ls -1 --filter="${lxc_filter}")
+
+ Distributor=$(lxc-attach -n "${container}" -- lsb_release -a | grep "Distributor ID" | awk '{print $3}')
+
+ if [ "${Distributor}" != "Ubuntu" -a "${service_name}" != "keystone" -a "${service_name}" != "neutron-server" ]; then
+ service_name="openstack-"${service_name}
+ elif [ "${Distributor}" = "Ubuntu" -a "${service_name}" = "keystone" ]; then
+ service_name="apache2"
+ elif [ "${service_name}" = "keystone" ]; then
+ service_name="httpd"
+ fi
+
+ if lxc-attach -n "${container}" -- which systemctl 2>/dev/null; then
+ lxc-attach -n "${container}" -- systemctl start "${service_name}"
+ else
+ lxc-attach -n "${container}" -- service "${service_name}" start
+ fi
+ fi
+fi
diff --git a/yardstick/benchmark/scenarios/availability/monitor_conf.yaml b/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
index 511449221..a08347d2d 100644
--- a/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
+++ b/yardstick/benchmark/scenarios/availability/monitor_conf.yaml
@@ -13,6 +13,8 @@ schema: "yardstick:task:0.1"
process-status:
monitor_script: ha_tools/check_process_python.bash
+lxc_process-status:
+ monitor_script: ha_tools/check_lxc_process_python.bash
nova-image-list:
monitor_script: ha_tools/nova_image_list.bash
service-status:
diff --git a/yardstick/benchmark/scenarios/networking/pktgen.py b/yardstick/benchmark/scenarios/networking/pktgen.py
index e6aa7e5fb..8ca1ca60e 100644
--- a/yardstick/benchmark/scenarios/networking/pktgen.py
+++ b/yardstick/benchmark/scenarios/networking/pktgen.py
@@ -9,6 +9,7 @@
from __future__ import absolute_import
from __future__ import print_function
+import os
import logging
import pkg_resources
@@ -19,6 +20,9 @@ from yardstick.benchmark.scenarios import base
LOG = logging.getLogger(__name__)
+VNIC_TYPE_LIST = ["ovs", "sriov"]
+SRIOV_DRIVER_LIST = ["ixgbevf", "i40evf"]
+
class Pktgen(base.Scenario):
"""Execute pktgen between two hosts
@@ -44,7 +48,11 @@ class Pktgen(base.Scenario):
def __init__(self, scenario_cfg, context_cfg):
self.scenario_cfg = scenario_cfg
self.context_cfg = context_cfg
+ self.vnic_name = "eth0"
+ self.vnic_type = "ovs"
+ self.queue_number = 1
self.setup_done = False
+ self.multiqueue_setup_done = False
def setup(self):
"""scenario setup"""
@@ -67,6 +75,212 @@ class Pktgen(base.Scenario):
self.setup_done = True
+ def multiqueue_setup(self):
+ # one time setup stuff
+ cmd = "sudo sysctl -w net.core.netdev_budget=3000"
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ cmd = "sudo sysctl -w net.core.netdev_max_backlog=100000"
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ """multiqueue setup"""
+ if not self._is_irqbalance_disabled():
+ self._disable_irqbalance()
+
+ vnic_driver_name = self._get_vnic_driver_name()
+ if vnic_driver_name in SRIOV_DRIVER_LIST:
+ self.vnic_type = "sriov"
+
+ # one time setup stuff
+ cmd = "sudo ethtool -G %s rx 4096 tx 4096" % self.vnic_name
+ self.server.send_command(cmd)
+ self.client.send_command(cmd)
+
+ self.queue_number = self._get_sriov_queue_number()
+ self._setup_irqmapping_sriov(self.queue_number)
+ else:
+ self.vnic_type = "ovs"
+ self.queue_number = self._enable_ovs_multiqueue()
+ self._setup_irqmapping_ovs(self.queue_number)
+
+ self.multiqueue_setup_done = True
+
+ def _get_vnic_driver_name(self):
+ cmd = "readlink /sys/class/net/%s/device/driver" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return os.path.basename(stdout.strip())
+
+ def _is_irqbalance_disabled(self):
+ """Did we disable irqbalance already in the guest?"""
+ is_disabled = False
+ cmd = "grep ENABLED /etc/default/irqbalance"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ if "0" in stdout:
+ is_disabled = True
+
+ return is_disabled
+
+ def _disable_irqbalance(self):
+ cmd = "sudo sed -i -e 's/ENABLED=\"1\"/ENABLED=\"0\"/g' " \
+ "/etc/default/irqbalance"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "sudo service irqbalance stop"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "sudo service irqbalance disable"
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _setup_irqmapping_ovs(self, queue_number):
+ cmd = "grep 'virtio0-input.0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "grep 'virtio0-output.0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'"
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ if queue_number == 1:
+ return
+
+ for i in range(1, queue_number):
+ cmd = "grep 'virtio0-input.%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "grep 'virtio0-output.%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _setup_irqmapping_sriov(self, queue_number):
+ cmd = "grep '%s-TxRx-0' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % self.vnic_name
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo 1 | sudo tee /proc/irq/%s/smp_affinity" % (int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ if queue_number == 1:
+ return
+
+ for i in range(1, queue_number):
+ cmd = "grep '%s-TxRx-%s' /proc/interrupts |" \
+ "awk '{match($0,/ +[0-9]+/)} " \
+ "{print substr($1,RSTART,RLENGTH-1)}'" % (self.vnic_name, i)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ cmd = "echo %s | sudo tee /proc/irq/%s/smp_affinity" \
+ % (1 << i, int(stdout))
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+
+ def _get_sriov_queue_number(self):
+ """Get queue number from server as both VMs are the same"""
+ cmd = "grep %s-TxRx- /proc/interrupts | wc -l" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _get_available_queue_number(self):
+ """Get queue number from client as both VMs are the same"""
+ cmd = "sudo ethtool -l %s | grep Combined | head -1 |" \
+ "awk '{printf $2}'" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _get_usable_queue_number(self):
+ """Get queue number from client as both VMs are the same"""
+ cmd = "sudo ethtool -l %s | grep Combined | tail -1 |" \
+ "awk '{printf $2}'" % self.vnic_name
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return int(stdout)
+
+ def _enable_ovs_multiqueue(self):
+ available_queue_number = self._get_available_queue_number()
+ usable_queue_number = self._get_usable_queue_number()
+ if available_queue_number > 1 and \
+ available_queue_number != usable_queue_number:
+ cmd = "sudo ethtool -L %s combined %s" % \
+ (self.vnic_name, available_queue_number)
+ LOG.debug("Executing command: %s", cmd)
+ status, stdout, stderr = self.server.execute(cmd)
+ status, stdout, stderr = self.client.execute(cmd)
+ if status:
+ raise RuntimeError(stderr)
+ return available_queue_number
+
def _iptables_setup(self):
"""Setup iptables on server to monitor for received packets"""
cmd = "sudo iptables -F; " \
@@ -99,6 +313,14 @@ class Pktgen(base.Scenario):
options = self.scenario_cfg['options']
packetsize = options.get("packetsize", 60)
self.number_of_ports = options.get("number_of_ports", 10)
+ self.vnic_name = options.get("vnic_name", "eth0")
+ ovs_dpdk = options.get("ovs_dpdk", False)
+ pps = options.get("pps", 1000000)
+ multiqueue = options.get("multiqueue", False)
+
+ if multiqueue and not self.multiqueue_setup_done:
+ self.multiqueue_setup()
+
# if run by a duration runner
duration_time = self.scenario_cfg["runner"].get("duration", None) \
if "runner" in self.scenario_cfg else None
@@ -114,8 +336,18 @@ class Pktgen(base.Scenario):
self._iptables_setup()
- cmd = "sudo bash pktgen.sh %s %s %s %s" \
- % (ipaddr, self.number_of_ports, packetsize, duration)
+ queue_number = self.queue_number
+
+ # For native OVS, half of vCPUs are used by vhost kernel threads
+ # hence set the queue_number to half number of vCPUs
+ # e.g. set queue_number to 2 if there are 4 vCPUs
+ if self.vnic_type == "ovs" and not ovs_dpdk and self.queue_number > 1:
+ queue_number = self.queue_number / 2
+
+ cmd = "sudo bash pktgen.sh %s %s %s %s %s %s" \
+ % (ipaddr, self.number_of_ports, packetsize,
+ duration, queue_number, pps)
+
LOG.debug("Executing command: %s", cmd)
status, stdout, stderr = self.client.execute(cmd)
@@ -131,12 +363,15 @@ class Pktgen(base.Scenario):
sent = result['packets_sent']
received = result['packets_received']
ppm = 1000000 * (sent - received) / sent
+ # if ppm is 1, then 11 out of 10 million is no pass
+ ppm += (sent - received) % sent > 0
+ LOG.debug("Lost packets %d - Lost ppm %d", (sent - received), ppm)
sla_max_ppm = int(self.scenario_cfg["sla"]["max_ppm"])
assert ppm <= sla_max_ppm, "ppm %d > sla_max_ppm %d; " \
% (ppm, sla_max_ppm)
-def _test():
+def _test(): # pragma: no cover
"""internal test function"""
key_filename = pkg_resources.resource_filename('yardstick.resources',
'files/yardstick_key')
@@ -165,6 +400,5 @@ def _test():
p.run(result)
print(result)
-
if __name__ == '__main__':
_test()
diff --git a/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
index 4224c5abf..e338a1b09 100644
--- a/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
+++ b/yardstick/benchmark/scenarios/networking/pktgen_benchmark.bash
@@ -16,6 +16,8 @@ DST_IP=$1 # destination IP address
NUM_PORTS=$2 # number of source ports
PKT_SIZE=$3 # packet size
DURATION=$4 # test duration (seconds)
+TRXQUEUE=$5 # number of RX/TX queues to use
+PPS=$6 # packets per second to send
# Configuration
UDP_SRC_MIN=1000 # UDP source port min
@@ -37,62 +39,100 @@ pgset()
fi
}
+# remove all devices from thread
+pgclean()
+{
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ #
+ # Thread commands
+ #
+
+ PGDEV=/proc/net/pktgen/kpktgend_${COUNTER}
+
+ # Remove all devices from this thread
+ pgset "rem_device_all"
+ let COUNTER=COUNTER+1
+ done
+}
+
# configure pktgen (see pktgen doc for details)
pgconfig()
{
- #
- # Thread commands
- #
+ pps=$(( PPS / TRXQUEUE ))
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ #
+ # Thread commands
+ #
- PGDEV=/proc/net/pktgen/kpktgend_0
+ PGDEV=/proc/net/pktgen/kpktgend_${COUNTER}
- # Remove all devices from this thread
- pgset "rem_device_all"
+ # Add device to thread
+ pgset "add_device $DEV@${COUNTER}"
- # Add device to thread
- pgset "add_device $DEV"
+ #
+ # Device commands
+ #
- #
- # Device commands
- #
+ PGDEV=/proc/net/pktgen/$DEV@${COUNTER}
- PGDEV=/proc/net/pktgen/$DEV
+ # 0 means continious sends untill explicitly stopped
+ pgset "count 0"
- # 0 means continious sends untill explicitly stopped
- pgset "count 0"
+ # set pps count to test with an explicit number. if 0 will try with bandwidth
+ if [ ${pps} -gt 0 ]
+ then
+ pgset "ratep ${pps}"
+ fi
- # use single SKB for all transmits
- pgset "clone_skb 0"
+ pgset "clone_skb 10"
- # packet size, NIC adds 4 bytes CRC
- pgset "pkt_size $PKT_SIZE"
+ # use different queue per thread
+ pgset "queue_map_min ${COUNTER}"
+ pgset "queue_map_max ${COUNTER}"
- # random address within the min-max range
- pgset "flag IPDST_RND UDPSRC_RND UDPDST_RND"
+ # packet size, NIC adds 4 bytes CRC
+ pgset "pkt_size $PKT_SIZE"
- # destination IP
- pgset "dst_min $DST_IP"
- pgset "dst_max $DST_IP"
+ # random address within the min-max range
+ pgset "flag UDPDST_RND"
+ pgset "flag UDPSRC_RND"
+ pgset "flag IPDST_RND"
- # destination MAC address
- pgset "dst_mac $MAC"
+ # destination IP
+ pgset "dst_min $DST_IP"
+ pgset "dst_max $DST_IP"
+
+ # destination MAC address
+ pgset "dst_mac $MAC"
+
+ # source UDP port range
+ pgset "udp_src_min $UDP_SRC_MIN"
+ pgset "udp_src_max $UDP_SRC_MAX"
- # source UDP port range
- pgset "udp_src_min $UDP_SRC_MIN"
- pgset "udp_src_max $UDP_SRC_MAX"
+ # destination UDP port range
+ pgset "udp_dst_min $UDP_DST_MIN"
+ pgset "udp_dst_max $UDP_DST_MAX"
- # destination UDP port range
- pgset "udp_dst_min $UDP_DST_MIN"
- pgset "udp_dst_max $UDP_DST_MAX"
+ let COUNTER=COUNTER+1
+
+ done
}
# run pktgen
pgrun()
{
- # Time to run, result can be vieved in /proc/net/pktgen/$DEV
+ # Time to run, result can be viewed in /proc/net/pktgen/$DEV
PGDEV=/proc/net/pktgen/pgctrl
# Will hang, Ctrl-C or SIGINT to stop
pgset "start" start
+
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ taskset -c ${COUNTER} kpktgend_${COUNTER}
+ let COUNTER=COUNTER+1
+ done
}
# run pktgen for ${DURATION} seconds
@@ -111,19 +151,28 @@ run_test()
# write the result to stdout in json format
output_json()
{
- sent=$(awk '/^Result:/{print $5}' <$PGDEV)
- pps=$(awk 'match($0,/'\([0-9]+\)pps'/, a) {print a[1]}' <$PGDEV)
- errors=$(awk '/errors:/{print $5}' <$PGDEV)
+ sent=0
+ result_pps=0
+ errors=0
+ PGDEV=/proc/net/pktgen/$DEV@
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ sent=$(($sent + $(awk '/^Result:/{print $5}' <$PGDEV${COUNTER})))
+ result_pps=$(($result_pps + $(awk 'match($0,/'\([0-9]+\)pps'/, a) {print a[1]}' <$PGDEV${COUNTER})))
+ errors=$(($errors + $(awk '/errors:/{print $5}' <$PGDEV${COUNTER})))
+ let COUNTER=COUNTER+1
+ done
flows=$(( NUM_PORTS * (NUM_PORTS + 1) ))
- echo { '"packets_sent"':$sent , '"packets_per_second"':$pps, '"flows"':$flows, '"errors"':$errors }
+ echo '{ "packets_sent"':${sent} , '"packets_per_second"':${result_pps}, '"flows"':${flows}, '"errors"':${errors} '}'
}
# main entry
main()
{
modprobe pktgen
+ pgclean
ping -c 3 $DST_IP >/dev/null
@@ -137,16 +186,20 @@ main()
pgconfig
# run the test
- run_test >/dev/null
+ run_test
- PGDEV=/proc/net/pktgen/$DEV
+ PGDEV=/proc/net/pktgen/$DEV@
# check result
- result=$(cat $PGDEV | fgrep "Result: OK:")
- if [ "$result" = "" ]; then
- cat $PGDEV | fgrep Result: >/dev/stderr
- exit 1
- fi
+ COUNTER=0
+ while [ ${COUNTER} -lt ${TRXQUEUE} ]; do
+ result=$(cat $PGDEV${COUNTER} | fgrep "Result: OK:")
+ if [ "$result" = "" ]; then
+ cat $PGDEV${COUNTER} | fgrep Result: >/dev/stderr
+ exit 1
+ fi
+ let COUNTER=COUNTER+1
+ done
# output result
output_json
diff --git a/yardstick/benchmark/scenarios/storage/fio.py b/yardstick/benchmark/scenarios/storage/fio.py
index ad34817a7..b99e34270 100644
--- a/yardstick/benchmark/scenarios/storage/fio.py
+++ b/yardstick/benchmark/scenarios/storage/fio.py
@@ -40,10 +40,26 @@ class Fio(base.Scenario):
type: string
unit: na
default: write
+ rwmixwrite - percentage of a mixed workload that should be writes
+ type: int
+ unit: percentage
+ default: 50
ramp_time - run time before logging any performance
type: int
unit: seconds
default: 20
+ direct - whether use non-buffered I/O or not
+ type: boolean
+ unit: na
+ default: 1
+ size - total size of I/O for this job.
+ type: string
+ unit: na
+ default: 1g
+ numjobs - number of clones (processes/threads performing the same workload) of this job
+ type: int
+ unit: na
+ default: 1
Read link below for more fio args description:
http://www.bluestop.org/fio/HOWTO.txt
@@ -74,8 +90,8 @@ class Fio(base.Scenario):
def run(self, result):
"""execute the benchmark"""
- default_args = "-ioengine=libaio -direct=1 -group_reporting " \
- "-numjobs=1 -time_based --output-format=json"
+ default_args = "-ioengine=libaio -group_reporting -time_based -time_based " \
+ "--output-format=json"
if not self.setup_done:
self.setup()
@@ -86,6 +102,10 @@ class Fio(base.Scenario):
iodepth = options.get("iodepth", "1")
rw = options.get("rw", "write")
ramp_time = options.get("ramp_time", 20)
+ size = options.get("size", "1g")
+ direct = options.get("direct", "1")
+ numjobs = options.get("numjobs", "1")
+ rwmixwrite = options.get("rwmixwrite", 50)
name = "yardstick-fio"
# if run by a duration runner
duration_time = self.scenario_cfg["runner"].get("duration", None) \
@@ -99,10 +119,10 @@ class Fio(base.Scenario):
else:
runtime = 30
- cmd_args = "-filename=%s -bs=%s -iodepth=%s -rw=%s -ramp_time=%s " \
- "-runtime=%s -name=%s %s" \
- % (filename, bs, iodepth, rw, ramp_time, runtime, name,
- default_args)
+ cmd_args = "-filename=%s -direct=%s -bs=%s -iodepth=%s -rw=%s -rwmixwrite=%s " \
+ "-size=%s -ramp_time=%s -numjobs=%s -runtime=%s -name=%s %s" \
+ % (filename, direct, bs, iodepth, rw, rwmixwrite, size, ramp_time, numjobs,
+ runtime, name, default_args)
cmd = "sudo bash fio.sh %s %s" % (filename, cmd_args)
LOG.debug("Executing command: %s", cmd)
# Set timeout, so that the cmd execution does not exit incorrectly
diff --git a/yardstick/benchmark/scenarios/storage/storperf.py b/yardstick/benchmark/scenarios/storage/storperf.py
index c10118ad1..f0b2361d6 100644
--- a/yardstick/benchmark/scenarios/storage/storperf.py
+++ b/yardstick/benchmark/scenarios/storage/storperf.py
@@ -87,8 +87,9 @@ class StorPerf(base.Scenario):
def setup(self):
"""Set the configuration."""
env_args = {}
- env_args_payload_list = ["agent_count", "public_network",
- "agent_image", "volume_size"]
+ env_args_payload_list = ["agent_count", "agent_flavor",
+ "public_network", "agent_image",
+ "volume_size"]
for env_argument in env_args_payload_list:
try:
@@ -206,7 +207,7 @@ class StorPerf(base.Scenario):
# terminate_res = requests.delete('http://%s:5000/api/v1.0
# /jobs' % self.target)
# else:
- # time.sleep(int(est_time)/2)
+ # time.sleep(int(esti_time)/2)
result_res = requests.get('http://%s:5000/api/v1.0/jobs?id=%s' %
(self.target, job_id))
diff --git a/yardstick/common/constants.py b/yardstick/common/constants.py
index 69485a4e4..8e8114fbb 100644
--- a/yardstick/common/constants.py
+++ b/yardstick/common/constants.py
@@ -77,6 +77,7 @@ INFLUXDB_PASS = get_param('influxdb.password', 'root')
INFLUXDB_DB_NAME = get_param('influxdb.db_name', 'yardstick')
INFLUXDB_IMAGE = get_param('influxdb.image', 'tutum/influxdb')
INFLUXDB_TAG = get_param('influxdb.tag', '0.13')
+INFLUXDB_DASHBOARD_PORT = 8083
# grafana
GRAFANA_IP = get_param('grafana.ip', SERVER_IP)
@@ -85,6 +86,7 @@ GRAFANA_USER = get_param('grafana.username', 'admin')
GRAFANA_PASS = get_param('grafana.password', 'admin')
GRAFANA_IMAGE = get_param('grafana.image', 'grafana/grafana')
GRAFANA_TAG = get_param('grafana.tag', '3.1.1')
+GRAFANA_MAPPING_PORT = 1948
# api
API_PORT = 5000
diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py
index 92bb7b7d3..7a64b8ca2 100644
--- a/yardstick/common/utils.py
+++ b/yardstick/common/utils.py
@@ -172,7 +172,15 @@ def write_file(path, data, mode='w'):
def parse_ini_file(path):
parser = configparser.ConfigParser()
- parser.read(path)
+
+ try:
+ files = parser.read(path)
+ except configparser.MissingSectionHeaderError:
+ logger.exception('invalid file type')
+ raise
+ else:
+ if not files:
+ raise RuntimeError('file not exist')
try:
default = {k: v for k, v in parser.items('DEFAULT')}
diff --git a/yardstick/network_services/vnf_generic/vnf/base.py b/yardstick/network_services/vnf_generic/vnf/base.py
index 1d770f724..2df6037f3 100644
--- a/yardstick/network_services/vnf_generic/vnf/base.py
+++ b/yardstick/network_services/vnf_generic/vnf/base.py
@@ -96,7 +96,6 @@ class GenericVNF(object):
return address.version
def _ip_to_hex(self, ip_addr):
- ip_to_convert = ip_addr.split(".")
ip_x = ip_addr
if self.get_ip_version(ip_addr) == 4:
ip_to_convert = ip_addr.split(".")
diff --git a/yardstick/orchestrator/heat.py b/yardstick/orchestrator/heat.py
index 2a907d124..57b23d393 100644
--- a/yardstick/orchestrator/heat.py
+++ b/yardstick/orchestrator/heat.py
@@ -231,13 +231,16 @@ name (i.e. %s).\
}
def add_network(self, name, physical_network='physnet1', provider=None,
- segmentation_id=None):
+ segmentation_id=None, port_security_enabled=True):
"""add to the template a Neutron Net"""
log.debug("adding Neutron::Net '%s'", name)
if provider is None:
self.resources[name] = {
'type': 'OS::Neutron::Net',
- 'properties': {'name': name}
+ 'properties': {
+ 'name': name,
+ 'port_security_enabled': port_security_enabled,
+ }
}
else:
self.resources[name] = {
@@ -245,12 +248,12 @@ name (i.e. %s).\
'properties': {
'name': name,
'network_type': 'vlan',
- 'physical_network': physical_network
- }
+ 'physical_network': physical_network,
+ 'port_security_enabled': port_security_enabled,
+ },
}
if segmentation_id:
- seg_id_dit = {'segmentation_id': segmentation_id}
- self.resources[name]["properties"].update(seg_id_dit)
+ self.resources[name]['properties']['segmentation_id'] = segmentation_id
def add_server_group(self, name, policies): # pragma: no cover
"""add to the template a ServerGroup"""
@@ -262,8 +265,9 @@ name (i.e. %s).\
'policies': policies}
}
- def add_subnet(self, name, network, cidr):
- """add to the template a Neutron Subnet"""
+ def add_subnet(self, name, network, cidr, enable_dhcp='true', gateway_ip=None):
+ """add to the template a Neutron Subnet
+ """
log.debug("adding Neutron::Subnet '%s' in network '%s', cidr '%s'",
name, network, cidr)
self.resources[name] = {
@@ -272,9 +276,12 @@ name (i.e. %s).\
'properties': {
'name': name,
'cidr': cidr,
- 'network_id': {'get_resource': network}
+ 'network_id': {'get_resource': network},
+ 'enable_dhcp': enable_dhcp,
}
}
+ if gateway_ip is not None:
+ self.resources[name]['properties']['gateway_ip'] = gateway_ip
self._template['outputs'][name] = {
'description': 'subnet %s ID' % name,
@@ -316,9 +323,10 @@ name (i.e. %s).\
}
}
- def add_port(self, name, network_name, subnet_name, sec_group_id=None,
- provider=None):
- """add to the template a named Neutron Port"""
+ def add_port(self, name, network_name, subnet_name, sec_group_id=None, provider=None,
+ allowed_address_pairs=None):
+ """add to the template a named Neutron Port
+ """
log.debug("adding Neutron::Port '%s', network:'%s', subnet:'%s', "
"secgroup:%s", name, network_name, subnet_name, sec_group_id)
self.resources[name] = {
@@ -341,6 +349,10 @@ name (i.e. %s).\
self.resources[name]['properties']['security_groups'] = \
[sec_group_id]
+ if allowed_address_pairs:
+ self.resources[name]['properties'][
+ 'allowed_address_pairs'] = allowed_address_pairs
+
self._template['outputs'][name] = {
'description': 'Address for interface %s' % name,
'value': {'get_attr': [name, 'fixed_ips', 0, 'ip_address']}