Beispiel #1
0
    def step_run(self):
        """ Execute actions specified by TestSteps list

        :return: False if any error was detected
                 True otherwise
        """
        # anything to do?
        if not self.test:
            return True

        # required for VNFs initialization
        loader = Loader()
        # initialize list with results
        self._step_result = [None] * len(self.test)

        # run test step by step...
        for i, step in enumerate(self.test):
            step_ok = not self._step_check
            step_check = self._step_check
            regex = None
            # configure step result mapping if step alias/label is detected
            if step[0].startswith('#'):
                key = step[0][1:]
                if key.isdigit():
                    raise RuntimeError(
                        'Step alias can\'t be an integer value {}'.format(key))
                if key in self._step_result_mapping:
                    raise RuntimeError(
                        'Step alias {} has been used already for step '
                        '{}'.format(key, self._step_result_mapping[key]))
                self._step_result_mapping[step[0][1:]] = i
                step = step[1:]

            # store regex filter if it is specified
            if isinstance(step[-1], str) and step[-1].startswith('|'):
                # evalute macros and variables used in regex
                regex = self.step_eval_params([step[-1][1:]],
                                              self._step_result[:i])[0]
                step = step[:-1]

            # check if step verification should be suppressed
            if step[0].startswith('!'):
                step_check = False
                step_ok = True
                step[0] = step[0][1:]
            if step[0] == 'vswitch':
                test_object = self._vswitch_ctl.get_vswitch()
            elif step[0] == 'namespace':
                test_object = namespace
            elif step[0] == 'veth':
                test_object = veth
            elif step[0] == 'settings':
                test_object = S
            elif step[0] == 'tools':
                test_object = TestStepsTools()
                step[1] = step[1].title()
            elif step[0] == 'trafficgen':
                test_object = self._traffic_ctl
                # in case of send_traffic or send_traffic_async methods, ensure
                # that specified traffic values are merged with existing self._traffic
                if step[1].startswith('send_traffic'):
                    tmp_traffic = copy.deepcopy(self._traffic)
                    tmp_traffic.update(step[2])
                    step[2] = tmp_traffic
                    # store indication that traffic has been sent
                    # so it is not sent again after the execution of teststeps
                    self._step_send_traffic = True
            elif step[0].startswith('vnf'):
                # use vnf started within TestSteps
                if not self._step_vnf_list[step[0]]:
                    # initialize new VM
                    self._step_vnf_list[step[0]] = loader.get_vnf_class()()
                test_object = self._step_vnf_list[step[0]]
            elif step[0].startswith('VNF'):
                if step[1] in ('start', 'stop'):
                    raise RuntimeError(
                        "Cannot execute start() or stop() method of "
                        "VNF deployed automatically by scenario.")
                # use vnf started by scenario deployment (e.g. pvp)
                vnf_index = int(step[0][3:])
                try:
                    test_object = self._vnf_list[vnf_index]
                except IndexError:
                    raise RuntimeError(
                        "VNF with index {} is not running.".format(vnf_index))
            elif step[0] == 'wait':
                input(os.linesep + "Step {}: Press Enter to continue with "
                      "the next step...".format(i) + os.linesep + os.linesep)
                continue
            elif step[0] == 'sleep':
                self._logger.debug("Sleep %s seconds", step[1])
                time.sleep(int(step[1]))
                continue
            elif step[0] == 'log':
                test_object = self._logger
                # there isn't a need for validation of log entry
                step_check = False
                step_ok = True
            elif step[0] == 'pdb':
                import pdb
                pdb.set_trace()
                continue
            else:
                self._logger.error("Unsupported test object %s", step[0])
                self._step_status = {
                    'status': False,
                    'details': ' '.join(step)
                }
                self.step_report_status("Step '{}'".format(' '.join(step)),
                                        self._step_status['status'])
                return False

            test_method = getattr(test_object, step[1])
            if step_check:
                test_method_check = getattr(test_object,
                                            CHECK_PREFIX + step[1])
            else:
                test_method_check = None

            step_params = []
            try:
                # eval parameters, but use only valid step_results
                # to support negative indexes
                step_params = self.step_eval_params(step[2:],
                                                    self._step_result[:i])
                step_log = '{} {}'.format(' '.join(step[:2]), step_params)
                step_log += ' filter "{}"'.format(regex) if regex else ''
                self._logger.debug("Step %s '%s' start", i, step_log)
                self._step_result[i] = test_method(*step_params)
                if regex:
                    # apply regex to step output
                    self._step_result[i] = functions.filter_output(
                        self._step_result[i], regex)

                self._logger.debug("Step %s '%s' results '%s'", i, step_log,
                                   self._step_result[i])
                time.sleep(S.getValue('TEST_STEP_DELAY'))
                if step_check:
                    step_ok = test_method_check(self._step_result[i],
                                                *step_params)
            except (AssertionError, AttributeError, IndexError) as ex:
                step_ok = False
                self._logger.error("Step %s raised %s", i, type(ex).__name__)

            if step_check:
                self.step_report_status("Step {} - '{}'".format(i, step_log),
                                        step_ok)

            if not step_ok:
                self._step_status = {'status': False, 'details': step_log}
                # Stop all VNFs started by TestSteps
                self.step_stop_vnfs()
                return False

        # all steps processed without any issue
        return True
Beispiel #2
0
    def step_run(self):
        """ Execute actions specified by TestSteps list

        :return: False if any error was detected
                 True otherwise
        """
        # anything to do?
        if not self.test:
            return True

        # required for VNFs initialization
        loader = Loader()
        # initialize list with results
        self._step_result = [None] * len(self.test)

        # We have to suppress pylint report, because test_object has to be set according
        # to the test step definition
        # pylint: disable=redefined-variable-type
        # run test step by step...
        for i, step in enumerate(self.test):
            step_ok = not self._step_check
            if step[0] == 'vswitch':
                test_object = self._vswitch_ctl.get_vswitch()
            elif step[0] == 'namespace':
                test_object = namespace
            elif step[0] == 'veth':
                test_object = veth
            elif step[0] == 'settings':
                test_object = S
            elif step[0] == 'tools':
                test_object = TestStepsTools()
                step[1] = step[1].title()
            elif step[0] == 'trafficgen':
                test_object = self._traffic_ctl
                # in case of send_traffic or send_traffic_async methods, ensure
                # that specified traffic values are merged with existing self._traffic
                if step[1].startswith('send_traffic'):
                    tmp_traffic = copy.deepcopy(self._traffic)
                    tmp_traffic.update(step[2])
                    step[2] = tmp_traffic
            elif step[0].startswith('vnf'):
                if not self._step_vnf_list[step[0]]:
                    # initialize new VM
                    self._step_vnf_list[step[0]] = loader.get_vnf_class()()
                test_object = self._step_vnf_list[step[0]]
            elif step[0] == 'wait':
                input(os.linesep + "Step {}: Press Enter to continue with "
                      "the next step...".format(i) + os.linesep + os.linesep)
                continue
            elif step[0] == 'sleep':
                self._logger.debug("Sleep %s seconds", step[1])
                time.sleep(int(step[1]))
                continue
            else:
                self._logger.error("Unsupported test object %s", step[0])
                self._step_status = {
                    'status': False,
                    'details': ' '.join(step)
                }
                self.step_report_status("Step '{}'".format(' '.join(step)),
                                        self._step_status['status'])
                return False

            test_method = getattr(test_object, step[1])
            if self._step_check:
                test_method_check = getattr(test_object,
                                            CHECK_PREFIX + step[1])
            else:
                test_method_check = None

            step_params = []
            try:
                # eval parameters, but use only valid step_results
                # to support negative indexes
                step_params = TestCase.step_eval_params(
                    step[2:], self._step_result[:i])
                step_log = '{} {}'.format(' '.join(step[:2]), step_params)
                self._logger.debug("Step %s '%s' start", i, step_log)
                self._step_result[i] = test_method(*step_params)
                self._logger.debug("Step %s '%s' results '%s'", i, step_log,
                                   self._step_result[i])
                time.sleep(S.getValue('TEST_STEP_DELAY'))
                if self._step_check:
                    step_ok = test_method_check(self._step_result[i],
                                                *step_params)
            except (AssertionError, AttributeError, IndexError) as ex:
                step_ok = False
                self._logger.error("Step %s raised %s", i, type(ex).__name__)

            if self._step_check:
                self.step_report_status("Step {} - '{}'".format(i, step_log),
                                        step_ok)

            if not step_ok:
                self._step_status = {'status': False, 'details': step_log}
                # Stop all VNFs started by TestSteps
                self.step_stop_vnfs()
                return False

        # all steps processed without any issue
        return True
Beispiel #3
0
    def run_initialize(self):
        """ Prepare test execution environment
        """
        # mount hugepages if needed
        self._mount_hugepages()

        self._logger.debug("Controllers:")
        loader = Loader()
        self._traffic_ctl = component_factory.create_traffic(
            self._traffic['traffic_type'], loader.get_trafficgen_class())

        self._vnf_ctl = component_factory.create_vnf(self.deployment,
                                                     loader.get_vnf_class(),
                                                     len(self._step_vnf_list))

        self._vnf_list = self._vnf_ctl.get_vnfs()

        self._pod_ctl = component_factory.create_pod(self.deployment,
                                                     loader.get_pod_class())

        self._pod_list = self._pod_ctl.get_pods()

        # verify enough hugepages are free to run the testcase
        if not self._check_for_enough_hugepages():
            raise RuntimeError('Not enough hugepages free to run test.')

        # perform guest related handling
        tmp_vm_count = self._vnf_ctl.get_vnfs_number() + len(
            self._step_vnf_list)
        if tmp_vm_count:
            # copy sources of l2 forwarding tools into VM shared dir if needed
            self._copy_fwd_tools_for_all_guests(tmp_vm_count)

            # in case of multi VM in parallel, set the number of streams to the number of VMs
            if self.deployment.startswith('pvpv'):
                # for each VM NIC pair we need an unique stream
                streams = 0
                for vm_nic in S.getValue('GUEST_NICS_NR')[:tmp_vm_count]:
                    streams += int(vm_nic / 2) if vm_nic > 1 else 1
                self._logger.debug(
                    "VMs with parallel connection were detected. "
                    "Thus Number of streams was set to %s", streams)
                # update streams if needed; In case of additional VNFs deployed by TestSteps
                # user can define a proper stream count manually
                if 'multistream' not in self._traffic or self._traffic[
                        'multistream'] < streams:
                    self._traffic.update({'multistream': streams})

            # OVS Vanilla requires guest VM MAC address and IPs to work
            if 'linux_bridge' in S.getValue('GUEST_LOOPBACK'):
                self._traffic['l2'].update({
                    'srcmac':
                    S.getValue('VANILLA_TGEN_PORT1_MAC'),
                    'dstmac':
                    S.getValue('VANILLA_TGEN_PORT2_MAC')
                })
                self._traffic['l3'].update({
                    'srcip':
                    S.getValue('VANILLA_TGEN_PORT1_IP'),
                    'dstip':
                    S.getValue('VANILLA_TGEN_PORT2_IP')
                })

        if self._vswitch_none:
            self._vswitch_ctl = component_factory.create_pktfwd(
                self.deployment, loader.get_pktfwd_class())
        else:
            self._vswitch_ctl = component_factory.create_vswitch(
                self.deployment, loader.get_vswitch_class(), self._traffic,
                self._tunnel_operation)

        self._collector = component_factory.create_collector(
            loader.get_collector_class(), self._results_dir, self.name)
        self._loadgen = component_factory.create_loadgen(
            loader.get_loadgen_class(), self._load_cfg)

        self._output_file = os.path.join(
            self._results_dir,
            "result_{}_{}_{}.csv".format(str(S.getValue('_TEST_INDEX')),
                                         self.name, self.deployment))

        self._step_status = {'status': True, 'details': ''}

        # Perform LLC-allocations
        if S.getValue('LLC_ALLOCATION'):
            self._rmd.setup_llc_allocation()

        self._logger.debug("Setup:")
Beispiel #4
0
    def run(self):
        """Run the test

        All setup and teardown through controllers is included.
        """
        self._logger.debug(self.name)

        # copy sources of l2 forwarding tools into VM shared dir if needed
        self._copy_fwd_tools_for_guest()

        self._logger.debug("Controllers:")
        loader = Loader()
        traffic_ctl = component_factory.create_traffic(
            self._traffic['traffic_type'], loader.get_trafficgen_class())
        vnf_ctl = component_factory.create_vnf(self.deployment,
                                               loader.get_vnf_class())
        vswitch_ctl = component_factory.create_vswitch(
            self.deployment, loader.get_vswitch_class(), self._traffic)
        collector = component_factory.create_collector(
            loader.get_collector_class(), self._results_dir, self.name)
        loadgen = component_factory.create_loadgen(self._loadgen,
                                                   self._load_cfg)

        self._logger.debug("Setup:")
        with vswitch_ctl, loadgen:
            with vnf_ctl, collector:
                vswitch = vswitch_ctl.get_vswitch()
                # TODO BOM 15-08-07 the frame mod code assumes that the
                # physical ports are ports 1 & 2. The actual numbers
                # need to be retrived from the vSwitch and the metadata value
                # updated accordingly.
                bridge = S.getValue('VSWITCH_BRIDGE_NAME')
                if self._frame_mod == "vlan":
                    # 0x8100 => VLAN ethertype
                    self._logger.debug(" ****   VLAN   ***** ")
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '2',
                        'actions': ['push_vlan:0x8100', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '1',
                        'actions': ['push_vlan:0x8100', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "mpls":
                    # 0x8847 => MPLS unicast ethertype
                    self._logger.debug(" ****   MPLS  ***** ")
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '2',
                        'actions': ['push_mpls:0x8847', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '1',
                        'actions': ['push_mpls:0x8847', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "mac":
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '2',
                        'actions':
                        ['mod_dl_src:22:22:22:22:22:22', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '1',
                        'actions':
                        ['mod_dl_src:11:11:11:11:11:11', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "dscp":
                    # DSCP 184d == 0x4E<<2 => 'Expedited Forwarding'
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '2',
                        'dl_type': '0x0800',
                        'actions': ['mod_nw_tos:184', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '1',
                        'dl_type': '0x0800',
                        'actions': ['mod_nw_tos:184', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "ttl":
                    # 251 and 241 are the highest prime numbers < 255
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '2',
                        'dl_type': '0x0800',
                        'actions': ['mod_nw_ttl:251', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table': '2',
                        'priority': '1000',
                        'metadata': '1',
                        'dl_type': '0x0800',
                        'actions': ['mod_nw_ttl:241', 'goto_table:3']
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "ip_addr":
                    flow = {
                        'table':
                        '2',
                        'priority':
                        '1000',
                        'metadata':
                        '2',
                        'dl_type':
                        '0x0800',
                        'actions': [
                            'mod_nw_src:10.10.10.10', 'mod_nw_dst:20.20.20.20',
                            'goto_table:3'
                        ]
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table':
                        '2',
                        'priority':
                        '1000',
                        'metadata':
                        '1',
                        'dl_type':
                        '0x0800',
                        'actions': [
                            'mod_nw_src:20.20.20.20', 'mod_nw_dst:10.10.10.10',
                            'goto_table:3'
                        ]
                    }
                    vswitch.add_flow(bridge, flow)
                elif self._frame_mod == "ip_port":
                    # TODO BOM 15-08-27 The traffic generated is assumed
                    # to be UDP (nw_proto 17d) which is the default case but
                    # we will need to pick up the actual traffic params in use.
                    flow = {
                        'table':
                        '2',
                        'priority':
                        '1000',
                        'metadata':
                        '2',
                        'dl_type':
                        '0x0800',
                        'nw_proto':
                        '17',
                        'actions': [
                            'mod_tp_src:44444', 'mod_tp_dst:44444',
                            'goto_table:3'
                        ]
                    }
                    vswitch.add_flow(bridge, flow)
                    flow = {
                        'table':
                        '2',
                        'priority':
                        '1000',
                        'metadata':
                        '1',
                        'dl_type':
                        '0x0800',
                        'nw_proto':
                        '17',
                        'actions': [
                            'mod_tp_src:44444', 'mod_tp_dst:44444',
                            'goto_table:3'
                        ]
                    }
                    vswitch.add_flow(bridge, flow)
                else:
                    pass

                with traffic_ctl:
                    traffic_ctl.send_traffic(self._traffic)

                # dump vswitch flows before they are affected by VNF termination
                vswitch_ctl.dump_vswitch_flows()

        self._logger.debug("Traffic Results:")
        traffic_ctl.print_results()

        self._logger.debug("Collector Results:")
        collector.print_results()

        output_file = os.path.join(
            self._results_dir,
            "result_" + self.name + "_" + self.deployment + ".csv")

        tc_results = self._append_results(traffic_ctl.get_results())
        TestCase._write_result_to_file(tc_results, output_file)

        report.generate(output_file, tc_results, collector.get_results())