X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fcommon%2Futils.py;h=9eba896e255e09884d87e4be0155b3d023689ddb;hb=51fcd65a47991a62235f32b63c0b4f732551fca5;hp=f9fe0e336e9e39267c35b6c4c88e05d338ad9b18;hpb=9580bf1d0009b98b71d54c0a8231d45eae99d254;p=yardstick.git diff --git a/yardstick/common/utils.py b/yardstick/common/utils.py index f9fe0e336..9eba896e2 100644 --- a/yardstick/common/utils.py +++ b/yardstick/common/utils.py @@ -21,6 +21,7 @@ import importlib import ipaddress import logging import os +import pydoc import random import re import signal @@ -28,6 +29,8 @@ import socket import subprocess import sys import time +import threading +import math import six from flask import jsonify @@ -193,20 +196,16 @@ def parse_ini_file(path): def get_port_mac(sshclient, port): cmd = "ifconfig |grep HWaddr |grep %s |awk '{print $5}' " % port - status, stdout, stderr = sshclient.execute(cmd) + _, stdout, _ = sshclient.execute(cmd, raise_on_error=True) - if status: - raise RuntimeError(stderr) return stdout.rstrip() def get_port_ip(sshclient, port): cmd = "ifconfig %s |grep 'inet addr' |awk '{print $2}' " \ "|cut -d ':' -f2 " % port - status, stdout, stderr = sshclient.execute(cmd) + _, stdout, _ = sshclient.execute(cmd, raise_on_error=True) - if status: - raise RuntimeError(stderr) return stdout.rstrip() @@ -281,11 +280,30 @@ def get_free_port(ip): def mac_address_to_hex_list(mac): - octets = ["0x{:02x}".format(int(elem, 16)) for elem in mac.split(':')] - assert len(octets) == 6 and all(len(octet) == 4 for octet in octets) + try: + octets = ["0x{:02x}".format(int(elem, 16)) for elem in mac.split(':')] + except ValueError: + raise exceptions.InvalidMacAddress(mac_address=mac) + if len(octets) != 6 or all(len(octet) != 4 for octet in octets): + raise exceptions.InvalidMacAddress(mac_address=mac) return octets +def make_ipv4_address(ip_addr): + return ipaddress.IPv4Address(six.text_type(ip_addr)) + + +def get_ip_range_count(iprange): + start_range, end_range = iprange.split("-") + start = int(make_ipv4_address(start_range)) + end = int(make_ipv4_address(end_range)) + return end - start + + +def get_ip_range_start(iprange): + return str(make_ipv4_address(iprange.split("-")[0])) + + def safe_ip_address(ip_addr): """ get ip address version v6 or v4 """ try: @@ -335,6 +353,14 @@ def ip_to_hex(ip_addr, separator=''): return separator.join('{:02x}'.format(octet) for octet in address.packed) +def get_mask_from_ip_range(ip_low, ip_high): + _ip_low = ipaddress.ip_address(ip_low) + _ip_high = ipaddress.ip_address(ip_high) + _ip_low_int = int(_ip_low) + _ip_high_int = int(_ip_high) + return _ip_high.max_prefixlen - (_ip_high_int ^ _ip_low_int).bit_length() + + def try_int(s, *args): """Convert to integer if possible.""" try: @@ -467,6 +493,9 @@ class Timer(object): def __del__(self): # pragma: no cover signal.alarm(0) + def delta_time_sec(self): + return (datetime.datetime.now() - self.start).total_seconds() + def read_meminfo(ssh_client): """Read "/proc/meminfo" file and parse all keys and values""" @@ -482,6 +511,23 @@ def read_meminfo(ssh_client): return output +def setup_hugepages(ssh_client, size_kb): + """Setup needed number of hugepages for the size specified""" + + NR_HUGEPAGES_PATH = '/proc/sys/vm/nr_hugepages' + meminfo = read_meminfo(ssh_client) + hp_size_kb = int(meminfo['Hugepagesize']) + hp_number = int(math.ceil(size_kb / float(hp_size_kb))) + ssh_client.execute( + 'echo %s | sudo tee %s' % (hp_number, NR_HUGEPAGES_PATH)) + hp = six.BytesIO() + ssh_client.get_file_obj(NR_HUGEPAGES_PATH, hp) + hp_number_set = int(hp.getvalue().decode('utf-8').splitlines()[0]) + logger.info('Hugepages size (kB): %s, number claimed: %s, number set: %s', + hp_size_kb, hp_number, hp_number_set) + return hp_size_kb, hp_number, hp_number_set + + def find_relative_file(path, task_path): """ Find file in one of places: in abs of path or relative to a directory path, @@ -513,17 +559,73 @@ def open_relative_file(path, task_path): def wait_until_true(predicate, timeout=60, sleep=1, exception=None): """Wait until callable predicate is evaluated as True + When in a thread different from the main one, Timer(timeout) will fail + because signal is not handled. In this case + :param predicate: (func) callable deciding whether waiting should continue :param timeout: (int) timeout in seconds how long should function wait :param sleep: (int) polling interval for results in seconds :param exception: exception instance to raise on timeout. If None is passed (default) then WaitTimeout exception is raised. """ - try: - with Timer(timeout=timeout): - while not predicate(): + if isinstance(threading.current_thread(), threading._MainThread): + try: + with Timer(timeout=timeout): + while not predicate(): + time.sleep(sleep) + except exceptions.TimerTimeout: + if exception and issubclass(exception, Exception): + raise exception # pylint: disable=raising-bad-type + raise exceptions.WaitTimeout + else: + with Timer() as timer: + while timer.delta_time_sec() < timeout: + if predicate(): + return time.sleep(sleep) - except exceptions.TimerTimeout: if exception and issubclass(exception, Exception): raise exception # pylint: disable=raising-bad-type raise exceptions.WaitTimeout + + +def send_socket_command(host, port, command): + """Send a string command to a specific port in a host + + :param host: (str) ip or hostname of the host + :param port: (int) port number + :param command: (str) command to send + :return: 0 if success, error number if error + """ + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + ret = 0 + try: + err_number = sock.connect_ex((host, int(port))) + if err_number != 0: + return err_number + sock.sendall(six.b(command)) + except Exception: # pylint: disable=broad-except + ret = 1 + finally: + sock.close() + return ret + + +def safe_cast(value, type_to_convert, default_value): + """Convert value to type, in case of error return default_value + + :param value: value to convert + :param type_to_convert: type to convert, could be "type" or "string" + :param default_value: default value to return + :return: converted value or default_value + """ + if isinstance(type_to_convert, type): + _type = type_to_convert + else: + _type = pydoc.locate(type_to_convert) + if not _type: + raise exceptions.InvalidType(type_to_convert=type_to_convert) + + try: + return _type(value) + except ValueError: + return default_value