Modify IxNextgen API for traffic model configuration 13/63113/1
authorSerhiy Pshyk <serhiyx.pshyk@intel.com>
Tue, 25 Sep 2018 16:37:05 +0000 (17:37 +0100)
committerAbhijit Sinha <abhijit.sinha@intel.com>
Wed, 3 Oct 2018 09:10:22 +0000 (09:10 +0000)
Changes to IxNextgen API:
 - modify API for traffic model configuration so that it can be used
   to create/configure different models
 - add methods to start and stop protocols on IxNetwork
 - add method for getting assigned ports

JIRA: YARDSTICK-1455

Change-Id: I43c10fea9ba83994caf373ceff8b0252a45439b3
Signed-off-by: Serhiy Pshyk <serhiyx.pshyk@intel.com>
(cherry picked from commit 7237241a396871d637f9906c1fc93a8587a7b726)

yardstick/network_services/libs/ixia_libs/ixnet/ixnet_api.py
yardstick/tests/unit/network_services/libs/ixia_libs/test_ixnet_api.py

index 12f081d..cf625d4 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright (c) 2016-2017 Intel Corporation
+# Copyright (c) 2016-2018 Intel Corporation
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -121,6 +121,11 @@ class IxNextgen(object):  # pragma: no cover
             return self._ixnet
         raise exceptions.IxNetworkClientNotConnected()
 
+    def get_vports(self):
+        """Return the list of assigned ports (vport objects)"""
+        vports = self.ixnet.getList(self.ixnet.getRoot(), 'vport')
+        return vports
+
     def _get_config_element_by_flow_group_name(self, flow_group_name):
         """Get a config element using the flow group name
 
@@ -252,7 +257,7 @@ class IxNextgen(object):  # pragma: no cover
             if self.ixnet.getAttribute(vport, '-state') != 'up':
                 log.warning('Port %s is down', vport)
 
-    def _create_traffic_item(self):
+    def _create_traffic_item(self, traffic_type='raw'):
         """Create the traffic item to hold the flow groups
 
         The traffic item tracking by "Traffic Item" is enabled to retrieve the
@@ -262,7 +267,7 @@ class IxNextgen(object):  # pragma: no cover
         traffic_item = self.ixnet.add(self.ixnet.getRoot() + '/traffic',
                                       'trafficItem')
         self.ixnet.setMultiAttribute(traffic_item, '-name', 'RFC2544',
-                                     '-trafficType', 'raw')
+                                     '-trafficType', traffic_type)
         self.ixnet.commit()
 
         traffic_item_id = self.ixnet.remapIds(traffic_item)[0]
@@ -270,27 +275,25 @@ class IxNextgen(object):  # pragma: no cover
                                 '-trackBy', 'trafficGroupId0')
         self.ixnet.commit()
 
-    def _create_flow_groups(self):
-        """Create the flow groups between the assigned ports"""
+    def _create_flow_groups(self, uplink, downlink):
+        """Create the flow groups between the endpoints"""
         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]
+
         index = 0
-        for up, down in zip(uplink_ports, downlink_ports):
+        for up, down in zip(uplink, downlink):
             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, '-name', str(index + 1),
-                '-sources', [up + '/protocols'],
-                '-destinations', [down + '/protocols'])
+                '-sources', [up],
+                '-destinations', [down])
             self.ixnet.setMultiAttribute(
                 endpoint_set_2, '-name', str(index + 2),
-                '-sources', [down + '/protocols'],
-                '-destinations', [up + '/protocols'])
+                '-sources', [down],
+                '-destinations', [up])
             self.ixnet.commit()
             index += 2
 
@@ -300,7 +303,7 @@ class IxNextgen(object):  # pragma: no cover
                     '/traffic/protocolTemplate:"{}"'.format(protocol_name))
         self.ixnet.execute('append', previous_element, protocol)
 
-    def _setup_config_elements(self):
+    def _setup_config_elements(self, add_default_proto=True):
         """Setup the config elements
 
         The traffic item is configured to allow individual configurations per
@@ -322,12 +325,13 @@ class IxNextgen(object):  # pragma: no cover
             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"')
+            if add_default_proto:
+                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):
+    def create_traffic_model(self, uplink_ports, downlink_ports):
         """Create a traffic item and the needed flow groups
 
         Each flow group inside the traffic item (only one is present)
@@ -338,10 +342,27 @@ class IxNextgen(object):  # pragma: no cover
             FlowGroup3: port3    -> port4
             FlowGroup4: port3    <- port4
         """
-        self._create_traffic_item()
-        self._create_flow_groups()
+        self._create_traffic_item('raw')
+        uplink_endpoints = [port + '/protocols' for port in uplink_ports]
+        downlink_endpoints = [port + '/protocols' for port in downlink_ports]
+        self._create_flow_groups(uplink_endpoints, downlink_endpoints)
         self._setup_config_elements()
 
+    def create_ipv4_traffic_model(self, uplink_topologies, downlink_topologies):
+        """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 topologies:
+                        (uplink)    (downlink)
+            FlowGroup1: uplink1    -> downlink1
+            FlowGroup2: uplink1    <- downlink1
+            FlowGroup3: uplink2    -> downlink2
+            FlowGroup4: uplink2    <- downlink2
+        """
+        self._create_traffic_item('ipv4')
+        self._create_flow_groups(uplink_topologies, downlink_topologies)
+        self._setup_config_elements(False)
+
     def _update_frame_mac(self, ethernet_descriptor, field, mac_address):
         """Set the MAC address in a config element stack Ethernet field
 
@@ -589,6 +610,12 @@ class IxNextgen(object):  # pragma: no cover
                                           self.LATENCY_NAME_MAP))
         return stats
 
+    def start_protocols(self):
+        self.ixnet.execute('startAllProtocols')
+
+    def stop_protocols(self):
+        self.ixnet.execute('stopAllProtocols')
+
     def start_traffic(self):
         """Start the traffic injection in the traffic item
 
index 4e3199a..01ed4e3 100644 (file)
@@ -421,17 +421,24 @@ class TestIxNextgen(unittest.TestCase):
                                 '-trackBy', 'trafficGroupId0')
 
     def test__create_flow_groups(self):
+        uplink_endpoints = ['up_endp1', 'up_endp2']
+        downlink_endpoints = ['down_endp1', 'down_endp2']
         self.ixnet_gen.ixnet.getList.side_effect = [['traffic_item'], ['1', '2']]
-        self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2']
-        self.ixnet_gen._create_flow_groups()
+        self.ixnet_gen.ixnet.add.side_effect = ['endp1', 'endp2', 'endp3',
+                                                'endp4']
+        self.ixnet_gen._create_flow_groups(uplink_endpoints, downlink_endpoints)
         self.ixnet_gen.ixnet.add.assert_has_calls([
             mock.call('traffic_item', 'endpointSet'),
             mock.call('traffic_item', 'endpointSet')])
         self.ixnet_gen.ixnet.setMultiAttribute.assert_has_calls([
-            mock.call('endp1', '-name', '1', '-sources', ['1/protocols'],
-                      '-destinations', ['2/protocols']),
-            mock.call('endp2', '-name', '2', '-sources', ['2/protocols'],
-                      '-destinations', ['1/protocols'])])
+            mock.call('endp1', '-name', '1', '-sources', ['up_endp1'],
+                      '-destinations', ['down_endp1']),
+            mock.call('endp2', '-name', '2', '-sources', ['down_endp1'],
+                      '-destinations', ['up_endp1']),
+            mock.call('endp3', '-name', '3', '-sources', ['up_endp2'],
+                      '-destinations', ['down_endp2']),
+            mock.call('endp4', '-name', '4', '-sources', ['down_endp2'],
+                      '-destinations', ['up_endp2'])])
 
     def test__append_protocol_to_stack(self):
 
@@ -461,12 +468,31 @@ class TestIxNextgen(unittest.TestCase):
     def test_create_traffic_model(self, mock__setup_config_elements,
                                   mock__create_flow_groups,
                                   mock__create_traffic_item):
-
-        self.ixnet_gen.create_traffic_model()
-        mock__create_traffic_item.assert_called_once()
-        mock__create_flow_groups.assert_called_once()
+        uplink_ports = ['port1', 'port3']
+        downlink_ports = ['port2', 'port4']
+        uplink_endpoints = ['port1/protocols', 'port3/protocols']
+        downlink_endpoints = ['port2/protocols', 'port4/protocols']
+        self.ixnet_gen.create_traffic_model(uplink_ports, downlink_ports)
+        mock__create_traffic_item.assert_called_once_with('raw')
+        mock__create_flow_groups.assert_called_once_with(uplink_endpoints,
+                                                         downlink_endpoints)
         mock__setup_config_elements.assert_called_once()
 
+    @mock.patch.object(ixnet_api.IxNextgen, '_create_traffic_item')
+    @mock.patch.object(ixnet_api.IxNextgen, '_create_flow_groups')
+    @mock.patch.object(ixnet_api.IxNextgen, '_setup_config_elements')
+    def test_create_ipv4_traffic_model(self, mock__setup_config_elements,
+                                       mock__create_flow_groups,
+                                       mock__create_traffic_item):
+        uplink_topologies = ['up1', 'up3']
+        downlink_topologies = ['down2', 'down4']
+        self.ixnet_gen.create_ipv4_traffic_model(uplink_topologies,
+                                                 downlink_topologies)
+        mock__create_traffic_item.assert_called_once_with('ipv4')
+        mock__create_flow_groups.assert_called_once_with(uplink_topologies,
+                                                         downlink_topologies)
+        mock__setup_config_elements.assert_called_once_with(False)
+
     def test__update_frame_mac(self):
         with mock.patch.object(self.ixnet_gen, '_get_field_in_stack_item') as \
                 mock_get_field:
@@ -672,3 +698,16 @@ class TestIxNextgen(unittest.TestCase):
         self.assertIsNone(result)
         self.ixnet.getList.assert_called_once()
         self.assertEqual(3, self.ixnet_gen._ixnet.execute.call_count)
+
+    def test_start_protocols(self):
+        self.ixnet_gen.start_protocols()
+        self.ixnet.execute.assert_called_once_with('startAllProtocols')
+
+    def test_stop_protocols(self):
+        self.ixnet_gen.stop_protocols()
+        self.ixnet.execute.assert_called_once_with('stopAllProtocols')
+
+    def test_get_vports(self):
+        self.ixnet_gen._ixnet.getRoot.return_value = 'root'
+        self.ixnet_gen.get_vports()
+        self.ixnet.getList.assert_called_once_with('root', 'vport')