Remove OS_REGION_NAME from OpenStack credentials check
[functest.git] / testcases / config_functest.py
1 #!/usr/bin/env python
2 #
3 # Copyright (c) 2015 Ericsson
4 # jose.lausuch@ericsson.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
11 import re, json, os, urllib2, argparse, logging, shutil, subprocess, yaml, sys, getpass
12 import functest_utils
13 from git import Repo
14 from os import stat
15 from pwd import getpwuid
16
17 actions = ['start', 'check', 'clean']
18 parser = argparse.ArgumentParser()
19 parser.add_argument("repo_path", help="Path to the repository")
20 parser.add_argument("action", help="Possible actions are: '{d[0]}|{d[1]}|{d[2]}' ".format(d=actions))
21 parser.add_argument("-d", "--debug", help="Debug mode",  action="store_true")
22 parser.add_argument("-f", "--force", help="Force",  action="store_true")
23 args = parser.parse_args()
24
25
26 """ logging configuration """
27 logger = logging.getLogger('config_functest')
28 logger.setLevel(logging.DEBUG)
29
30 ch = logging.StreamHandler()
31 if args.debug:
32     ch.setLevel(logging.DEBUG)
33 else:
34     ch.setLevel(logging.INFO)
35
36 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
37 ch.setFormatter(formatter)
38 logger.addHandler(ch)
39
40 if not os.path.exists(args.repo_path):
41     logger.error("Repo directory not found '%s'" % args.repo_path)
42     exit(-1)
43
44 with open(args.repo_path+"testcases/config_functest.yaml") as f:
45     functest_yaml = yaml.safe_load(f)
46 f.close()
47
48
49
50
51 """ global variables """
52 # Directories
53 HOME = os.environ['HOME']+"/"
54 REPO_PATH = args.repo_path
55 RALLY_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_rally")
56 RALLY_REPO_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_repo")
57 RALLY_INSTALLATION_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_inst")
58 RALLY_RESULT_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_res")
59 VPING_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_vping")
60 ODL_DIR = REPO_PATH + functest_yaml.get("general").get("directories").get("dir_odl")
61
62
63 #GLANCE image parameters
64 IMAGE_URL = functest_yaml.get("general").get("openstack").get("image_url")
65 IMAGE_DISK_FORMAT = functest_yaml.get("general").get("openstack").get("image_disk_format")
66 IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name")
67 IMAGE_FILE_NAME = IMAGE_URL.rsplit('/')[-1]
68 IMAGE_DIR = HOME + functest_yaml.get("general").get("openstack").get("image_download_path")
69 IMAGE_PATH = IMAGE_DIR + IMAGE_FILE_NAME
70
71
72 def action_start():
73     """
74     Start the functest environment installation
75     """
76     if not check_permissions():
77         logger.error("Bad Python cache directory ownership.")
78         exit(-1)
79
80     if not functest_utils.check_internet_connectivity():
81         logger.error("There is no Internet connectivity. Please check the network configuration.")
82         exit(-1)
83
84     if action_check():
85         logger.info("Functest environment already installed. Nothing to do.")
86         exit(0)
87
88     else:
89         # Clean in case there are left overs
90         logger.debug("Cleaning possible functest environment leftovers.")
91         action_clean()
92
93         logger.info("Installing ODL environment...")
94         if not install_odl():
95             logger.error("There has been a problem while installing Robot.")
96             action_clean()
97             exit(-1)
98
99         logger.info("Starting installation of functest environment")
100         logger.info("Installing Rally...")
101         if not install_rally():
102             logger.error("There has been a problem while installing Rally.")
103             action_clean()
104             exit(-1)
105
106         # Create result folder under functest if necessary
107         if not os.path.exists(RALLY_RESULT_DIR):
108             os.makedirs(RALLY_RESULT_DIR)
109
110         logger.info("Downloading image...")
111         if not functest_utils.download_url(IMAGE_URL, IMAGE_DIR):
112             logger.error("There has been a problem downloading the image '%s'." %IMAGE_URL)
113             action_clean()
114             exit(-1)
115
116         logger.info("Creating Glance image: %s ..." %IMAGE_NAME)
117         if not create_glance_image(IMAGE_PATH,IMAGE_NAME,IMAGE_DISK_FORMAT):
118             logger.error("There has been a problem while creating the Glance image.")
119             action_clean()
120             exit(-1)
121
122         exit(0)
123
124
125 def action_check():
126     """
127     Check if the functest environment is properly installed
128     """
129     errors_all = False
130
131     logger.info("Checking current functest configuration...")
132
133     logger.debug("Checking script directories...")
134     errors = False
135     dirs = [RALLY_DIR, RALLY_INSTALLATION_DIR, VPING_DIR, ODL_DIR]
136     for dir in dirs:
137         if not os.path.exists(dir):
138             logger.debug("The directory '%s' does NOT exist." % dir)
139             errors = True
140             errors_all = True
141         else:
142             logger.debug("   %s found" % dir)
143     if not errors:
144         logger.debug("...OK")
145     else:
146         logger.debug("...FAIL")
147
148
149     logger.debug("Checking Rally deployment...")
150     if not check_rally():
151         logger.debug("   Rally deployment NOT installed.")
152         errors_all = True
153         logger.debug("...FAIL")
154     else:
155         logger.debug("...OK")
156
157     logger.debug("Checking Image...")
158     errors = False
159     if not os.path.isfile(IMAGE_PATH):
160         logger.debug("   Image file '%s' NOT found." % IMAGE_PATH)
161         errors = True
162         errors_all = True
163     else:
164         logger.debug("   Image file found in %s" % IMAGE_PATH)
165
166     cmd="glance image-list | grep " + IMAGE_NAME
167     FNULL = open(os.devnull, 'w');
168     logger.debug('   Executing command : {}'.format(cmd))
169     p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
170     #if the command does not exist or there is no glance image
171     line = p.stdout.readline()
172     if line == "":
173         logger.debug("   Glance image NOT found.")
174         errors = True
175         errors_all = True
176     else:
177         logger.debug("   Glance image found.")
178
179     if not errors:
180         logger.debug("...OK")
181     else:
182         logger.debug("...FAIL")
183
184     #TODO: check OLD environment setup
185     if errors_all:
186         return False
187     else:
188         return True
189
190
191
192
193 def action_clean():
194     """
195     Clean the existing functest environment
196     """
197     logger.info("Removing current functest environment...")
198     if os.path.exists(RALLY_INSTALLATION_DIR):
199         logger.debug("Removing Rally installation directory %s" % RALLY_INSTALLATION_DIR)
200         shutil.rmtree(RALLY_INSTALLATION_DIR,ignore_errors=True)
201
202     if os.path.exists(RALLY_REPO_DIR):
203         logger.debug("Removing Rally repository %s" % RALLY_REPO_DIR)
204         cmd = "sudo rm -rf " + RALLY_REPO_DIR #need to be sudo, not possible with rmtree
205         functest_utils.execute_command(cmd,logger)
206
207     if os.path.exists(IMAGE_PATH):
208         logger.debug("Deleting image")
209         os.remove(IMAGE_PATH)
210
211     cmd = "glance image-list | grep "+IMAGE_NAME+" | cut -c3-38"
212     p = os.popen(cmd,"r")
213
214     #while image_id = p.readline()
215     for image_id in p.readlines():
216         cmd = "glance image-delete " + image_id
217         functest_utils.execute_command(cmd,logger)
218
219     if os.path.exists(RALLY_RESULT_DIR):
220         logger.debug("Removing Result directory")
221         shutil.rmtree(RALLY_RESULT_DIR,ignore_errors=True)
222
223
224     logger.info("Functest environment clean!")
225
226
227
228 def check_permissions():
229     current_user = getpass.getuser()
230     cache_dir = HOME+".cache/pip"
231     logger.info("Checking permissions of '%s'..." %cache_dir)
232     logger.debug("Current user is '%s'" %current_user)
233     cache_user = getpwuid(stat(cache_dir).st_uid).pw_name
234     logger.debug("Cache directory owner is '%s'" %cache_user)
235     if cache_user != current_user:
236         logger.info("The owner of '%s' is '%s'. Please run 'sudo chown -R %s %s'." %(cache_dir, cache_user, current_user, cache_dir))
237         return False
238
239     return True
240
241
242 def install_rally():
243     if check_rally():
244         logger.info("Rally is already installed.")
245     else:
246         logger.debug("Cloning repository...")
247         url = "https://git.openstack.org/openstack/rally"
248         Repo.clone_from(url, RALLY_REPO_DIR)
249
250         logger.debug("Executing %s./install_rally.sh..." %RALLY_REPO_DIR)
251         install_script = RALLY_REPO_DIR + "install_rally.sh"
252         cmd = 'sudo ' + install_script
253         functest_utils.execute_command(cmd,logger)
254
255         logger.debug("Creating Rally environment...")
256         cmd = "rally deployment create --fromenv --name=opnfv-arno-rally"
257         functest_utils.execute_command(cmd,logger)
258
259         logger.debug("Installing tempest...")
260         cmd = "rally-manage tempest install"
261         functest_utils.execute_command(cmd,logger)
262
263         cmd = "rally deployment check"
264         functest_utils.execute_command(cmd,logger)
265         #TODO: check that everything is 'Available' and warn if not
266
267         cmd = "rally show images"
268         functest_utils.execute_command(cmd,logger)
269
270         cmd = "rally show flavors"
271         functest_utils.execute_command(cmd,logger)
272
273     return True
274
275
276
277 def check_rally():
278     """
279     Check if Rally is installed and properly configured
280     """
281     if os.path.exists(RALLY_INSTALLATION_DIR):
282         logger.debug("   Rally installation directory found in %s" % RALLY_INSTALLATION_DIR)
283         FNULL = open(os.devnull, 'w');
284         cmd="rally deployment list | grep opnfv";
285         logger.debug('   Executing command : {}'.format(cmd))
286         p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
287         #if the command does not exist or there is no deployment
288         line = p.stdout.readline()
289         if line == "":
290             logger.debug("   Rally deployment NOT found")
291             return False
292         logger.debug("   Rally deployment found")
293         return True
294     else:
295         return False
296
297
298 def install_odl():
299     cmd = "chmod +x " + ODL_DIR + "start_tests.sh"
300     functest_utils.execute_command(cmd,logger)
301     cmd = "chmod +x " + ODL_DIR + "create_venv.sh"
302     functest_utils.execute_command(cmd,logger)
303     cmd = ODL_DIR + "create_venv.sh"
304     functest_utils.execute_command(cmd,logger)
305     return True
306
307
308
309 def create_glance_image(path,name,disk_format):
310     """
311     Create a glance image given the absolute path of the image, its name and the disk format
312     """
313     cmd = "glance image-create --name "+name+" --is-public true --disk-format "+disk_format+" --container-format bare --file "+path
314     functest_utils.execute_command(cmd,logger)
315     return True
316
317
318
319
320 def main():
321     if not (args.action in actions):
322         logger.error('argument not valid')
323         exit(-1)
324
325
326     if not functest_utils.check_credentials():
327         logger.error("Please source the openrc credentials and run the script again.")
328         #TODO: source the credentials in this script
329         exit(-1)
330
331     if args.action == "start":
332         action_start()
333
334     if args.action == "check":
335         if action_check():
336             logger.info("Functest environment correctly installed")
337         else:
338             logger.info("Functest environment not found or faulty")
339
340     if args.action == "clean":
341         if args.force :
342             action_clean()
343         else :
344             while True:
345                 print("Are you sure? [y|n]")
346                 answer = raw_input("")
347                 if answer == "y":
348                     action_clean()
349                     break
350                 elif answer == "n":
351                     break
352                 else:
353                     print("Invalid option.")
354     exit(0)
355
356
357 if __name__ == '__main__':
358     main()
359