1993f1e8320c4aa989eba7417da56f145b4de089
[functest.git] / functest / utils / functest_utils.py
1 #!/usr/bin/env python
2 #
3 # jose.lausuch@ericsson.com
4 # valentin.boucher@orange.com
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9
10 # pylint: disable=missing-docstring
11
12 from __future__ import print_function
13 import logging
14 import subprocess
15 import sys
16 import yaml
17
18 LOGGER = logging.getLogger(__name__)
19
20
21 def execute_command_raise(cmd, info=False, error_msg="",
22                           verbose=True, output_file=None):
23     ret = execute_command(cmd, info, error_msg, verbose, output_file)
24     if ret != 0:
25         raise Exception(error_msg)
26
27
28 def execute_command(cmd, info=False, error_msg="",
29                     verbose=True, output_file=None):
30     if not error_msg:
31         error_msg = ("The command '%s' failed." % cmd)
32     msg_exec = ("Executing command: '%s'" % cmd)
33     if verbose:
34         if info:
35             LOGGER.info(msg_exec)
36         else:
37             LOGGER.debug(msg_exec)
38     popen = subprocess.Popen(
39         cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
40     if output_file:
41         ofd = open(output_file, "w")
42     for line in iter(popen.stdout.readline, b''):
43         if output_file:
44             ofd.write(line)
45         else:
46             line = line.replace('\n', '')
47             print(line)
48             sys.stdout.flush()
49     if output_file:
50         ofd.close()
51     popen.stdout.close()
52     returncode = popen.wait()
53     if returncode != 0:
54         if verbose:
55             LOGGER.error(error_msg)
56
57     return returncode
58
59
60 def get_parameter_from_yaml(parameter, yfile):
61     """
62     Returns the value of a given parameter in file.yaml
63     parameter must be given in string format with dots
64     Example: general.openstack.image_name
65     """
66     with open(yfile) as yfd:
67         file_yaml = yaml.safe_load(yfd)
68     value = file_yaml
69     for element in parameter.split("."):
70         value = value.get(element)
71         if value is None:
72             raise ValueError("The parameter %s is not defined in"
73                              " %s" % (parameter, yfile))
74     return value
75
76
77 def get_nova_version(cloud):
78     """ Get Nova API microversion
79
80     Returns:
81
82     - Nova API microversion
83     - None on operation error
84     """
85     # pylint: disable=protected-access
86     try:
87         request = cloud._compute_client.request("/", "GET")
88         LOGGER.debug('cloud._compute_client.request: %s', request)
89         version = request["version"]["version"]
90         major, minor = version.split('.')
91         LOGGER.debug('nova version: %s', (int(major), int(minor)))
92         return (int(major), int(minor))
93     except Exception:  # pylint: disable=broad-except
94         LOGGER.exception("Cannot detect Nova version")
95         return None
96
97
98 def get_openstack_version(cloud):
99     """ Detect OpenStack version via Nova API microversion
100
101     It follows `MicroversionHistory
102     <https://docs.openstack.org/nova/latest/reference/api-microversion-history.html>`_.
103
104     Returns:
105
106     - OpenStack release
107     - Unknown on operation error
108     """
109     version = get_nova_version(cloud)
110     try:
111         assert version
112         if version > (2, 60):
113             osversion = "Rocky or newer"
114         elif version > (2, 53):
115             osversion = "Queens"
116         elif version > (2, 42):
117             osversion = "Pike"
118         elif version > (2, 38):
119             osversion = "Ocata"
120         elif version > (2, 25):
121             osversion = "Newton"
122         elif version > (2, 12):
123             osversion = "Mitaka"
124         elif version > (2, 3):
125             osversion = "Liberty"
126         elif version >= (2, 1):
127             osversion = "Kilo"
128         else:
129             osversion = "Unknown"
130         LOGGER.info('Detect OpenStack version: %s', osversion)
131         return osversion
132     except AssertionError:
133         LOGGER.exception("Cannot detect OpenStack version")
134         return "Unknown"