Merge "Add untracked files to ignore"
[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 import argparse
11 import logging
12 import os
13 import shutil
14 import subprocess
15 import sys
16 import yaml
17 import functest_utils
18 import openstack_utils
19 from neutronclient.v2_0 import client as neutronclient
20
21 actions = ['start', 'check', 'clean']
22 parser = argparse.ArgumentParser()
23 parser.add_argument("action", help="Possible actions are: "
24                     "'{d[0]}|{d[1]}|{d[2]}' ".format(d=actions))
25 parser.add_argument("-d", "--debug", help="Debug mode", action="store_true")
26 parser.add_argument("-f", "--force", help="Force", action="store_true")
27 args = parser.parse_args()
28
29
30 """ logging configuration """
31 logger = logging.getLogger('config_functest')
32 logger.setLevel(logging.DEBUG)
33
34 ch = logging.StreamHandler()
35 if args.debug:
36     ch.setLevel(logging.DEBUG)
37 else:
38     ch.setLevel(logging.INFO)
39
40 formatter = logging.Formatter('%(asctime)s - %(name)s - '
41                               '%(levelname)s - %(message)s')
42 ch.setFormatter(formatter)
43 logger.addHandler(ch)
44
45 REPOS_DIR = os.environ['repos_dir']
46 FUNCTEST_REPO = REPOS_DIR + '/functest/'
47 if not os.path.exists(FUNCTEST_REPO):
48     logger.error("Functest repository directory not found '%s'"
49                  % FUNCTEST_REPO)
50     exit(-1)
51 sys.path.append(FUNCTEST_REPO + "testcases/")
52
53 with open("/home/opnfv/functest/conf/config_functest.yaml") as f:
54     functest_yaml = yaml.safe_load(f)
55 f.close()
56
57
58 """ global variables """
59 # Directories
60 RALLY_DIR = FUNCTEST_REPO + functest_yaml.get("general").get(
61     "directories").get("dir_rally")
62 RALLY_REPO_DIR = functest_yaml.get("general").get(
63     "directories").get("dir_repo_rally")
64 RALLY_INSTALLATION_DIR = functest_yaml.get("general").get(
65     "directories").get("dir_rally_inst")
66 RALLY_RESULT_DIR = functest_yaml.get("general").get(
67     "directories").get("dir_rally_res")
68 TEMPEST_REPO_DIR = functest_yaml.get("general").get(
69     "directories").get("dir_repo_tempest")
70 VPING_DIR = FUNCTEST_REPO + functest_yaml.get("general").get(
71     "directories").get("dir_vping")
72 ODL_DIR = FUNCTEST_REPO + functest_yaml.get("general").get(
73     "directories").get("dir_odl")
74 DATA_DIR = functest_yaml.get("general").get(
75     "directories").get("dir_functest_data")
76
77 # Tempest/Rally configuration details
78 DEPLOYMENT_MAME = functest_yaml.get("rally").get("deployment_name")
79
80 # Image (cirros)
81 IMAGE_FILE_NAME = functest_yaml.get("general").get("openstack").get(
82     "image_file_name")
83 IMAGE_PATH = DATA_DIR + "/" + IMAGE_FILE_NAME
84
85 # NEUTRON Private Network parameters
86 NEUTRON_PRIVATE_NET_NAME = functest_yaml.get("general").get(
87     "openstack").get("neutron_private_net_name")
88 NEUTRON_PRIVATE_SUBNET_NAME = functest_yaml.get("general").get(
89     "openstack").get("neutron_private_subnet_name")
90 NEUTRON_PRIVATE_SUBNET_CIDR = functest_yaml.get("general").get(
91     "openstack").get("neutron_private_subnet_cidr")
92 NEUTRON_ROUTER_NAME = functest_yaml.get("general").get(
93     "openstack").get("neutron_router_name")
94
95 creds_neutron = openstack_utils.get_credentials("neutron")
96 neutron_client = neutronclient.Client(**creds_neutron)
97
98
99 def action_start():
100     """
101     Start the functest environment installation
102     """
103     if not functest_utils.check_internet_connectivity():
104         logger.info("No Internet connectivity. "
105                     "This may affect some test case suites.")
106
107     if action_check():
108         logger.info("Functest environment already installed. Nothing to do.")
109         exit(0)
110
111     else:
112         # Clean in case there are left overs
113         logger.debug("Cleaning possible functest environment leftovers.")
114         action_clean()
115         logger.info("Starting installation of functest environment")
116
117         private_net = openstack_utils.get_private_net(neutron_client)
118         if private_net is None:
119             # If there is no private network in the deployment we create one
120             if not create_private_neutron_net(neutron_client):
121                 logger.error("There has been a problem while "
122                              "creating the functest network.")
123                 action_clean()
124                 exit(-1)
125         else:
126             logger.info("Private network '%s' already existing in "
127                         "the deployment." % private_net['name'])
128
129         logger.info("Installing Rally...")
130         if not install_rally():
131             logger.error("There has been a problem while installing Rally.")
132             action_clean()
133             exit(-1)
134
135         # Create result folder under functest if necessary
136         if not os.path.exists(RALLY_RESULT_DIR):
137             os.makedirs(RALLY_RESULT_DIR)
138
139         try:
140             logger.info("CI: Generate the list of executable tests.")
141             runnable_test = functest_utils.generateTestcaseList(functest_yaml)
142             logger.info("List of runnable tests generated: %s" % runnable_test)
143         except:
144             logger.error("Impossible to generate the list of runnable tests")
145
146         exit(0)
147
148
149 def action_check():
150     """
151     Check if the functest environment is properly installed
152     """
153     errors_all = False
154     logger.info("Checking current functest configuration...")
155
156     logger.debug("Checking script directories...")
157
158     dirs = [RALLY_DIR, RALLY_INSTALLATION_DIR, VPING_DIR, ODL_DIR]
159     for dir in dirs:
160         if not os.path.exists(dir):
161             logger.debug("   %s NOT found" % dir)
162             errors_all = True
163         else:
164             logger.debug("   %s found" % dir)
165
166     logger.debug("Checking Rally deployment...")
167     if not check_rally():
168         logger.debug("   Rally deployment NOT installed.")
169         errors_all = True
170
171     logger.debug("Checking Image...")
172     if not os.path.isfile(IMAGE_PATH):
173         logger.debug("   Image file '%s' NOT found." % IMAGE_PATH)
174         errors_all = True
175     else:
176         logger.debug("   Image file found in %s" % IMAGE_PATH)
177
178     # TODO: check OLD environment setup
179     return not errors_all
180
181
182 def action_clean():
183     """
184     Clean the existing functest environment
185     """
186     logger.info("Removing current functest environment...")
187     if os.path.exists(RALLY_INSTALLATION_DIR):
188         logger.debug("Removing Rally installation directory %s"
189                      % RALLY_INSTALLATION_DIR)
190         shutil.rmtree(RALLY_INSTALLATION_DIR, ignore_errors=True)
191
192     if os.path.exists(RALLY_RESULT_DIR):
193         logger.debug("Removing Result directory")
194         shutil.rmtree(RALLY_RESULT_DIR, ignore_errors=True)
195
196     logger.info("Functest environment clean!")
197
198
199 def install_rally():
200     if check_rally():
201         logger.info("Rally is already installed.")
202     else:
203         logger.debug("Creating Rally environment...")
204         cmd = "rally deployment create --fromenv --name=" + DEPLOYMENT_MAME
205         functest_utils.execute_command(cmd, logger)
206
207         logger.debug("Installing tempest from existing repo...")
208         cmd = ("rally verify install --source " + TEMPEST_REPO_DIR +
209                " --system-wide")
210         functest_utils.execute_command(cmd, logger)
211
212         cmd = "rally deployment check"
213         functest_utils.execute_command(cmd, logger)
214         # TODO: check that everything is 'Available' and warn if not
215
216         cmd = "rally show images"
217         functest_utils.execute_command(cmd, logger)
218
219         cmd = "rally show flavors"
220         functest_utils.execute_command(cmd, logger)
221
222     return True
223
224
225 def check_rally():
226     """
227     Check if Rally is installed and properly configured
228     """
229     if os.path.exists(RALLY_INSTALLATION_DIR):
230         logger.debug("   Rally installation directory found in %s"
231                      % RALLY_INSTALLATION_DIR)
232         FNULL = open(os.devnull, 'w')
233         cmd = "rally deployment list | grep " + DEPLOYMENT_MAME
234         logger.debug('   Executing command : {}'.format(cmd))
235         p = subprocess.Popen(cmd, shell=True,
236                              stdout=subprocess.PIPE, stderr=FNULL)
237         # if the command does not exist or there is no deployment
238         line = p.stdout.readline()
239         if line == "":
240             logger.debug("   Rally deployment NOT found")
241             return False
242         logger.debug("   Rally deployment found")
243         return True
244     else:
245         return False
246
247
248 def create_private_neutron_net(neutron):
249     neutron.format = 'json'
250     logger.info("Creating network '%s'..." % NEUTRON_PRIVATE_NET_NAME)
251     network_id = openstack_utils.create_neutron_net(
252         neutron, NEUTRON_PRIVATE_NET_NAME)
253
254     if not network_id:
255         return False
256     logger.debug("Network '%s' created successfully." % network_id)
257
258     logger.info("Updating network '%s' with shared=True..."
259                 % NEUTRON_PRIVATE_NET_NAME)
260     if openstack_utils.update_neutron_net(neutron, network_id, shared=True):
261         logger.debug("Network '%s' updated successfully." % network_id)
262     else:
263         logger.info("Updating neutron network '%s' failed" % network_id)
264
265     logger.info("Creating Subnet....")
266     subnet_id = openstack_utils.create_neutron_subnet(
267         neutron, NEUTRON_PRIVATE_SUBNET_NAME, NEUTRON_PRIVATE_SUBNET_CIDR,
268         network_id)
269     if not subnet_id:
270         return False
271     logger.debug("Subnet '%s' created successfully." % subnet_id)
272     logger.info("Creating Router...")
273     router_id = openstack_utils.create_neutron_router(neutron,
274                                                       NEUTRON_ROUTER_NAME)
275
276     if not router_id:
277         return False
278
279     logger.debug("Router '%s' created successfully." % router_id)
280     logger.info("Adding router to subnet...")
281
282     result = openstack_utils.add_interface_router(neutron,
283                                                   router_id,
284                                                   subnet_id)
285
286     if not result:
287         return False
288
289     logger.debug("Interface added successfully.")
290     return True
291
292
293 def main():
294     if not (args.action in actions):
295         logger.error('argument not valid')
296         exit(-1)
297
298     if not openstack_utils.check_credentials():
299         logger.error("Please source the openrc credentials and "
300                      "run the script again.")
301         # TODO: source the credentials in this script
302         exit(-1)
303
304     if args.action == "start":
305         action_start()
306
307     if args.action == "check":
308         if action_check():
309             logger.info("Functest environment correctly installed")
310         else:
311             logger.info("Functest environment not found or faulty")
312
313     if args.action == "clean":
314         if args.force:
315             action_clean()
316         else:
317             while True:
318                 print("Are you sure? [y|n]")
319                 answer = raw_input("")
320                 if answer == "y":
321                     action_clean()
322                     break
323                 elif answer == "n":
324                     break
325                 else:
326                     print("Invalid option.")
327     exit(0)
328
329
330 if __name__ == '__main__':
331     main()