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