Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 146 additions & 8 deletions tests/common/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
import sys
import threading
import time
import re

from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from ansible.vars.manager import VariableManager

logger = logging.getLogger(__name__)


def wait(seconds, msg=""):
Expand All @@ -15,7 +22,7 @@ def wait(seconds, msg=""):
@param seconds: Number of seconds to pause
@param msg: Optional extra message for pause reason
"""
logging.info("Pause %d seconds, reason: %s" % (seconds, msg))
logger.info("Pause %d seconds, reason: %s" % (seconds, msg))
time.sleep(seconds)


Expand All @@ -30,29 +37,29 @@ def wait_until(timeout, interval, condition, *args, **kwargs):
@return: If the condition function returns True before timeout, return True. If the condition function raises an
exception, log the error and keep waiting and polling.
"""
logging.debug("Wait until %s is True, timeout is %s seconds, checking interval is %s" % \
logger.debug("Wait until %s is True, timeout is %s seconds, checking interval is %s" % \
(condition.__name__, timeout, interval))
start_time = time.time()
elapsed_time = 0
while elapsed_time < timeout:
logging.debug("Time elapsed: %f seconds" % elapsed_time)
logger.debug("Time elapsed: %f seconds" % elapsed_time)

try:
check_result = condition(*args, **kwargs)
except Exception as e:
logging.error("Exception caught while checking %s: %s" % (condition.__name__, repr(e)))
logger.error("Exception caught while checking %s: %s" % (condition.__name__, repr(e)))
check_result = False

if check_result:
logging.debug("%s is True, exit early with True" % condition.__name__)
logger.debug("%s is True, exit early with True" % condition.__name__)
return True
else:
logging.debug("%s is False, wait %d seconds and check again" % (condition.__name__, interval))
logger.debug("%s is False, wait %d seconds and check again" % (condition.__name__, interval))
time.sleep(interval)
elapsed_time = time.time() - start_time

if elapsed_time >= timeout:
logging.debug("%s is still False after %d seconds, exit with False" % (condition.__name__, timeout))
logger.debug("%s is still False after %d seconds, exit with False" % (condition.__name__, timeout))
return False


Expand All @@ -70,7 +77,7 @@ def wait_tcp_connection(client, server_hostname, listening_port, timeout_s = 30)
timeout=timeout_s,
module_ignore_errors=True)
if 'exception' in res:
logging.warn("Failed to establish TCP connection to %s:%d, timeout=%d" % (str(server_hostname), listening_port, timeout_s))
logger.warn("Failed to establish TCP connection to %s:%d, timeout=%d" % (str(server_hostname), listening_port, timeout_s))
return False
return True

Expand Down Expand Up @@ -127,3 +134,134 @@ def join_all(threads, timeout):
else:
raise RuntimeError("Timeout on waiting threads: %s" %
[repr(thread) for thread in threads])


def get_inventory_manager(inv_files):
return InventoryManager(loader=DataLoader(), sources=inv_files)


def get_variable_manager(inv_files):
return VariableManager(loader=DataLoader(), inventory=get_inventory_manager(inv_files))


def get_host_vars(inv_files, hostname, variable=None):
"""Use ansible's InventoryManager to get value of variables defined for the specified host in the specified
inventory files.

Args:
inv_files (list or string): List of inventory file pathes, or string of a single inventory file path. In tests,
it can be get from request.config.getoption("ansible_inventory").
hostname (string): Hostname
variable (string or None): Variable name. Defaults to None.

Returns:
string or dict or None: If variable name is specified, return the variable value. If variable is not found,
return None. If variable name is not specified, return all variables in a dictionary. If the host is not
found, return None.
"""
im = get_inventory_manager(inv_files)
host = im.get_host(hostname)
if not host:
logger.error("Unable to find host {} in {}".format(hostname, str(inv_files)))
return None

if variable:
return host.vars.get(variable, None)
else:
return host.vars


def get_host_visible_vars(inv_files, hostname, variable=None):
"""Use ansible's VariableManager and InventoryManager to get value of variables visible to the specified host.
The variable could be defined in host_vars or in group_vars that the host belongs to.

Args:
inv_files (list or string): List of inventory file pathes, or string of a single inventory file path. In tests,
it can be get from request.config.getoption("ansible_inventory").
hostname (string): Hostname
variable (string or None): Variable name. Defaults to None.

Returns:
string or dict or None: If variable name is specified, return the variable value. If variable is not found,
return None. If variable name is not specified, return all variables in a dictionary. If the host is not
found, return None.
"""
vm = get_variable_manager(inv_files)
im = vm._inventory
host = im.get_host(hostname)
if not host:
logger.error("Unable to find host {} in {}".format(hostname, str(inv_files)))
return None
if variable:
return vm.get_vars(host=host).get(variable, None)
else:
return vm.get_vars(host=host)


def get_group_visible_vars(inv_files, group_name, variable=None):
"""Use ansible's VariableManager and InventoryManager to get value of variables visible to the first host belongs
to the specified group. The variable could be defined in host_vars of the first host or in group_vars that the host
belongs to.

Args:
inv_files (list or string): List of inventory file pathes, or string of a single inventory file path. In tests,
it can be get from request.config.getoption("ansible_inventory").
group_name (string): Name of group in ansible inventory.
variable (string or None): Variable name. Defaults to None.

Returns:
string or dict or None: If variable name is specified, return the variable value. If variable is not found,
return None. If variable name is not specified, return all variables in a dictionary. If the group is not
found or there is no host in the group, return None.
"""
vm = get_variable_manager(inv_files)
im = vm._inventory
group = im.groups.get(group_name, None)
if not group:
logger.error("Unable to find group {} in {}".format(group_name, str(inv_files)))
return None
group_hosts = group.get_hosts()
if len(group_hosts) == 0:
logger.error("No host in group {}".format(group_name))
return None
first_host = group_hosts[0]
if variable:
return vm.get_vars(host=first_host).get(variable, None)
else:
return vm.get_vars(host=first_host)


def get_test_server_vars(inv_files, server, variable=None):
"""Use ansible's VariableManager and InventoryManager to get value of variables of test server belong to specified
server group.

In testbed.csv file, we can get the server name of each test setup under the 'server' column. For example
'server_1', 'server_2', etc. This server name is indeed a group name in used ansible inventory files. This group
contains children groups for test server and VMs. This function is try to just return the variables of test servers
belong to the specified server group.

Args:
inv_files (list or string): List of inventory file pathes, or string of a single inventory file path. In tests,
it can be get from request.config.getoption("ansible_inventory").
server (string): Server of test setup in testbed.csv file.
variable (string or None): Variable name. Defaults to None.

Returns:
string or dict or None: If variable name is specified, return the variable value. If variable is not found,
return None. If variable name is not specified, return all variables in a dictionary. If the server group
is not found or there is no test server host in the group, return None.
"""
vm = get_variable_manager(inv_files)
im = vm._inventory
group = im.groups.get(server, None)
if not group:
logger.error("Unable to find group {} in {}".format(server, str(inv_files)))
return None
for host in group.get_hosts():
if not re.match(r'VM\d+', host.name): # This must be the test server host
if variable:
return host.vars.get(variable, None)
else:
return host.vars
logger.error("Unable to find test server host under group {}".format(server))
return None