Merge "Adding Labels"
[yardstick.git] / yardstick / common / utils.py
1 # Copyright 2013: Mirantis Inc.
2 # All Rights Reserved.
3 #
4 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
5 #    not use this file except in compliance with the License. You may obtain
6 #    a copy of the License at
7 #
8 #         http://www.apache.org/licenses/LICENSE-2.0
9 #
10 #    Unless required by applicable law or agreed to in writing, software
11 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 #    License for the specific language governing permissions and limitations
14 #    under the License.
15
16 # yardstick comment: this is a modified copy of rally/rally/common/utils.py
17
18 from __future__ import absolute_import
19 from __future__ import print_function
20
21 import errno
22 import logging
23 import os
24 import subprocess
25 import sys
26 from functools import reduce
27
28 import yaml
29 from six.moves import configparser
30 from oslo_utils import importutils
31 from oslo_serialization import jsonutils
32
33 import yardstick
34
35 logger = logging.getLogger(__name__)
36 logger.setLevel(logging.DEBUG)
37
38
39 # Decorator for cli-args
40 def cliargs(*args, **kwargs):
41     def _decorator(func):
42         func.__dict__.setdefault('arguments', []).insert(0, (args, kwargs))
43         return func
44     return _decorator
45
46
47 def itersubclasses(cls, _seen=None):
48     """Generator over all subclasses of a given class in depth first order."""
49
50     if not isinstance(cls, type):
51         raise TypeError("itersubclasses must be called with "
52                         "new-style classes, not %.100r" % cls)
53     _seen = _seen or set()
54     try:
55         subs = cls.__subclasses__()
56     except TypeError:   # fails only when cls is type
57         subs = cls.__subclasses__(cls)
58     for sub in subs:
59         if sub not in _seen:
60             _seen.add(sub)
61             yield sub
62             for sub in itersubclasses(sub, _seen):
63                 yield sub
64
65
66 def try_append_module(name, modules):
67     if name not in modules:
68         modules[name] = importutils.import_module(name)
69
70
71 def import_modules_from_package(package):
72     """Import modules from package and append into sys.modules
73
74     :param: package - Full package name. For example: rally.deploy.engines
75     """
76     path = [os.path.dirname(yardstick.__file__), ".."] + package.split(".")
77     path = os.path.join(*path)
78     for root, dirs, files in os.walk(path):
79         for filename in files:
80             if filename.startswith("__") or not filename.endswith(".py"):
81                 continue
82             new_package = ".".join(root.split(os.sep)).split("....")[1]
83             module_name = "%s.%s" % (new_package, filename[:-3])
84             try_append_module(module_name, sys.modules)
85
86
87 def get_para_from_yaml(file_path, args):
88
89     def func(a, b):
90         if a is None:
91             return None
92         return a.get(b)
93
94     if os.path.exists(file_path):
95         with open(file_path) as f:
96             value = yaml.safe_load(f)
97             value = reduce(func, args.split('.'), value)
98
99             if value is None:
100                 print('parameter not found')
101                 return None
102
103             return value
104     else:
105         print('file not exist')
106         return None
107
108
109 def makedirs(d):
110     try:
111         os.makedirs(d)
112     except OSError as e:
113         if e.errno != errno.EEXIST:
114             raise
115
116
117 def execute_command(cmd):
118     exec_msg = "Executing command: '%s'" % cmd
119     logger.debug(exec_msg)
120
121     output = subprocess.check_output(cmd.split()).split(os.linesep)
122
123     return output
124
125
126 def source_env(env_file):
127     p = subprocess.Popen(". %s; env" % env_file, stdout=subprocess.PIPE,
128                          shell=True)
129     output = p.communicate()[0]
130     env = dict((line.split('=', 1) for line in output.splitlines()))
131     os.environ.update(env)
132     return env
133
134
135 def read_json_from_file(path):
136     with open(path, 'r') as f:
137         j = f.read()
138     # don't use jsonutils.load() it conflicts with already decoded input
139     return jsonutils.loads(j)
140
141
142 def write_json_to_file(path, data, mode='w'):
143     with open(path, mode) as f:
144         jsonutils.dump(data, f)
145
146
147 def write_file(path, data, mode='w'):
148     with open(path, mode) as f:
149         f.write(data)
150
151
152 def parse_ini_file(path):
153     parser = configparser.ConfigParser()
154     parser.read(path)
155
156     try:
157         default = {k: v for k, v in parser.items('DEFAULT')}
158     except configparser.NoSectionError:
159         default = {}
160
161     config = dict(DEFAULT=default,
162                   **{s: {k: v for k, v in parser.items(
163                       s)} for s in parser.sections()})
164
165     return config