Fix image properties parsing
[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 import six
19
20 LOGGER = logging.getLogger(__name__)
21
22
23 def execute_command_raise(cmd, info=False, error_msg="",
24                           verbose=True, output_file=None):
25     ret = execute_command(cmd, info, error_msg, verbose, output_file)
26     if ret != 0:
27         raise Exception(error_msg)
28
29
30 def execute_command(cmd, info=False, error_msg="",
31                     verbose=True, output_file=None):
32     if not error_msg:
33         error_msg = ("The command '%s' failed." % cmd)
34     msg_exec = ("Executing command: '%s'" % cmd)
35     if verbose:
36         if info:
37             LOGGER.info(msg_exec)
38         else:
39             LOGGER.debug(msg_exec)
40     popen = subprocess.Popen(
41         cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
42     if output_file:
43         ofd = open(output_file, "w")
44     for line in iter(popen.stdout.readline, b''):
45         if output_file:
46             ofd.write(line)
47         else:
48             line = line.replace('\n', '')
49             print(line)
50             sys.stdout.flush()
51     if output_file:
52         ofd.close()
53     popen.stdout.close()
54     returncode = popen.wait()
55     if returncode != 0:
56         if verbose:
57             LOGGER.error(error_msg)
58
59     return returncode
60
61
62 def get_parameter_from_yaml(parameter, yfile):
63     """
64     Returns the value of a given parameter in file.yaml
65     parameter must be given in string format with dots
66     Example: general.openstack.image_name
67     """
68     with open(yfile) as yfd:
69         file_yaml = yaml.safe_load(yfd)
70     value = file_yaml
71     for element in parameter.split("."):
72         value = value.get(element)
73         if value is None:
74             raise ValueError("The parameter %s is not defined in"
75                              " %s" % (parameter, yfile))
76     return value
77
78
79 def get_nova_version(cloud):
80     """ Get Nova API microversion
81
82     Returns:
83
84     - Nova API microversion
85     - None on operation error
86     """
87     # pylint: disable=protected-access
88     try:
89         request = cloud._compute_client.request("/", "GET")
90         LOGGER.debug('cloud._compute_client.request: %s', request)
91         version = request["version"]["version"]
92         major, minor = version.split('.')
93         LOGGER.debug('nova version: %s', (int(major), int(minor)))
94         return (int(major), int(minor))
95     except Exception:  # pylint: disable=broad-except
96         LOGGER.exception("Cannot detect Nova version")
97         return None
98
99
100 def get_openstack_version(cloud):
101     """ Detect OpenStack version via Nova API microversion
102
103     It follows `MicroversionHistory
104     <https://docs.openstack.org/nova/latest/reference/api-microversion-history.html>`_.
105
106     Returns:
107
108     - OpenStack release
109     - Unknown on operation error
110     """
111     version = get_nova_version(cloud)
112     try:
113         assert version
114         if version > (2, 65):
115             osversion = "Master"
116         elif version > (2, 60):
117             osversion = "Rocky"
118         elif version > (2, 53):
119             osversion = "Queens"
120         elif version > (2, 42):
121             osversion = "Pike"
122         elif version > (2, 38):
123             osversion = "Ocata"
124         elif version > (2, 25):
125             osversion = "Newton"
126         elif version > (2, 12):
127             osversion = "Mitaka"
128         elif version > (2, 3):
129             osversion = "Liberty"
130         elif version >= (2, 1):
131             osversion = "Kilo"
132         else:
133             osversion = "Unknown"
134         LOGGER.info('Detect OpenStack version: %s', osversion)
135         return osversion
136     except AssertionError:
137         LOGGER.exception("Cannot detect OpenStack version")
138         return "Unknown"
139
140
141 def convert_dict_to_ini(value):
142     "Convert dict to oslo.conf input"
143     assert isinstance(value, dict)
144     return ",".join("{}:{}".format(
145         key, val) for (key, val) in six.iteritems(value))
146
147
148 def convert_list_to_ini(value):
149     "Convert list to oslo.conf input"
150     assert isinstance(value, list)
151     return ",".join("{}".format(val) for val in value)
152
153
154 def convert_ini_to_dict(value):
155     "Convert oslo.conf input to dict"
156     assert isinstance(value, str)
157     try:
158         return {k: v for k, v in (x.split(':') for x in value.split(','))}
159     except ValueError:
160         return {}
161
162
163 def convert_ini_to_list(value):
164     "Convert list to oslo.conf input"
165     assert isinstance(value, str)
166     if not value:
167         return []
168     return [x for x in value.split(',')]