diff options
author | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-04-10 08:39:16 +0100 |
---|---|---|
committer | Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com> | 2018-06-25 11:38:58 +0000 |
commit | ba36ea248487f93d6a4183abcc5c58568d24c39f (patch) | |
tree | d05f7c6211332f9a1e6968776c175fd1c5b4d432 | |
parent | 2190402565343fbc712d5cba936b8d7d6dba56b4 (diff) |
Improve IXIA IxNetwork library and traffic profile (1)
This patch introduces a new way to configure the TCL IxNetwork server.
All the configuration is done using the TCL API, removing the need of
using the pre-saved configuration file.
"IxNextgen.assign_ports" creates and assigns the virtual ports for each
physical port defined in the test case.
"IxNextgen.create_traffic_item" creates one traffic item and two flow
groups per pair of ports, in both directions.
"IxNextgen.gt_statistics" retrieves only the required statistics to
generate the samples blob in the traffic generator.
JIRA: YARDSTICK-1116
Change-Id: I8f1c0c55e99c274b2ed8276ed9a385c502e16d93
Signed-off-by: Rodolfo Alonso Hernandez <rodolfo.alonso.hernandez@intel.com>
Signed-off-by: Emma Foley <emma.l.foley@intel.com>
(cherry picked from commit ee721fd3e8b77ccfe4252a107a9af8dc41ccc389)
4 files changed, 432 insertions, 243 deletions
diff --git a/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py b/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py index 61fc012bc..04cd9e858 100644 --- a/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py +++ b/tests/unit/network_services/vnf_generic/vnf/test_tg_rfc2544_ixia.py @@ -11,7 +11,6 @@ # 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 @@ -19,41 +18,50 @@ import mock import six import unittest -from tests.unit import STL_MOCKS - -STLClient = mock.MagicMock() -stl_patch = mock.patch.dict("sys.modules", STL_MOCKS) -stl_patch.start() +from yardstick.network_services.vnf_generic.vnf import tg_rfc2544_ixia +from yardstick.network_services.traffic_profile import base as tp_base -if stl_patch: - from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia import IxiaTrafficGen - from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia import IxiaRfc2544Helper - from yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia import IxiaResourceHelper - from yardstick.network_services.traffic_profile.base import TrafficProfile TEST_FILE_YAML = 'nsb_test_case.yaml' NAME = "tg__1" -@mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen") class TestIxiaResourceHelper(unittest.TestCase): - def test___init___with_custom_rfc_helper(self, *args): - class MyRfcHelper(IxiaRfc2544Helper): + + def setUp(self): + self._mock_IxNextgen = mock.patch.object(tg_rfc2544_ixia, '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 = IxiaResourceHelper(mock.Mock(), MyRfcHelper) + ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper( + mock.Mock(), MyRfcHelper) self.assertIsInstance(ixia_resource_helper.rfc_helper, MyRfcHelper) - def test_stop_collect_with_client(self, *args): + def test_stop_collect_with_client(self): mock_client = mock.Mock() - ixia_resource_helper = IxiaResourceHelper(mock.Mock()) + ixia_resource_helper = tg_rfc2544_ixia.IxiaResourceHelper(mock.Mock()) ixia_resource_helper.client = mock_client ixia_resource_helper.stop_collect() self.assertEqual(mock_client.ix_stop_traffic.call_count, 1) + # NOTE(ralonsoh): to be updated in next patchset + def test__initialise_client(self): + pass + + # NOTE(ralonsoh): to be updated in next patchset + def test_run_traffic(self): + pass + @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.IxNextgen") class TestIXIATrafficGen(unittest.TestCase): @@ -160,7 +168,7 @@ class TestIXIATrafficGen(unittest.TestCase): ssh.from_node.return_value = ssh_mock vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] # NOTE(ralonsoh): check the object returned. - IxiaTrafficGen(NAME, vnfd) + tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd) def test_listen_traffic(self, *args): with mock.patch("yardstick.ssh.SSH") as ssh: @@ -169,7 +177,7 @@ class TestIXIATrafficGen(unittest.TestCase): mock.Mock(return_value=(0, "", "")) ssh.from_node.return_value = ssh_mock vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - ixnet_traffic_gen = IxiaTrafficGen(NAME, vnfd) + ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd) self.assertIsNone(ixnet_traffic_gen.listen_traffic({})) def test_instantiate(self, *args): @@ -181,7 +189,7 @@ class TestIXIATrafficGen(unittest.TestCase): mock.Mock(return_value=(0, "", "")) ssh.from_node.return_value = ssh_mock vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - ixnet_traffic_gen = IxiaTrafficGen(NAME, vnfd) + ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd) scenario_cfg = {'tc': "nsb_test_case", "topology": "", 'ixia_profile': "ixload.cfg"} scenario_cfg.update({'options': {'packetsize': 64, @@ -209,7 +217,7 @@ class TestIXIATrafficGen(unittest.TestCase): mock.Mock(return_value=(0, "", "")) ssh.from_node.return_value = ssh_mock vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - ixnet_traffic_gen = IxiaTrafficGen(NAME, vnfd) + ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd) ixnet_traffic_gen.data = {} restult = ixnet_traffic_gen.collect_kpi() self.assertEqual({}, restult) @@ -221,7 +229,7 @@ class TestIXIATrafficGen(unittest.TestCase): ssh_mock.execute = \ mock.Mock(return_value=(0, "", "")) ssh.from_node.return_value = ssh_mock - ixnet_traffic_gen = IxiaTrafficGen(NAME, vnfd) + ixnet_traffic_gen = tg_rfc2544_ixia.IxiaTrafficGen(NAME, vnfd) ixnet_traffic_gen._terminated = mock.MagicMock() ixnet_traffic_gen._terminated.value = 0 ixnet_traffic_gen._ixia_traffic_gen = mock.MagicMock() @@ -237,13 +245,13 @@ class TestIXIATrafficGen(unittest.TestCase): def test__check_status(self, *args): vnfd = self.VNFD['vnfd:vnfd-catalog']['vnfd'][0] - sut = IxiaTrafficGen('vnf1', vnfd) + sut = tg_rfc2544_ixia.IxiaTrafficGen('vnf1', vnfd) sut._check_status() @mock.patch("yardstick.network_services.vnf_generic.vnf.tg_rfc2544_ixia.time") @mock.patch("yardstick.ssh.SSH") def test_traffic_runner(self, mock_ssh, *args): - mock_traffic_profile = mock.Mock(autospec=TrafficProfile) + 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 @@ -302,7 +310,7 @@ class TestIXIATrafficGen(unittest.TestCase): mock_traffic_profile.execute_traffic.return_value = ['Completed', samples] mock_traffic_profile.get_drop_percentage.return_value = ['Completed', samples] - sut = IxiaTrafficGen(name, vnfd) + 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 = "" diff --git a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py b/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py index c538ceeba..0cf2a4126 100644 --- a/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py +++ b/yardstick/network_services/libs/ixia_libs/IxNet/IxNet.py @@ -23,6 +23,11 @@ log = logging.getLogger(__name__) IP_VERSION_4 = 4 IP_VERSION_6 = 6 +PROTO_IPV4 = 'ipv4' +PROTO_IPV6 = 'ipv6' +PROTO_UDP = 'udp' +PROTO_TCP = 'tcp' +PROTO_VLAN = 'vlan' class TrafficStreamHelper(object): @@ -77,17 +82,6 @@ class FramesizeHelper(object): class IxNextgen(object): - STATS_NAME_MAP = { - "traffic_item": 'Traffic Item', - "Tx_Frames": 'Tx Frames', - "Rx_Frames": 'Rx Frames', - "Tx_Frame_Rate": 'Tx Frame Rate', - "Rx_Frame_Rate": 'Tx Frame Rate', - "Store-Forward_Avg_latency_ns": 'Store-Forward Avg Latency (ns)', - "Store-Forward_Min_latency_ns": 'Store-Forward Min Latency (ns)', - "Store-Forward_Max_latency_ns": 'Store-Forward Max Latency (ns)', - } - PORT_STATS_NAME_MAP = { "stat_name": 'Stat Name', "Frames_Tx": 'Frames Tx.', @@ -118,11 +112,6 @@ class IxNextgen(object): MODE_SEEDS_DEFAULT = 'downlink', ['2048', '256'] @staticmethod - def find_view_obj(view_name, views): - edited_view_name = '::ixNet::OBJ-/statistics/view:"{}"'.format(view_name) - return next((view for view in views if edited_view_name == view), '') - - @staticmethod def get_config(tg_cfg): card = [] port = [] @@ -150,7 +139,6 @@ class IxNextgen(object): self.ixnet = ixnet self._objRefs = dict() self._cfg = None - self._logger = logging.getLogger(__name__) self._params = None self._bidir = None @@ -197,41 +185,137 @@ class IxNextgen(object): self.ixnet.commit() - def _connect(self, tg_cfg): + def connect(self, tg_cfg): self._cfg = self.get_config(tg_cfg) self.ixnet = IxNetwork.IxNet() machine = self._cfg['machine'] port = str(self._cfg['port']) version = str(self._cfg['version']) - result = self.ixnet.connect(machine, '-port', port, '-version', version) - return result + return self.ixnet.connect(machine, '-port', port, + '-version', version) - def clear_ixia_config(self): + def clear_config(self): + """Wipe out any possible configuration present in the client""" self.ixnet.execute('newConfig') - def load_ixia_profile(self, profile): - self.ixnet.execute('loadConfig', self.ixnet.readFrom(profile)) - - def ix_load_config(self, profile): - self.clear_ixia_config() - self.load_ixia_profile(profile) - - def ix_assign_ports(self): - vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport') - ports = [] - - chassis = self._cfg['chassis'] - ports = [(chassis, card, port) for card, port in + def assign_ports(self): + """Create and assign vports for each physical port defined in config + + This configuration is present in the IXIA profile file. E.g.: + name: trafficgen_1 + role: IxNet + interfaces: + xe0: + vpci: "2:15" # Card:port + driver: "none" + dpdk_port_num: 0 + local_ip: "152.16.100.20" + netmask: "255.255.0.0" + local_mac: "00:98:10:64:14:00" + xe1: + ... + """ + chassis_ip = self._cfg['chassis'] + ports = [(chassis_ip, card, port) for card, port in zip(self._cfg['cards'], self._cfg['ports'])] - vport_list = self.ixnet.getList("/", "vport") - self.ixnet.execute('assignPorts', ports, [], vport_list, True) + log.info('Create and assign vports: %s', ports) + for port in ports: + vport = self.ixnet.add(self.ixnet.getRoot(), 'vport') + self.ixnet.commit() + self.ixnet.execute('assignPorts', [port], [], [vport], True) + self.ixnet.commit() + if self.ixnet.getAttribute(vport, '-state') != 'up': + log.warning('Port %s is down', vport) + + def _create_traffic_item(self): + """Create the traffic item to hold the flow groups + + The traffic item tracking by "Traffic Item" is enabled to retrieve the + latency statistics. + """ + log.info('Create the traffic item "RFC2544"') + traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic', + 'trafficItem') + self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544', + '-trafficType', 'raw') self.ixnet.commit() - for vport in vports: - if self.ixnet.getAttribute(vport, '-state') != 'up': - log.error("Both thr ports are down...") + traffic_item_id = self.ixnet.remapIds(traffic_item)[0] + self.ixnet.setAttribute(traffic_item_id + '/tracking', + '-trackBy', 'trafficGroupId0') + self.ixnet.commit() + + def _create_flow_groups(self): + """Create the flow groups between the assigned ports""" + traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic', + 'trafficItem')[0] + log.info('Create the flow groups') + vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport') + uplink_ports = vports[::2] + downlink_ports = vports[1::2] + for up, down in zip(uplink_ports, downlink_ports): + log.info('FGs: %s <--> %s', up, down) + endpoint_set_1 = self.ixnet.add(traffic_item_id, 'endpointSet') + endpoint_set_2 = self.ixnet.add(traffic_item_id, 'endpointSet') + self.ixnet.setMultiAttribute( + endpoint_set_1, + '-sources', [up + ' /protocols'], + '-destinations', [down + '/protocols']) + self.ixnet.setMultiAttribute( + endpoint_set_2, + '-sources', [down + ' /protocols'], + '-destinations', [up + '/protocols']) + self.ixnet.commit() + + def _append_procotol_to_stack(self, protocol_name, previous_element): + """Append a new element in the packet definition stack""" + protocol = (self.ixnet.getRoot() + + '/traffic/protocolTemplate:"{}"'.format(protocol_name)) + self.ixnet.execute('append', previous_element, protocol) + + def _setup_config_elements(self): + """Setup the config elements + + The traffic item is configured to allow individual configurations per + config element. The default frame configuration is applied: + Ethernet II: added by default + IPv4: element to add + UDP: element to add + Payload: added by default + Ethernet II (Trailer): added by default + :return: + """ + traffic_item_id = self.ixnet.getList(self.ixnet.getRoot() + 'traffic', + 'trafficItem')[0] + log.info('Split the frame rate distribution per config element') + config_elements = self.ixnet.getList(traffic_item_id, 'configElement') + for config_element in config_elements: + self.ixnet.setAttribute(config_element + '/frameRateDistribution', + '-portDistribution', 'splitRateEvenly') + self.ixnet.setAttribute(config_element + '/frameRateDistribution', + '-streamDistribution', 'splitRateEvenly') + self.ixnet.commit() + self._append_procotol_to_stack( + PROTO_UDP, config_element + '/stack:"ethernet-1"') + self._append_procotol_to_stack( + PROTO_IPV4, config_element + '/stack:"ethernet-1"') + + def create_traffic_model(self): + """Create a traffic item and the needed flow groups + + Each flow group inside the traffic item (only one is present) + represents the traffic between two ports: + (uplink) (downlink) + FlowGroup1: port1 -> port2 + FlowGroup2: port1 <- port2 + FlowGroup3: port3 -> port4 + FlowGroup4: port3 <- port4 + """ + self._create_traffic_item() + self._create_flow_groups() + self._setup_config_elements() def ix_update_frame(self, params): streams = ["configElement"] @@ -245,7 +329,7 @@ class IxNextgen(object): self.ixnet.setMultiAttribute(helper.transmissionControl, '-type', '{0}'.format(param.get('traffic_type', - 'continuous')), + 'fixedDuration')), '-duration', '{0}'.format(param.get('duration', "30"))) @@ -314,21 +398,22 @@ class IxNextgen(object): self.ixnet.execute('stop', '/traffic') def build_stats_map(self, view_obj, name_map): - return {kl: self.execute_get_column_values(view_obj, kr) for kl, kr in name_map.items()} - - def execute_get_column_values(self, view_obj, name): - return self.ixnet.execute('getColumnValues', view_obj, name) - - def ix_get_statistics(self): - views = self.ixnet.getList('/statistics', 'view') - stats = {} - view_obj = self.find_view_obj("Traffic Item Statistics", views) - stats = self.build_stats_map(view_obj, self.STATS_NAME_MAP) - - view_obj = self.find_view_obj("Port Statistics", views) - ports_stats = self.build_stats_map(view_obj, self.PORT_STATS_NAME_MAP) - - view_obj = self.find_view_obj("Flow Statistics", views) - stats["latency"] = self.build_stats_map(view_obj, self.LATENCY_NAME_MAP) - - return stats, ports_stats + return {data_yardstick: self.ixnet.execute( + 'getColumnValues', view_obj, data_ixia) + for data_yardstick, data_ixia in name_map.items()} + + def get_statistics(self): + """Retrieve port and flow statistics + + "Port Statistics" parameters are stored in self.PORT_STATS_NAME_MAP. + "Flow Statistics" parameters are stored in self.LATENCY_NAME_MAP. + + :return: dictionary with the statistics; the keys of this dictionary + are PORT_STATS_NAME_MAP and LATENCY_NAME_MAP keys. + """ + port_statistics = '::ixNet::OBJ-/statistics/view:"Port Statistics"' + flow_statistics = '::ixNet::OBJ-/statistics/view:"Flow Statistics"' + stats = self.build_stats_map(port_statistics, self.PORT_STATS_NAME_MAP) + stats.update(self.build_stats_map(flow_statistics, + self.LATENCY_NAME_MAP)) + return stats diff --git a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py index 94ab69891..f8799c88b 100644 --- a/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py +++ b/yardstick/network_services/vnf_generic/vnf/tg_rfc2544_ixia.py @@ -18,11 +18,11 @@ import logging import sys from yardstick.common import exceptions -from yardstick.common import utils from yardstick.network_services.vnf_generic.vnf.sample_vnf import SampleVNFTrafficGen from yardstick.network_services.vnf_generic.vnf.sample_vnf import ClientResourceHelper from yardstick.network_services.vnf_generic.vnf.sample_vnf import Rfc2544ResourceHelper + LOG = logging.getLogger(__name__) WAIT_AFTER_CFG_LOAD = 10 @@ -62,10 +62,10 @@ class IxiaResourceHelper(ClientResourceHelper): self._connect() def _connect(self, client=None): - self.client._connect(self.vnfd_helper) + self.client.connect(self.vnfd_helper) def get_stats(self, *args, **kwargs): - return self.client.ix_get_statistics() + return self.client.get_statistics() def stop_collect(self): self._terminated.value = 1 @@ -108,6 +108,12 @@ class IxiaResourceHelper(ClientResourceHelper): return samples + def _initialize_client(self): + """Initialize the IXIA IxNetwork client and configure the server""" + self.client.clear_config() + self.client.assign_ports() + self.client.create_traffic_model() + def run_traffic(self, traffic_profile): if self._terminated.value: return @@ -117,16 +123,7 @@ class IxiaResourceHelper(ClientResourceHelper): default = "00:00:00:00:00:00" self._build_ports() - - # we don't know client_file_name until runtime as instantiate - client_file_name = \ - utils.find_relative_file( - self.scenario_helper.scenario_cfg['ixia_profile'], - self.scenario_helper.scenario_cfg["task_path"]) - self.client.ix_load_config(client_file_name) - time.sleep(WAIT_AFTER_CFG_LOAD) - - self.client.ix_assign_ports() + self._initialize_client() mac = {} for port_name in self.vnfd_helper.port_pairs.all_ports: diff --git a/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py b/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py index 7ca2f0f19..deae69314 100644 --- a/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py +++ b/yardstick/tests/unit/network_services/libs/ixia_libs/test_IxNet.py @@ -11,92 +11,193 @@ # 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 -from yardstick.network_services.libs.ixia_libs.IxNet.IxNet import IxNextgen -from yardstick.network_services.libs.ixia_libs.IxNet.IxNet import IP_VERSION_4 -from yardstick.network_services.libs.ixia_libs.IxNet.IxNet import IP_VERSION_6 +from yardstick.network_services.libs.ixia_libs.IxNet import IxNet + -UPLINK = "uplink" -DOWNLINK = "downlink" +UPLINK = 'uplink' +DOWNLINK = 'downlink' class TestIxNextgen(unittest.TestCase): + def setUp(self): + self.ixnet = mock.Mock() + self.ixnet.execute = mock.Mock() + def test___init__(self): - ixnet_gen = IxNextgen() + ixnet_gen = IxNet.IxNextgen() + self.assertIsNone(ixnet_gen.ixnet) + self.assertTrue(isinstance(ixnet_gen._objRefs, dict)) + self.assertIsNone(ixnet_gen._cfg) + self.assertIsNone(ixnet_gen._params) self.assertIsNone(ixnet_gen._bidir) + def test___init__ixnet(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + self.assertIsNotNone(ixnet_gen.ixnet) + @mock.patch.object(IxNetwork, 'IxNet') def test_connect(self, mock_ixnet): - ixnet_instance = mock.Mock() - mock_ixnet.return_value = ixnet_instance - ixnet_gen = IxNextgen() + mock_ixnet.return_value = self.ixnet + ixnet_gen = IxNet.IxNextgen() with mock.patch.object(ixnet_gen, 'get_config') as mock_config: mock_config.return_value = {'machine': 'machine_fake', 'port': 'port_fake', 'version': 12345} - ixnet_gen._connect(mock.ANY) + ixnet_gen.connect(mock.ANY) - ixnet_instance.connect.assert_called_once_with( + self.ixnet.connect.assert_called_once_with( 'machine_fake', '-port', 'port_fake', '-version', '12345') mock_config.assert_called_once() - def test_clear_ixia_config(self): - ixnet = mock.MagicMock() - ixnet.execute = mock.Mock() - - ixnet_gen = IxNextgen(ixnet) - - result = ixnet_gen.clear_ixia_config() - self.assertIsNone(result) - self.assertEqual(ixnet.execute.call_count, 1) - - def test_load_ixia_profile(self): - ixnet = mock.MagicMock() - ixnet.execute = mock.Mock() + def test_connect_invalid_config_no_machine(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.get_config = mock.Mock(return_value={ + 'port': 'port_fake', + 'version': '12345'}) + self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY) + self.ixnet.connect.assert_not_called() + + def test_connect_invalid_config_no_port(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.get_config = mock.Mock(return_value={ + 'machine': 'machine_fake', + 'version': '12345'}) + self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY) + self.ixnet.connect.assert_not_called() + + def test_connect_invalid_config_no_version(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.get_config = mock.Mock(return_value={ + 'machine': 'machine_fake', + 'port': 'port_fake'}) + self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY) + self.ixnet.connect.assert_not_called() + + def test_connect_no_config(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.get_config = mock.Mock(return_value={}) + self.assertRaises(KeyError, ixnet_gen.connect, mock.ANY) + self.ixnet.connect.assert_not_called() + + def test_clear_config(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.clear_config() + self.ixnet.execute.assert_called_once_with('newConfig') + + def test_assign_ports_2_ports(self): + self.ixnet.getAttribute.side_effect = ['up', 'down'] - ixnet_gen = IxNextgen(ixnet) - - result = ixnet_gen.load_ixia_profile({}) - self.assertIsNone(result) - self.assertEqual(ixnet.execute.call_count, 1) + config = { + 'chassis': '1.1.1.1', + 'cards': ['1', '2'], + 'ports': ['2', '2'], + } - def test_load_ixia_config(self): - ixnet = mock.MagicMock() - ixnet.execute = mock.Mock() + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen._cfg = config - ixnet_gen = IxNextgen(ixnet) + self.assertIsNone(ixnet_gen.assign_ports()) - result = ixnet_gen.ix_load_config({}) - self.assertIsNone(result) - self.assertEqual(ixnet.execute.call_count, 2) + self.assertEqual(self.ixnet.execute.call_count, 2) + self.assertEqual(self.ixnet.commit.call_count, 4) + self.assertEqual(self.ixnet.getAttribute.call_count, 2) - @mock.patch('yardstick.network_services.libs.ixia_libs.IxNet.IxNet.log') - def test_ix_assign_ports(self, mock_logger): - ixnet = mock.MagicMock() - ixnet.getList.return_value = [0, 1] - ixnet.getAttribute.side_effect = ['up', 'down'] + @mock.patch.object(IxNet, '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': ['2', '2'], + 'ports': ['3', '4'], } - - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) ixnet_gen._cfg = config - - result = ixnet_gen.ix_assign_ports() - self.assertIsNone(result) - self.assertEqual(ixnet.execute.call_count, 1) - self.assertEqual(ixnet.commit.call_count, 1) - self.assertEqual(ixnet.getAttribute.call_count, 2) - self.assertEqual(mock_logger.error.call_count, 1) + ixnet_gen.assign_ports() + mock_log.warning.assert_called() + + def test_assign_ports_no_config(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen._cfg = {} + + self.assertRaises(KeyError, ixnet_gen.assign_ports) + + def test__create_traffic_item(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + self.ixnet.getRoot.return_value = 'rootyrootroot' + self.ixnet.add.return_value = 'my_new_traffic_item' + self.ixnet.remapIds.return_value = ['my_traffic_item_id'] + + ixnet_gen._create_traffic_item() + + self.ixnet.add.assert_called_once_with( + 'rootyrootroot/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): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + self.ixnet.getRoot.return_value = 'rootyrootroot' + ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']] + ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2'] + ixnet_gen._create_flow_groups() + ixnet_gen.ixnet.add.assert_has_calls([ + mock.call('traffic_item', 'endpointSet'), + mock.call('traffic_item', 'endpointSet')]) + ixnet_gen.ixnet.setMultiAttribute.asser_has_calls([ + mock.call('endp1', '-sources', ['1/protocols'], '-destinations', + ['2/protocols']), + mock.call('endp2', '-sources', ['2/protocols'], '-destinations', + ['1/protocols'])]) + + def test__append_protocol_to_stack(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + self.ixnet.getRoot.return_value = 'my_root' + + 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): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + ixnet_gen.ixnet.getRoot.return_value = 'root_element' + ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], + ['cfg_element']] + with mock.patch.object(ixnet_gen, '_append_procotol_to_stack') as \ + mock_append_proto: + ixnet_gen._setup_config_elements() + mock_append_proto.assert_has_calls([ + mock.call(IxNet.PROTO_UDP, 'cfg_element/stack:"ethernet-1"'), + mock.call(IxNet.PROTO_IPV4, 'cfg_element/stack:"ethernet-1"')]) + 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.IxNextgen, '_create_traffic_item') + @mock.patch.object(IxNet.IxNextgen, '_create_flow_groups') + @mock.patch.object(IxNet.IxNextgen, '_setup_config_elements') + def test_create_traffic_model(self, mock__setup_config_elements, + mock__create_flow_groups, + mock__create_traffic_item): + ixnet_gen = IxNet.IxNextgen(self.ixnet) + + ixnet_gen.create_traffic_model() + mock__create_traffic_item.assert_called_once() + mock__create_flow_groups.assert_called_once() + mock__setup_config_elements.assert_called_once() def test_ix_update_frame(self): static_traffic_params = { @@ -185,11 +286,10 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.remapIds.return_value = ["0"] - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] - ixnet.getList.side_effect = [ + self.ixnet.remapIds.return_value = ["0"] + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [ [1], [1], [1], @@ -199,76 +299,77 @@ class TestIxNextgen(unittest.TestCase): ], ] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_update_frame(static_traffic_params) self.assertIsNone(result) - self.assertEqual(ixnet.setMultiAttribute.call_count, 7) - self.assertEqual(ixnet.commit.call_count, 2) + self.assertEqual(self.ixnet.setMultiAttribute.call_count, 7) + self.assertEqual(self.ixnet.commit.call_count, 2) - def test_ix_update_udp(self): - ixnet = mock.MagicMock() + # NOTE(ralonsoh): to be updated in next patchset + def test_update_ether_multi_attribute(self): + pass + + # NOTE(ralonsoh): to be updated in next patchset + def test_update_ether_multi_attributes(self): + pass + + # NOTE(ralonsoh): to be updated in next patchset + def test_update_ether(self): + pass - ixnet_gen = IxNextgen(ixnet) + # NOTE(ralonsoh): to be updated in next patchset + def test_ix_update_udp(self): + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_update_udp({}) self.assertIsNone(result) + # NOTE(ralonsoh): to be updated in next patchset def test_ix_update_tcp(self): - ixnet = mock.MagicMock() - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_update_tcp({}) self.assertIsNone(result) + # NOTE(ralonsoh): to be updated in next patchset def test_ix_start_traffic(self): - ixnet = mock.MagicMock() - ixnet.getList.return_value = [0] - ixnet.getAttribute.return_value = 'down' + self.ixnet.getList.return_value = [0] + self.ixnet.getAttribute.return_value = 'down' - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_start_traffic() self.assertIsNone(result) - self.assertEqual(ixnet.getList.call_count, 1) - self.assertEqual(ixnet.execute.call_count, 3) + self.ixnet.getList.assert_called_once() + self.assertEqual(self.ixnet.execute.call_count, 3) + # NOTE(ralonsoh): to be updated in next patchset def test_ix_stop_traffic(self): - ixnet = mock.MagicMock() - ixnet.getList.return_value = [0] + self.ixnet.getList.return_value = [0] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_stop_traffic() self.assertIsNone(result) - self.assertEqual(ixnet.getList.call_count, 1) - self.assertEqual(ixnet.execute.call_count, 1) + self.ixnet.getList.assert_called_once() + self.ixnet.execute.assert_called_once() - def test_ix_get_statistics(self): - ixnet = mock.MagicMock() - ixnet.execute.return_value = "" - ixnet.getList.side_effect = [ - [ - '::ixNet::OBJ-/statistics/view:"Traffic Item Statistics"', - '::ixNet::OBJ-/statistics/view:"Port Statistics"', - ], - [ - '::ixNet::OBJ-/statistics/view:"Flow Statistics"', - ], - ] + # NOTE(ralonsoh): to be updated in next patchset + def test_build_stats_map(self): + pass - ixnet_gen = IxNextgen(ixnet) + # NOTE(ralonsoh): to be updated in next patchset + def test_get_statistics(self): + self.ixnet.execute.return_value = "" - result = ixnet_gen.ix_get_statistics() - self.assertIsNotNone(result) - self.assertEqual(ixnet.getList.call_count, 1) - self.assertEqual(ixnet.execute.call_count, 20) + ixnet_gen = IxNet.IxNextgen(self.ixnet) - def test_find_view_obj_no_where(self): - views = ['here', 'there', 'everywhere'] - result = IxNextgen.find_view_obj('no_where', views) - self.assertEqual(result, '') + result = ixnet_gen.get_statistics() + self.assertIsNotNone(result) + self.assertEqual(self.ixnet.execute.call_count, 12) + # NOTE(ralonsoh): to be updated in next patchset def test_add_ip_header_v4(self): static_traffic_params = { "uplink_0": { @@ -354,18 +455,18 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.remapIds.return_value = ["0"] - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] - ixnet.getList.side_effect = [[1], [0], [0], ["srcIp", "dstIp"]] + self.ixnet.remapIds.return_value = ["0"] + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [[1], [0], [0], ["srcIp", "dstIp"]] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) - result = ixnet_gen.add_ip_header(static_traffic_params, IP_VERSION_4) + result = ixnet_gen.add_ip_header(static_traffic_params, + IxNet.IP_VERSION_4) self.assertIsNone(result) - self.assertGreater(ixnet.setMultiAttribute.call_count, 0) - self.assertEqual(ixnet.commit.call_count, 1) + self.ixnet.setMultiAttribute.assert_called() + self.ixnet.commit.assert_called_once() def test_add_ip_header_v4_nothing_to_do(self): static_traffic_params = { @@ -452,18 +553,18 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.remapIds.return_value = ["0"] - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] - ixnet.getList.side_effect = [[1], [0, 1], [0], ["srcIp", "dstIp"]] + self.ixnet.remapIds.return_value = ["0"] + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [[1], [0, 1], [0], ["srcIp", "dstIp"]] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) - result = ixnet_gen.add_ip_header(static_traffic_params, IP_VERSION_4) + result = ixnet_gen.add_ip_header(static_traffic_params, + IxNet.IP_VERSION_4) self.assertIsNone(result) - self.assertGreater(ixnet.setMultiAttribute.call_count, 0) - self.assertEqual(ixnet.commit.call_count, 1) + self.ixnet.setMultiAttribute.assert_called() + self.ixnet.commit.assert_called_once() def test_add_ip_header_v6(self): static_traffic_profile = { @@ -535,18 +636,18 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.getList.side_effect = [[1], [1], [1], ["srcIp", "dstIp"]] - ixnet.remapIds.return_value = ["0"] - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [[1], [1], [1], ["srcIp", "dstIp"]] + self.ixnet.remapIds.return_value = ["0"] + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) - result = ixnet_gen.add_ip_header(static_traffic_profile, IP_VERSION_6) + result = ixnet_gen.add_ip_header(static_traffic_profile, + IxNet.IP_VERSION_6) self.assertIsNone(result) - self.assertGreater(ixnet.setMultiAttribute.call_count, 0) - self.assertEqual(ixnet.commit.call_count, 1) + self.ixnet.setMultiAttribute.assert_called() + self.ixnet.commit.assert_called_once() def test_add_ip_header_v6_nothing_to_do(self): static_traffic_params = { @@ -617,21 +718,21 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.getList.side_effect = [[1], [0, 1], [1], ["srcIP", "dstIP"]] - ixnet.remapIds.return_value = ["0"] - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [[1], [0, 1], [1], ["srcIP", "dstIP"]] + self.ixnet.remapIds.return_value = ["0"] + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) - result = ixnet_gen.add_ip_header(static_traffic_params, IP_VERSION_6) + result = ixnet_gen.add_ip_header(static_traffic_params, + IxNet.IP_VERSION_6) self.assertIsNone(result) - self.assertEqual(ixnet.setMultiAttribute.call_count, 0) + self.ixnet.setMultiAttribute.assert_not_called() def test_set_random_ip_multi_attributes_bad_ip_version(self): bad_ip_version = object() - ixnet_gen = IxNextgen(mock.Mock()) + ixnet_gen = IxNet.IxNextgen(mock.Mock()) with self.assertRaises(ValueError): ixnet_gen.set_random_ip_multi_attributes( mock.Mock(), bad_ip_version, mock.Mock(), mock.Mock()) @@ -676,8 +777,8 @@ class TestIxNextgen(unittest.TestCase): 'bidir': True, } - result = IxNextgen.get_config(tg_cfg) - self.assertDictEqual(result, expected) + result = IxNet.IxNextgen.get_config(tg_cfg) + self.assertEqual(result, expected) def test_ix_update_ether(self): static_traffic_params = { @@ -763,10 +864,9 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] - ixnet.getList.side_effect = [ + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [ [1], [1], [1], @@ -776,11 +876,11 @@ class TestIxNextgen(unittest.TestCase): ], ] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_update_ether(static_traffic_params) self.assertIsNone(result) - self.assertGreater(ixnet.setMultiAttribute.call_count, 0) + self.ixnet.setMultiAttribute.assert_called() def test_ix_update_ether_nothing_to_do(self): static_traffic_params = { @@ -854,10 +954,9 @@ class TestIxNextgen(unittest.TestCase): } } - ixnet = mock.MagicMock() - ixnet.setMultiAttribute.return_value = [1] - ixnet.commit.return_value = [1] - ixnet.getList.side_effect = [ + self.ixnet.setMultiAttribute.return_value = [1] + self.ixnet.commit.return_value = [1] + self.ixnet.getList.side_effect = [ [1], [1], [1], @@ -867,8 +966,8 @@ class TestIxNextgen(unittest.TestCase): ], ] - ixnet_gen = IxNextgen(ixnet) + ixnet_gen = IxNet.IxNextgen(self.ixnet) result = ixnet_gen.ix_update_ether(static_traffic_params) self.assertIsNone(result) - self.assertEqual(ixnet.setMultiAttribute.call_count, 0) + self.ixnet.setMultiAttribute.assert_not_called() |