Add deployment_handler printout to prepare env
[functest.git] / functest / ci / prepare_env.py
1 #!/usr/bin/env python
2 #
3 # Author: Jose Lausuch (jose.lausuch@ericsson.com)
4 #
5 # Installs the Functest framework within the Docker container
6 # and run the tests automatically
7 #
8 #
9 # All rights reserved. This program and the accompanying materials
10 # are made available under the terms of the Apache License, Version 2.0
11 # which accompanies this distribution, and is available at
12 # http://www.apache.org/licenses/LICENSE-2.0
13 #
14
15
16 import argparse
17 import json
18 import os
19 import re
20 import subprocess
21 import sys
22
23 import yaml
24
25 from opnfv.deployment import factory
26 from opnfv.utils import constants as opnfv_constants
27
28 import functest.utils.functest_logger as ft_logger
29 import functest.utils.functest_utils as ft_utils
30 import functest.utils.openstack_utils as os_utils
31 from functest.utils.constants import CONST
32
33 actions = ['start', 'check']
34
35 """ logging configuration """
36 logger = ft_logger.Logger("prepare_env").getLogger()
37
38
39 CONFIG_FUNCTEST_PATH = CONST.CONFIG_FUNCTEST_YAML
40 CONFIG_PATCH_PATH = os.path.join(os.path.dirname(
41     CONFIG_FUNCTEST_PATH), "config_patch.yaml")
42
43 with open(CONFIG_PATCH_PATH) as f:
44     functest_patch_yaml = yaml.safe_load(f)
45
46
47 class PrepareEnvParser():
48
49     def __init__(self):
50         self.parser = argparse.ArgumentParser()
51         self.parser.add_argument("action", help="Possible actions are: "
52                                  "'{d[0]}|{d[1]}' ".format(d=actions),
53                                  choices=actions)
54         self.parser.add_argument("-d", "--debug", help="Debug mode",
55                                  action="store_true")
56
57     def parse_args(self, argv=[]):
58         return vars(self.parser.parse_args(argv))
59
60
61 def print_separator():
62     logger.info("==============================================")
63
64
65 def check_env_variables():
66     print_separator()
67     logger.info("Checking environment variables...")
68
69     if CONST.INSTALLER_TYPE is None:
70         logger.warning("The env variable 'INSTALLER_TYPE' is not defined.")
71         CONST.INSTALLER_TYPE = "undefined"
72     else:
73         if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
74             logger.warning("INSTALLER_TYPE=%s is not a valid OPNFV installer. "
75                            "Available OPNFV Installers are : %s. "
76                            "Setting INSTALLER_TYPE=undefined."
77                            % (CONST.INSTALLER_TYPE,
78                               opnfv_constants.INSTALLERS))
79             CONST.INSTALLER_TYPE = "undefined"
80         else:
81             logger.info("    INSTALLER_TYPE=%s"
82                         % CONST.INSTALLER_TYPE)
83
84     if CONST.INSTALLER_IP is None:
85         logger.warning("The env variable 'INSTALLER_IP' is not defined. "
86                        "It is needed to fetch the OpenStack credentials. "
87                        "If the credentials are not provided to the "
88                        "container as a volume, please add this env variable "
89                        "to the 'docker run' command.")
90     else:
91         logger.info("    INSTALLER_IP=%s" % CONST.INSTALLER_IP)
92
93     if CONST.DEPLOY_SCENARIO is None:
94         logger.warning("The env variable 'DEPLOY_SCENARIO' is not defined. "
95                        "Setting CI_SCENARIO=undefined.")
96         CONST.DEPLOY_SCENARIO = "undefined"
97     else:
98         logger.info("    DEPLOY_SCENARIO=%s" % CONST.DEPLOY_SCENARIO)
99     if CONST.CI_DEBUG:
100         logger.info("    CI_DEBUG=%s" % CONST.CI_DEBUG)
101
102     if CONST.NODE_NAME:
103         logger.info("    NODE_NAME=%s" % CONST.NODE_NAME)
104
105     if CONST.BUILD_TAG:
106         logger.info("    BUILD_TAG=%s" % CONST.BUILD_TAG)
107
108     if CONST.IS_CI_RUN:
109         logger.info("    IS_CI_RUN=%s" % CONST.IS_CI_RUN)
110
111
112 def print_deployment_info():
113     handler = None
114     if CONST.INSTALLER_IP:
115         if CONST.INSTALLER_TYPE == 'apex':
116             pkey = '/root/.ssh/id_rsa'
117             if os.path.isfile(pkey):
118                 handler = factory.Factory.get_handler(CONST.INSTALLER_TYPE,
119                                                       CONST.INSTALLER_IP,
120                                                       'stack',
121                                                       pkey_file=pkey)
122         elif CONST.INSTALLER_TYPE == 'fuel':
123             handler = factory.Factory.get_handler(CONST.INSTALLER_TYPE,
124                                                   CONST.INSTALLER_IP,
125                                                   'root',
126                                                   installer_pwd='r00tme')
127
128     if handler:
129         logger.info('\n\nDeployment information:\n%s' %
130                     handler.get_deployment_info())
131
132
133 def create_directories():
134     print_separator()
135     logger.info("Creating needed directories...")
136     if not os.path.exists(CONST.dir_functest_conf):
137         os.makedirs(CONST.dir_functest_conf)
138         logger.info("    %s created." % CONST.dir_functest_conf)
139     else:
140         logger.debug("   %s already exists."
141                      % CONST.dir_functest_conf)
142
143     if not os.path.exists(CONST.dir_functest_data):
144         os.makedirs(CONST.dir_functest_data)
145         logger.info("    %s created." % CONST.dir_functest_data)
146     else:
147         logger.debug("   %s already exists."
148                      % CONST.dir_functest_data)
149
150
151 def source_rc_file():
152     print_separator()
153     logger.info("Fetching RC file...")
154
155     if CONST.openstack_creds is None:
156         logger.warning("The environment variable 'creds' must be set and"
157                        "pointing to the local RC file. Using default: "
158                        "/home/opnfv/functest/conf/openstack.creds ...")
159         os.path.join(CONST.dir_functest_conf, 'openstack.creds')
160
161     if not os.path.isfile(CONST.openstack_creds):
162         logger.info("RC file not provided. "
163                     "Fetching it from the installer...")
164         if CONST.INSTALLER_IP is None:
165             logger.error("The env variable CI_INSTALLER_IP must be provided in"
166                          " order to fetch the credentials from the installer.")
167             raise Exception("Missing CI_INSTALLER_IP.")
168         if CONST.INSTALLER_TYPE not in opnfv_constants.INSTALLERS:
169             logger.error("Cannot fetch credentials. INSTALLER_TYPE=%s is "
170                          "not a valid OPNFV installer. Available "
171                          "installers are : %s." %
172                          (CONST.INSTALLER_TYPE,
173                           opnfv_constants.INSTALLERS))
174             raise Exception("Wrong INSTALLER_TYPE.")
175
176         cmd = ("/home/opnfv/repos/releng/utils/fetch_os_creds.sh "
177                "-d %s -i %s -a %s"
178                % (CONST.openstack_creds,
179                   CONST.INSTALLER_TYPE,
180                   CONST.INSTALLER_IP))
181         logger.debug("Executing command: %s" % cmd)
182         p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
183         output = p.communicate()[0]
184         logger.debug("\n%s" % output)
185         if p.returncode != 0:
186             raise Exception("Failed to fetch credentials from installer.")
187     else:
188         logger.info("RC file provided in %s."
189                     % CONST.openstack_creds)
190         if os.path.getsize(CONST.openstack_creds) == 0:
191             raise Exception("The file %s is empty." % CONST.openstack_creds)
192
193     logger.info("Sourcing the OpenStack RC file...")
194     os_utils.source_credentials(
195         CONST.openstack_creds)
196     for key, value in os.environ.iteritems():
197         if re.search("OS_", key):
198             if key == 'OS_AUTH_URL':
199                 CONST.OS_AUTH_URL = value
200             elif key == 'OS_USERNAME':
201                 CONST.OS_USERNAME = value
202             elif key == 'OS_TENANT_NAME':
203                 CONST.OS_TENANT_NAME = value
204             elif key == 'OS_PASSWORD':
205                 CONST.OS_PASSWORD = value
206
207
208 def patch_config_file():
209     updated = False
210     for key in functest_patch_yaml:
211         if key in CONST.DEPLOY_SCENARIO:
212             new_functest_yaml = dict(ft_utils.merge_dicts(
213                 ft_utils.get_functest_yaml(), functest_patch_yaml[key]))
214             updated = True
215
216     if updated:
217         os.remove(CONFIG_FUNCTEST_PATH)
218         with open(CONFIG_FUNCTEST_PATH, "w") as f:
219             f.write(yaml.dump(new_functest_yaml, default_style='"'))
220         f.close()
221
222
223 def verify_deployment():
224     print_separator()
225     logger.info("Verifying OpenStack services...")
226     cmd = ("%s/functest/ci/check_os.sh" % CONST.dir_repo_functest)
227
228     logger.debug("Executing command: %s" % cmd)
229     p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
230
231     while p.poll() is None:
232         line = p.stdout.readline().rstrip()
233         if "ERROR" in line:
234             logger.error(line)
235             raise Exception("Problem while running 'check_os.sh'.")
236         logger.info(line)
237
238
239 def install_rally():
240     print_separator()
241     logger.info("Creating Rally environment...")
242
243     cmd = "rally deployment destroy opnfv-rally"
244     ft_utils.execute_command(cmd, error_msg=(
245         "Deployment %s does not exist."
246         % CONST.rally_deployment_name),
247         verbose=False)
248     rally_conf = os_utils.get_credentials_for_rally()
249     with open('rally_conf.json', 'w') as fp:
250         json.dump(rally_conf, fp)
251     cmd = ("rally deployment create "
252            "--file=rally_conf.json --name={}"
253            .format(CONST.rally_deployment_name))
254     ft_utils.execute_command(cmd,
255                              error_msg=("Problem while creating "
256                                         "Rally deployment"))
257
258     cmd = "rally deployment check"
259     ft_utils.execute_command(cmd,
260                              error_msg=("OpenStack not responding or "
261                                         "faulty Rally deployment."))
262
263     cmd = "rally deployment list"
264     ft_utils.execute_command(cmd,
265                              error_msg=("Problem while listing "
266                                         "Rally deployment."))
267
268     cmd = "rally plugin list | head -5"
269     ft_utils.execute_command(cmd,
270                              error_msg=("Problem while showing "
271                                         "Rally plugins."))
272
273
274 def install_tempest():
275     logger.info("Installing tempest from existing repo...")
276     cmd = ("rally verify create-verifier --source {0} "
277            "--name {1} --type tempest"
278            .format(CONST.dir_repo_tempest, CONST.tempest_deployment_name))
279     ft_utils.execute_command(cmd,
280                              error_msg="Problem while installing Tempest.")
281
282
283 def create_flavor():
284     os_utils.get_or_create_flavor('m1.tiny',
285                                   '512',
286                                   '1',
287                                   '1',
288                                   public=True)
289
290
291 def check_environment():
292     msg_not_active = "The Functest environment is not installed."
293     if not os.path.isfile(CONST.env_active):
294         raise Exception(msg_not_active)
295
296     with open(CONST.env_active, "r") as env_file:
297         s = env_file.read()
298         if not re.search("1", s):
299             raise Exception(msg_not_active)
300
301     logger.info("Functest environment is installed.")
302
303
304 def main(**kwargs):
305     try:
306         if not (kwargs['action'] in actions):
307             logger.error('Argument not valid.')
308             return -1
309         elif kwargs['action'] == "start":
310             logger.info("######### Preparing Functest environment #########\n")
311             check_env_variables()
312             print_deployment_info()
313             create_directories()
314             source_rc_file()
315             patch_config_file()
316             verify_deployment()
317             install_rally()
318             install_tempest()
319             create_flavor()
320             with open(CONST.env_active, "w") as env_file:
321                 env_file.write("1")
322             check_environment()
323         elif kwargs['action'] == "check":
324             check_environment()
325     except Exception as e:
326         logger.error(e)
327         return -1
328     return 0
329
330
331 if __name__ == '__main__':
332     parser = PrepareEnvParser()
333     args = parser.parse_args(sys.argv[1:])
334     sys.exit(main(**args))