change default image name for bench testing
[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
12 from git import Repo
13
14 from neutronclient.v2_0 import client
15
16 actions = ['start', 'check', 'clean']
17
18
19
20 parser = argparse.ArgumentParser()
21 parser.add_argument("action", help="Possible actions are: '{d[0]}|{d[1]}|{d[2]}' ".format(d=actions))
22 parser.add_argument("-d", "--debug", help="Debug mode",  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
41
42 yaml_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/functest.yaml'
43 name = yaml_url.rsplit('/')[-1]
44 dest = "./" + name
45 if not os.path.exists(dest):
46     logger.info("Downloading functest.yaml...")
47     try:
48         response = urllib2.urlopen(yaml_url)
49     except (urllib2.HTTPError, urllib2.URLError):
50         logger.error("Error in fetching %s" %yaml_url)
51         exit(-1)
52     with open(dest, 'wb') as f:
53         f.write(response.read())
54     logger.info("functest.yaml stored in %s" % dest)
55 else:
56     logger.info("functest.yaml found in %s" % dest)
57
58
59 with open('./functest.yaml') as f:
60     functest_yaml = yaml.safe_load(f)
61 f.close()
62
63
64 """ global variables """
65 # Directories
66 HOME = os.environ['HOME']+"/"
67 FUNCTEST_BASE_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_functest")
68 RALLY_REPO_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_repo")
69 RALLY_TEST_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally")
70 RALLY_INSTALLATION_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_inst")
71 BENCH_TESTS_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_rally_scn")
72 VPING_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_vping")
73 ODL_DIR = HOME + functest_yaml.get("general").get("directories").get("dir_odl")
74
75 # NEUTRON Public Network parameters
76 NEUTRON_PUBLIC_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_public_net_name")
77 NEUTRON_PUBLIC_SUBNET_NAME = functest_yaml.get("general").get("openstack").get("neutron_public_subnet_name")
78 NEUTRON_PUBLIC_SUBNET_CIDR = functest_yaml.get("general").get("openstack").get("neutron_public_subnet_cidr")
79 NEUTRON_PUBLIC_SUBNET_START = functest_yaml.get("general").get("openstack").get("neutron_public_subnet_start")
80 NEUTRON_PUBLIC_SUBNET_END = functest_yaml.get("general").get("openstack").get("neutron_public_subnet_end")
81
82 # NEUTRON Private Network parameters
83 NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_net_name")
84 NEUTRON_PRIVATE_SUBNET_NAME = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_name")
85 NEUTRON_PRIVATE_SUBNET_CIDR = functest_yaml.get("general").get("openstack").get("neutron_private_subnet_cidr")
86 ROUTER_NAME = functest_yaml.get("general").get("openstack").get("neutron_router_name")
87
88 #GLANCE image parameters
89 IMAGE_URL = functest_yaml.get("general").get("openstack").get("image_url")
90 IMAGE_DISK_FORMAT = functest_yaml.get("general").get("openstack").get("image_disk_format")
91 IMAGE_NAME = functest_yaml.get("general").get("openstack").get("image_name")
92 IMAGE_FILE_NAME = IMAGE_URL.rsplit('/')[-1]
93 IMAGE_DOWNLOAD_PATH = FUNCTEST_BASE_DIR + IMAGE_FILE_NAME
94
95 credentials = None
96 neutron_client = None
97
98 def config_functest_start():
99     """
100     Start the functest environment installation
101     """
102
103     if config_functest_check():
104         logger.info("Functest environment already installed in %s. Nothing to do." %FUNCTEST_BASE_DIR)
105         exit(0)
106
107     if not check_internet_connectivity():
108         logger.error("There is no Internet connectivity. Please check the network configuration.")
109         exit(-1)
110     elif not check_credentials():
111         logger.error("Please source the openrc credentials and run the script again.")
112         #TODO: source the credentials in this script
113         exit(-1)
114
115     else:
116         # Clean in case there are left overs
117
118         config_functest_clean()
119
120         logger.info("Starting installationg of functest environment in %s" % FUNCTEST_BASE_DIR)
121         os.makedirs(FUNCTEST_BASE_DIR)
122         if not os.path.exists(FUNCTEST_BASE_DIR):
123             logger.error("There has been a problem while creating the environment directory.")
124             exit(-1)
125
126         logger.info("Donwloading test scripts and scenarios...")
127         if not download_tests():
128             logger.error("There has been a problem while downloading the test scripts and scenarios.")
129             config_functest_clean()
130             exit(-1)
131
132         logger.info("Installing Rally...")
133         if not install_rally():
134             logger.error("There has been a problem while installing Rally.")
135             config_functest_clean()
136             exit(-1)
137
138         logger.info("Installing ODL environment...")
139         if not install_odl():
140             logger.error("There has been a problem while installing Robot.")
141             config_functest_clean()
142             exit(-1)
143
144         credentials = get_credentials()
145         neutron_client = client.Client(**credentials)
146
147         logger.info("Configuring Neutron...")
148         logger.info("Checking if public network '%s' exists..." % NEUTRON_PUBLIC_NET_NAME)
149         #Now: if exists we don't create it again (the clean command does not clean the neutron networks yet)
150         if check_neutron_net(neutron_client, NEUTRON_PUBLIC_NET_NAME):
151             logger.info("Public network '%s' found. No need to create another one." % NEUTRON_PUBLIC_NET_NAME)
152         else:
153             logger.info("Public network '%s' not found. Creating..." % NEUTRON_PUBLIC_NET_NAME)
154             if not create_public_neutron_net(neutron_client):
155                 logger.error("There has been a problem while creating the Neutron network.")
156                 #config_functest_clean()
157                 exit(-1)
158
159
160         logger.info("Checking if private network '%s' exists..." % NEUTRON_PRIVATE_NET_NAME)
161         #Now: if exists we don't create it again (the clean command does not clean the neutron networks yet)
162         if check_neutron_net(neutron_client, NEUTRON_PRIVATE_NET_NAME):
163             logger.info("Private network '%s' found. No need to create another one." % NEUTRON_PRIVATE_NET_NAME)
164         else:
165             logger.info("Private network '%s' not found. Creating..." % NEUTRON_PRIVATE_NET_NAME)
166             if not create_private_neutron_net(neutron_client):
167                 logger.error("There has been a problem while creating the Neutron network.")
168                 #config_functest_clean()
169                 exit(-1)
170
171
172         logger.info("Donwloading image...")
173         if not download_url_with_progress(IMAGE_URL, FUNCTEST_BASE_DIR):
174             logger.error("There has been a problem while downloading the image.")
175             config_functest_clean()
176             exit(-1)
177
178         logger.info("Creating Glance image: %s ..." %IMAGE_NAME)
179         if not create_glance_image(IMAGE_DOWNLOAD_PATH,IMAGE_NAME,IMAGE_DISK_FORMAT):
180             logger.error("There has been a problem while creating the Glance image.")
181             config_functest_clean()
182             exit(-1)
183
184         exit(0)
185
186
187
188 def config_functest_check():
189     """
190     Check if the functest environment is properly installed
191     """
192     errors_all = False
193
194     logger.info("Checking current functest configuration...")
195     credentials = get_credentials()
196     neutron_client = client.Client(**credentials)
197
198     logger.debug("Checking directories...")
199     errors = False
200     dirs = [FUNCTEST_BASE_DIR, RALLY_INSTALLATION_DIR, RALLY_REPO_DIR, RALLY_TEST_DIR, BENCH_TESTS_DIR, VPING_DIR, ODL_DIR]
201     for dir in dirs:
202         if not os.path.exists(dir):
203             logger.debug("The directory '%s' does NOT exist." % dir)
204             errors = True
205             errors_all = True
206         else:
207             logger.debug("   %s found" % dir)
208     if not errors:
209         logger.debug("...OK")
210     else:
211         logger.debug("...FAIL")
212
213
214     logger.debug("Checking Rally deployment...")
215     if not check_rally():
216         logger.debug("Rally deployment NOT found.")
217         errors_all = True
218         logger.debug("...FAIL")
219     else:
220         logger.debug("...OK")
221
222
223     logger.debug("Checking Neutron...")
224     errors = False
225     if not check_neutron_net(neutron_client, NEUTRON_PRIVATE_NET_NAME):
226         logger.debug("   Private network '%s' NOT found." % NEUTRON_PRIVATE_NET_NAME)
227         errors = True
228         errors_all = True
229     else:
230         logger.debug("   Private network '%s' found." % NEUTRON_PRIVATE_NET_NAME)
231
232     if not check_neutron_net(neutron_client, NEUTRON_PUBLIC_NET_NAME):
233         logger.debug("   Public network '%s' NOT found." % NEUTRON_PUBLIC_NET_NAME)
234         errors = True
235         errors_all = True
236     else:
237         logger.debug("   Public network '%s' found." % NEUTRON_PUBLIC_NET_NAME)
238
239     if not errors:
240         logger.debug("...OK")
241     else:
242         logger.debug("...FAIL")
243
244
245     logger.debug("Checking Image...")
246     errors = False
247     if not os.path.isfile(IMAGE_DOWNLOAD_PATH):
248         logger.debug("   Image file '%s' NOT found." % IMAGE_DOWNLOAD_PATH)
249         errors = True
250         errors_all = True
251     else:
252         logger.debug("   Image file found in %s" % IMAGE_DOWNLOAD_PATH)
253
254     cmd="glance image-list | grep " + IMAGE_NAME
255     FNULL = open(os.devnull, 'w');
256     logger.debug('   Executing command : {}'.format(cmd))
257     p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
258     #if the command does not exist or there is no glance image
259     line = p.stdout.readline()
260     if line == "":
261         logger.debug("   Glance image NOT found.")
262         errors = True
263         errors_all = True
264     else:
265         logger.debug("   Glance image found.")
266
267     if not errors:
268         logger.debug("...OK")
269     else:
270         logger.debug("...FAIL")
271
272     #TODO: check OLD environment setup
273     if errors_all:
274         return False
275     else:
276         return True
277
278
279
280
281 def config_functest_clean():
282     """
283     Clean the existing functest environment
284     """
285     logger.info("Removing current functest environment...")
286     if os.path.exists(RALLY_INSTALLATION_DIR):
287         logger.debug("Removing rally installation directory %s" % RALLY_INSTALLATION_DIR)
288         shutil.rmtree(RALLY_INSTALLATION_DIR,ignore_errors=True)
289
290     if os.path.exists(FUNCTEST_BASE_DIR):
291         logger.debug("Removing functest directory %s" % FUNCTEST_BASE_DIR)
292         cmd = "sudo rm -rf " + FUNCTEST_BASE_DIR #need to be sudo, not possible with rmtree
293         execute_command(cmd)
294
295     #logger.debug("Deleting Neutron network %s" % NEUTRON_PRIVATE_NET_NAME)
296     #if not delete_neutron_net() :
297     #    logger.error("Error deleting the network. Remove it manually.")
298
299     logger.debug("Deleting glance images")
300     cmd = "glance image-list | grep "+IMAGE_NAME+" | cut -c3-38"
301     p = os.popen(cmd,"r")
302
303     #while image_id = p.readline()
304     for image_id in p.readlines():
305         cmd = "glance image-delete " + image_id
306         execute_command(cmd)
307
308     return True
309
310
311
312
313
314 def install_rally():
315     if check_rally():
316         logger.info("Rally is already installed.")
317     else:
318         logger.debug("Cloning repository...")
319         url = "https://git.openstack.org/openstack/rally"
320         Repo.clone_from(url, RALLY_REPO_DIR)
321
322         logger.debug("Executing %s./install_rally.sh..." %RALLY_REPO_DIR)
323         install_script = RALLY_REPO_DIR + "install_rally.sh"
324         cmd = 'sudo ' + install_script
325         execute_command(cmd)
326         #subprocess.call(['sudo', install_script])
327
328         logger.debug("Creating Rally environment...")
329         cmd = "rally deployment create --fromenv --name=opnfv-arno-rally"
330         execute_command(cmd)
331
332         logger.debug("Installing tempest...")
333         cmd = "rally-manage tempest install"
334         execute_command(cmd)
335
336         cmd = "rally deployment check"
337         execute_command(cmd)
338         #TODO: check that everything is 'Available' and warn if not
339
340         cmd = "rally show images"
341         execute_command(cmd)
342
343         cmd = "rally show flavors"
344         execute_command(cmd)
345
346     return True
347
348
349
350 def check_rally():
351     """
352     Check if Rally is installed and properly configured
353     """
354     if os.path.exists(RALLY_INSTALLATION_DIR):
355         logger.debug("   Rally installation directory found in %s" % RALLY_INSTALLATION_DIR)
356         FNULL = open(os.devnull, 'w');
357         cmd="rally deployment list | grep opnfv";
358         logger.debug('   Executing command : {}'.format(cmd))
359         p=subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=FNULL);
360         #if the command does not exist or there is no deployment
361         line = p.stdout.readline()
362         if line == "":
363             logger.debug("   Rally deployment not found")
364             return False
365         logger.debug("   Rally deployment found")
366         return True
367     else:
368         logger.debug("   Rally installation directory not found")
369         return False
370
371
372 def install_odl():
373     cmd = "chmod +x " + ODL_DIR + "create_venv.sh"
374     execute_command(cmd)
375     cmd = ODL_DIR + "create_venv.sh"
376     execute_command(cmd)
377     return True
378
379
380 def check_credentials():
381     """
382     Check if the OpenStack credentials (openrc) are sourced
383     """
384     #TODO: there must be a short way to do this, doing if os.environ["something"] == "" throws an error
385     try:
386        os.environ['OS_AUTH_URL']
387     except KeyError:
388         return False
389     try:
390        os.environ['OS_USERNAME']
391     except KeyError:
392         return False
393     try:
394        os.environ['OS_PASSWORD']
395     except KeyError:
396         return False
397     try:
398        os.environ['OS_TENANT_NAME']
399     except KeyError:
400         return False
401     try:
402        os.environ['OS_REGION_NAME']
403     except KeyError:
404         return False
405     return True
406
407
408 def get_credentials():
409     d = {}
410     d['username'] = os.environ['OS_USERNAME']
411     d['password'] = os.environ['OS_PASSWORD']
412     d['auth_url'] = os.environ['OS_AUTH_URL']
413     d['tenant_name'] = os.environ['OS_TENANT_NAME']
414     return d
415
416 def get_nova_credentials():
417     d = {}
418     d['username'] = os.environ['OS_USERNAME']
419     d['api_key'] = os.environ['OS_PASSWORD']
420     d['auth_url'] = os.environ['OS_AUTH_URL']
421     d['project_id'] = os.environ['OS_TENANT_NAME']
422     return d
423
424
425 def download_tests():
426     os.makedirs(VPING_DIR)
427     os.makedirs(ODL_DIR)
428     os.makedirs(BENCH_TESTS_DIR)
429
430     logger.info("Copying functest.yaml to functest environment...")
431     try:
432         shutil.copy("./functest.yaml", FUNCTEST_BASE_DIR+"functest.yaml")
433     except:
434         print "Error copying the file:", sys.exc_info()[0]
435         return False
436
437     logger.info("Downloading vPing test...")
438     vPing_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/vPing/CI/libraries/vPing.py'
439     if not download_url(vPing_url,VPING_DIR):
440         return False
441
442
443     logger.info("Downloading Rally bench tests...")
444     run_rally_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/libraries/run_rally.py'
445     if not download_url(run_rally_url,RALLY_TEST_DIR):
446         return False
447
448     rally_bench_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/VIM/OpenStack/CI/suites/'
449     bench_tests = ['authenticate', 'cinder', 'glance', 'heat', 'keystone', 'neutron', 'nova', 'quotas', 'requests', 'tempest', 'vm']
450     for i in bench_tests:
451         rally_bench_url = rally_bench_base_url + "opnfv-" + i + ".json"
452         logger.debug("Downloading %s" %rally_bench_url)
453         if not download_url(rally_bench_url,BENCH_TESTS_DIR):
454             return False
455
456     logger.info("Downloading OLD tests...")
457     odl_base_url = 'https://git.opnfv.org/cgit/functest/plain/testcases/Controllers/ODL/CI/'
458     odl_tests = ['create_venv.sh', 'requirements.pip', 'start_tests.sh', 'test_list.txt']
459     for i in odl_tests:
460         odl_url = odl_base_url + i
461         logger.debug("Downloading %s" %odl_url)
462         if not download_url(odl_url,ODL_DIR):
463             return False
464
465     return True
466
467 def create_public_neutron_net(neutron):
468     try:
469         neutron.format = 'json'
470         logger.debug('Creating Neutron network %s...' % NEUTRON_PUBLIC_NET_NAME)
471         json_body = {'network': {'name': NEUTRON_PUBLIC_NET_NAME, 'admin_state_up': True, 'router:external': True}}
472         netw = neutron.create_network(body=json_body)
473         net_dict = netw['network']
474         network_id = net_dict['id']
475         logger.debug("Network '%s' created successfully" % network_id)
476
477         logger.debug('Creating Subnet....')
478         json_body = {'subnets': [{'cidr': NEUTRON_PUBLIC_SUBNET_CIDR,
479                            'ip_version': 4, 'network_id': network_id}]}
480         subnet = neutron.create_subnet(body=json_body)
481         logger.debug("Subnet '%s' created successfully" % subnet)
482     except:
483         print "Error:", sys.exc_info()[0]
484         return False
485
486     logger.info("Public Neutron network created successfully.")
487     return True
488
489 def create_private_neutron_net(neutron):
490     try:
491         neutron.format = 'json'
492         logger.debug('Creating Neutron network %s...' % NEUTRON_PRIVATE_NET_NAME)
493         json_body = {'network': {'name': NEUTRON_PRIVATE_NET_NAME,
494                     'admin_state_up': True}}
495         netw = neutron.create_network(body=json_body)
496         net_dict = netw['network']
497         network_id = net_dict['id']
498         logger.debug("Network '%s' created successfully" % network_id)
499
500         logger.debug('Creating Subnet....')
501         json_body = {'subnets': [{'cidr': NEUTRON_PRIVATE_SUBNET_CIDR,
502                            'ip_version': 4, 'network_id': network_id}]}
503         subnet = neutron.create_subnet(body=json_body)
504         logger.debug("Subnet '%s' created successfully" % subnet)
505
506         logger.debug('Creating Router...')
507         json_body = {'router': {'name': ROUTER_NAME, 'admin_state_up': True}}
508         router = neutron.create_router(json_body)
509         logger.debug("Router '%s' created successfully" % router)
510         router_id = router['router']['id']
511
512         logger.debug('Creating Port')
513         json_body = {'port': {
514          'admin_state_up': True,
515          'device_id': router_id,
516          'name': 'port1',
517          'network_id': network_id,
518         }}
519         response = neutron.create_port(body=json_body)
520         logger.debug("Port created successfully.")
521
522         logger.debug('Setting up gateway...')
523         public_network_id = get_network_id(neutron,NEUTRON_PUBLIC_NET_NAME)
524         json_body = {'network_id': public_network_id, 'enable_snat' :  True}
525         gateway = neutron.add_gateway_router(router_id,body=json_body)
526         logger.debug("Gateway '%s' added successfully" % gateway)
527     except:
528         print "Error:", sys.exc_info()[0]
529         return False
530
531     logger.info("Private Neutron network created successfully.")
532     return True
533
534 def get_network_id(neutron, network_name):
535     networks = neutron.list_networks()['networks']
536     id  = ''
537     for n in networks:
538         if n['name'] == network_name:
539             id = n['id']
540             break
541     return id
542
543 def check_neutron_net(neutron, net_name):
544     for network in neutron.list_networks()['networks']:
545         if network['name'] == net_name :
546             for subnet in network['subnets']:
547                 return True
548     return False
549
550 def delete_neutron_net(neutron):
551     #TODO: remove router, ports
552     try:
553         #https://github.com/isginf/openstack_tools/blob/master/openstack_remove_tenant.py
554         for network in neutron.list_networks()['networks']:
555             if network['name'] == NEUTRON_PRIVATE_NET_NAME :
556                 for subnet in network['subnets']:
557                     print "Deleting subnet " + subnet
558                     neutron.delete_subnet(subnet)
559                 print "Deleting network " + network['name']
560                 neutron.delete_neutron_net(network['id'])
561     finally:
562         return True
563     return False
564
565
566
567
568
569 def create_glance_image(path,name,disk_format):
570     """
571     Create a glance image given the absolute path of the image, its name and the disk format
572     """
573     cmd = "glance image-create --name "+name+" --is-public true --disk-format "+disk_format+" --container-format bare --file "+path
574     execute_command(cmd)
575     return True
576
577
578
579
580
581 def download_url(url, dest_path):
582     """
583     Download a file to a destination path given a URL
584     """
585     name = url.rsplit('/')[-1]
586     dest = dest_path + name
587     try:
588         response = urllib2.urlopen(url)
589     except (urllib2.HTTPError, urllib2.URLError):
590         logger.error("Error in fetching %s" %url)
591         return False
592
593     with open(dest, 'wb') as f:
594         f.write(response.read())
595     return True
596
597
598 def download_url_with_progress(url, dest_path):
599     """
600     Download a file to a destination path given a URL showing the progress
601     """
602     name = url.rsplit('/')[-1]
603     dest = dest_path + name
604     try:
605         response = urllib2.urlopen(url)
606     except (urllib2.HTTPError, urllib2.URLError):
607         logger.error("Error in fetching %s" %url)
608         return False
609
610     f = open(dest, 'wb')
611     meta = response.info()
612     file_size = int(meta.getheaders("Content-Length")[0])
613     logger.info("Downloading: %s Bytes: %s" %(dest, file_size))
614
615     file_size_dl = 0
616     block_sz = 8192
617     while True:
618         buffer = response.read(block_sz)
619         if not buffer:
620             break
621
622         file_size_dl += len(buffer)
623         f.write(buffer)
624         status = r"%10d  [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
625         status = status + chr(8)*(len(status)+1)
626         print status,
627
628     f.close()
629     print("\n")
630     return True
631
632
633 def check_internet_connectivity(url='http://www.google.com/'):
634     """
635     Check if there is access to the internet
636     """
637     try:
638         urllib2.urlopen(url, timeout=5)
639         return True
640     except urllib.request.URLError:
641         return False
642
643 def execute_command(cmd):
644     """
645     Execute Linux command
646     """
647     logger.debug('Executing command : {}'.format(cmd))
648     #p = os.popen(cmd,"r")
649     #logger.debug(p.read())
650     output_file = "/tmp/output.txt"
651     f = open(output_file, 'w+')
652     p = subprocess.call(cmd,shell=True, stdout=f, stderr=subprocess.STDOUT)
653     f.close()
654     f = open(output_file, 'r')
655     logger.debug(f.read())
656     #p = subprocess.call(cmd,shell=True);
657     if p == 0 :
658         return True
659     else:
660         logger.error("Error when executing command %s" %cmd)
661         exit(-1)
662
663
664
665
666 def main():
667     if not (args.action in actions):
668         logger.error('argument not valid')
669         exit(-1)
670
671     if args.action == "start":
672         config_functest_start()
673
674     if args.action == "check":
675         if config_functest_check():
676             logger.info("Functest environment correctly installed")
677         else:
678             logger.info("Functest environment not found or faulty")
679
680     if args.action == "clean":
681         while True:
682             print("Are you sure? [y|n]")
683             answer = raw_input("")
684             if answer == "y":
685                 config_functest_clean()
686                 break
687             elif answer == "n":
688                 break
689             else:
690                 print("Invalid option.")
691     exit(0)
692
693
694 if __name__ == '__main__':
695     main()
696