import logging
import os
import random
+import re
+import signal
import socket
import subprocess
import sys
+import time
import six
from flask import jsonify
from six.moves import configparser
from oslo_serialization import jsonutils
+from oslo_utils import encodeutils
import yardstick
+from yardstick.common import exceptions
+
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
yield sub
-def import_modules_from_package(package):
+def import_modules_from_package(package, raise_exception=False):
"""Import modules given a package name
:param: package - Full package name. For example: rally.deploy.engines
for module_name in missing_modules:
try:
importlib.import_module(module_name)
- except (ImportError, SyntaxError):
+ except (ImportError, SyntaxError) as exc:
+ if raise_exception:
+ raise exc
logger.exception('Unable to import module %s', module_name)
+NON_NONE_DEFAULT = object()
+
+
+def get_key_with_default(data, key, default=NON_NONE_DEFAULT):
+ value = data.get(key, default)
+ if value is NON_NONE_DEFAULT:
+ raise KeyError(key)
+ return value
+
+
+def make_dict_from_map(data, key_map):
+ return {dest_key: get_key_with_default(data, src_key, default)
+ for dest_key, (src_key, default) in key_map.items()}
+
+
def makedirs(d):
try:
os.makedirs(d)
raise
-def execute_command(cmd):
+def execute_command(cmd, **kwargs):
exec_msg = "Executing command: '%s'" % cmd
logger.debug(exec_msg)
- output = subprocess.check_output(cmd.split()).split(os.linesep)
-
- return output
+ output = subprocess.check_output(cmd.split(), **kwargs)
+ return encodeutils.safe_decode(output, incoming='utf-8').split(os.linesep)
def source_env(env_file):
p = subprocess.Popen(". %s; env" % env_file, stdout=subprocess.PIPE,
shell=True)
output = p.communicate()[0]
+
+ # sometimes output type would be binary_type, and it don't have splitlines
+ # method, so we need to decode
+ if isinstance(output, six.binary_type):
+ output = encodeutils.safe_decode(output)
env = dict(line.split('=', 1) for line in output.splitlines() if '=' in line)
os.environ.update(env)
return env
class Timer(object):
- def __init__(self):
+ def __init__(self, timeout=None):
super(Timer, self).__init__()
self.start = self.delta = None
+ self._timeout = int(timeout) if timeout else None
+
+ def _timeout_handler(self, *args):
+ raise exceptions.TimerTimeout(timeout=self._timeout)
def __enter__(self):
self.start = datetime.datetime.now()
+ if self._timeout:
+ signal.signal(signal.SIGALRM, self._timeout_handler)
+ signal.alarm(self._timeout)
return self
def __exit__(self, *_):
+ if self._timeout:
+ signal.alarm(0)
self.delta = datetime.datetime.now() - self.start
def __getattr__(self, item):
return getattr(self.delta, item)
+
+
+def read_meminfo(ssh_client):
+ """Read "/proc/meminfo" file and parse all keys and values"""
+
+ cpuinfo = six.BytesIO()
+ ssh_client.get_file_obj('/proc/meminfo', cpuinfo)
+ lines = cpuinfo.getvalue().decode('utf-8')
+ matches = re.findall(r"([\w\(\)]+):\s+(\d+)( kB)*", lines)
+ output = {}
+ for match in matches:
+ output[match[0]] = match[1]
+
+ return output
+
+
+def find_relative_file(path, task_path):
+ """
+ Find file in one of places: in abs of path or relative to a directory path,
+ in this order.
+
+ :param path:
+ :param task_path:
+ :return str: full path to file
+ """
+ # fixme: create schema to validate all fields have been provided
+ for lookup in [os.path.abspath(path), os.path.join(task_path, path)]:
+ try:
+ with open(lookup):
+ return lookup
+ except IOError:
+ pass
+ raise IOError(errno.ENOENT, 'Unable to find {} file'.format(path))
+
+
+def open_relative_file(path, task_path):
+ try:
+ return open(path)
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ return open(os.path.join(task_path, path))
+ raise
+
+
+def wait_until_true(predicate, timeout=60, sleep=1, exception=None):
+ """Wait until callable predicate is evaluated as True
+
+ :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():
+ time.sleep(sleep)
+ except exceptions.TimerTimeout:
+ if exception and issubclass(exception, Exception):
+ raise exception # pylint: disable=raising-bad-type
+ raise exceptions.WaitTimeout