summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml135
-rw-r--r--tests/unit/benchmark/contexts/standalone_sample.yaml112
-rw-r--r--tests/unit/benchmark/contexts/test_standalone.py131
-rw-r--r--yardstick/benchmark/contexts/standalone.py116
4 files changed, 494 insertions, 0 deletions
diff --git a/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml b/tests/unit/benchmark/contexts/standalone_duplicate_sample.yaml
new file mode 100644
index 000000000..e468d0465
--- /dev/null
+++ b/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/tests/unit/benchmark/contexts/standalone_sample.yaml b/tests/unit/benchmark/contexts/standalone_sample.yaml
new file mode 100644
index 000000000..95e12d62f
--- /dev/null
+++ b/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/tests/unit/benchmark/contexts/test_standalone.py b/tests/unit/benchmark/contexts/test_standalone.py
new file mode 100644
index 000000000..687ef7305
--- /dev/null
+++ b/tests/unit/benchmark/contexts/test_standalone.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+# 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.
+#
+
+# Unittest for yardstick.benchmark.contexts.standalone
+
+from __future__ import absolute_import
+import os
+import unittest
+
+from yardstick.benchmark.contexts import standalone
+
+
+class StandaloneContextTestCase(unittest.TestCase):
+
+ NODES_SAMPLE = "standalone_sample.yaml"
+ NODES_DUPLICATE_SAMPLE = "standalone_duplicate_sample.yaml"
+
+ def setUp(self):
+ self.test_context = standalone.StandaloneContext()
+
+ def test_construct(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.nfvi_node, [])
+
+ def test_unsuccessful_init(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath("error_file")
+ }
+
+ self.assertRaises(IOError, self.test_context.init, attrs)
+
+ def test_successful_init(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ self.test_context.init(attrs)
+
+ self.assertEqual(self.test_context.name, "foo")
+ self.assertEqual(len(self.test_context.nodes), 3)
+ self.assertEqual(len(self.test_context.nfvi_node), 1)
+ self.assertEqual(self.test_context.nfvi_node[0]["name"], "node2")
+
+ def test__get_server_with_dic_attr_name(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ self.test_context.init(attrs)
+
+ attr_name = {'name': 'foo.bar'}
+ result = self.test_context._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_not_found(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ self.test_context.init(attrs)
+
+ attr_name = 'bar.foo'
+ result = self.test_context._get_server(attr_name)
+
+ self.assertEqual(result, None)
+
+ def test__get_server_duplicate(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath(self.NODES_DUPLICATE_SAMPLE)
+ }
+
+ self.test_context.init(attrs)
+
+ attr_name = 'node2.foo'
+
+ self.assertRaises(ValueError, self.test_context._get_server, attr_name)
+
+ def test__get_server_found(self):
+
+ attrs = {
+ 'name': 'foo',
+ 'file': self._get_file_abspath(self.NODES_SAMPLE)
+ }
+
+ self.test_context.init(attrs)
+
+ attr_name = 'node1.foo'
+ result = self.test_context._get_server(attr_name)
+
+ self.assertEqual(result['ip'], '1.1.1.1')
+ self.assertEqual(result['name'], 'node1.foo')
+ self.assertEqual(result['user'], 'root')
+
+ def test_deploy(self):
+ self.assertIsNone(self.test_context.deploy())
+
+ def test_undeploy(self):
+ self.assertIsNone(self.test_context.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
diff --git a/yardstick/benchmark/contexts/standalone.py b/yardstick/benchmark/contexts/standalone.py
new file mode 100644
index 000000000..c1d963f50
--- /dev/null
+++ b/yardstick/benchmark/contexts/standalone.py
@@ -0,0 +1,116 @@
+# 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.
+"""This module handle non managed standalone virtualization node."""
+
+from __future__ import absolute_import
+import logging
+import errno
+import collections
+import yaml
+
+from yardstick.benchmark.contexts.base import Context
+from yardstick.definitions import YARDSTICK_ROOT_PATH
+
+LOG = logging.getLogger(__name__)
+
+
+class StandaloneContext(Context):
+ """ This class handles standalone nodes - VM running on Non-Managed NFVi
+ Configuration: vswitch, ovs, ovs-dpdk, sr-iov, linuxbridge
+ """
+
+ __context_type__ = "Standalone"
+
+ def __init__(self):
+ self.name = None
+ self.file_path = None
+ self.nodes = []
+ self.nfvi_node = []
+ super(self.__class__, self).__init__()
+
+ def read_config_file(self):
+ """Read from config file"""
+
+ with open(self.file_path) as stream:
+ LOG.info("Parsing pod file: %s", self.file_path)
+ cfg = yaml.load(stream)
+ return cfg
+
+ def init(self, attrs):
+ """initializes itself from the supplied arguments"""
+
+ self.name = attrs["name"]
+ self.file_path = attrs.get("file", "pod.yaml")
+ LOG.info("Parsing pod file: %s", self.file_path)
+
+ try:
+ cfg = self.read_config_file()
+ except IOError as ioerror:
+ if ioerror.errno == errno.ENOENT:
+ self.file_path = YARDSTICK_ROOT_PATH + self.file_path
+ cfg = self.read_config_file()
+ else:
+ raise
+
+ self.nodes.extend(cfg["nodes"])
+ self.nfvi_node.extend([node for node in cfg["nodes"]
+ if node["role"] == "nfvi_node"])
+ LOG.debug("Nodes: %r", self.nodes)
+ LOG.debug("NFVi Node: %r", self.nfvi_node)
+
+ def deploy(self):
+ """don't need to deploy"""
+
+ # Todo: NFVi deploy (sriov, vswitch, ovs etc) based on the config.
+ pass
+
+ def undeploy(self):
+ """don't need to undeploy"""
+
+ # Todo: NFVi undeploy (sriov, vswitch, ovs etc) based on the config.
+ pass
+
+ def _get_server(self, attr_name):
+ """lookup server info by name from context
+
+ Keyword arguments:
+ attr_name -- A name for a server listed in nodes config file
+ """
+
+ if isinstance(attr_name, collections.Mapping):
+ return None
+
+ if self.name.split("-")[0] != attr_name.split(".")[1]:
+ return None
+
+ node_name = attr_name.split(".")[0]
+ matching_nodes = (n for n in self.nodes if n["name"] == node_name)
+
+ try:
+ # A clone is created in order to avoid affecting the
+ # original one.
+ node = dict(next(matching_nodes))
+ except StopIteration:
+ return None
+
+ try:
+ duplicate = next(matching_nodes)
+ except StopIteration:
+ pass
+ else:
+ raise ValueError("Duplicate nodes!!! Nodes: %s %s",
+ (matching_nodes, duplicate))
+
+ node["name"] = attr_name
+ return node