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
11 import re, json, os, urllib2, argparse, logging, shutil, subprocess
14 actions = ['start', 'check', 'clean']
16 """ global variables """
17 functest_dir = os.environ['HOME'] + '/.functest/'
18 #image_url = 'https://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-disk1.img'
19 image_url = 'http://download.cirros-cloud.net/0.3.0/cirros-0.3.0-i386-disk.img'
21 image_disk_format = 'raw'
22 image_name = image_url.rsplit('/')[-1]
23 image_path = functest_dir + image_name
24 rally_repo_dir = functest_dir + "Rally_repo/"
25 rally_test_dir = functest_dir + "Rally_test/"
26 bench_tests_dir = rally_test_dir + "scenarios/"
27 rally_installation_dir = os.environ['HOME'] + "/.rally"
28 vPing_dir = functest_dir + "vPing/"
29 odl_dir = functest_dir + "ODL/"
32 parser = argparse.ArgumentParser()
33 parser.add_argument("action", help="Possible actions are: '{d[0]}|{d[1]}|{d[2]}' ".format(d=actions))
34 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
35 args = parser.parse_args()
38 """ logging configuration """
39 logger = logging.getLogger('config_functest')
40 logger.setLevel(logging.DEBUG)
42 ch = logging.StreamHandler()
44 ch.setLevel(logging.DEBUG)
46 ch.setLevel(logging.INFO)
48 formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
49 ch.setFormatter(formatter)
54 def config_functest_start():
56 Start the functest environment installation
58 if config_functest_check():
59 logger.info("Functest environment already installed in %s. Nothing to do." %functest_dir)
61 elif not check_internet_connectivity():
62 logger.error("There is no Internet connectivity. Please check the network configuration.")
64 elif not check_credentials():
65 logger.error("Please source the openrc credentials and run the script again.")
66 #TODO: source the credentials in this script
69 config_functest_clean()
71 logger.info("Starting installationg of functest environment in %s" %functest_dir)
72 os.makedirs(functest_dir)
73 if not os.path.exists(functest_dir):
74 logger.error("There has been a problem while creating the environment directory.")
77 logger.info("Donwloading test scripts and scenarios...")
78 if not download_tests():
79 logger.error("There has been a problem while downloading the test scripts and scenarios.")
80 config_functest_clean()
83 logger.info("Installing Rally...")
84 if not install_rally():
85 logger.error("There has been a problem while installing Rally.")
86 config_functest_clean()
89 logger.info("Installing ODL environment...")
91 logger.error("There has been a problem while installing Robot.")
92 config_functest_clean()
95 logger.info("Donwloading image...")
96 if not download_url_with_progress(image_url, functest_dir):
97 logger.error("There has been a problem while downloading the image.")
98 config_functest_clean()
101 logger.info("Creating Glance image: %s ..." %image_name)
102 if not create_glance_image(image_path,image_name,image_disk_format):
103 logger.error("There has been a problem while creating the Glance image.")
104 config_functest_clean()
111 def config_functest_check():
113 Check if the functest environment is properly installed
115 logger.info("Checking current functest configuration...")
117 logger.debug("Checking directories...")
118 dirs = [functest_dir, rally_installation_dir, rally_repo_dir, rally_test_dir, bench_tests_dir, vPing_dir, odl_dir]
120 if not os.path.exists(dir):
121 logger.debug("The directory %s does not exist." %dir)
123 logger.debug(" %s found" % dir)
125 logger.debug("...OK")
126 logger.debug("Checking Rally deployment...")
127 if not check_rally():
128 logger.debug("Rally deployment not found.")
130 logger.debug("...OK")
132 logger.debug("Checking Image...")
133 if not os.path.isfile(image_path):
135 logger.debug(" Image file found in %s" %image_path)
137 cmd="glance image-list | grep " + image_name
138 FNULL = open(os.devnull, 'w');
139 logger.debug(' Executing command : {}'.format(cmd))
140 p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
141 #if the command does not exist or there is no glance image
142 line = p.stdout.readline()
144 logger.debug(" Glance image not found")
146 logger.debug(" Glance image found")
147 logger.debug("...OK")
149 #TODO: check OLD environment setup
156 def config_functest_clean():
158 Clean the existing functest environment
160 logger.info("Removing current functest environment...")
161 if os.path.exists(rally_installation_dir):
162 logger.debug("Removing rally installation directory %s" % rally_installation_dir)
163 shutil.rmtree(rally_installation_dir,ignore_errors=True)
165 if os.path.exists(functest_dir):
166 logger.debug("Removing functest directory %s" % functest_dir)
167 cmd = "sudo rm -rf " + functest_dir #need to be sudo, not possible with rmtree
170 logger.debug("Deleting glance images")
171 cmd = "glance image-list | grep "+image_name+" | cut -c3-38"
172 p = os.popen(cmd,"r")
174 #while image_id = p.readline()
175 for image_id in p.readlines():
176 cmd = "glance image-delete " + image_id
184 logger.info("Rally is already installed.")
186 logger.debug("Cloning repository...")
187 url = "https://git.openstack.org/openstack/rally"
188 Repo.clone_from(url, rally_repo_dir)
190 logger.debug("Executing %s./install_rally.sh..." %rally_repo_dir)
191 install_script = rally_repo_dir + "install_rally.sh"
192 cmd = 'sudo ' + install_script
194 #subprocess.call(['sudo', install_script])
196 logger.debug("Creating Rally environment...")
197 cmd = "rally deployment create --fromenv --name=opnfv-arno-rally"
200 logger.debug("Installing tempest...")
201 cmd = "rally-manage tempest install"
204 cmd = "rally deployment check"
206 #TODO: check that everything is 'Available' and warn if not
208 cmd = "rally show images"
211 cmd = "rally show flavors"
220 Check if Rally is installed and properly configured
222 if os.path.exists(rally_installation_dir):
223 logger.debug(" Rally installation directory found in %s" % rally_installation_dir)
224 FNULL = open(os.devnull, 'w');
225 cmd="rally deployment list | grep opnfv";
226 logger.debug(' Executing command : {}'.format(cmd))
227 p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
228 #if the command does not exist or there is no deployment
229 line = p.stdout.readline()
231 logger.debug(" Rally deployment not found")
233 logger.debug(" Rally deployment found")
236 logger.debug(" Rally installation directory not found")
241 cmd = "chmod +x " + odl_dir + "create_venv.sh"
243 cmd = odl_dir + "create_venv.sh"
248 def check_credentials():
250 Check if the OpenStack credentials (openrc) are sourced
252 #TODO: there must be a short way to do this, doing if os.environ["something"] == "" throws an error
254 os.environ['OS_AUTH_URL']
258 os.environ['OS_USERNAME']
262 os.environ['OS_PASSWORD']
266 os.environ['OS_TENANT_NAME']
270 os.environ['OS_REGION_NAME']
276 def download_tests():
277 os.makedirs(vPing_dir)
279 os.makedirs(bench_tests_dir)
281 logger.info("Downloading vPing test...")
282 vPing_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/vPing/CI/libraries/vPing.py'
283 if not download_url(vPing_url,vPing_dir):
287 logger.info("Downloading Rally bench tests...")
288 run_rally_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/libraries/run_rally.py'
289 if not download_url(run_rally_url,rally_test_dir):
292 rally_bench_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/suites/'
293 bench_tests = ['authenticate', 'cinder', 'glance', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'tempest', 'vm']
294 for i in bench_tests:
295 rally_bench_url = rally_bench_base_url + "opnfv-" + i + ".json"
296 logger.debug("Downloading %s" %rally_bench_url)
297 if not download_url(rally_bench_url,bench_tests_dir):
300 logger.info("Downloading OLD tests...")
301 odl_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/Controllers/ODL/CI/'
302 odl_tests = ['create_venv.sh', 'requirements.pip', 'start_tests.sh', 'test_list.txt']
304 odl_url = odl_base_url + i
305 logger.debug("Downloading %s" %odl_url)
306 if not download_url(odl_url,odl_dir):
313 def create_glance_image(path,name,disk_format):
315 Create a glance image given the absolute path of the image, its name and the disk format
317 cmd = "glance image-create --name "+name+" --is-public true --disk-format "+disk_format+" --container-format bare --file "+path
322 def download_url(url, dest_path):
324 Download a file to a destination path given a URL
326 name = url.rsplit('/')[-1]
327 dest = dest_path + name
329 response = urllib2.urlopen(url)
330 except (urllib2.HTTPError, urllib2.URLError):
331 logger.error("Error in fetching %s" %url)
334 with open(dest, 'wb') as f:
335 f.write(response.read())
339 def download_url_with_progress(url, dest_path):
341 Download a file to a destination path given a URL showing the progress
343 name = url.rsplit('/')[-1]
344 dest = dest_path + name
346 response = urllib2.urlopen(url)
347 except (urllib2.HTTPError, urllib2.URLError):
348 logger.error("Error in fetching %s" %url)
352 meta = response.info()
353 file_size = int(meta.getheaders("Content-Length")[0])
354 logger.info("Downloading: %s Bytes: %s" %(dest, file_size))
359 buffer = response.read(block_sz)
363 file_size_dl += len(buffer)
365 status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
366 status = status + chr(8)*(len(status)+1)
374 def check_internet_connectivity(url='http://www.google.com/'):
376 Check if there is access to the internet
379 urllib2.urlopen(url, timeout=5)
381 except urllib.request.URLError:
384 def execute_command(cmd):
386 Execute Linux command
388 logger.debug('Executing command : {}'.format(cmd))
389 #p = os.popen(cmd,"r")
390 #logger.debug(p.read())
391 output_file = "/tmp/output.txt"
392 f = open(output_file, 'w+')
393 p = subprocess.call(cmd,shell=True, stdout=f, stderr=subprocess.STDOUT)
395 f = open(output_file, 'r')
396 logger.debug(f.read())
397 #p = subprocess.call(cmd,shell=True);
401 logger.error("Error when executing command %s" %cmd)
408 if not (args.action in actions):
409 logger.error('argument not valid')
412 if args.action == "start":
413 config_functest_start()
415 if args.action == "check":
416 if config_functest_check():
417 logger.info("Functest environment correctly installed")
419 logger.info("Functest environment not found or faulty")
421 if args.action == "clean":
423 print("Are you sure? [y|n]")
424 answer = raw_input("")
426 config_functest_clean()
431 print("Invalid option.")
435 if __name__ == '__main__':