Example #1
0
    def exec_command(self, cmd, timeout=10):
        """Execute SSH command on a new channel on the connected Node.

        Returns (return_code, stdout, stderr).
        """
        start = time()
        chan = self._ssh.get_transport().open_session()
        if timeout is not None:
            chan.settimeout(int(timeout))
        chan.exec_command(cmd)
        end = time()
        logger.trace('exec_command "{0}" on {1} took {2} seconds'.format(cmd,
            self._hostname, end-start))


        stdout = ""
        while True:
            buf = chan.recv(self.__MAX_RECV_BUF)
            stdout += buf
            if not buf:
                break

        stderr = ""
        while True:
            buf = chan.recv_stderr(self.__MAX_RECV_BUF)
            stderr += buf
            if not buf:
                break

        return_code = chan.recv_exit_status()
        logger.trace('chan_recv/_stderr took {} seconds'.format(time()-end))

        return (return_code, stdout, stderr)
Example #2
0
 def get(self, message_template, timeout=None, header_filter=None):
     header_fields = message_template.header_parameters
     logger.trace("Get message with params %s" % header_fields)
     msg = self._get_from_cache(message_template, header_fields, header_filter)
     if msg:
         logger.trace("Cache hit. Cache currently has %s messages" % len(self._cache))
         return msg
     while True:
         header, pdu_bytes = self._protocol.read(self._stream, timeout=timeout)
         if self._matches(header, header_fields, header_filter):
             return self._to_msg(message_template, header, pdu_bytes)
         self._cache.append((header, pdu_bytes))
Example #3
0
    def setup_framework(self, nodes):
        """Pack the whole directory and extract in temp on each node."""

        tarball = self.__pack_framework_dir()
        logger.console('Framework packed to {0}'.format(tarball))
        remote_tarball = "/tmp/{0}".format(basename(tarball))

        for node in nodes.values():
            self.__copy_tarball_to_node(tarball, node)
            self.__extract_tarball_at_node(remote_tarball, node)

        logger.trace('Test framework copied to all topology nodes')
        self.__delete_local_tarball(tarball)
Example #4
0
    def show_statistics_on_all_duts(nodes, sleeptime=5):
        """Show VPP statistics on all DUTs.

        :param nodes: VPP nodes.
        :type nodes: dict
        :param sleeptime: Time to wait for traffic to arrive back to TG.
        :type sleeptime: int
        """
        logger.trace('Waiting for statistics to be collected')
        time.sleep(sleeptime)
        for node in nodes.values():
            if node['type'] == NodeType.DUT:
                VppCounters.show_vpp_statistics(node)
Example #5
0
    def setup_dut(self, node):
        ssh = SSH()
        ssh.connect(node)

        ssh.scp('resources/libraries/bash/dut_setup.sh', '/tmp/dut_setup.sh')
        (ret_code, stdout, stderr) = \
            ssh.exec_command('sudo -Sn bash /tmp/dut_setup.sh')
        logger.trace(stdout)
        if 0 != int(ret_code):
            logger.error('DUT {0} setup script failed: "{1}"'.
                    format(node['host'], stdout + stderr))
            raise Exception('DUT test setup script failed at node {}'.
                    format(node['host']))
Example #6
0
    def stop_timer(self, benchmark_name='default'):
        logger.trace("Timer::stop_timer({})".format(benchmark_name))
        """
        Stops a single timer
        Parameters:
        - ``benchmark_name`` Name of the benchmark, optional. Defaults to 'default'

        Example:
        | Stop Timer | mytimer |
        """
        if benchmark_name not in self.benchmarks:
            raise DataError('Benchmark "%s" not started.' % benchmark_name)
        self.benchmarks[benchmark_name]['stop'] = timer()
Example #7
0
 def run_teardown_only_once(self, keyword, *args):
     """
     Runs a keyword only once after all executions have gone throught this step in the last possible moment.
     [https://pabot.org/PabotLib.html?ref=log#run-teardown-only-once|Open online docs.]
     """
     last_level = BuiltIn().get_variable_value('${%s}' % PABOT_LAST_LEVEL)
     if last_level is None:
         BuiltIn().run_keyword(keyword, *args)
         return
     logger.trace('Current path "%s" and last level "%s"' %
                  (self._path, last_level))
     if not self._path.startswith(last_level):
         logger.info("Teardown skipped in this item")
         return
     queue_index = int(
         BuiltIn().get_variable_value('${%s}' % PABOT_QUEUE_INDEX) or 0)
     logger.trace("Queue index (%d)" % queue_index)
     if self._remotelib:
         while self.get_parallel_value_for_key(
                 PABOT_MIN_QUEUE_INDEX_EXECUTING_PARALLEL_VALUE
         ) < queue_index:
             logger.trace(
                 self.get_parallel_value_for_key(
                     PABOT_MIN_QUEUE_INDEX_EXECUTING_PARALLEL_VALUE))
             time.sleep(0.3)
     logger.trace("Teardown conditions met. Executing keyword.")
     BuiltIn().run_keyword(keyword, *args)
Example #8
0
    def create_session(self, node, hello, time_out=10):
        """Create an SSH session, connect to Honeycomb on the specified node,
        open a communication channel to the Netconf subsystem and exchange hello
        messages.

        :param node: Honeycomb node.
        :param hello: Hello message and capability list to be sent to Honeycomb.
        :param time_out: Timeout value for the connection in seconds.
        :type node: dict
        :type hello: str
        :type time_out: int
        """

        start = time()
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        client.connect(node['host'],
                       username=node['honeycomb']['user'],
                       password=node['honeycomb']['passwd'],
                       pkey=None,
                       port=node['honeycomb']['netconf_port'],
                       timeout=time_out)

        logger.trace('Connect took {0} seconds'.format(time() - start))
        logger.debug('New ssh: {0}'.format(client))
        logger.debug('Connect peer: {0}'.
                     format(client.get_transport().getpeername()))
        logger.debug(client)

        channel = client.get_transport().open_session()
        channel.settimeout(time_out)
        channel.set_combine_stderr(True)
        channel.get_pty()
        channel.invoke_subsystem("netconf")
        logger.debug(channel)

        self.client = client
        self.channel = channel

        # read OpenDaylight's hello message and capability list
        self.get_response(
            size=131072,
            time_out=time_out,
            err="Timeout on getting hello message."
        )

        self.channel.send(hello)
        if not self.channel.active:
            raise HoneycombError("Channel closed on capabilities exchange.")
    def run_traffic_script_on_node(script_file_name, node, script_args,
                                   timeout=60):
        """Run traffic script on the TG node.

        :param script_file_name: Traffic script name.
        :param node: Node to run traffic script on.
        :param script_args: Traffic scripts arguments.
        :param timeout: Timeout (optional).
        :type script_file_name: str
        :type node: dict
        :type script_args: str
        :type timeout: int
        :raises RuntimeError: ICMP echo Rx timeout.
        :raises RuntimeError: DHCP REQUEST Rx timeout.
        :raises RuntimeError: DHCP DISCOVER Rx timeout.
        :raises RuntimeError: TCP/UDP Rx timeout.
        :raises RuntimeError: ARP reply timeout.
        :raises RuntimeError: Traffic script execution failed.
        """
        logger.trace("{}".format(timeout))
        ssh = SSH()
        ssh.connect(node)
        cmd = ("cd {}; " +
               "virtualenv --system-site-packages --never-download env && " +
               "export PYTHONPATH=${{PWD}}; " +
               ". ${{PWD}}/env/bin/activate; " +
               "resources/traffic_scripts/{} {}") \
                  .format(Constants.REMOTE_FW_DIR, script_file_name,
                          script_args)
        (ret_code, stdout, stderr) = ssh.exec_command_sudo(
            'sh -c "{}"'.format(TrafficScriptExecutor._escape(cmd)),
            timeout=timeout)
        logger.debug("stdout: {}".format(stdout))
        logger.debug("stderr: {}".format(stderr))
        logger.debug("ret_code: {}".format(ret_code))
        if ret_code != 0:
            if "RuntimeError: ICMP echo Rx timeout" in stderr:
                raise RuntimeError("ICMP echo Rx timeout")
            elif "RuntimeError: DHCP REQUEST Rx timeout" in stderr:
                raise RuntimeError("DHCP REQUEST Rx timeout")
            elif "RuntimeError: DHCP DISCOVER Rx timeout" in stderr:
                raise RuntimeError("DHCP DISCOVER Rx timeout")
            elif "RuntimeError: TCP/UDP Rx timeout" in stderr:
                raise RuntimeError("TCP/UDP Rx timeout")
            elif "Error occurred: ARP reply timeout" in stdout:
                raise RuntimeError("ARP reply timeout")
            elif "RuntimeError: ESP packet Rx timeout" in stderr:
                raise RuntimeError("ESP packet Rx timeout")
            else:
                raise RuntimeError("Traffic script execution failed")
Example #10
0
def get_webelements_in_active_area(xpath, **kwargs):
    """Find element under another element.

    If ${ACTIVE_AREA_FUNC} returns an element then the xpath is searched from
    that element. Otherwise the element is searched under body element.

    Parameters
    ----------
    xpath : str
        Xpath expression without xpath= prefix.

    Returns
    -------
    :obj:`list` of :obj:`WebElement`
        List of visible WebElements.
    """
    active_area_xpath = CONFIG["ActiveAreaXpath"]
    if ACTIVE_AREA_FUNCTION is not None:
        active_area = ACTIVE_AREA_FUNCTION()
        if active_area:
            xpath = xpath.replace('//', './/', 1)
        else:
            driver = browser.get_current_browser()
            active_area = driver.find_element(By.XPATH, active_area_xpath)
    else:
        driver = browser.get_current_browser()
        try:
            active_area = driver.find_element(By.XPATH, active_area_xpath)
            if active_area is None:
                logger.debug('Got None for active area. Is page still loading '
                             'or is it missing body tag?')
                return None
        # //body not found, is page still loading? Return None to continue looping
        except NoSuchElementException:
            logger.debug(
                "Cannot locate //body element. Is page still loading?")
            return None

    try:
        webelements = active_area.find_elements(By.XPATH, xpath)

        logger.trace('XPath {} matched {} webelements'.format(
            xpath, len(webelements)))
        webelements = get_visible_elements_from_elements(webelements, **kwargs)
    except StaleElementReferenceException as se:
        raise QWebStalingElementError('Got StaleElementException') from se
    except (JavascriptException, InvalidSelectorException) as e:
        logger.debug('Got {}, returning None'.format(e))
        webelements = None
    return webelements
Example #11
0
 def search_from_frames(driver=None, current_frame=None):
     keep_frame = kwargs.get('stay_in_current_frame',
                             CONFIG['StayInCurrentFrame'])
     if keep_frame:
         return fn(*args, **kwargs)
     err = None
     if not driver:
         driver = browser.get_current_browser()
         driver.switch_to.default_content()
     if current_frame:
         try:
             driver.switch_to.frame(current_frame)
             logger.debug('switching to childframe {}'.format(str(fn)))
         except (StaleElementReferenceException,
                 WebDriverException) as e:
             logger.warn(e)
             driver.switch_to.default_content()
             raise e
     try:
         web_element = fn(*args, **kwargs)
     except QWebElementNotFoundError as e:
         err = e
         web_element = None
     if is_valid(web_element):
         return web_element
     start = time.time()
     timeout = CONFIG['FrameTimeout']
     while time.time() < timeout + start:
         frames = fc.check_frames(driver)
         for frame in frames:
             web_element = search_from_frames(driver=driver,
                                              current_frame=frame)
             if is_valid(web_element):
                 logger.debug(
                     'Found webelement = {}'.format(web_element))
                 return web_element
             try:
                 driver.switch_to.parent_frame()
             except WebDriverException as e:
                 driver.switch_to.default_content()
                 raise e
             config.set_config('FrameTimeout',
                               float(timeout + start - time.time()))
             logger.trace('Frame timeout: {}'.format(timeout))
         if err:
             raise err
         return web_element
     driver.switch_to.default_content()
     raise QWebTimeoutError(
         'From frame decorator: Unable to locate element in given time')
Example #12
0
    def scp(self, local_path, remote_path):
        """Copy files from local_path to remote_path.

        connect() method has to be called first!
        """
        logger.trace('SCP {0} to {1}:{2}'.format(
            local_path, self._ssh.get_transport().getpeername(), remote_path))
        # SCPCLient takes a paramiko transport as its only argument
        scp = SCPClient(self._ssh.get_transport(), socket_timeout=10)
        start = time()
        scp.put(local_path, remote_path)
        scp.close()
        end = time()
        logger.trace('SCP took {0} seconds'.format(end-start))
Example #13
0
    def scp(self, local_path, remote_path):
        """Copy files from local_path to remote_path.

        connect() method has to be called first!
        """
        logger.trace('SCP {0} to {1}:{2}'.format(
            local_path, self._hostname, remote_path))
        # SCPCLient takes a paramiko transport as its only argument
        scp = SCPClient(self._ssh.get_transport())
        start = time()
        scp.put(local_path, remote_path)
        scp.close()
        end = time()
        logger.trace('SCP took {0} seconds'.format(end-start))
Example #14
0
def process_vxlan_dump(data):
    """
    Process API reply acl_dump and return dictionary of usable values.

    :param data: API reply from acl_dump call,
    :type data: dict
    :return: Values ready for comparison with Agent or ETCD values.
    :rtype: dict
    """

    if len(data) > 1:
        logger.debug(len(data))
        logger.trace(data)
        raise RuntimeError("Data contains more than one API reply.")

    data = data["vxlan_tunnel_details"]

    index = int(data["sw_if_index"])
    mcast_index = int(data["mcast_sw_if_index"])

    ipv6 = int(data["is_ipv6"])

    if ipv6:
        destination_address = data["dst_address"]["ipv6"]
        source_address = data["src_address"]["ipv6"]
    else:
        destination_address = data["dst_address"]["ipv4"]
        source_address = data["src_address"]["ipv4"]

    vrf_id = int(data["encap_vrf_id"])
    vni = int(data["vni"])

    next_index = int(data["decap_next_index"])

    instance = int(data["instance"])

    output = {
        "sw_if_index": index,
        "ipv6": ipv6,
        "vrf": vrf_id,
        "vni": vni,
        "dst_address": destination_address,
        "src_address": source_address,
        "next_index": next_index,
        "mcast_index": mcast_index,
        "instance": instance
    }

    return output
Example #15
0
    def connect(self, node):
        """Connect to node prior to running exec_command or scp.

        If there already is a connection to the node, this method reuses it.
        """
        self._hostname = node['host']
        node_hash = self._node_hash(node)
        if node_hash in self.__existing_connections:
            self._ssh = self.__existing_connections[node_hash]
        else:
            start = time()
            self._ssh.connect(node['host'], username=node['username'],
                    password=node['password'])
            self.__existing_connections[node_hash] = self._ssh
            logger.trace('connect took {} seconds'.format(time() - start))
Example #16
0
def get_dropdown_element_by_css_selector(locator, anchor, index, **kwargs):
    """Get Dropdown element using css selectors.
       Parameters
       ----------
       locator : str
           Label text or attribute that points to the dropdown.
           Looking for placeholder and commonly used tooltip-attributes first.
           If locator is label text, finds input element by it's for attribute.
           if for attribute is not available, then finds element by doing some
           DOM traversing.
       anchor : str
           Using if locator is not an XPath.
       index : int
           If multiple elements use index to pick correct one.
       Returns
       -------
       WebElement
   """
    dropdown_elements = []
    partial_matches = []
    css = 'select'
    if 'qweb_old' not in kwargs:
        full_matches, partial_matches = element.get_elements_by_css(
            locator, css, **kwargs)
        if full_matches:
            if index != 0:
                try:
                    return full_matches[index]
                except IndexError:
                    raise QWebInstanceDoesNotExistError(
                        f'Found {len(full_matches)} elements. Given index was {index}'
                    )
            correct_element = text.get_element_using_anchor(
                full_matches, anchor)
            return correct_element
    try:
        locator_element = text.get_text_using_anchor(locator, anchor)
        dropdown_elements = list(
            dict.fromkeys(
                element.get_element_from_childnodes(locator_element, css, **
                                                    kwargs) + partial_matches))
    except QWebElementNotFoundError:
        logger.trace(
            'Element not found by visible text. Trying with partial match')
        dropdown_elements = partial_matches
    if dropdown_elements:
        return dropdown_elements[index]
    return None
Example #17
0
 def _qemu_qga_flush(self):
     """Flush the QGA parser state
     """
     qga_cmd = '(printf "\xFF"; sleep 1) | sudo -S socat - UNIX-CONNECT:' + \
               self._qga_sock
     #TODO: probably need something else
     (ret_code, stdout, stderr) = self._ssh.exec_command(qga_cmd)
     if int(ret_code) != 0:
         logger.debug('QGA execute failed {0}'.format(stderr))
         raise RuntimeError('QGA execute "{0}" '
                            'failed on {1}'.format(qga_cmd,
                                                   self._node['host']))
     logger.trace(stdout)
     if not stdout:
         return {}
     return json.loads(stdout.split('\n', 1)[0])
Example #18
0
File: ssh.py Project: yedan2010/vpp
    def connect(self, node):
        """Connect to node prior to running exec_command or scp.

        If there already is a connection to the node, this method reuses it.
        """
        self._hostname = node['host']
        node_hash = self._node_hash(node)
        if node_hash in self.__existing_connections:
            self._ssh = self.__existing_connections[node_hash]
        else:
            start = time()
            self._ssh.connect(node['host'],
                              username=node['username'],
                              password=node['password'])
            self.__existing_connections[node_hash] = self._ssh
            logger.trace('connect took {} seconds'.format(time() - start))
Example #19
0
    def vpp_show_threads(node):
        """Show VPP threads on node.

        :param node: Node to run command on.
        :type node: dict
        :returns: VPP thread data.
        :rtype: list
        """
        cmd = u"show_threads"
        with PapiSocketExecutor(node) as papi_exec:
            reply = papi_exec.add(cmd).get_reply()

        threads_data = reply[u"thread_data"]
        logger.trace(f"show threads:\n{threads_data}")

        return threads_data
Example #20
0
    def verify_all_timers(self, fail_on_errors=True):
        """
        Verifies all timers within a testsuite. Timer's must be done, eg `Start Timer` and `Stop Timer` keywords must have been called for it and it has to have been configured with `Configure Timer` keyword and lower_than parameter.
        Keyword will also write a html table into the logs that shows all finished timers and their status.
        Parameters:
        - ``fail_on_errors`` Should we throw an error if any timers are not within given ranges. Defaults to True
        Example:
        | Verify All Timers | fail_on_errors=False |
        """
        logger.trace("Timer::verify_all_timers({})".format(fail_on_errors))
        failures = []
        fail_on_errors = is_truthy(fail_on_errors)
        html = [
            '<table class="statistics"><tr><th>Timer</th><th>Lower than</th><th>Execution Time</th><th>Higher Than</th></tr>'
        ]
        for item in filter(lambda timer: timer_done(timer[1]),
                           self.benchmarks.items()):
            benchmark_name = item[0]
            benchmark_data = item[1]
            difference = int(
                (benchmark_data['stop'] - benchmark_data['start']) * 1000)
            lower_than = benchmark_data['lower_than']
            higher_than = benchmark_data['higher_than']
            if not _is_within_range(difference, lower_than, higher_than):
                html.append(
                    html_row("fail", benchmark_name, lower_than, difference,
                             higher_than))
                failures.append(
                    assert_string(benchmark_name, difference, lower_than,
                                  higher_than))
            else:
                html.append(
                    html_row("pass", benchmark_name, lower_than, difference,
                             higher_than))

        html.append("</table")
        logger.info("".join(html), html=True)
        if failures:
            if fail_on_errors:
                raise AssertionError("\n".join(failures))
            else:
                logger.warn("\n".join(failures))

        if failures:
            return False

        return True
Example #21
0
    def _wait_until_vm_boot(self, timeout=60):
        """Wait until QEMU VM is booted.

        First try to flush qga until there is output.
        Then ping QEMU guest agent each 5s until VM booted or timeout.

        :param timeout: Waiting timeout in seconds (optional, default 60s).
        :type timeout: int
        """
        start = time()
        while True:
            if time() - start > timeout:
                raise RuntimeError('timeout, VM {disk} not booted on {host}'.
                                   format(disk=self._qemu_opt['disk_image'],
                                          host=self._node['host']))
            out = None
            try:
                out = self._qemu_qga_flush()
            except ValueError:
                logger.trace('QGA qga flush unexpected output {out}'.
                             format(out=out))
            # Empty output - VM not booted yet
            if not out:
                sleep(5)
            else:
                break
        while True:
            if time() - start > timeout:
                raise RuntimeError('timeout, VM with {disk} not booted '
                                   'on {host}'.
                                   format(disk=self._qemu_opt['disk_image'],
                                          host=self._node['host']))
            out = None
            try:
                out = self._qemu_qga_exec('guest-ping')
            except ValueError:
                logger.trace('QGA guest-ping unexpected output {out}'.
                             format(out=out))
            # Empty output - VM not booted yet
            if not out:
                sleep(5)
            # Non-error return - VM booted
            elif out.get('return') is not None:
                break
            # Skip error and wait
            elif out.get('error') is not None:
                sleep(5)
            else:
                # If there is an unexpected output from QGA guest-info, try
                # again until timeout.
                logger.trace('QGA guest-ping unexpected output {out}'.
                             format(out=out))

        logger.trace('VM with {disk_image} booted on {host}'.
                     format(disk_image=self._qemu_opt['disk_image'],
                            host=self._node['host']))
Example #22
0
    def get_sw_if_index(self, err_msg=u"Failed to get reply."):
        """Get sw_if_index from reply from VPP Python API.

        Frequently, the caller is only interested in sw_if_index field
        of the reply, this wrapper makes such call sites shorter.

        TODO: Discuss exception types to raise, unify with inner methods.

        :param err_msg: The message used if the PAPI command(s) execution fails.
        :type err_msg: str
        :returns: Response, sw_if_index value of the reply.
        :rtype: int
        :raises AssertionError: If retval is nonzero, parsing or ssh error.
        """
        reply = self.get_reply(err_msg=err_msg)
        logger.trace(f"Getting index from {reply!r}")
        return reply[u"sw_if_index"]
def packet_operation(expression_str, deviation_str=None, reason=None):
    """
    Provide logical and mathematical operation with packet

    - expression_str: operand1 operation operand2

    | Example | Comments |
    | 1M * 2 | Multiple Packet size 2M |
    | 1M + 10K | Return packet size 1.01M |
    | 1M + 10% | Return packet size 1.1M |

    Options:
    - deviation: add on for comparison verifications (eq, ,gt, lt, ge, le)

    Equality Examples:

    | Operand1  Operation  Operand2 | Deviation   | Result    | Comments  |
    | 10M  == 12M                   | 25%       | TRUE      | (10M - 25%) < 12M < (10M + 25%)   |
    | 10M  == 12M                   | 0.25       | TRUE      | (10M - 25%) < 12M < (10M + 25%)   |
    | 10M  == 12M                   | -25%       | FALSE      | (10M - 25%) < 12M < 10M   |
    | 10M  == 12M                   | +25%      | TRUE      | 10M < 12M < (10M + 25%)   |

    - reason: Custom fail reason

    return: TRUE/FALSE for logical operation and value for math operation
    """
    try:

        logger.trace(
            f"{expression_str}{', ' + deviation_str  if deviation_str else ''}"
        )
        _deviation = format_factory(deviation_str,
                                    Percent) if deviation_str else None
        operand1, operation, operand2 = _parse_line(expression_str, DataPacket,
                                                    Percent)
        result = _type_evaluation(operand1=operand1,
                                  operand2=operand2,
                                  operation=operation,
                                  deviation=_deviation,
                                  special_eq=packet_eq)
        assert result is not False, f"{operand1} {operation.__name__} {operand2} False" if reason is None else reason
        return result
    except AssertionError as e:
        raise e
    except Exception as e:
        raise FrameworkError(e)
Example #24
0
    def set_traffic_input(self, iput):
        """ Assign all given traffic data input into this class instance.

        Example:
        | Set Traffic Input | @{iput} |.
        """
        self.traffic.data = iput

        # Format 'vlan' key in entity list
        for index in xrange(len(self.traffic.data['entities'])):
            if 'vlan' in self.traffic.data['entities'][index]:
                self.traffic.data['entities'][index]['vlan'] = self._format_vlan_key(
                    self.traffic.data['entities'][index]['vlan'])

        logger.trace(json.dumps(self.traffic.data['serversAndCredentials'], indent=4, separators=(',', ': ')))

        return True
Example #25
0
 def perform(*args, **kwargs):
     params = signature(fn).parameters
     args, kwargs = _args_to_kwargs(params, args, kwargs)
     timeout = get_timeout(**kwargs)
     err = None
     msg = None
     performed = False
     logger.debug('time to run {}'.format(timeout))
     start = time.time()
     while time.time() < timeout + start:
         try:
             return fn(*args, **kwargs)
         except QWebValueMismatchError as mismatch:
             if 'text_appearance' not in str(
                     fn) and 'get_or_compare_text' not in str(fn):
                 err = QWebValueError
                 msg = mismatch
             logger.trace('Value mismatch: {}'.format(mismatch))
             continue
         except (QWebElementNotFoundError, UnexpectedAlertPresentException):
             logger.debug('Not found')
             time.sleep(SHORT_DELAY)
         except QWebValueError as ve:
             if performed:
                 break
             raise ve
         except (QWebStalingElementError,
                 StaleElementReferenceException) as S:
             if 'execute_click' in str(fn) or 'text_appearance' in str(fn):
                 logger.info('Got staling element err from retry click.'
                             'Action is probably triggered.')
                 raise QWebUnexpectedConditionError(S)
             raise QWebStalingElementError('Staling element')
         except (WebDriverException, QWebDriverError) as wde:
             if 'alert' in str(fn):
                 time.sleep(LONG_DELAY)
                 logger.info(
                     "Got webdriver exception..{}. Retrying..".format(wde))
                 err = QWebDriverError
                 msg = wde
             else:
                 raise QWebDriverError(wde)
     if msg:
         raise err(msg)
     raise QWebTimeoutError('Timeout exceeded')
Example #26
0
    def measure_loss(self, rate, frame_size, loss_acceptance,
                     loss_acceptance_type, traffic_type):
        """Runs the traffic and evaluate the measured results.

        :param rate: Offered traffic load.
        :param frame_size: Size of frame.
        :param loss_acceptance: Permitted drop ratio or frames count.
        :param loss_acceptance_type: Type of permitted loss.
        :param traffic_type: Traffic profile ([2,3]-node-L[2,3], ...).
        :type rate: int
        :type frame_size: str
        :type loss_acceptance: float
        :type loss_acceptance_type: LossAcceptanceType
        :type traffic_type: str
        :returns: Drop threshold exceeded? (True/False)
        :rtype: bool
        :raises: NotImplementedError if TG is not supported.
        :raises: RuntimeError if TG is not specified.
        """
        # we need instance of TrafficGenerator instantiated by Robot Framework
        # to be able to use trex_stl-*()
        tg_instance = BuiltIn().get_library_instance(
            'resources.libraries.python.TrafficGenerator')

        if tg_instance.node['subtype'] is None:
            raise RuntimeError('TG subtype not defined')
        elif tg_instance.node['subtype'] == NodeSubTypeTG.TREX:
            unit_rate = str(rate) + self.get_rate_type_str()
            tg_instance.trex_stl_start_remote_exec(self.get_duration(),
                                                   unit_rate, frame_size,
                                                   traffic_type)
            loss = tg_instance.get_loss()
            sent = tg_instance.get_sent()
            if self.loss_acceptance_type_is_percentage():
                loss = (float(loss) / float(sent)) * 100

            logger.trace("comparing: {} < {} {}".format(loss,
                                                        loss_acceptance,
                                                        loss_acceptance_type))
            if float(loss) > float(loss_acceptance):
                return False
            else:
                return True
        else:
            raise NotImplementedError("TG subtype not supported")
Example #27
0
def check_vxlan_tunnel_presence_from_api(data, src, dst, vni):

    for iface in data:
        if iface["src_address"] == src and iface[
                "dst_address"] == dst and iface["vni"] == int(vni):
            logger.trace(
                "matched interface: {interface}".format(interface=iface))
            return True, iface["sw_if_index"]
    else:
        logger.debug("interface with:\n"
                     "src_addr: {src_address}\n"
                     "dst_addr: {dst_address}\n"
                     "vni: {vni}\n"
                     "not found in dump. Full dump:\n"
                     "{data}".format(src_address=src,
                                     dst_address=dst,
                                     vni=vni,
                                     data=data))
Example #28
0
 def run_dirs3arch(self, url, extensions, wordlist, results_path):
     self.url = url
     self.extensions = extensions
     self.wordlist = wordlist
     self.results_path = results_path
     results_mount = Mount("/dirs3arch_results",
                           self.results_path,
                           type="bind")
     wordlist_mount = Mount("/wordlist.txt", self.wordlist, type="bind")
     mounts = [results_mount, wordlist_mount]
     command = '-u {0} -e {1} -w {2} --json-report=/dirs3arch_results/dirs3arch_results.json'.format(
         self.url, self.extensions, '/wordlist.txt')
     self.client.containers.run(self.dirs3arch_docker,
                                mounts=mounts,
                                command=command)
     logger.trace(
         "Successfully ran dirs3arch against the target URL {0}. Please find the *.json output in the results directory"
         .format(self.url))
Example #29
0
def process_bridge_domain_dump(data):
    """Process API reply bridge_domain_dump and return dictionary of usable values.

    :param data: API reply from bridge_domain_dump call,
    :type data: dict
    :return: Values ready for comparison with Agent or ETCD values.
    :rtype: dict
    :raises RuntimeError: If the data is in an unexpceted format,
    """

    if len(data) > 1:
        logger.debug(len(data))
        logger.trace(data)
        raise RuntimeError("Data contains more than one API reply.")

    data = data["bridge_domain_details"]

    return data
Example #30
0
    def setup_framework(nodes):
        """Pack the whole directory and extract in temp on each node.

        :param nodes: Topology nodes.
        :type nodes: dict
        :raises RuntimeError: If setup framework failed.
        """

        tarball = pack_framework_dir()
        msg = f"Framework packed to {tarball}"
        logger.console(msg)
        logger.trace(msg)
        remote_tarball = f"{tarball}"

        results = list()
        logs = list()
        threads = list()

        for node in nodes.values():
            args = node, tarball, remote_tarball, results, logs
            thread = threading.Thread(target=setup_node, args=args)
            thread.start()
            threads.append(thread)

        logger.info(
            u"Executing node setups in parallel, waiting for threads to end.")

        for thread in threads:
            thread.join()

        logger.info(f"Results: {results}")

        for log in logs:
            logger.trace(log)

        delete_local_tarball(tarball)
        if all(results):
            logger.console(u"All nodes are ready.")
            for node in nodes.values():
                logger.info(
                    f"Setup of node {node[u'type']} host {node[u'host']}, "
                    f"port {node[u'port']} done.")
        else:
            raise RuntimeError(u"Failed to setup framework.")
Example #31
0
    def crypto_device_verify(node, force_init=False, numvfs=32):
        """Verify if Crypto QAT device virtual functions are initialized on all
        DUTs. If parameter force initialization is set to True, then try to
        initialize or disable QAT.

        :param node: DUT node.
        :param force_init: If True then try to initialize to specific value.
        :param numvfs: Number of VFs to initialize, 0 - disable the VFs.
        :type node: dict
        :type force_init: bool
        :type numvfs: int
        :returns: nothing
        :raises RuntimeError: If QAT is not initialized or failed to initialize.
        """

        ssh = SSH()
        ssh.connect(node)

        cryptodev = Topology.get_cryptodev(node)
        cmd = 'cat /sys/bus/pci/devices/{0}/sriov_numvfs'.\
            format(cryptodev.replace(':', r'\:'))

        # Try to read number of VFs from PCI address of QAT device
        for _ in range(3):
            ret_code, stdout, _ = ssh.exec_command(cmd)
            if int(ret_code) == 0:
                try:
                    sriov_numvfs = int(stdout)
                except ValueError:
                    logger.trace(
                        'Reading sriov_numvfs info failed on {0}'.format(
                            node['host']))
                else:
                    if sriov_numvfs != numvfs:
                        if force_init:
                            # QAT is not initialized and we want to initialize
                            # with numvfs
                            DUTSetup.crypto_device_init(node, numvfs)
                        else:
                            raise RuntimeError(
                                'QAT device {0} is not '
                                'initialized to {1} on host {2}'.format(
                                    cryptodev, numvfs, node['host']))
                    break
Example #32
0
    def connect(self, node, attempts=5):
        """Connect to node prior to running exec_command or scp.

        If there already is a connection to the node, this method reuses it.
        """
        try:
            self._node = node
            node_hash = self._node_hash(node)
            if node_hash in SSH.__existing_connections:
                self._ssh = SSH.__existing_connections[node_hash]
                logger.debug('reusing ssh: {0}'.format(self._ssh))
            else:
                start = time()
                pkey = None
                if 'priv_key' in node:
                    pkey = RSAKey.from_private_key(
                        StringIO.StringIO(node['priv_key']))

                self._ssh = paramiko.SSHClient()
                self._ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

                self._ssh.connect(node['host'],
                                  username=node['username'],
                                  password=node.get('password'),
                                  pkey=pkey,
                                  port=node['port'])

                self._ssh.get_transport().set_keepalive(10)

                SSH.__existing_connections[node_hash] = self._ssh

                logger.trace('connect took {} seconds'.format(time() - start))
                logger.debug('new ssh: {0}'.format(self._ssh))

            logger.debug('Connect peer: {0}'.format(
                self._ssh.get_transport().getpeername()))
            logger.debug('Connections: {0}'.format(
                str(SSH.__existing_connections)))
        except:
            if attempts > 0:
                self._reconnect(attempts - 1)
            else:
                raise
Example #33
0
    def put_honeycomb_data(node,
                           url_file,
                           data,
                           path="",
                           data_representation=DataRepresentation.JSON):
        """Send configuration data using PUT request and return the status code
        and response content.

        :param node: Honeycomb node.
        :param url_file: URL file. The argument contains only the name of file
        without extension, not the full path.
        :param data: Configuration data to be sent to Honeycomb.
        :param path: Path which is added to the base path to identify the data.
        :param data_representation: How the data is represented.
        :type node: dict
        :type url_file: str
        :type data: dict, str
        :type path: str
        :type data_representation: DataRepresentation
        :returns: Status code and content of response.
        :rtype: tuple
        :raises HoneycombError: If the given data representation is not defined
        in HEADERS.
        """

        try:
            header = HEADERS[data_representation]
        except AttributeError as err:
            raise HoneycombError(
                "Wrong data representation: {0}.".format(data_representation),
                repr(err))
        if data_representation == DataRepresentation.JSON:
            data = dumps(data)

        logger.trace(data)

        base_path = HoneycombUtil.read_path_from_url_file(url_file)
        path = base_path + path
        logger.trace(path)
        return HTTPRequest.put(node=node,
                               path=path,
                               headers=header,
                               payload=data)
Example #34
0
    def __init__(self, node, json_param=True):
        json_text = u" json" if json_param else u""
        self.json = json_param
        self._node = node
        self._ssh = SSH()
        self._ssh.connect(self._node)
        try:
            self._tty = self._ssh.interactive_terminal_open()
        except Exception:
            raise RuntimeError(
                f"Cannot open interactive terminal on node "
                f"{self._node[u'host']}"
            )

        for _ in range(3):
            try:
                self._ssh.interactive_terminal_exec_command(
                    self._tty, f"sudo -S {Constants.VAT_BIN_NAME}{json_text}",
                    self.__VAT_PROMPT
                )
            except Exception:
                continue
            else:
                break
        else:
            vpp_pid = get_vpp_pid(self._node)
            if vpp_pid:
                if isinstance(vpp_pid, int):
                    logger.trace(f"VPP running on node {self._node[u'host']}")
                else:
                    logger.error(
                        f"More instances of VPP running "
                        f"on node {self._node[u'host']}."
                    )
            else:
                logger.error(f"VPP not running on node {self._node[u'host']}.")
            raise RuntimeError(
                f"Failed to open VAT console on node {self._node[u'host']}"
            )

        self._exec_failure = False
        self.vat_stdout = None
Example #35
0
    def get_pci_dev_driver(node, pci_addr):
        """Get current PCI device driver on node.

        :param node: DUT node.
        :param pci_addr: PCI device address.
        :type node: dict
        :type pci_addr: str
        :returns: Driver or None
        :raises RuntimeError: If PCI rescan or lspci command execution failed.
        """
        ssh = SSH()
        ssh.connect(node)

        for i in range(3):
            logger.trace('Try {0}: Get interface driver'.format(i))
            cmd = 'sh -c "echo 1 > /sys/bus/pci/rescan"'
            ret_code, _, _ = ssh.exec_command_sudo(cmd)
            if int(ret_code) != 0:
                raise RuntimeError("'{0}' failed on '{1}'".format(
                    cmd, node['host']))

            cmd = 'lspci -vmmks {0}'.format(pci_addr)
            ret_code, stdout, _ = ssh.exec_command(cmd)
            if int(ret_code) != 0:
                raise RuntimeError("'{0}' failed on '{1}'".format(
                    cmd, node['host']))

            for line in stdout.splitlines():
                if len(line) == 0:
                    continue
                name = None
                value = None
                try:
                    name, value = line.split("\t", 1)
                except ValueError:
                    if name == "Driver:":
                        return None
                if name == 'Driver:':
                    return value
        else:
            return None
Example #36
0
    def __init__(self, node, json_param=True):
        json_text = ' json' if json_param else ''
        self.json = json_param
        self._node = node
        self._ssh = SSH()
        self._ssh.connect(self._node)
        try:
            self._tty = self._ssh.interactive_terminal_open()
        except Exception:
            raise RuntimeError(
                "Cannot open interactive terminal on node {0}".format(
                    self._node))

        for _ in range(3):
            try:
                self._ssh.interactive_terminal_exec_command(
                    self._tty, 'sudo -S {0}{1}'.format(Constants.VAT_BIN_NAME,
                                                       json_text),
                    self.__VAT_PROMPT)
            except Exception:
                continue
            else:
                break
        else:
            vpp_pid = get_vpp_pid(self._node)
            if vpp_pid:
                if isinstance(vpp_pid, int):
                    logger.trace("VPP running on node {0}".format(
                        self._node['host']))
                else:
                    logger.error(
                        "More instances of VPP running on node {0}.".format(
                            self._node['host']))
            else:
                logger.error("VPP not running on node {0}.".format(
                    self._node['host']))
            raise RuntimeError("Failed to open VAT console on node {0}".format(
                self._node['host']))

        self._exec_failure = False
        self.vat_stdout = None
Example #37
0
    def execute_script(self, local_path, node, timeout=10, json_out=True):
        """Copy local_path script to node, execute it and return result.
        
        Returns (rc, stdout, stderr tuple).
        """

        ssh = SSH()
        ssh.connect(node)

        local_basename = os.path.basename(local_path)
        remote_file_path = self.__TMP_DIR + local_basename
        remote_file_out = remote_file_path + ".out"

        ssh.scp(local_path, remote_file_path)

        cmd = "sudo -S {vat} {json} < {input}".format(vat=self.__VAT_BIN, 
                json="json" if json_out == True else "",
                input=remote_file_path)
        (ret_code, stdout, stderr) = ssh.exec_command(cmd, timeout)
        self._ret_code = ret_code
        self._stdout = stdout
        self._stderr = stderr

        logger.trace("Command '{0}' returned {1}'".format(cmd, self._ret_code))
        logger.trace("stdout: '{0}'".format(self._stdout))
        logger.trace("stderr: '{0}'".format(self._stderr))

        #TODO: download vpp_api_test output file
        self._delete_files(node, remote_file_path, remote_file_out)
Example #38
0
    def _trace(self, message):

        logger.trace(msg=message)
 def test_logged_to_python(self):
     logger.info("Foo")
     logger.debug("Boo")
     logger.trace("Goo")
     logger.write("Doo", 'INFO')
     self.assertEquals(self.handler.messages, ['Foo', 'Boo', 'Goo', 'Doo'])
Example #40
0
 def msg(self, msg, *args):
     # Forward telnetlib's debug messages to log
     logger.trace(msg % args)