pkt_gen: update testcenter implementation 69/3169/3
authorMaryam Tahhan <maryam.tahhan@intel.com>
Mon, 9 Nov 2015 02:47:09 +0000 (02:47 +0000)
committerMaryam Tahhan <maryam.tahhan@intel.com>
Wed, 11 Nov 2015 17:59:46 +0000 (17:59 +0000)
Update testcenter implementation to move settings to
generic settings file and change windows line endings.
JIRA: VSPERF-126
Change-Id: I156005f261bc0df6c3d8009db72ba2d5991c6166

Signed-off-by: Maryam Tahhan <maryam.tahhan@intel.com>
Reviewed-by: Martin Klozik <martinx.klozik@intel.com>
Reviewed-by: Billy O Mahony <billy.o.mahony@intel.com>
Reviewed-by: Al Morton <acmorton@att.com>
Reviewed-by: Brian Castelli <brian.castelli@spirent.com>
Reviewed-by: Gene Snider <eugene.snider@huawei.com>
conf/03_traffic.conf
conf/10_custom.conf
tools/pkt_gen/testcenter/__init__.py [changed mode: 0755->0644]
tools/pkt_gen/testcenter/testcenter-rfc2544-throughput.py

index efc1b2f..7e3019a 100644 (file)
@@ -23,7 +23,10 @@ LOG_FILE_TRAFFIC_GEN = 'traffic-gen.log'
 TRAFFICGEN_DIR = os.path.join(ROOT_DIR, 'tools/pkt_gen')
 
 # traffic generator to use in tests
-TRAFFICGEN = 'IxNet'
+#TRAFFICGEN = 'TestCenter'
+TRAFFICGEN = 'Dummy'
+#TRAFFICGEN = 'IxNet'
+#TRAFFICGEN = 'Ixia'
 
 # List of packet sizes to send.
 # Expand like this: (64, 128, 256, 512, 1024)
@@ -55,3 +58,103 @@ TRAFFICGEN_IXNET_TESTER_RESULT_DIR = ''
 # The result directory on DUT. This needs to map to the same directory
 # as the previous one
 TRAFFICGEN_IXNET_DUT_RESULT_DIR = ''
+
+###########################################
+# Spirent TestCenter Configuration -- BEGIN
+
+# Path to Python 2 executable
+TRAFFICGEN_STC_PYTHON2_PATH = "/bin/python2.7"
+
+# Path to the location of the TestCenter files
+TRAFFICGEN_STC_TESTCENTER_PATH = os.path.join(ROOT_DIR, 'tools/pkt_gen/testcenter')
+
+# Name of the TestCenter RFC2544 Tput helper python script
+TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME = "testcenter-rfc2544-throughput.py"
+
+# The address of the Spirent Lab Server to use
+TRAFFICGEN_STC_LAB_SERVER_ADDR = ""
+
+# The address of the Spirent License Server in your environment
+TRAFFICGEN_STC_LICENSE_SERVER_ADDR = ""
+
+# The address of the TestCenter chassis that holds the east port
+TRAFFICGEN_STC_EAST_CHASSIS_ADDR = ""
+
+# The slot number of the card that holds the east port
+TRAFFICGEN_STC_EAST_SLOT_NUM = ""
+
+# The port number on the card that holds the east port
+TRAFFICGEN_STC_EAST_PORT_NUM = ""
+
+# The address of the TestCenter chassis that holds the west port
+TRAFFICGEN_STC_WEST_CHASSIS_ADDR = ""
+
+# The slot number of the card that holds the west port
+TRAFFICGEN_STC_WEST_SLOT_NUM = ""
+
+# The port number on the card that holds the west port
+TRAFFICGEN_STC_WEST_PORT_NUM = ""
+
+# The friendly name to identify the Spirent Lab Server test session
+TRAFFICGEN_STC_TEST_SESSION_NAME = "RFC2544 Tput"
+# The directory to copy results to
+
+TRAFFICGEN_STC_RESULTS_DIR = "./Results"
+#  The prefix for the CSV results file
+
+TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX = "RFC2544_tput"
+# The number of trials to execute during the test
+
+TRAFFICGEN_STC_NUMBER_OF_TRIALS = "1"
+
+# The duration of each trial executed during the test, in seconds
+TRAFFICGEN_STC_TRIAL_DURATION_SEC = "60"
+
+# The traffic pattern between endpoints, BACKBONE, MESH or PAIR
+TRAFFICGEN_STC_TRAFFIC_PATTERN = "PAIR"
+
+# The search mode used to find the throughput rate, COMBO, STEP or BINARY
+TRAFFICGEN_STC_SEARCH_MODE = "BINARY"
+
+# The learning mode used during the test, AUTO, L2_LEARNING, L3_LERNING, or NONE
+TRAFFICGEN_STC_LEARNING_MODE = "AUTO"
+
+# The minimum percent line rate that will be used during the test
+TRAFFICGEN_STC_RATE_LOWER_LIMIT_PCT = "1.0"
+
+# The maximum percent line rate that will be used during the test
+TRAFFICGEN_STC_RATE_UPPER_LIMIT_PCT = "99.0"
+
+# If SearchMode is BINARY, the percent line rate that will be used at the start of the test
+TRAFFICGEN_STC_RATE_INITIAL_PCT = "99.0"
+
+# When SearchMode is STEP, the percent increase in load per step
+TRAFFICGEN_STC_RATE_STEP_PCT = "10.0"
+
+# The minimum percentage of load adjustment between iterations
+TRAFFICGEN_STC_RESOLUTION_PCT = "1.0"
+
+# The frame size, in bytes
+TRAFFICGEN_STC_FRAME_SIZE = "256"
+
+# The maximum acceptable frame loss percent in any iteration
+TRAFFICGEN_STC_ACCEPTABLE_FRAME_LOSS_PCT = "0.0"
+
+# The address to assign to the first emulated device interface on the first east port
+TRAFFICGEN_STC_EAST_INTF_ADDR = ""
+
+# The gateway address to assign to the first emulated device interface on the first east port
+TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR = ""
+
+# The address to assign to the first emulated device interface on the first west port
+TRAFFICGEN_STC_WEST_INTF_ADDR = ""
+
+# The gateway address to assign to the first emulated device interface on the first west port
+TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = ""
+
+# Print additional information to the terminal during the test
+TRAFFICGEN_STC_VERBOSE = "True"
+
+# Spirent TestCenter Configuration -- END
+#########################################
+
index 3f98d54..8883cb7 100644 (file)
 RTE_TARGET = '' # the relevant DPDK build target
 
 # traffic generator to use in tests
-TRAFFICGEN = 'TestCenter'
-#TRAFFICGEN = 'Dummy'
+#TRAFFICGEN = 'TestCenter'
+TRAFFICGEN = 'Dummy'
 #TRAFFICGEN = 'IxNet'
 #TRAFFICGEN = 'Ixia'
 
 ###########################################
 # Spirent TestCenter Configuration -- BEGIN
-# Path to Python 2 executable
-TRAFFICGEN_STC_PYTHON2_PATH = "/usr/local/bin/python2.7"
-# Path to the location of the TestCenter files
-TRAFFICGEN_STC_TESTCENTER_PATH = "./tools/pkt_gen/testcenter"
-# Name of the TestCenter RFC2544 Tput helper python script
-TRAFFICGEN_STC_RFC2544_TPUT_TEST_FILE_NAME = "testcenter-rfc2544-throughput.py"
-# The address of the Spirent Lab Server to use
 TRAFFICGEN_STC_LAB_SERVER_ADDR = "10.134.156.93"
-# The address of the Spirent License Server in your environment
+
 TRAFFICGEN_STC_LICENSE_SERVER_ADDR = "10.134.156.96"
-# The address of the TestCenter chassis that holds the east port
+
 TRAFFICGEN_STC_EAST_CHASSIS_ADDR = "10.134.156.70"
-# The slot number of the card that holds the east port
 TRAFFICGEN_STC_EAST_SLOT_NUM = "1"
-# The port number on the card that holds the east port
 TRAFFICGEN_STC_EAST_PORT_NUM = "1"
-# The address of the TestCenter chassis that holds the west port
+TRAFFICGEN_STC_EAST_INTF_ADDR = "192.85.1.3"
+TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR = "192.85.1.103"
+
 TRAFFICGEN_STC_WEST_CHASSIS_ADDR = "10.134.156.70"
-# The slot number of the card that holds the west port
 TRAFFICGEN_STC_WEST_SLOT_NUM = "1"
-# The port number on the card that holds the west port
 TRAFFICGEN_STC_WEST_PORT_NUM = "2"
-# The friendly name to identify the Spirent Lab Server test session
-TRAFFICGEN_STC_TEST_SESSION_NAME = "RFC2544 Tput"
-# The directory to copy results to
-TRAFFICGEN_STC_RESULTS_DIR = "./Results"
-#  The prefix for the CSV results file
-TRAFFICGEN_STC_CSV_RESULTS_FILE_PREFIX = "RFC2544_tput"
-# The number of trials to execute during the test
-TRAFFICGEN_STC_NUMBER_OF_TRIALS = "1"
-# The duration of each trial executed during the test, in seconds
-TRAFFICGEN_STC_TRIAL_DURATION_SEC = "60"
-# The traffic pattern between endpoints, BACKBONE, MESH or PAIR
-TRAFFICGEN_STC_TRAFFIC_PATTERN = "PAIR"
-# The search mode used to find the throughput rate, COMBO, STEP or BINARY
-TRAFFICGEN_STC_SEARCH_MODE = "BINARY"
-# The learning mode used during the test, AUTO, L2_LEARNING, L3_LERNING, or NONE
-TRAFFICGEN_STC_LEARNING_MODE = "AUTO"
-# The minimum percent line rate that will be used during the test
-TRAFFICGEN_STC_RATE_LOWER_LIMIT_PCT = "1.0"
-# The maximum percent line rate that will be used during the test
-TRAFFICGEN_STC_RATE_UPPER_LIMIT_PCT = "99.0"
-# If SearchMode is BINARY, the percent line rate that will be used at the start of the test
-TRAFFICGEN_STC_RATE_INITIAL_PCT = "99.0"
-# When SearchMode is STEP, the percent increase in load per step
-TRAFFICGEN_STC_RATE_STEP_PCT = "10.0"
-# The minimum percentage of load adjustment between iterations
-TRAFFICGEN_STC_RESOLUTION_PCT = "1.0"
-# The frame size, in bytes
-TRAFFICGEN_STC_FRAME_SIZE = "256"
-# The maximum acceptable frame loss percent in any iteration
-TRAFFICGEN_STC_ACCEPTABLE_FRAME_LOSS_PCT = "0.0"
-# The address to assign to the first emulated device interface on the first east port
-TRAFFICGEN_STC_EAST_INTF_ADDR = "192.85.1.3"
-# The gateway address to assign to the first emulated device interface on the first east port
-TRAFFICGEN_STC_EAST_INTF_GATEWAY_ADDR = "192.85.1.103"
-# The address to assign to the first emulated device interface on the first west port
 TRAFFICGEN_STC_WEST_INTF_ADDR = "192.85.1.103"
-# The gateway address to assign to the first emulated device interface on the first west port
 TRAFFICGEN_STC_WEST_INTF_GATEWAY_ADDR = "192.85.1.3"
-# Print additional information to the terminal during the test
-TRAFFICGEN_STC_VERBOSE = "True"
 # Spirent TestCenter Configuration -- END
 #########################################
 
+
 # Ixia/IxNet configuration
 TRAFFICGEN_IXIA_CARD = ''
 TRAFFICGEN_IXIA_PORT1 = ''
old mode 100755 (executable)
new mode 100644 (file)
index 2b875c6..becf787 100644 (file)
-# Copyright 2015 Spirent Communications.\r
-#\r
-# Licensed under the Apache License, Version 2.0 (the "License");\r
-# you may not use this file except in compliance with the License.\r
-# You may obtain a copy of the License at\r
-#\r
-#   http://www.apache.org/licenses/LICENSE-2.0\r
-#\r
-# Unless required by applicable law or agreed to in writing, software\r
-# distributed under the License is distributed on an "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-# See the License for the specific language governing permissions and\r
-# limitations under the License.\r
-\r
-'''\r
-@author Spirent Comunications\r
-\r
-This test automates the RFC2544 throughput test using the Spirent\r
-TestCenter command sequencer. This test supports Python 2.7.\r
-\r
-'''\r
-from __future__ import print_function\r
-import argparse\r
-import os\r
-\r
-\r
-def create_dir(path):\r
-    if not os.path.exists(path):\r
-        try:\r
-            os.makedirs(path)\r
-        except Exception, e:\r
-            print("Failed to create directory %s: %s" % (path, str(e)))\r
-            raise\r
-\r
-\r
-def write_query_results_to_csv(results_path, csv_results_file_prefix, query_results):\r
-    create_dir(results_path)\r
-    file = os.path.join(results_path, csv_results_file_prefix + ".csv")\r
-    with open(file, "wb") as f:\r
-        f.write(query_results["Columns"].replace(" ", ",") + "\n")\r
-        for row in query_results["Output"].replace("} {", ",").replace("{", "").replace("}", "").split(","):\r
-            f.write(row.replace(" ", ",") + "\n")\r
-\r
-\r
-def destroy_session(stc, lab_server_addr, test_session_name):\r
-    stc.perform("CSServerConnectCommand",\r
-                Host=lab_server_addr)\r
-\r
-    cs_server = stc.get("system1", "children-csserver")\r
-\r
-    cs_test_sessions = stc.get(cs_server, "children-cstestsession").split()\r
-\r
-    for session in cs_test_sessions:\r
-        name = stc.get(session, "Name")\r
-        if test_session_name in name:\r
-            stc.perform("CSDestroyTestSession",\r
-                        testSession=session)\r
-            break\r
-\r
-\r
-def create_session(stc, lab_server_addr, test_session_name):\r
-    destroy_session(stc, lab_server_addr, test_session_name)\r
-    stc.perform("CSTestSessionConnect",\r
-                Host=lab_server_addr,\r
-                CreateNewTestSession="TRUE",\r
-                TestSessionName=test_session_name)\r
-\r
-\r
-def positive_int(value):\r
-    ivalue = int(value)\r
-    if ivalue <= 0:\r
-        raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value)\r
-    return ivalue\r
-\r
-\r
-def percent_float(value):\r
-    pvalue = float(value)\r
-    if pvalue < 0.0 or pvalue > 100.0:\r
-        raise argparse.ArgumentTypeError("%s not in range [0.0, 100.0]" % pvalue)\r
-    return pvalue\r
-\r
-\r
-def main():\r
-    parser = argparse.ArgumentParser()\r
-    # Required parameters\r
-    requirednamed = parser.add_argument_group("required named arguments")\r
-    requirednamed.add_argument("--lab_server_addr",\r
-                               required=True,\r
-                               help="The IP address of the Spirent Lab Server",\r
-                               dest="lab_server_addr")\r
-    requirednamed.add_argument("--license_server_addr",\r
-                               required=True,\r
-                               help="The IP address of the Spirent License Server",\r
-                               dest="license_server_addr")\r
-    requirednamed.add_argument("--east_chassis_addr",\r
-                               required=True,\r
-                               help="The TestCenter chassis IP address to use for the east test port",\r
-                               dest="east_chassis_addr")\r
-    requirednamed.add_argument("--east_slot_num",\r
-                               type=positive_int,\r
-                               required=True,\r
-                               help="The TestCenter slot number to use for the east test port",\r
-                               dest="east_slot_num")\r
-    requirednamed.add_argument("--east_port_num",\r
-                               type=positive_int,\r
-                               required=True,\r
-                               help="The TestCenter port number to use for the east test port",\r
-                               dest="east_port_num")\r
-    requirednamed.add_argument("--west_chassis_addr",\r
-                               required=True,\r
-                               help="The TestCenter chassis IP address to use for the west test port",\r
-                               dest="west_chassis_addr")\r
-    requirednamed.add_argument("--west_slot_num",\r
-                               type=positive_int,\r
-                               required=True,\r
-                               help="The TestCenter slot number to use for the west test port",\r
-                               dest="west_slot_num")\r
-    requirednamed.add_argument("--west_port_num",\r
-                               type=positive_int,\r
-                               required=True,\r
-                               help="The TestCenter port number to use for the west test port",\r
-                               dest="west_port_num")\r
-    # Optional parameters\r
-    optionalnamed = parser.add_argument_group("optional named arguments")\r
-    optionalnamed.add_argument("--test_session_name",\r
-                               required=False,\r
-                               default="RFC2544 East-West Throughput",\r
-                               help="The friendly name to identify the Spirent Lab Server test session",\r
-                               dest="test_session_name")\r
-    optionalnamed.add_argument("--results_dir",\r
-                               required=False,\r
-                               default="./Results",\r
-                               help="The directory to copy results to",\r
-                               dest="results_dir")\r
-    optionalnamed.add_argument("--csv_results_file_prefix",\r
-                               required=False,\r
-                               default="Rfc2544Tput",\r
-                               help="The prefix for the CSV results files",\r
-                               dest="csv_results_file_prefix")\r
-    optionalnamed.add_argument("--num_trials",\r
-                               type=positive_int,\r
-                               required=False,\r
-                               default=1,\r
-                               help="The number of trials to execute during the test",\r
-                               dest="num_trials")\r
-    optionalnamed.add_argument("--trial_duration_sec",\r
-                               type=positive_int,\r
-                               required=False,\r
-                               default=60,\r
-                               help="The duration of each trial executed during the test",\r
-                               dest="trial_duration_sec")\r
-    optionalnamed.add_argument("--traffic_pattern",\r
-                               required=False,\r
-                               choices=["BACKBONE", "MESH", "PAIR"],\r
-                               default="PAIR",\r
-                               help="The traffic pattern between endpoints",\r
-                               dest="traffic_pattern")\r
-    optionalnamed.add_argument("--search_mode",\r
-                               required=False,\r
-                               choices=["COMBO", "STEP", "BINARY"],\r
-                               default="BINARY",\r
-                               help="The search mode used to find the throughput rate",\r
-                               dest="search_mode")\r
-    optionalnamed.add_argument("--learning_mode",\r
-                               required=False,\r
-                               choices=["AUTO", "L2_LEARNING", "L3_LEARNING", "NONE"],\r
-                               default="AUTO",\r
-                               help="The learning mode used during the test, default = 'NONE'",\r
-                               dest="learning_mode")\r
-    optionalnamed.add_argument("--rate_lower_limit_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=1.0,\r
-                               help="The minimum percent line rate that will be used during the test",\r
-                               dest="rate_lower_limit_pct")\r
-    optionalnamed.add_argument("--rate_upper_limit_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=99.0,\r
-                               help="The maximum percent line rate that will be used during the test",\r
-                               dest="rate_upper_limit_pct")\r
-    optionalnamed.add_argument("--rate_initial_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=99.0,\r
-                               help="If Search Mode is BINARY, the percent line rate that will be used at the start of the test",\r
-                               dest="rate_initial_pct")\r
-    optionalnamed.add_argument("--rate_step_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=10.0,\r
-                               help="If SearchMode is STEP, the percent load increase per step",\r
-                               dest="rate_step_pct")\r
-    optionalnamed.add_argument("--resolution_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=1.0,\r
-                               help="The minimum percentage of load adjustment between iterations",\r
-                               dest="resolution_pct")\r
-    optionalnamed.add_argument("--frame_size_list",\r
-                               type=lambda s: [int(item) for item in s.split(',')],\r
-                               required=False,\r
-                               default=[256],\r
-                               help="A comma-delimited list of frame sizes",\r
-                               dest="frame_size_list")\r
-    optionalnamed.add_argument("--acceptable_frame_loss_pct",\r
-                               type=percent_float,\r
-                               required=False,\r
-                               default=0.0,\r
-                               help="The maximum acceptable frame loss percent in any iteration",\r
-                               dest="acceptable_frame_loss_pct")\r
-    optionalnamed.add_argument("--east_intf_addr",\r
-                               required=False,\r
-                               default="192.85.1.3",\r
-                               help="The address to assign to the first emulated device interface on the first east port",\r
-                               dest="east_intf_addr")\r
-    optionalnamed.add_argument("--east_intf_gateway_addr",\r
-                               required=False,\r
-                               default="192.85.1.53",\r
-                               help="The gateway address to assign to the first emulated device interface on the first east port",\r
-                               dest="east_intf_gateway_addr")\r
-    optionalnamed.add_argument("--west_intf_addr",\r
-                               required=False,\r
-                               default="192.85.1.53",\r
-                               help="The address to assign to the first emulated device interface on the first west port",\r
-                               dest="west_intf_addr")\r
-    optionalnamed.add_argument("--west_intf_gateway_addr",\r
-                               required=False,\r
-                               default="192.85.1.53",\r
-                               help="The gateway address to assign to the first emulated device interface on the first west port",\r
-                               dest="west_intf_gateway_addr")\r
-    parser.add_argument("-v",\r
-                        "--verbose",\r
-                        required=False,\r
-                        default=False,\r
-                        help="More output during operation when present",\r
-                        action="store_true",\r
-                        dest="verbose")\r
-    args = parser.parse_args()\r
-\r
-    if args.verbose:\r
-        print("Make sure results directory exists")\r
-    create_dir(args.results_dir)\r
-\r
-    # Load Spirent Test Center library\r
-    from StcPython import StcPython\r
-    stc = StcPython()\r
-\r
-    tx_port_loc = "//%s/%s/%s" % (args.east_chassis_addr,\r
-                                  args.east_slot_num,\r
-                                  args.east_port_num)\r
-    rx_port_loc = "//%s/%s/%s" % (args.west_chassis_addr,\r
-                                  args.west_slot_num,\r
-                                  args.west_port_num)\r
-\r
-    # This line will write the TestCenter commands to a log file\r
-    stc.config("automationoptions", logto="test-op", loglevel="DEBUG")\r
-\r
-    # Retrieve and display the current API version.\r
-    if args.verbose:\r
-        print ("SpirentTestCenter system version: %s" % stc.get("system1", "version"))\r
-\r
-    create_session(stc, args.lab_server_addr, args.test_session_name)\r
-\r
-    try:\r
-        device_list = []\r
-\r
-        if args.verbose:\r
-            print("Bring up license server")\r
-        license_mgr = stc.get("system1", "children-licenseservermanager")\r
-        if args.verbose:\r
-            print("license_mgr = %s" % license_mgr)\r
-        stc.create("LicenseServer", under=license_mgr, server=args.license_server_addr)\r
-\r
-        # Create the root project object\r
-        if args.verbose:\r
-            print ("Creating project ...")\r
-        project = stc.get("System1", "children-Project")\r
-\r
-        # Create ports\r
-        if args.verbose:\r
-            print ("Creating ports ...")\r
-        east_chassis_port = stc.create("port",\r
-                                       under=project,\r
-                                       location=tx_port_loc,\r
-                                       useDefaultHost="False")\r
-        west_chassis_port = stc.create("port",\r
-                                       under=project,\r
-                                       location=rx_port_loc,\r
-                                       useDefaultHost="False")\r
-\r
-        if args.verbose:\r
-            print ("Creating devices...")\r
-        # Create emulated genparam for east port\r
-        east_device_gen_params = stc.create("EmulatedDeviceGenParams",\r
-                                            under=project,\r
-                                            Port=east_chassis_port)\r
-        # Create the DeviceGenEthIIIfParams object\r
-        stc.create("DeviceGenEthIIIfParams",\r
-                   under=east_device_gen_params)\r
-        # Configuring Ipv4 interfaces\r
-        stc.create("DeviceGenIpv4IfParams",\r
-                   under=east_device_gen_params,\r
-                   Addr=args.east_intf_addr,\r
-                   Gateway=args.east_intf_gateway_addr)\r
-        # Create Devices using the Device Wizard\r
-        device_gen_config = stc.perform("DeviceGenConfigExpand",\r
-                                        DeleteExisting="No",\r
-                                        GenParams=east_device_gen_params)\r
-        # Append to the device list\r
-        device_list.append(device_gen_config['ReturnList'])\r
-\r
-        # Create emulated genparam for west port\r
-        west_device_gen_params = stc.create("EmulatedDeviceGenParams",\r
-                                            under=project,\r
-                                            Port=west_chassis_port)\r
-        # Create the DeviceGenEthIIIfParams object\r
-        stc.create("DeviceGenEthIIIfParams",\r
-                   under=west_device_gen_params)\r
-        # Configuring Ipv4 interfaces\r
-        stc.create("DeviceGenIpv4IfParams",\r
-                   under=west_device_gen_params,\r
-                   Addr=args.west_intf_addr,\r
-                   Gateway=args.west_intf_gateway_addr)\r
-        # Create Devices using the Device Wizard\r
-        device_gen_config = stc.perform("DeviceGenConfigExpand",\r
-                                        DeleteExisting="No",\r
-                                        GenParams=west_device_gen_params)\r
-        # Append to the device list\r
-        device_list.append(device_gen_config['ReturnList'])\r
-\r
-        if args.verbose:\r
-            print(device_list)\r
-\r
-        # Create the RFC 2544 throughput test\r
-        if args.verbose:\r
-            print ("Set up the RFC2544 throughput test...")\r
-        stc.perform("Rfc2544SetupThroughputTestCommand",\r
-                    AcceptableFrameLoss=args.acceptable_frame_loss_pct,\r
-                    Duration=args.trial_duration_sec,\r
-                    FrameSizeList=args.frame_size_list,\r
-                    LearningMode=args.learning_mode,\r
-                    NumOfTrials=args.num_trials,\r
-                    RateInitial=args.rate_initial_pct,\r
-                    RateLowerLimit=args.rate_lower_limit_pct,\r
-                    RateStep=args.rate_step_pct,\r
-                    RateUpperLimit=args.rate_upper_limit_pct,\r
-                    Resolution=args.resolution_pct,\r
-                    SearchMode=args.search_mode,\r
-                    TrafficPattern=args.traffic_pattern)\r
-\r
-        # Save the configuration\r
-        stc.perform("SaveToTcc", Filename="2544.tcc")\r
-\r
-        # Connect to the hardware...\r
-        stc.perform("AttachPorts", portList=stc.get("system1.project", "children-port"), autoConnect="TRUE")\r
-\r
-        # Apply configuration.\r
-        if args.verbose:\r
-            print("Apply configuration...")\r
-        stc.apply\r
-\r
-        if args.verbose:\r
-            print("Starting the sequencer...")\r
-        stc.perform("SequencerStart")\r
-\r
-        # Wait for sequencer to finish\r
-        print("Starting test... Please wait for the test to complete...")\r
-        stc.waitUntilComplete()\r
-        print("The test has completed... Saving results...")\r
-\r
-        # Determine what the results database filename is...\r
-        lab_server_resultsdb = stc.get("system1.project.TestResultSetting", "CurrentResultFileName")\r
-\r
-        if args.verbose:\r
-            print("The lab server results database is %s" % lab_server_resultsdb)\r
-\r
-        stc.perform("CSSynchronizeFiles",\r
-                    DefaultDownloadDir=args.results_dir)\r
-\r
-        resultsdb = args.results_dir + lab_server_resultsdb.split("/Results")[1]\r
-\r
-        print("The local summary DB file has been saved to %s" % resultsdb)\r
-\r
-        # The returns the "RFC2544ThroughputTestResultDetailedSummaryView" table view from the results database.\r
-        # There are other views available.\r
-        resultsdict = stc.perform("QueryResult",\r
-                                  DatabaseConnectionString=resultsdb,\r
-                                  ResultPath="RFC2544ThroughputTestResultDetailedSummaryView")\r
-        if args.verbose:\r
-            print("resultsdict[\"Columns\"]: %s" % resultsdict["Columns"])\r
-            print("resultsdict[\"Output\"]: %s" % resultsdict["Output"])\r
-\r
-        if args.verbose:\r
-            print("Result paths: %s" % stc.perform("GetTestResultSettingPaths"))\r
-\r
-        # Write results to csv\r
-        if args.verbose:\r
-            print("Writing CSV file to results directory %s" % args.results_dir)\r
-        write_query_results_to_csv(args.results_dir, args.csv_results_file_prefix, resultsdict)\r
-\r
-    except Exception, e:\r
-        print("Exception: %s" % str(e))\r
-        # destroy_session(stc, args.lab_server_addr, args.test_session_name)\r
-        raise\r
-\r
-    if args.verbose:\r
-        print("Disconnect from lab server")\r
-    stc.perform("CSTestSessionDisconnect")\r
-\r
-    if args.verbose:\r
-        print("Destroy session on lab server")\r
-    # destroy_session(stc, args.lab_server_addr, args.test_session_name)\r
-    print("Test complete!")\r
-\r
-\r
-if __name__ == "__main__":\r
-    main()\r
+# Copyright 2015 Spirent Communications.
+#
+# 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.
+
+'''
+@author Spirent Comunications
+
+This test automates the RFC2544 throughput test using the Spirent
+TestCenter command sequencer. This test supports Python 2.7.
+
+'''
+from __future__ import print_function
+import argparse
+import os
+
+
+def create_dir(path):
+    if not os.path.exists(path):
+        try:
+            os.makedirs(path)
+        except Exception, e:
+            print("Failed to create directory %s: %s" % (path, str(e)))
+            raise
+
+
+def write_query_results_to_csv(results_path, csv_results_file_prefix, query_results):
+    create_dir(results_path)
+    file = os.path.join(results_path, csv_results_file_prefix + ".csv")
+    with open(file, "wb") as f:
+        f.write(query_results["Columns"].replace(" ", ",") + "\n")
+        for row in query_results["Output"].replace("} {", ",").replace("{", "").replace("}", "").split(","):
+            f.write(row.replace(" ", ",") + "\n")
+
+
+def destroy_session(stc, lab_server_addr, test_session_name):
+    stc.perform("CSServerConnectCommand",
+                Host=lab_server_addr)
+
+    cs_server = stc.get("system1", "children-csserver")
+
+    cs_test_sessions = stc.get(cs_server, "children-cstestsession").split()
+
+    for session in cs_test_sessions:
+        name = stc.get(session, "Name")
+        if test_session_name in name:
+            stc.perform("CSDestroyTestSession",
+                        testSession=session)
+            break
+
+
+def create_session(stc, lab_server_addr, test_session_name):
+    destroy_session(stc, lab_server_addr, test_session_name)
+    stc.perform("CSTestSessionConnect",
+                Host=lab_server_addr,
+                CreateNewTestSession="TRUE",
+                TestSessionName=test_session_name)
+
+
+def positive_int(value):
+    ivalue = int(value)
+    if ivalue <= 0:
+        raise argparse.ArgumentTypeError("%s is an invalid positive int value" % value)
+    return ivalue
+
+
+def percent_float(value):
+    pvalue = float(value)
+    if pvalue < 0.0 or pvalue > 100.0:
+        raise argparse.ArgumentTypeError("%s not in range [0.0, 100.0]" % pvalue)
+    return pvalue
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    # Required parameters
+    requirednamed = parser.add_argument_group("required named arguments")
+    requirednamed.add_argument("--lab_server_addr",
+                               required=True,
+                               help="The IP address of the Spirent Lab Server",
+                               dest="lab_server_addr")
+    requirednamed.add_argument("--license_server_addr",
+                               required=True,
+                               help="The IP address of the Spirent License Server",
+                               dest="license_server_addr")
+    requirednamed.add_argument("--east_chassis_addr",
+                               required=True,
+                               help="The TestCenter chassis IP address to use for the east test port",
+                               dest="east_chassis_addr")
+    requirednamed.add_argument("--east_slot_num",
+                               type=positive_int,
+                               required=True,
+                               help="The TestCenter slot number to use for the east test port",
+                               dest="east_slot_num")
+    requirednamed.add_argument("--east_port_num",
+                               type=positive_int,
+                               required=True,
+                               help="The TestCenter port number to use for the east test port",
+                               dest="east_port_num")
+    requirednamed.add_argument("--west_chassis_addr",
+                               required=True,
+                               help="The TestCenter chassis IP address to use for the west test port",
+                               dest="west_chassis_addr")
+    requirednamed.add_argument("--west_slot_num",
+                               type=positive_int,
+                               required=True,
+                               help="The TestCenter slot number to use for the west test port",
+                               dest="west_slot_num")
+    requirednamed.add_argument("--west_port_num",
+                               type=positive_int,
+                               required=True,
+                               help="The TestCenter port number to use for the west test port",
+                               dest="west_port_num")
+    # Optional parameters
+    optionalnamed = parser.add_argument_group("optional named arguments")
+    optionalnamed.add_argument("--test_session_name",
+                               required=False,
+                               default="RFC2544 East-West Throughput",
+                               help="The friendly name to identify the Spirent Lab Server test session",
+                               dest="test_session_name")
+    optionalnamed.add_argument("--results_dir",
+                               required=False,
+                               default="./Results",
+                               help="The directory to copy results to",
+                               dest="results_dir")
+    optionalnamed.add_argument("--csv_results_file_prefix",
+                               required=False,
+                               default="Rfc2544Tput",
+                               help="The prefix for the CSV results files",
+                               dest="csv_results_file_prefix")
+    optionalnamed.add_argument("--num_trials",
+                               type=positive_int,
+                               required=False,
+                               default=1,
+                               help="The number of trials to execute during the test",
+                               dest="num_trials")
+    optionalnamed.add_argument("--trial_duration_sec",
+                               type=positive_int,
+                               required=False,
+                               default=60,
+                               help="The duration of each trial executed during the test",
+                               dest="trial_duration_sec")
+    optionalnamed.add_argument("--traffic_pattern",
+                               required=False,
+                               choices=["BACKBONE", "MESH", "PAIR"],
+                               default="PAIR",
+                               help="The traffic pattern between endpoints",
+                               dest="traffic_pattern")
+    optionalnamed.add_argument("--search_mode",
+                               required=False,
+                               choices=["COMBO", "STEP", "BINARY"],
+                               default="BINARY",
+                               help="The search mode used to find the throughput rate",
+                               dest="search_mode")
+    optionalnamed.add_argument("--learning_mode",
+                               required=False,
+                               choices=["AUTO", "L2_LEARNING", "L3_LEARNING", "NONE"],
+                               default="AUTO",
+                               help="The learning mode used during the test, default = 'NONE'",
+                               dest="learning_mode")
+    optionalnamed.add_argument("--rate_lower_limit_pct",
+                               type=percent_float,
+                               required=False,
+                               default=1.0,
+                               help="The minimum percent line rate that will be used during the test",
+                               dest="rate_lower_limit_pct")
+    optionalnamed.add_argument("--rate_upper_limit_pct",
+                               type=percent_float,
+                               required=False,
+                               default=99.0,
+                               help="The maximum percent line rate that will be used during the test",
+                               dest="rate_upper_limit_pct")
+    optionalnamed.add_argument("--rate_initial_pct",
+                               type=percent_float,
+                               required=False,
+                               default=99.0,
+                               help="If Search Mode is BINARY, the percent line rate that will be used at the start of the test",
+                               dest="rate_initial_pct")
+    optionalnamed.add_argument("--rate_step_pct",
+                               type=percent_float,
+                               required=False,
+                               default=10.0,
+                               help="If SearchMode is STEP, the percent load increase per step",
+                               dest="rate_step_pct")
+    optionalnamed.add_argument("--resolution_pct",
+                               type=percent_float,
+                               required=False,
+                               default=1.0,
+                               help="The minimum percentage of load adjustment between iterations",
+                               dest="resolution_pct")
+    optionalnamed.add_argument("--frame_size_list",
+                               type=lambda s: [int(item) for item in s.split(',')],
+                               required=False,
+                               default=[256],
+                               help="A comma-delimited list of frame sizes",
+                               dest="frame_size_list")
+    optionalnamed.add_argument("--acceptable_frame_loss_pct",
+                               type=percent_float,
+                               required=False,
+                               default=0.0,
+                               help="The maximum acceptable frame loss percent in any iteration",
+                               dest="acceptable_frame_loss_pct")
+    optionalnamed.add_argument("--east_intf_addr",
+                               required=False,
+                               default="192.85.1.3",
+                               help="The address to assign to the first emulated device interface on the first east port",
+                               dest="east_intf_addr")
+    optionalnamed.add_argument("--east_intf_gateway_addr",
+                               required=False,
+                               default="192.85.1.53",
+                               help="The gateway address to assign to the first emulated device interface on the first east port",
+                               dest="east_intf_gateway_addr")
+    optionalnamed.add_argument("--west_intf_addr",
+                               required=False,
+                               default="192.85.1.53",
+                               help="The address to assign to the first emulated device interface on the first west port",
+                               dest="west_intf_addr")
+    optionalnamed.add_argument("--west_intf_gateway_addr",
+                               required=False,
+                               default="192.85.1.53",
+                               help="The gateway address to assign to the first emulated device interface on the first west port",
+                               dest="west_intf_gateway_addr")
+    parser.add_argument("-v",
+                        "--verbose",
+                        required=False,
+                        default=False,
+                        help="More output during operation when present",
+                        action="store_true",
+                        dest="verbose")
+    args = parser.parse_args()
+
+    if args.verbose:
+        print("Make sure results directory exists")
+    create_dir(args.results_dir)
+
+    # Load Spirent Test Center library
+    from StcPython import StcPython
+    stc = StcPython()
+
+    tx_port_loc = "//%s/%s/%s" % (args.east_chassis_addr,
+                                  args.east_slot_num,
+                                  args.east_port_num)
+    rx_port_loc = "//%s/%s/%s" % (args.west_chassis_addr,
+                                  args.west_slot_num,
+                                  args.west_port_num)
+
+    # This line will write the TestCenter commands to a log file
+    stc.config("automationoptions", logto="test-op", loglevel="DEBUG")
+
+    # Retrieve and display the current API version.
+    if args.verbose:
+        print ("SpirentTestCenter system version: %s" % stc.get("system1", "version"))
+
+    create_session(stc, args.lab_server_addr, args.test_session_name)
+
+    try:
+        device_list = []
+
+        if args.verbose:
+            print("Bring up license server")
+        license_mgr = stc.get("system1", "children-licenseservermanager")
+        if args.verbose:
+            print("license_mgr = %s" % license_mgr)
+        stc.create("LicenseServer", under=license_mgr, server=args.license_server_addr)
+
+        # Create the root project object
+        if args.verbose:
+            print ("Creating project ...")
+        project = stc.get("System1", "children-Project")
+
+        # Create ports
+        if args.verbose:
+            print ("Creating ports ...")
+        east_chassis_port = stc.create("port",
+                                       under=project,
+                                       location=tx_port_loc,
+                                       useDefaultHost="False")
+        west_chassis_port = stc.create("port",
+                                       under=project,
+                                       location=rx_port_loc,
+                                       useDefaultHost="False")
+
+        if args.verbose:
+            print ("Creating devices...")
+        # Create emulated genparam for east port
+        east_device_gen_params = stc.create("EmulatedDeviceGenParams",
+                                            under=project,
+                                            Port=east_chassis_port)
+        # Create the DeviceGenEthIIIfParams object
+        stc.create("DeviceGenEthIIIfParams",
+                   under=east_device_gen_params)
+        # Configuring Ipv4 interfaces
+        stc.create("DeviceGenIpv4IfParams",
+                   under=east_device_gen_params,
+                   Addr=args.east_intf_addr,
+                   Gateway=args.east_intf_gateway_addr)
+        # Create Devices using the Device Wizard
+        device_gen_config = stc.perform("DeviceGenConfigExpand",
+                                        DeleteExisting="No",
+                                        GenParams=east_device_gen_params)
+        # Append to the device list
+        device_list.append(device_gen_config['ReturnList'])
+
+        # Create emulated genparam for west port
+        west_device_gen_params = stc.create("EmulatedDeviceGenParams",
+                                            under=project,
+                                            Port=west_chassis_port)
+        # Create the DeviceGenEthIIIfParams object
+        stc.create("DeviceGenEthIIIfParams",
+                   under=west_device_gen_params)
+        # Configuring Ipv4 interfaces
+        stc.create("DeviceGenIpv4IfParams",
+                   under=west_device_gen_params,
+                   Addr=args.west_intf_addr,
+                   Gateway=args.west_intf_gateway_addr)
+        # Create Devices using the Device Wizard
+        device_gen_config = stc.perform("DeviceGenConfigExpand",
+                                        DeleteExisting="No",
+                                        GenParams=west_device_gen_params)
+        # Append to the device list
+        device_list.append(device_gen_config['ReturnList'])
+
+        if args.verbose:
+            print(device_list)
+
+        # Create the RFC 2544 throughput test
+        if args.verbose:
+            print ("Set up the RFC2544 throughput test...")
+        stc.perform("Rfc2544SetupThroughputTestCommand",
+                    AcceptableFrameLoss=args.acceptable_frame_loss_pct,
+                    Duration=args.trial_duration_sec,
+                    FrameSizeList=args.frame_size_list,
+                    LearningMode=args.learning_mode,
+                    NumOfTrials=args.num_trials,
+                    RateInitial=args.rate_initial_pct,
+                    RateLowerLimit=args.rate_lower_limit_pct,
+                    RateStep=args.rate_step_pct,
+                    RateUpperLimit=args.rate_upper_limit_pct,
+                    Resolution=args.resolution_pct,
+                    SearchMode=args.search_mode,
+                    TrafficPattern=args.traffic_pattern)
+
+        # Save the configuration
+        stc.perform("SaveToTcc", Filename="2544.tcc")
+
+        # Connect to the hardware...
+        stc.perform("AttachPorts", portList=stc.get("system1.project", "children-port"), autoConnect="TRUE")
+
+        # Apply configuration.
+        if args.verbose:
+            print("Apply configuration...")
+        stc.apply
+
+        if args.verbose:
+            print("Starting the sequencer...")
+        stc.perform("SequencerStart")
+
+        # Wait for sequencer to finish
+        print("Starting test... Please wait for the test to complete...")
+        stc.waitUntilComplete()
+        print("The test has completed... Saving results...")
+
+        # Determine what the results database filename is...
+        lab_server_resultsdb = stc.get("system1.project.TestResultSetting", "CurrentResultFileName")
+
+        if args.verbose:
+            print("The lab server results database is %s" % lab_server_resultsdb)
+
+        stc.perform("CSSynchronizeFiles",
+                    DefaultDownloadDir=args.results_dir)
+
+        resultsdb = args.results_dir + lab_server_resultsdb.split("/Results")[1]
+
+        print("The local summary DB file has been saved to %s" % resultsdb)
+
+        # The returns the "RFC2544ThroughputTestResultDetailedSummaryView" table view from the results database.
+        # There are other views available.
+        resultsdict = stc.perform("QueryResult",
+                                  DatabaseConnectionString=resultsdb,
+                                  ResultPath="RFC2544ThroughputTestResultDetailedSummaryView")
+        if args.verbose:
+            print("resultsdict[\"Columns\"]: %s" % resultsdict["Columns"])
+            print("resultsdict[\"Output\"]: %s" % resultsdict["Output"])
+
+        if args.verbose:
+            print("Result paths: %s" % stc.perform("GetTestResultSettingPaths"))
+
+        # Write results to csv
+        if args.verbose:
+            print("Writing CSV file to results directory %s" % args.results_dir)
+        write_query_results_to_csv(args.results_dir, args.csv_results_file_prefix, resultsdict)
+
+    except Exception, e:
+        print("Exception: %s" % str(e))
+        # destroy_session(stc, args.lab_server_addr, args.test_session_name)
+        raise
+
+    if args.verbose:
+        print("Disconnect from lab server")
+    stc.perform("CSTestSessionDisconnect")
+
+    if args.verbose:
+        print("Destroy session on lab server")
+    # destroy_session(stc, args.lab_server_addr, args.test_session_name)
+    print("Test complete!")
+
+
+if __name__ == "__main__":
+    main()