Merge branch 'feature628'
[osm/RO.git] / test / test_RO.py
1 #!/usr/bin/env python2
2 # -*- coding: utf-8 -*-
3
4 ##
5 # Copyright 2015 Telefónica Investigación y Desarrollo, S.A.U.
6 # This file is part of openmano
7 # All Rights Reserved.
8 #
9 # Licensed under the Apache License, Version 2.0 (the "License"); you may
10 # not use this file except in compliance with the License. You may obtain
11 # a copy of the License at
12 #
13 # http://www.apache.org/licenses/LICENSE-2.0
14 #
15 # Unless required by applicable law or agreed to in writing, software
16 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18 # License for the specific language governing permissions and limitations
19 # under the License.
20 #
21 # For those usages not covered by the Apache License, Version 2.0 please
22 # contact with: nfvlabs@tid.es
23 ##
24
25 '''
26 Module for testing openmano functionality. It uses openmanoclient.py for invoking openmano
27 '''
28 __author__="Pablo Montes"
29 __date__ ="$16-Feb-2017 17:08:16$"
30 __version__="0.0.1"
31 version_date="Feb 2017"
32
33 import logging
34 import imp
35 import os
36 from optparse import OptionParser
37 import unittest
38 import string
39 import inspect
40 import random
41 import traceback
42 import glob
43 import yaml
44 import sys
45 import time
46
47 global test_number
48 global test_directory
49 global scenario_test_folder
50 global test_image_name
51 global management_network
52 global manual
53
54 def check_instance_scenario_active(uuid):
55 instance = client.get_instance(uuid=uuid)
56
57 for net in instance['nets']:
58 status = net['status']
59 if status != 'ACTIVE':
60 return (False, status)
61
62 for vnf in instance['vnfs']:
63 for vm in vnf['vms']:
64 status = vm['status']
65 if status != 'ACTIVE':
66 return (False, status)
67
68 return (True, None)
69
70 '''
71 IMPORTANT NOTE
72 All unittest classes for code based tests must have prefix 'test_' in order to be taken into account for tests
73 '''
74 class test_tenant_operations(unittest.TestCase):
75 test_index = 1
76 tenant_name = None
77 test_text = None
78
79 @classmethod
80 def setUpClass(cls):
81 logger.info("{}. {}".format(test_number, cls.__name__))
82
83 @classmethod
84 def tearDownClass(cls):
85 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
86
87 def tearDown(self):
88 exec_info = sys.exc_info()
89 if exec_info == (None, None, None):
90 logger.info(self.__class__.test_text+" -> TEST OK")
91 else:
92 logger.warning(self.__class__.test_text+" -> TEST NOK")
93 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
94 msg = ""
95 for line in error_trace:
96 msg = msg + line
97 logger.critical("{}".format(msg))
98
99 def test_000_create_RO_tenant(self):
100 self.__class__.tenant_name = _get_random_string(20)
101 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
102 inspect.currentframe().f_code.co_name)
103 self.__class__.test_index += 1
104 tenant = client.create_tenant(name=self.__class__.tenant_name, description=self.__class__.tenant_name)
105 logger.debug("{}".format(tenant))
106 self.assertEqual(tenant.get('tenant', {}).get('name', ''), self.__class__.tenant_name)
107
108 def test_010_list_RO_tenant(self):
109 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
110 inspect.currentframe().f_code.co_name)
111 self.__class__.test_index += 1
112 tenant = client.get_tenant(name=self.__class__.tenant_name)
113 logger.debug("{}".format(tenant))
114 self.assertEqual(tenant.get('tenant', {}).get('name', ''), self.__class__.tenant_name)
115
116 def test_020_delete_RO_tenant(self):
117 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
118 inspect.currentframe().f_code.co_name)
119 self.__class__.test_index += 1
120 tenant = client.delete_tenant(name=self.__class__.tenant_name)
121 logger.debug("{}".format(tenant))
122 assert('deleted' in tenant.get('result',""))
123
124 class test_datacenter_operations(unittest.TestCase):
125 test_index = 1
126 datacenter_name = None
127 test_text = None
128
129 @classmethod
130 def setUpClass(cls):
131 logger.info("{}. {}".format(test_number, cls.__name__))
132
133 @classmethod
134 def tearDownClass(cls):
135 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
136
137 def tearDown(self):
138 exec_info = sys.exc_info()
139 if exec_info == (None, None, None):
140 logger.info(self.__class__.test_text+" -> TEST OK")
141 else:
142 logger.warning(self.__class__.test_text+" -> TEST NOK")
143 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
144 msg = ""
145 for line in error_trace:
146 msg = msg + line
147 logger.critical("{}".format(msg))
148
149 def test_000_create_datacenter(self):
150 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
151 inspect.currentframe().f_code.co_name)
152 self.__class__.datacenter_name = _get_random_string(20)
153 self.__class__.test_index += 1
154 self.datacenter = client.create_datacenter(name=self.__class__.datacenter_name, vim_url="http://fakeurl/fake")
155 logger.debug("{}".format(self.datacenter))
156 self.assertEqual (self.datacenter.get('datacenter', {}).get('name',''), self.__class__.datacenter_name)
157
158 def test_010_list_datacenter(self):
159 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
160 inspect.currentframe().f_code.co_name)
161
162 self.__class__.test_index += 1
163 self.datacenter = client.get_datacenter(all_tenants=True, name=self.__class__.datacenter_name)
164 logger.debug("{}".format(self.datacenter))
165 self.assertEqual (self.datacenter.get('datacenter', {}).get('name', ''), self.__class__.datacenter_name)
166
167 def test_020_attach_datacenter(self):
168 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
169 inspect.currentframe().f_code.co_name)
170
171 self.__class__.test_index += 1
172 self.datacenter = client.attach_datacenter(name=self.__class__.datacenter_name, vim_tenant_name='fake')
173 logger.debug("{}".format(self.datacenter))
174 assert ('vim_tenants' in self.datacenter.get('datacenter', {}))
175
176 def test_030_list_attached_datacenter(self):
177 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
178 inspect.currentframe().f_code.co_name)
179
180 self.__class__.test_index += 1
181 self.datacenter = client.get_datacenter(all_tenants=False, name=self.__class__.datacenter_name)
182 logger.debug("{}".format(self.datacenter))
183 self.assertEqual (self.datacenter.get('datacenter', {}).get('name', ''), self.__class__.datacenter_name)
184
185 def test_040_detach_datacenter(self):
186 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
187 inspect.currentframe().f_code.co_name)
188
189 self.__class__.test_index += 1
190 self.datacenter = client.detach_datacenter(name=self.__class__.datacenter_name)
191 logger.debug("{}".format(self.datacenter))
192 assert ('detached' in self.datacenter.get('result', ""))
193
194 def test_050_delete_datacenter(self):
195 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
196 inspect.currentframe().f_code.co_name)
197
198 self.__class__.test_index += 1
199 self.datacenter = client.delete_datacenter(name=self.__class__.datacenter_name)
200 logger.debug("{}".format(self.datacenter))
201 assert('deleted' in self.datacenter.get('result',""))
202
203 class test_VIM_network_operations(unittest.TestCase):
204 test_index = 1
205 vim_network_name = None
206 test_text = None
207 vim_network_uuid = None
208
209 @classmethod
210 def setUpClass(cls):
211 logger.info("{}. {}".format(test_number, cls.__name__))
212
213 @classmethod
214 def tearDownClass(cls):
215 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
216
217 def tearDown(self):
218 exec_info = sys.exc_info()
219 if exec_info == (None, None, None):
220 logger.info(self.__class__.test_text + " -> TEST OK")
221 else:
222 logger.warning(self.__class__.test_text + " -> TEST NOK")
223 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
224 msg = ""
225 for line in error_trace:
226 msg = msg + line
227 logger.critical("{}".format(msg))
228
229 def test_000_create_VIM_network(self):
230 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
231 inspect.currentframe().f_code.co_name)
232 self.__class__.vim_network_name = _get_random_string(20)
233 self.__class__.test_index += 1
234 network = client.vim_action("create", "networks", name=self.__class__.vim_network_name)
235 logger.debug("{}".format(network))
236 self.__class__.vim_network_uuid = network["network"]["id"]
237 self.assertEqual(network.get('network', {}).get('name', ''), self.__class__.vim_network_name)
238
239 def test_010_list_VIM_networks(self):
240 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
241 inspect.currentframe().f_code.co_name)
242 self.__class__.test_index += 1
243 networks = client.vim_action("list", "networks")
244 logger.debug("{}".format(networks))
245
246 def test_020_get_VIM_network_by_uuid(self):
247 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
248 inspect.currentframe().f_code.co_name)
249
250 self.__class__.test_index += 1
251 network = client.vim_action("show", "networks", uuid=self.__class__.vim_network_uuid)
252 logger.debug("{}".format(network))
253 self.assertEqual(network.get('network', {}).get('name', ''), self.__class__.vim_network_name)
254
255 def test_030_delete_VIM_network_by_uuid(self):
256 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
257 inspect.currentframe().f_code.co_name)
258
259 self.__class__.test_index += 1
260 network = client.vim_action("delete", "networks", uuid=self.__class__.vim_network_uuid)
261 logger.debug("{}".format(network))
262 assert ('deleted' in network.get('result', ""))
263
264 class test_VIM_image_operations(unittest.TestCase):
265 test_index = 1
266 test_text = None
267
268 @classmethod
269 def setUpClass(cls):
270 logger.info("{}. {}".format(test_number, cls.__name__))
271
272 @classmethod
273 def tearDownClass(cls):
274 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
275
276 def tearDown(self):
277 exec_info = sys.exc_info()
278 if exec_info == (None, None, None):
279 logger.info(self.__class__.test_text + " -> TEST OK")
280 else:
281 logger.warning(self.__class__.test_text + " -> TEST NOK")
282 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
283 msg = ""
284 for line in error_trace:
285 msg = msg + line
286 logger.critical("{}".format(msg))
287
288 def test_000_list_VIM_images(self):
289 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
290 inspect.currentframe().f_code.co_name)
291 self.__class__.test_index += 1
292 images = client.vim_action("list", "images")
293 logger.debug("{}".format(images))
294
295 '''
296 The following is a non critical test that will fail most of the times.
297 In case of OpenStack datacenter these tests will only success if RO has access to the admin endpoint
298 This test will only be executed in case it is specifically requested by the user
299 '''
300 class test_VIM_tenant_operations(unittest.TestCase):
301 test_index = 1
302 vim_tenant_name = None
303 test_text = None
304 vim_tenant_uuid = None
305
306 @classmethod
307 def setUpClass(cls):
308 logger.info("{}. {}".format(test_number, cls.__name__))
309 logger.warning("In case of OpenStack datacenter these tests will only success "
310 "if RO has access to the admin endpoint")
311
312 @classmethod
313 def tearDownClass(cls):
314 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
315
316 def tearDown(self):
317 exec_info = sys.exc_info()
318 if exec_info == (None, None, None):
319 logger.info(self.__class__.test_text + " -> TEST OK")
320 else:
321 logger.warning(self.__class__.test_text + " -> TEST NOK")
322 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
323 msg = ""
324 for line in error_trace:
325 msg = msg + line
326 logger.critical("{}".format(msg))
327
328 def test_000_create_VIM_tenant(self):
329 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
330 inspect.currentframe().f_code.co_name)
331 self.__class__.vim_tenant_name = _get_random_string(20)
332 self.__class__.test_index += 1
333 tenant = client.vim_action("create", "tenants", name=self.__class__.vim_tenant_name)
334 logger.debug("{}".format(tenant))
335 self.__class__.vim_tenant_uuid = tenant["tenant"]["id"]
336 self.assertEqual(tenant.get('tenant', {}).get('name', ''), self.__class__.vim_tenant_name)
337
338 def test_010_list_VIM_tenants(self):
339 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
340 inspect.currentframe().f_code.co_name)
341 self.__class__.test_index += 1
342 tenants = client.vim_action("list", "tenants")
343 logger.debug("{}".format(tenants))
344
345 def test_020_get_VIM_tenant_by_uuid(self):
346 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
347 inspect.currentframe().f_code.co_name)
348
349 self.__class__.test_index += 1
350 tenant = client.vim_action("show", "tenants", uuid=self.__class__.vim_tenant_uuid)
351 logger.debug("{}".format(tenant))
352 self.assertEqual(tenant.get('tenant', {}).get('name', ''), self.__class__.vim_tenant_name)
353
354 def test_030_delete_VIM_tenant_by_uuid(self):
355 self.__class__.test_text = "{}.{}. TEST {}".format(test_number, self.__class__.test_index,
356 inspect.currentframe().f_code.co_name)
357
358 self.__class__.test_index += 1
359 tenant = client.vim_action("delete", "tenants", uuid=self.__class__.vim_tenant_uuid)
360 logger.debug("{}".format(tenant))
361 assert ('deleted' in tenant.get('result', ""))
362
363 '''
364 IMPORTANT NOTE
365 The following unittest class does not have the 'test_' on purpose. This test is the one used for the
366 scenario based tests.
367 '''
368 class descriptor_based_scenario_test(unittest.TestCase):
369 test_index = 0
370 test_text = None
371 scenario_test_path = None
372 scenario_uuid = None
373 instance_scenario_uuid = None
374 to_delete_list = []
375
376 @classmethod
377 def setUpClass(cls):
378 cls.test_index = 1
379 cls.to_delete_list = []
380 cls.scenario_test_path = test_directory + '/' + scenario_test_folder
381 logger.info("{}. {} {}".format(test_number, cls.__name__, scenario_test_folder))
382
383 @classmethod
384 def tearDownClass(cls):
385 globals().__setitem__('test_number', globals().__getitem__('test_number') + 1)
386
387 def tearDown(self):
388 exec_info = sys.exc_info()
389 if exec_info == (None, None, None):
390 logger.info(self.__class__.test_text + " -> TEST OK")
391 else:
392 logger.warning(self.__class__.test_text + " -> TEST NOK")
393 error_trace = traceback.format_exception(exec_info[0], exec_info[1], exec_info[2])
394 msg = ""
395 for line in error_trace:
396 msg = msg + line
397 logger.critical("{}".format(msg))
398
399
400 def test_000_load_scenario(self):
401 self.__class__.test_text = "{}.{}. TEST {} {}".format(test_number, self.__class__.test_index,
402 inspect.currentframe().f_code.co_name,
403 scenario_test_folder)
404 self.__class__.test_index += 1
405 vnfd_files = glob.glob(self.__class__.scenario_test_path+'/vnfd_*.yaml')
406 scenario_file = glob.glob(self.__class__.scenario_test_path + '/scenario_*.yaml')
407 if len(vnfd_files) == 0 or len(scenario_file) > 1:
408 raise Exception('Test '+scenario_test_folder+' not valid. It must contain an scenario file and at least one'
409 ' vnfd file')
410
411 #load all vnfd
412 for vnfd in vnfd_files:
413 with open(vnfd, 'r') as stream:
414 vnf_descriptor = yaml.load(stream)
415
416 vnfc_list = vnf_descriptor['vnf']['VNFC']
417 for vnfc in vnfc_list:
418 vnfc['image name'] = test_image_name
419 devices = vnfc.get('devices',[])
420 for device in devices:
421 if device['type'] == 'disk' and 'image name' in device:
422 device['image name'] = test_image_name
423
424 logger.debug("VNF descriptor: {}".format(vnf_descriptor))
425 vnf = client.create_vnf(descriptor=vnf_descriptor)
426 logger.debug(vnf)
427 self.__class__.to_delete_list.insert(0, {"item": "vnf", "function": client.delete_vnf,
428 "params": {"uuid": vnf['vnf']['uuid']}})
429
430 #load the scenario definition
431 with open(scenario_file[0], 'r') as stream:
432 scenario_descriptor = yaml.load(stream)
433 networks = scenario_descriptor['scenario']['networks']
434 networks[management_network] = networks.pop('mgmt')
435 logger.debug("Scenario descriptor: {}".format(scenario_descriptor))
436 scenario = client.create_scenario(descriptor=scenario_descriptor)
437 logger.debug(scenario)
438 self.__class__.to_delete_list.insert(0,{"item": "scenario", "function": client.delete_scenario,
439 "params":{"uuid": scenario['scenario']['uuid']} })
440 self.__class__.scenario_uuid = scenario['scenario']['uuid']
441
442 def test_010_instantiate_scenario(self):
443 self.__class__.test_text = "{}.{}. TEST {} {}".format(test_number, self.__class__.test_index,
444 inspect.currentframe().f_code.co_name,
445 scenario_test_folder)
446 self.__class__.test_index += 1
447
448 instance = client.create_instance(scenario_id=self.__class__.scenario_uuid, name=self.__class__.test_text)
449 self.__class__.instance_scenario_uuid = instance['uuid']
450 logger.debug(instance)
451 self.__class__.to_delete_list.insert(0, {"item": "instance", "function": client.delete_instance,
452 "params": {"uuid": instance['uuid']}})
453
454 def test_020_check_deployent(self):
455 self.__class__.test_text = "{}.{}. TEST {} {}".format(test_number, self.__class__.test_index,
456 inspect.currentframe().f_code.co_name,
457 scenario_test_folder)
458 self.__class__.test_index += 1
459
460 if manual:
461 raw_input('Scenario has been deployed. Perform manual check and press any key to resume')
462 return
463
464 keep_waiting = 50
465 instance_active = False
466 while(keep_waiting):
467 result = check_instance_scenario_active(self.__class__.instance_scenario_uuid)
468 if result[0]:
469 break
470 elif 'ERROR' in result[1]:
471 msg = 'Got error while waiting for the instance to get active: '+result[1]
472 logging.error(msg)
473 raise Exception(msg)
474
475 keep_waiting -= 1
476 time.sleep(5)
477
478 if keep_waiting == 0:
479 msg = 'Timeout reached while waiting instance scenario to get active'
480 logging.error(msg)
481 raise Exception(msg)
482
483 def test_030_clean_deployment(self):
484 self.__class__.test_text = "{}.{}. TEST {} {}".format(test_number, self.__class__.test_index,
485 inspect.currentframe().f_code.co_name,
486 scenario_test_folder)
487 self.__class__.test_index += 1
488 #At the moment if you delete an scenario right after creating it, in openstack datacenters
489 #sometimes scenario ports get orphaned. This sleep is just a dirty workaround
490 time.sleep(5)
491 for item in self.__class__.to_delete_list:
492 response = item["function"](**item["params"])
493 logger.debug(response)
494
495 def _get_random_string(maxLength):
496 '''generates a string with random characters string.letters and string.digits
497 with a random length up to maxLength characters. If maxLength is <15 it will be changed automatically to 15
498 '''
499 prefix = 'testing_'
500 min_string = 15
501 minLength = min_string - len(prefix)
502 if maxLength < min_string: maxLength = min_string
503 maxLength -= len(prefix)
504 length = random.randint(minLength,maxLength)
505 return 'testing_'+"".join([random.choice(string.letters+string.digits) for i in xrange(length)])
506
507 if __name__=="__main__":
508 sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
509 import openmanoclient
510
511 parser = OptionParser()
512
513 #Optional arguments
514 parser.add_option("-v",'--version', help='Show current version', dest='version', action="store_true", default=False)
515 parser.add_option('--debug', help='Set logs to debug level', dest='debug', action="store_true", default=False)
516 parser.add_option('--failed', help='Set logs to show only failed tests. --debug disables this option',
517 dest='failed', action="store_true", default=False)
518 parser.add_option('-u', '--url', dest='endpoint_url', help='Set the openmano server url. By default '
519 'http://localhost:9090/openmano',
520 default='http://localhost:9090/openmano')
521 default_logger_file = os.path.dirname(__file__)+'/'+os.path.splitext(os.path.basename(__file__))[0]+'.log'
522 parser.add_option('--logger_file', dest='logger_file', help='Set the logger file. By default '+default_logger_file,
523 default=default_logger_file)
524 parser.add_option('--list-tests', help='List all available tests', dest='list-tests', action="store_true",
525 default=False)
526 parser.add_option('-m', '--manual-check', help='Pause execution once deployed to allow manual checking of the deployed instance scenario', dest='manual', action="store_true", default=False)
527 parser.add_option('--test', '--tests', help='Specify the tests to run', dest='tests', default=None)
528
529 #Mandatory arguments
530 parser.add_option("-t", '--tenant', dest='tenant_name', help='MANDATORY. Set the tenant name to test')
531 parser.add_option('-d', '--datacenter', dest='datacenter_name', help='MANDATORY, Set the datacenter name to test')
532 parser.add_option("-i", '--image-name', dest='image-name', help='MANDATORY. Image name of an Ubuntu 16.04 image '
533 'that will be used for testing available in the '
534 'datacenter.')
535 parser.add_option("-n", '--mgmt-net-name', dest='mgmt-net', help='MANDATORY. Set the tenant name to test')
536
537 (options, args) = parser.parse_args()
538
539 # default logger level is INFO. Options --debug and --failed override this, being --debug prioritary
540 logger_level = 'INFO'
541 if options.__dict__['debug']:
542 logger_level = 'DEBUG'
543 elif options.__dict__['failed']:
544 logger_level = 'WARNING'
545 logger_name = os.path.basename(__file__)
546 logger = logging.getLogger(logger_name)
547 logger.setLevel(logger_level)
548
549 # Configure a logging handler to store in a logging file
550 fileHandler = logging.FileHandler(options.__dict__['logger_file'])
551 formatter_fileHandler = logging.Formatter('%(asctime)s %(name)s %(levelname)s: %(message)s')
552 fileHandler.setFormatter(formatter_fileHandler)
553 logger.addHandler(fileHandler)
554
555 # Configure a handler to print to stdout
556 consoleHandler = logging.StreamHandler(sys.stdout)
557 formatter_consoleHandler = logging.Formatter('%(message)s')
558 consoleHandler.setFormatter(formatter_consoleHandler)
559 logger.addHandler(consoleHandler)
560
561 logger.debug('Program started with the following arguments: ' + str(options.__dict__))
562
563 #If version is required print it and exit
564 if options.__dict__['version']:
565 logger.info("{}".format((sys.argv[0], __version__+" version", version_date)))
566 logger.info ("(c) Copyright Telefonica")
567 sys.exit(0)
568
569 test_directory = os.path.dirname(__file__) + "/RO_tests"
570 test_directory_content = os.listdir(test_directory)
571 clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)
572
573 # If only want to obtain a tests list print it and exit
574 if options.__dict__['list-tests']:
575 tests_names = []
576 for cls in clsmembers:
577 if cls[0].startswith('test_'):
578 tests_names.append(cls[0])
579
580 msg = "The code based tests are:\n\t" + ', '.join(sorted(tests_names))+'\n'+\
581 "The descriptor based tests are:\n\t"+ ', '.join(sorted(test_directory_content))+'\n'+\
582 "NOTE: The test test_VIM_tenant_operations will fail in case the used datacenter is type OpenStack " \
583 "unless RO has access to the admin endpoint. Therefore this test is excluded by default"
584
585 logger.info(msg)
586 sys.exit(0)
587
588 #Make sure required arguments are present
589 required = "tenant_name datacenter_name image-name mgmt-net".split()
590 error = False
591 for r in required:
592 if options.__dict__[r] is None:
593 print "ERROR: parameter "+r+" is required"
594 error = True
595 if error:
596 parser.print_help()
597 sys.exit(1)
598
599 # set test image name and management network
600 test_image_name = options.__dict__['image-name']
601 management_network = options.__dict__['mgmt-net']
602 manual = options.__dict__['manual']
603
604 #Create the list of tests to be run
605 descriptor_based_tests = []
606 code_based_tests = []
607 if options.__dict__['tests'] != None:
608 tests = sorted(options.__dict__['tests'].split(','))
609 for test in tests:
610 matches_code_based_tests = [item for item in clsmembers if item[0] == test]
611 if test in test_directory_content:
612 descriptor_based_tests.append(test)
613 elif len(matches_code_based_tests) > 0:
614 code_based_tests.append(matches_code_based_tests[0][1])
615 else:
616 logger.critical("Test {} is not among the possible ones".format(test))
617 sys.exit(1)
618 else:
619 #include all tests
620 descriptor_based_tests = test_directory_content
621 for cls in clsmembers:
622 #We exclude 'test_VIM_tenant_operations' unless it is specifically requested by the user
623 if cls[0].startswith('test_') and cls[0] != 'test_VIM_tenant_operations':
624 code_based_tests.append(cls[1])
625
626 logger.debug("descriptor_based_tests to be executed: {}".format(descriptor_based_tests))
627 logger.debug("code_based_tests to be executed: {}".format(code_based_tests))
628
629 # import openmanoclient from relative path
630 client = openmanoclient.openmanoclient(
631 endpoint_url=options.__dict__['endpoint_url'],
632 tenant_name=options.__dict__['tenant_name'],
633 datacenter_name = options.__dict__['datacenter_name'],
634 debug = options.__dict__['debug'], logger = logger_name)
635
636 # TextTestRunner stream is set to /dev/null in order to avoid the method to directly print the result of tests.
637 # This is handled in the tests using logging.
638 stream = open('/dev/null', 'w')
639 test_number=1
640 executed = 0
641 failed = 0
642
643 #Run code based tests
644 basic_tests_suite = unittest.TestSuite()
645 for test in code_based_tests:
646 basic_tests_suite.addTest(unittest.makeSuite(test))
647 result = unittest.TextTestRunner(stream=stream).run(basic_tests_suite)
648 executed += result.testsRun
649 failed += len(result.failures) + len(result.errors)
650 if len(result.failures) > 0:
651 logger.debug("failures : {}".format(result.failures))
652 if len(result.errors) > 0:
653 logger.debug("errors : {}".format(result.errors))
654
655 # Additionally to the previous tests, scenario based tests will be executed.
656 # This scenario based tests are defined as directories inside the directory defined in 'test_directory'
657 for test in descriptor_based_tests:
658 scenario_test_folder = test
659 test_suite = unittest.TestSuite()
660 test_suite.addTest(unittest.makeSuite(descriptor_based_scenario_test))
661 result = unittest.TextTestRunner(stream=stream).run(test_suite)
662 executed += result.testsRun
663 failed += len(result.failures) + len(result.errors)
664 if len(result.failures) > 0:
665 logger.debug("failures : {}".format(result.failures))
666 if len(result.errors) > 0:
667 logger.debug("errors : {}".format(result.errors))
668
669 #Log summary
670 logger.warning("Total number of tests: {}; Total number of failures/errors: {}".format(executed, failed))
671
672 sys.exit(0)