class testPLEXRegistration(unittest.TestCase): """ Tests the registration process of the Scaling Executive to the broker and the plugin manager, and the heartbeat process. """ def setUp(self): #a new Scaling Executive in another process for each test self.plex_proc = Process(target=ScalingExecutive) self.plex_proc.daemon = True if 'broker_man_host' in os.environ: self.man_host = os.environ['broker_man_host'] else: self.man_host = 'http://localhost:15672' if 'sm_broker_host' in os.environ: self.sm_host = os.environ['sm_broker_host'] else: self.sm_host = 'http://localhost:15672' url_user = "******".format(self.man_host) url_create = '{0}/api/vhosts/fsm-1234'.format(self.man_host) url_permission = '{0}/api/permissions/fsm-1234/specific-management'.format(self.man_host) self.headers = {'content-type': 'application/json'} data1 = '{"password":"******","tags":"son-sm"}' data2 = '{"configure":".*","write":".*","read":".*"}' res = requests.put(url=url_user, headers=self.headers, data=data1, auth=('guest', 'guest')) LOG.info(res.content) res1 = requests.put(url=url_create, headers=self.headers, auth=('guest', 'guest')) LOG.info(res1.content) res2= requests.put(url=url_permission, headers=self.headers, data=data2, auth=('guest', 'guest')) LOG.info(res2.content) #make a new connection with the broker before each test url = "{0}/fsm-1234".format(self.sm_host) self.manoconn = ManoBrokerRequestResponseConnection('son-plugin.SonPluginManager') self.sm_connection = ManoBrokerRequestResponseConnection('son-plugin.FSM', url=url) #Some threading events that can be used during the tests self.wait_for_event1 = threading.Event() self.wait_for_event1.clear() self.wait_for_event2 = threading.Event() self.wait_for_event2.clear() def tearDown(self): #Killing the scaling Executive if self.plex_proc is not None: self.plex_proc.terminate() del self.plex_proc #Killing the connection with the broker try: self.manoconn.stop_connection() self.sm_connection.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event1 del self.wait_for_event2 url_user = "******".format(self.man_host) url_vhost = "{0}/api/vhosts/fsm-1234".format(self.man_host) requests.delete(url=url_user, headers=self.headers, auth=('guest', 'guest')) requests.delete(url=url_vhost, headers=self.headers, auth=('guest', 'guest')) #Method that terminates the timer that waits for an event def eventFinished1(self): self.wait_for_event1.set() def eventFinished2(self): self.wait_for_event2.set() #Method that starts a timer, waiting for an event def waitForEvent1(self, timeout=5, msg="Event timed out."): if not self.wait_for_event1.wait(timeout): self.assertEqual(True, False, msg=msg) def waitForEvent2(self, timeout=5, msg="Event timed out."): if not self.wait_for_event2.wait(timeout): self.assertEqual(True, False, msg=msg) def test_1_SCEX_Registration(self): """ TEST: This test verifies whether the Scaling Executive is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. def on_register_receive(ch, method, properties, message): msg = yaml.load(message) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished1() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the Scaling Executive self.plex_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent1(timeout=5, msg="message not received.") def test_2_SCEX_request_response(self): def on_request_send(ch, method, properties, message): if properties.app_id == "son-plugin.ScalingExecutive": msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') self.assertIn('uuid', msg.keys(), msg='No uuid provided in message.') if isinstance(msg['uuid'], str): self.assertTrue(msg['uuid'] == '1234', msg='empty uuid provided.') self.assertNotIn('scale', msg.keys(), msg='wrong message!') res_payload = yaml.dump({'uuid': '1234', 'scale': '2'}) self.eventFinished1() return res_payload def on_response_send(ch, method, properties, message): if properties.app_id == "son-plugin.ScalingExecutive": msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') self.assertIn('uuid', msg.keys(), msg='No uuid provided in message.') if isinstance(msg['uuid'], str): self.assertTrue(msg['uuid'] == '1234', msg='empty uuid provided.') self.assertIn('scale', msg.keys(), msg='No scale provided in message.') if isinstance(msg['scale'], str): self.assertTrue(msg['scale'] == '2', msg='empty uuid provided.') self.eventFinished2() self.plex_proc.start() time.sleep(2) self.manoconn.subscribe(on_response_send, 'scaling.executive.request') self.sm_connection.register_async_endpoint(on_request_send, 'scaling.fsm.1234') req_payload = yaml.dump({'uuid': '1234'}) self.manoconn.publish("scaling.executive.request", message=req_payload) self.waitForEvent1(timeout=5, msg="response message not received.") self.waitForEvent2(timeout=5, msg="request message not received.")
class test_SMR_functionalities(unittest.TestCase): @classmethod def setUpClass(self): self.smr_proc = Process(target=SpecificManagerRegistry) self.smr_proc.daemon = True self.manoconn = ManoBrokerRequestResponseConnection('son-plugin.SpecificManagerRegistry') self.wait_for_ssm_event = threading.Event() self.wait_for_ssm_event.clear() self.wait_for_fsm_event = threading.Event() self.wait_for_fsm_event.clear() self.event1 = False self.event2 = False self.smr_proc.start() time.sleep(4) @classmethod def tearDownClass(self): if self.smr_proc is not None: self.smr_proc.terminate() del self.smr_proc try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") del self.wait_for_fsm_event del self.wait_for_ssm_event def ssm_eventFinished(self): self.wait_for_ssm_event.set() def waitForSSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_ssm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def fsm_eventFinished(self): self.wait_for_fsm_event.set() def waitForFSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_fsm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def test_1_SMR_onboard(self): self.event1 = False self.event2 = False def on_ssm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1','sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['error'] == 'None', msg='error in onbording sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1dumb1'], msg='not all FSMs results in VNFD1 received') self.assertTrue(result['sonfsmservice1function1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in onbording sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1']or list(result.keys()) == ['sonfsmservice1firewallconfiguration1','sonfsmservice1function1monitoring1'] , msg='not all FSMs results in VNFD2 received') self.assertTrue(result['sonfsmservice1function1monitoring1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1function1monitoring1']['error'] == 'None', msg='error in onbording sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg='error in onbording sonfsmservice1firewallconfiguration1') self.event2 = True if self.event1 and self.event2 == True: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_onboarding_result, 'specific.manager.registry.ssm.on-board') self.manoconn.subscribe(on_fsm_onboarding_result, 'specific.manager.registry.fsm.on-board') onboaring_proc = Process(target=fakeslm_onboarding) onboaring_proc.daemon = True onboaring_proc.start() self.waitForSSMEvent(timeout=70 , msg='SSM Onboarding request not received.') self.waitForFSMEvent(timeout=70, msg='FSM Onboarding request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() onboaring_proc.terminate() del onboaring_proc def test_2_SMR_instantiation(self): self.event1 = False self.event2 = False def on_ssm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1', 'sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in instantiation sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1placement1') self.assertTrue(result['sonssmservice1placement1']['error'] == 'None', msg='error in instantiation sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1dumb1'], msg='not all FSMs instantiation results in VNFD1 received') self.assertTrue(result['sonfsmservice1function1dumb1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1function1dumb1') self.assertTrue(result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in instantiation sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1'] or list(result.keys()) == ['sonfsmservice1firewallconfiguration1', 'sonfsmservice1function1monitoring1'] , msg='not all FSMs instantiation results in VNFD2 received') self.assertTrue(result['sonfsmservice1function1monitoring1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1function1monitoring1']['error'] == 'None', msg='error in instantiation sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1firewallconfiguration1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg='error in instantiation sonfsmservice1firewallconfiguration1') self.event2 = True if self.event1 and self.event2: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_instantiation_result, 'specific.manager.registry.ssm.instantiate') self.manoconn.subscribe(on_fsm_instantiation_result, 'specific.manager.registry.fsm.instantiate') instantiation_proc = Process(target=fakeslm_instantiation) instantiation_proc.daemon = True instantiation_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM instantiation request not received.') self.waitForFSMEvent(timeout=70, msg='FSM instantiation request not received.') self.wait_for_ssm_event.clear() self.wait_for_fsm_event.clear() instantiation_proc.terminate() del instantiation_proc def test_3_SMR_update(self): def on_ssm_updating_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'Updated', msg='error in updating status filed sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in updating error filed sonssmservice1dumb1') self.ssm_eventFinished() def on_fsm_updating_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonfsmservice1function1updateddumb1'] , msg='not all FSMs updating results in VNFD2 received') self.assertTrue(result['sonfsmservice1function1updateddumb1']['status'] == 'Updated', msg='error in updating sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1function1updateddumb1']['error'] == 'None', msg='error in updating sonfsmservice1function1monitoring1') self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_updating_result, 'specific.manager.registry.ssm.update') self.manoconn.subscribe(on_fsm_updating_result, 'specific.manager.registry.fsm.update') updating_proc = Process(target=fakeslm_updating) updating_proc.daemon = True updating_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM updating request not received.') self.waitForFSMEvent(timeout=70, msg='FSM updating request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() updating_proc.terminate() del updating_proc def test_4_SMR_terminate(self): self.event1 = False self.event2 = False def on_ssm_termination_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1','sonssmservice1placement1'] or ['sonssmservice1placement1','sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'Terminated', msg='error in termination status field sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in termination error field sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'Terminated', msg='error in termination status field sonssmservice1placement1') self.assertTrue(result['sonssmservice1placement1']['error'] == 'None', msg='error in termination error field sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_termination_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue(result['sonfsmservice1function1dumb1']['status'] == 'Terminated', msg='error in termination status field sonfsmservice1function1dumb1') self.assertTrue(result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in termination error field sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1monitoring1', 'sonfsmservice1function1updateddumb1'] or list(result.keys()) == ['sonfsmservice1function1updateddumb1', 'sonfsmservice1function1monitoring1'] , msg='not all FSMs Termination results in vnfdt2 received') self.assertTrue(result['sonfsmservice1function1monitoring1']['status'] == 'Terminated', msg='error in termination status field sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1function1monitoring1']['error'] == 'None', msg='error in termination error field sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1function1updateddumb1']['status'] == 'Terminated', msg='error in termination status field sonfsmservice1function1updateddumb1') self.assertTrue(result['sonfsmservice1function1updateddumb1']['error'] == 'None', msg='error in termination error field sonfsmservice1function1updateddumb1') self.event2 = True self.fsm_eventFinished() if self.event1 and self.event2: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_termination_result, 'specific.manager.registry.ssm.terminate') self.manoconn.subscribe(on_fsm_termination_result, 'specific.manager.registry.fsm.terminate') termination_proc = Process(target=fakeslm_termination) termination_proc.daemon = True termination_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM termination request not received.') self.waitForFSMEvent(timeout=70, msg='FSM termination request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() termination_proc.terminate() del termination_proc
class testSMRRegistration(unittest.TestCase): def setUp(self): #a new SMR in another process for each test self.smr_proc = Process(target=SpecificManagerRegistry) self.smr_proc.daemon = True #make a new connection with the broker before each test self.manoconn = ManoBrokerRequestResponseConnection('son-plugin.SonPluginManager') #Some threading events that can be used during the tests self.wait_for_event = threading.Event() self.wait_for_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing SMR if self.smr_proc is not None: self.smr_proc.terminate() del self.smr_proc #Killing the connection with the broker try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event #Method that terminates the timer that waits for an event def eventFinished(self): self.wait_for_event.set() #Method that starts a timer, waiting for an event def waitForEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_event.wait(timeout): self.assertEqual(True, False, msg=msg) def testSMRRegistration(self): """ TEST: This test verifies whether SMR is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. def on_register_receive(ch, method, properties, message): msg = yaml.load(message) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the Scaling Executive self.smr_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent(timeout=5, msg="message not received.")
class testSMRRegistration(unittest.TestCase): def setUp(self): #a new SMR in another process for each test self.smr_proc = Process(target=SpecificManagerRegistry) self.smr_proc.daemon = True #make a new connection with the broker before each test self.manoconn = ManoBrokerRequestResponseConnection('son-plugin.SonPluginManager') #Some threading events that can be used during the tests self.wait_for_event = threading.Event() self.wait_for_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing SMR if self.smr_proc is not None: self.smr_proc.terminate() del self.smr_proc #Killing the connection with the broker try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event #Method that terminates the timer that waits for an event def eventFinished(self): self.wait_for_event.set() #Method that starts a timer, waiting for an event def waitForEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_event.wait(timeout): self.assertEqual(True, False, msg=msg) def testSMRRegistration(self): """ TEST: This test verifies whether SMR is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. def on_register_receive(ch, method, properties, message): msg = yaml.load(message) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the Scaling Executive self.smr_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent(timeout=5, msg="message not received.")
class test_SMR_functionalities(unittest.TestCase): @classmethod def setUpClass(self): self.smr_proc = Process(target=SpecificManagerRegistry) self.smr_proc.daemon = True self.manoconn = ManoBrokerRequestResponseConnection( 'son-plugin.SpecificManagerRegistry') self.wait_for_ssm_event = threading.Event() self.wait_for_ssm_event.clear() self.wait_for_fsm_event = threading.Event() self.wait_for_fsm_event.clear() self.event1 = False self.event2 = False self.smr_proc.start() time.sleep(4) @classmethod def tearDownClass(self): if self.smr_proc is not None: self.smr_proc.terminate() del self.smr_proc try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") del self.wait_for_fsm_event del self.wait_for_ssm_event def ssm_eventFinished(self): self.wait_for_ssm_event.set() def waitForSSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_ssm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def fsm_eventFinished(self): self.wait_for_fsm_event.set() def waitForFSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_fsm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def test_1_SMR_onboard(self): self.event1 = False self.event2 = False def on_ssm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue( list(result.keys()) == ['sonssmservice1dumb1', 'sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue( result['sonssmservice1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue( result['sonssmservice1dumb1']['error'] == 'None', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue( result['sonssmservice1placement1']['error'] == 'None', msg='error in onbording sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue( list( result.keys()) == ['sonfsmservice1function1dumb1'], msg='not all FSMs results in VNFD1 received') self.assertTrue( result['sonfsmservice1function1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue( result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in onbording sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue( list(result.keys()) == [ 'sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1' ] or list(result.keys()) == [ 'sonfsmservice1firewallconfiguration1', 'sonfsmservice1function1monitoring1' ], msg='not all FSMs results in VNFD2 received') self.assertTrue( result['sonfsmservice1function1monitoring1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue( result['sonfsmservice1function1monitoring1']['error'] == 'None', msg= 'error in onbording sonfsmservice1function1monitoring1' ) self.assertTrue( result['sonfsmservice1firewallconfiguration1'] ['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue( result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg= 'error in onbording sonfsmservice1firewallconfiguration1' ) self.event2 = True if self.event1 and self.event2 == True: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_onboarding_result, 'specific.manager.registry.ssm.on-board') self.manoconn.subscribe(on_fsm_onboarding_result, 'specific.manager.registry.fsm.on-board') onboaring_proc = Process(target=fakeslm_onboarding) onboaring_proc.daemon = True onboaring_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM Onboarding request not received.') self.waitForFSMEvent(timeout=70, msg='FSM Onboarding request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() onboaring_proc.terminate() del onboaring_proc def test_2_SMR_instantiation(self): self.event1 = False self.event2 = False def on_ssm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue( list(result.keys()) == ['sonssmservice1dumb1', 'sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue( result['sonssmservice1dumb1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1dumb1') self.assertTrue( result['sonssmservice1dumb1']['error'] == 'None', msg='error in instantiation sonssmservice1dumb1') self.assertTrue( result['sonssmservice1placement1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1placement1') self.assertTrue( result['sonssmservice1placement1']['error'] == 'None', msg='error in instantiation sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue( list( result.keys()) == ['sonfsmservice1function1dumb1'], msg= 'not all FSMs instantiation results in VNFD1 received') self.assertTrue( result['sonfsmservice1function1dumb1']['status'] == 'Instantiated', msg= 'error in instantiation sonfsmservice1function1dumb1') self.assertTrue( result['sonfsmservice1function1dumb1']['error'] == 'None', msg= 'error in instantiation sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue( list(result.keys()) == [ 'sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1' ] or list(result.keys()) == [ 'sonfsmservice1firewallconfiguration1', 'sonfsmservice1function1monitoring1' ], msg= 'not all FSMs instantiation results in VNFD2 received') self.assertTrue( result['sonfsmservice1function1monitoring1']['status'] == 'Instantiated', msg= 'error in instantiation sonfsmservice1function1monitoring1' ) self.assertTrue( result['sonfsmservice1function1monitoring1']['error'] == 'None', msg= 'error in instantiation sonfsmservice1function1monitoring1' ) self.assertTrue( result['sonfsmservice1firewallconfiguration1'] ['status'] == 'Instantiated', msg= 'error in instantiation sonfsmservice1firewallconfiguration1' ) self.assertTrue( result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg= 'error in instantiation sonfsmservice1firewallconfiguration1' ) self.event2 = True if self.event1 and self.event2: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_instantiation_result, 'specific.manager.registry.ssm.instantiate') self.manoconn.subscribe(on_fsm_instantiation_result, 'specific.manager.registry.fsm.instantiate') instantiation_proc = Process(target=fakeslm_instantiation) instantiation_proc.daemon = True instantiation_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM instantiation request not received.') self.waitForFSMEvent(timeout=70, msg='FSM instantiation request not received.') self.wait_for_ssm_event.clear() self.wait_for_fsm_event.clear() instantiation_proc.terminate() del instantiation_proc def test_3_SMR_update(self): def on_ssm_updating_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue( result['sonssmservice1dumb1']['status'] == 'Updated', msg='error in updating status filed sonssmservice1dumb1') self.assertTrue( result['sonssmservice1dumb1']['error'] == 'None', msg='error in updating error filed sonssmservice1dumb1') self.ssm_eventFinished() def on_fsm_updating_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue( list(result.keys()) == [ 'sonfsmservice1function1updateddumb1' ], msg='not all FSMs updating results in VNFD2 received') self.assertTrue( result['sonfsmservice1function1updateddumb1']['status'] == 'Updated', msg='error in updating sonfsmservice1function1monitoring1') self.assertTrue( result['sonfsmservice1function1updateddumb1']['error'] == 'None', msg='error in updating sonfsmservice1function1monitoring1') self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_updating_result, 'specific.manager.registry.ssm.update') self.manoconn.subscribe(on_fsm_updating_result, 'specific.manager.registry.fsm.update') updating_proc = Process(target=fakeslm_updating) updating_proc.daemon = True updating_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM updating request not received.') self.waitForFSMEvent(timeout=70, msg='FSM updating request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() updating_proc.terminate() del updating_proc def test_4_SMR_terminate(self): self.event1 = False self.event2 = False def on_ssm_termination_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue( list(result.keys()) == ['sonssmservice1dumb1', 'sonssmservice1placement1'] or ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue( result['sonssmservice1dumb1']['status'] == 'Terminated', msg='error in termination status field sonssmservice1dumb1' ) self.assertTrue( result['sonssmservice1dumb1']['error'] == 'None', msg='error in termination error field sonssmservice1dumb1') self.assertTrue( result['sonssmservice1placement1']['status'] == 'Terminated', msg= 'error in termination status field sonssmservice1placement1' ) self.assertTrue( result['sonssmservice1placement1']['error'] == 'None', msg= 'error in termination error field sonssmservice1placement1' ) self.ssm_eventFinished() def on_fsm_termination_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue( result['sonfsmservice1function1dumb1']['status'] == 'Terminated', msg= 'error in termination status field sonfsmservice1function1dumb1' ) self.assertTrue( result['sonfsmservice1function1dumb1']['error'] == 'None', msg= 'error in termination error field sonfsmservice1function1dumb1' ) self.event1 = True else: self.assertTrue( list(result.keys()) == [ 'sonfsmservice1function1monitoring1', 'sonfsmservice1function1updateddumb1' ] or list(result.keys()) == [ 'sonfsmservice1function1updateddumb1', 'sonfsmservice1function1monitoring1' ], msg= 'not all FSMs Termination results in vnfdt2 received') self.assertTrue( result['sonfsmservice1function1monitoring1']['status'] == 'Terminated', msg= 'error in termination status field sonfsmservice1function1monitoring1' ) self.assertTrue( result['sonfsmservice1function1monitoring1']['error'] == 'None', msg= 'error in termination error field sonfsmservice1function1monitoring1' ) self.assertTrue( result['sonfsmservice1function1updateddumb1']['status'] == 'Terminated', msg= 'error in termination status field sonfsmservice1function1updateddumb1' ) self.assertTrue( result['sonfsmservice1function1updateddumb1']['error'] == 'None', msg= 'error in termination error field sonfsmservice1function1updateddumb1' ) self.event2 = True self.fsm_eventFinished() if self.event1 and self.event2: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_termination_result, 'specific.manager.registry.ssm.terminate') self.manoconn.subscribe(on_fsm_termination_result, 'specific.manager.registry.fsm.terminate') termination_proc = Process(target=fakeslm_termination) termination_proc.daemon = True termination_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM termination request not received.') self.waitForFSMEvent(timeout=70, msg='FSM termination request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() termination_proc.terminate() del termination_proc
class testSlmRegistrationAndHeartbeat(unittest.TestCase): """ Tests the registration process of the SLM to the broker and the plugin manager, and the heartbeat process. """ def setUp(self): #a new SLM in another process for each test self.slm_proc = Process(target=ServiceLifecycleManager) self.slm_proc.daemon = True #make a new connection with the broker before each test self.manoconn = ManoBrokerRequestResponseConnection( 'son-plugin.SonPluginManager') #Some threading events that can be used during the tests self.wait_for_event = threading.Event() self.wait_for_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing the slm if self.slm_proc is not None: self.slm_proc.terminate() del self.slm_proc #Killing the connection with the broker try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event #Method that terminates the timer that waits for an event def eventFinished(self): self.wait_for_event.set() #Method that starts a timer, waiting for an event def waitForEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_event.wait(timeout): self.assertEqual(True, False, msg=msg) def testSlmHeartbeat(self): """ TEST: This test verifies whether the SLM sends out a heartbeat as intended, once it is registered and whether this heartbeat message is correctly formatted. """ def on_registration_trigger(ch, method, properties, message): """ When the registration request from the plugin is received, this method replies as if it were the plugin manager """ self.eventFinished() return json.dumps({'status': 'OK', 'uuid': self.uuid}) def on_heartbeat_receive(ch, method, properties, message): """ When the heartbeat message is received, this method checks if it is formatted correctly """ msg = json.loads(str(message)) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg="Message is not a dictionary.") #CHECK: The dictionary should have a key 'uuid'. self.assertTrue("uuid" in msg.keys(), msg="uuid is not a key.") #CHECK: The value of 'uuid' should be a string. self.assertTrue(isinstance(msg["uuid"], str), msg="uuid is not a string.") #CHECK: The uuid in the message should be the same as the assigned uuid. self.assertEqual(self.uuid, msg["uuid"], msg="uuid not correct.") #CHECK: The dictionary should have a key 'state'. self.assertTrue("state" in msg.keys(), msg="state is not a key.") #CHECK: The value of 'state' should be a 'READY', 'RUNNING', 'PAUSED' or 'FAILED'. self.assertTrue(msg["state"] in ["READY", "RUNNING", "PAUSED", "FAILED"], msg="Not a valid state.") #Stop the wait self.eventFinished() #STEP1: subscribe to the correct topics self.manoconn.register_async_endpoint( on_registration_trigger, 'platform.management.plugin.register') self.manoconn.subscribe( on_heartbeat_receive, 'platform.management.plugin.' + self.uuid + '.heartbeat') #STEP2: Start the SLM self.slm_proc.start() #STEP3: Wait until the registration request has been answered self.waitForEvent(msg="No registration request received") self.wait_for_event.clear() #STEP4: Wait until the heartbeat message is received. def testSlmRegistration(self): """ TEST: This test verifies whether the SLM is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. TODO: check properties def on_register_receive(ch, method, properties, message): msg = json.loads(str(message)) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the SLM self.slm_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent(timeout=5, msg="message not received.")
class TestPluginManagerBase(unittest.TestCase): """ Commen functionalities used my many test cases """ pm_proc = None @classmethod def setUpClass(cls): # start the plugin manger in another process so that we can connect to it using its broker interface cls.pm_proc = Process(target=SonPluginManager) cls.pm_proc.daemon = True cls.pm_proc.start() time.sleep(1) # give the plugin manager some time to start @classmethod def tearDownClass(cls): if cls.pm_proc is not None: cls.pm_proc.terminate() del cls.pm_proc def setUp(self): # initialize messaging subsystem self.m = ManoBrokerRequestResponseConnection("pm-client" + self.id()) self.wait_for_reply = threading.Event() self.plugin_uuid = None def tearDown(self): self.m.stop_connection() self.m.stop_threads() del self.m def waitForMessage(self, timeout=5): self.wait_for_reply.clear() if not self.wait_for_reply.wait(timeout): raise Exception("Timeout in wait for reply message.") def messageReceived(self): self.wait_for_reply.set() def register(self): """ Helper: We need this in many tests. :return: """ def on_register_reply(ch, method, properties, message): msg = json.loads(str(message)) assert(msg.get("status") == "OK") assert(len(msg.get("uuid")) > 0) assert(msg.get("error") is None) # set internal state variables self.plugin_uuid = msg.get("uuid") # stop waiting self.messageReceived() # create register request message msg = dict(name="test-plugin", version="v0.01", description="description") # do the registration call self.m.call_async(on_register_reply, "platform.management.plugin.register", json.dumps(msg)) # make our test synchronous: wait self.waitForMessage() def deregister(self): """ Helper: We need this in many tests. :return: """ assert(self.plugin_uuid is not None) def on_deregister_reply(ch, method, properties, message): msg = json.loads(str(message)) assert(msg.get("status") == "OK") # stop waiting self.messageReceived() # create register request message msg = dict(uuid=self.plugin_uuid) # do the registration call self.m.call_async(on_deregister_reply, "platform.management.plugin.deregister", json.dumps(msg)) # make our test synchronous: wait self.waitForMessage()
class testSlmFunctionality(unittest.TestCase): """ Tests the tasks that the SLM should perform in the service life cycle of the network services. """ slm_proc = None uuid = '1' corr_id = '1ba347d6-6210-4de7-9ca3-a383e50d0330' ######################## #SETUP ######################## def setUp(self): def on_register_trigger(ch, method, properties, message): return json.dumps({'status': 'OK', 'uuid': self.uuid}) #vnfcounter for when needed self.vnfcounter = 0 #Generate a new corr_id for every test self.corr_id = str(uuid.uuid4()) #a new SLM in another process for each test self.slm_proc = ServiceLifecycleManager(auto_register=False, start_running=False) #We make a spy connection to listen to the different topics on the broker self.manoconn_spy = ManoBrokerRequestResponseConnection( 'son-plugin.SonSpy') #we need a connection to simulate messages from the gatekeeper self.manoconn_gk = ManoBrokerRequestResponseConnection( 'son-plugin.SonGateKeeper') #we need a connection to simulate messages from the infrastructure adaptor self.manoconn_ia = ManoBrokerRequestResponseConnection( 'son-plugin.SonInfrastructureAdapter') #Some threading events that can be used during the tests self.wait_for_first_event = threading.Event() self.wait_for_first_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing the slm self.slm_proc.manoconn.stop_connection() self.slm_proc.manoconn.stop_threads() try: del self.slm_proc except: pass #Killing the connection with the broker self.manoconn_spy.stop_connection() self.manoconn_gk.stop_connection() self.manoconn_ia.stop_connection() self.manoconn_spy.stop_threads() self.manoconn_gk.stop_threads() self.manoconn_ia.stop_threads() del self.manoconn_spy del self.manoconn_gk del self.manoconn_ia del self.wait_for_first_event ######################## #GENERAL ######################## def createGkNewServiceRequestMessage(self, correctlyFormatted=True): """ This method helps creating messages for the service request packets. If it needs to be wrongly formatted, the nsd part of the request is removed. """ path_descriptors = '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/' nsd_descriptor = open(path_descriptors + 'sonata-demo.yml', 'r') vnfd1_descriptor = open(path_descriptors + 'firewall-vnfd.yml', 'r') vnfd2_descriptor = open(path_descriptors + 'iperf-vnfd.yml', 'r') vnfd3_descriptor = open(path_descriptors + 'tcpdump-vnfd.yml', 'r') #import the nsd and vnfds that form the service if correctlyFormatted: service_request = { 'NSD': yaml.load(nsd_descriptor), 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } else: service_request = { 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } return yaml.dump(service_request) #Method that terminates the timer that waits for an event def firstEventFinished(self): self.wait_for_first_event.set() #Method that starts a timer, waiting for an event def waitForFirstEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_first_event.wait(timeout): self.assertEqual(True, False, msg=msg) def dummy(self, ch, method, properties, message): """ Sometimes, we need a cbf for a async_call, without actually using it. """ return ############################################################# #TEST1: test validate_deploy_request ############################################################# def test_validate_deploy_request(self): """ The method validate_deploy_request is used to check whether the received message that requests the deployment of a new service is correctly formatted. """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'original_corr_id': corr_id} #SUBTEST1: Check a correctly formatted message message = self.createGkNewServiceRequestMessage() service_dict[service_id]['payload'] = yaml.load(message) self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, { 'status': 'INSTANTIATING', 'error': None }, msg="outcome and expected result not equal SUBTEST1.") #SUBTEST2: Check a message that is not a dictionary message = "test message" service_dict[service_id]['payload'] = message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": payload is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST2.") #SUBTEST3: Check a message that contains no NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) del loaded_message['NSD'] service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": NSD is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST3.") #SUBTEST4: The number of VNFDs must be the same as listed in the NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['NSD']['network_functions'].append({}) service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": # of VNFDs doesn't match NSD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST4.") #SUBTEST5: VNFDs can not be empty message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['VNFD1'] = None service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": empty VNFD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST5.") ########################################################### #TEST2: Test start_next_task ########################################################### def test_start_next_task(self): """ This method tests the start_next_task method """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'corr_id': corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': True, 'kill_chain': False } #SUBTEST1: Check if next task is correctly called message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = ['validate_deploy_request'] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result generated_response = { 'status': result[service_id]['status'], 'error': result[service_id]['error'] } expected_response = {'status': 'INSTANTIATING', 'error': None} self.assertEqual(generated_response, expected_response, msg="outcome and expected result not equal SUBTEST1.") #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'corr_id': corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': False, 'kill_chain': False } #SUBTEST2: Check behavior if there is no next task message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = [] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result: if successful, service_id will not be a key in result self.assertFalse(service_id in result.keys(), msg="key is part of ledger in SUBTEST2.") # ############################################################### # #TEST3: Test service_instance_create # ############################################################### # def test_service_instance_create(self): # """ # This method tests the service_instance_create method of the SLM # """ # #Setup # message = self.createGkNewServiceRequestMessage() # corr_id = str(uuid.uuid4()) # topic = "service.instances.create" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': "Gatekeeper"} # properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) # schedule = self.slm_proc.service_instance_create('foo', # 'bar', # properties, # message) # #Check result: since we don't know how many of the tasks # #were completed by the time we got the result, we only check # #the final elements in the tasklist # #The last 7 elements from the generated result # generated_result = schedule[-7:] # #The expected last 7 elements in the list # expected_result = ['SLM_mapping', 'ia_prepare', 'vnf_deploy', # 'vnf_chain', 'wan_configure', # 'instruct_monitoring', 'inform_gk'] # self.assertEqual(generated_result, # expected_result, # msg='lists are not equal') ############################################################### #TEST4: Test resp_topo ############################################################### def test_resp_topo(self): """ This method tests the resp_topo method. """ #Setup #Create topology message first = { 'vim_uuid': str(uuid.uuid4()), 'memory_used': 5, 'memory_total': 12, 'core_used': 4, 'core_total': 6 } second = { 'vim_uuid': str(uuid.uuid4()), 'memory_used': 3, 'memory_total': 5, 'core_used': 4, 'core_total': 5 } third = { 'vim_uuid': str(uuid.uuid4()), 'memory_used': 6, 'memory_total': 7, 'core_used': 2, 'core_total': 12 } topology_message = [first, second, third] payload = yaml.dump(topology_message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'infrastructure': { 'topology': None }, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "infrastructure.management.compute.list" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'InfrastructureAdaptor' } properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_topo('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(topology_message, result[service_id]['infrastructure']['topology'], msg="Dictionaries are not equal") ############################################################### #TEST5: Test resp_vnf_depl ############################################################### def test_resp_vnf_depl(self): """ This method tests the resp_vnf_depl method. """ #SUBTEST1: Only one VNFD in the service #Setup #Create the message vnfr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = {'status': 'DEPLOYED', 'error': None, 'vnfr': vnfr} payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'function': [{ 'id': vnfr['id'] }], 'vnfs_to_deploy': 1, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 1") self.assertEqual(result[service_id]['vnfs_to_deploy'], 0, msg="Values not equal SUBTEST 1") #SUBTEST2: Two VNFDs in the service #Setup #Create the message vnfr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = {'status': 'DEPLOYED', 'error': None, 'vnfr': vnfr} payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'function': [{ 'id': vnfr['id'] }], 'vnfs_to_deploy': 2, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 2") self.assertEqual(result[service_id]['vnfs_to_deploy'], 1, msg="Values not equal SUBTEST 2") self.assertEqual(result[service_id]['schedule'], ['get_ledger'], msg="Lists not equal SUBTEST 2") ############################################################### #TEST6: Test resp_prepare ############################################################### def test_resp_prepare(self): """ This method tests the resp_prepare method. """ #SUBTEST 1: Successful response message #Setup #Create the message message = { 'request_status': 'COMPLETED', 'error': None, } payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "infrastructure.service.prepare" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'InfrastructureAdaptor' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_prepare('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertFalse('status' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1") self.assertFalse('error' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1") #SUBTEST 2: Failed response message def on_test_resp_prepare_subtest2(ch, mthd, prop, payload): message = yaml.load(payload) self.assertEqual(message['status'], 'ERROR', msg="Status not correct in SUBTEST 1") self.assertEqual(message['error'], 'BAR', msg="Error not correct in SUBTEST 1") self.assertTrue('timestamp' in message.keys(), msg="Timestamp missing in SUBTEST 1") self.assertEqual(len(message.keys()), 3, msg="Number of keys not correct in SUBTEST1") self.firstEventFinished() #Setup #Create the message message = { 'request_status': 'FOO', 'message': 'BAR', } payload = yaml.dump(message) #Listen on feedback topic self.manoconn_gk.subscribe(on_test_resp_prepare_subtest2, 'service.instances.create') #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "infrastructure.service.prepare" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'InfrastructureAdaptor' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_prepare('foo', 'bar', properties, payload) #Wait for the test to finish self.waitForFirstEvent(timeout=5) ############################################################### #TEST7: test contact_gk ############################################################### def test_contact_gk(self): """ This method tests the contact_gk method. """ #Check result SUBTEST 1 def on_contact_gk_subtest1(ch, mthd, prop, payload): message = yaml.load(payload) self.assertEqual(message['status'], 'FOO', msg="Status not correct in SUBTEST 1") self.assertEqual(message['error'], 'BAR', msg="Error not correct in SUBTEST 1") self.assertTrue('timestamp' in message.keys(), msg="Timestamp missing in SUBTEST 1") self.assertEqual(len(message.keys()), 3, msg="Number of keys not correct in SUBTEST1") self.firstEventFinished() #Check result SUBTEST2 def on_contact_gk_subtest2(ch, mthd, prop, payload): self.firstEventFinished() message = yaml.load(payload) self.assertEqual(message['status'], 'FOO', msg="Status not correct in SUBTEST 2") self.assertEqual(message['error'], 'BAR', msg="Error not correct in SUBTEST 2") self.assertEqual(message['FOO'], 'BAR', msg="Error not correct in SUBTEST 2") self.assertTrue('timestamp' in message.keys(), msg="Timestamp missing in SUBTEST 2") self.assertEqual(len(message.keys()), 4, msg="Number of keys not correct in SUBTEST2") #SUBTEST1: Without additional content #Setup #Create the ledger self.wait_for_first_event.clear() service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'status': 'FOO', 'error': 'BAR', 'kill_chain': False } #Set the ledger self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_spy.subscribe(on_contact_gk_subtest1, 'service.instances.create') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.contact_gk(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5) #SUBTEST2: With additional content #Setup self.wait_for_first_event.clear() #Create the ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) add_content = {'FOO': 'BAR'} service_dict[service_id] = { 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'status': 'FOO', 'error': 'BAR', 'add_content': add_content } self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_gk.subscribe(on_contact_gk_subtest2, 'service.instances.create') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.contact_gk(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5) ############################################################### #TEST8: test request_topology ############################################################### def test_request_topology(self): """ This method tests the request_topology method. """ #Check result SUBTEST 1 def on_request_topology_subtest1(ch, mthd, prop, payload): self.assertEqual(payload, "{}", msg="Payload is not empty") self.firstEventFinished() #SUBTEST1: Trigger request_topology #Setup #Create the ledger self.wait_for_first_event.clear() service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False, 'status': 'FOO', 'error': 'BAR', 'infrastructure': {} } #Set the ledger self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_spy.subscribe(on_request_topology_subtest1, 'infrastructure.management.compute.list') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.request_topology(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5) ############################################################### #TEST9: test ia_prepare ############################################################### # def test_ia_prepare(self): # """ # This method tests the request_topology method. # """ # #Check result SUBTEST 1 # def on_ia_prepare_subtest1(ch, mthd, prop, payload): # message = yaml.load(payload) # for func in service_dict[service_id]['function']: # self.assertIn(func['vim_uuid'], # message.keys(), # msg="VIM uuid missing from keys") # image = func['vnfd']['virtual_deployment_units'][0]['vm_image'] # self.assertIn(image, # message[func['vim_uuid']]['vm_images'], # msg="image not on correct Vim") # self.firstEventFinished() # #SUBTEST1: Check ia_prepare message if functions are mapped on # # different VIMs. # #Setup # #Create the ledger # self.wait_for_first_event.clear() # service_dict = {} # service_id = str(uuid.uuid4()) # corr_id = str(uuid.uuid4()) # service_dict[service_id] = {'schedule': ['get_ledger'], # 'original_corr_id':corr_id, # 'pause_chain': True, # 'kill_chain': False, # 'function': []} # path = '/plugins/son-mano-service-lifecycle-management/test/' # message = {} # message['instance_id'] = service_id # vnfd1 = open(path + 'test_descriptors/firewall-vnfd.yml', 'r') # vnfd2 = open(path + 'test_descriptors/iperf-vnfd.yml', 'r') # vnfd3 = open(path + 'test_descriptors/tcpdump-vnfd.yml', 'r') # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd1)}) # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd2)}) # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd3)}) # for vnfd in service_dict[service_id]['function']: # vim_uuid = str(uuid.uuid4()) # vnfd['vim_uuid'] = vim_uuid # #Set the ledger # self.slm_proc.set_services(service_dict) # #Spy the message bus # self.manoconn_spy.subscribe(on_ia_prepare_subtest1, # 'infrastructure.service.prepare') # #Wait until subscription is completed # time.sleep(0.1) # #Run the method # self.slm_proc.ia_prepare(service_id) # #Wait for the test to finish # self.waitForFirstEvent(timeout=5) # #SUBTEST2: Check ia_prepare message if functions are mapped on # # same VIMs. # #Setup # #Create the ledger # self.wait_for_first_event.clear() # service_dict = {} # service_id = str(uuid.uuid4()) # corr_id = str(uuid.uuid4()) # service_dict[service_id] = {'schedule': ['get_ledger'], # 'original_corr_id':corr_id, # 'pause_chain': True, # 'kill_chain': False, # 'function': []} # path = '/plugins/son-mano-service-lifecycle-management/test/' # vnfd1 = open(path + 'test_descriptors/firewall-vnfd.yml', 'r') # vnfd2 = open(path + 'test_descriptors/iperf-vnfd.yml', 'r') # vnfd3 = open(path + 'test_descriptors/tcpdump-vnfd.yml', 'r') # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd1)}) # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd2)}) # service_dict[service_id]['function'].append({'vnfd': yaml.load(vnfd3)}) # vim_uuid = str(uuid.uuid4()) # for vnfd in service_dict[service_id]['function']: # vnfd['vim_uuid'] = vim_uuid # #Set the ledger # self.slm_proc.set_services(service_dict) # #Run the method # self.slm_proc.ia_prepare(service_id) # #Wait for the test to finish # self.waitForFirstEvent(timeout=5) ############################################################### #TEST10: test vnf_deploy ############################################################### def test_vnf_deploy(self): """ This method tests the request_topology method. """ #Check result SUBTEST 1 def on_vnf_deploy_subtest1(ch, mthd, prop, payload): message = yaml.load(payload) self.assertIn(message, service_dict[service_id]['function'], msg="Payload is not correct") self.vnfcounter = self.vnfcounter + 1 if self.vnfcounter == len(service_dict[service_id]['function']): self.firstEventFinished() #SUBTEST1: Run test #Setup #Create the ledger self.wait_for_first_event.clear() service_dict = {} self.vnfcounter = 0 service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False, 'function': [] } path = '/plugins/son-mano-service-lifecycle-management/test/' vnfd1 = open(path + 'test_descriptors/firewall-vnfd.yml', 'r') vnfd2 = open(path + 'test_descriptors/iperf-vnfd.yml', 'r') vnfd3 = open(path + 'test_descriptors/tcpdump-vnfd.yml', 'r') service_dict[service_id]['function'].append({ 'vnfd': yaml.load(vnfd1), 'id': str(uuid.uuid4()), 'vim_uuid': str(uuid.uuid4()) }) service_dict[service_id]['function'].append({ 'vnfd': yaml.load(vnfd2), 'id': str(uuid.uuid4()), 'vim_uuid': str(uuid.uuid4()) }) service_dict[service_id]['function'].append({ 'vnfd': yaml.load(vnfd3), 'id': str(uuid.uuid4()), 'vim_uuid': str(uuid.uuid4()) }) #Set the ledger self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_spy.subscribe(on_vnf_deploy_subtest1, 'mano.function.deploy') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.vnf_deploy(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5) #SUBTEST2: TODO: test that only one message is sent per vnf ############################################################################### #TEST11: Test build_monitoring_message ############################################################################### def test_build_monitoring_message(self): """ This method tests the build_monitoring_message method """ #Setup gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #add ids to NSD and VNFDs (those used in the expected message) gk_request['NSD']['uuid'] = '005606ed-be7d-4ce3-983c-847039e3a5a2' gk_request['VNFD1']['uuid'] = '6a15313f-cb0a-4540-baa2-77cc6b3f5b68' gk_request['VNFD2']['uuid'] = '645db4fa-a714-4cba-9617-4001477d1281' gk_request['VNFD3']['uuid'] = '8a0aa837-ec1c-44e5-9907-898f6401c3ae' #load nsr_file, containing both NSR and the list of VNFRs message_from_ia = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) nsr_file = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-nsr.yml', 'r')) vnfrs_file = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-vnfrs.yml', 'r')) vnfd_firewall = gk_request['VNFD1'] vnfd_iperf = gk_request['VNFD2'] vnfd_tcpdump = gk_request['VNFD3'] vnfr_firewall = vnfrs_file[1] vnfr_iperf = vnfrs_file[0] vnfr_tcpdump = vnfrs_file[2] service = { 'nsd': gk_request['NSD'], 'nsr': nsr_file, 'vim_uuid': message_from_ia['instanceVimUuid'] } functions = [] functions.append({ 'vnfr': vnfr_iperf, 'vnfd': vnfd_iperf, 'id': vnfr_iperf['id'] }) functions.append({ 'vnfr': vnfr_firewall, 'vnfd': vnfd_firewall, 'id': vnfr_firewall['id'] }) functions.append({ 'vnfr': vnfr_tcpdump, 'vnfd': vnfd_tcpdump, 'id': vnfr_tcpdump['id'] }) #Call the method message = tools.build_monitoring_message(service, functions) #Load expected results expected_message = json.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/monitoring-message.json', 'r')) #Check result self.assertEqual(message, expected_message, "messages are not equals")
class testSlmFunctionality(unittest.TestCase): """ Tests the tasks that the SLM should perform in the service life cycle of the network services. """ slm_proc = None manoconn_pm = None uuid = '1' corr_id = '1ba347d6-6210-4de7-9ca3-a383e50d0330' ######################## #SETUP ######################## # @classmethod # def setUpClass(cls): # """ # Starts the SLM instance and takes care if its registration. # """ # def on_register_trigger(ch, method, properties, message): # return json.dumps({'status':'OK','uuid':cls.uuid}) # #Some threading events that can be used during the tests # cls.wait_for_first_event = threading.Event() # cls.wait_for_first_event.clear() # cls.wait_for_second_event = threading.Event() # cls.wait_for_second_event.clear() #Deploy SLM and a connection to the broker # cls.slm_proc = Process(target=ServiceLifecycleManager) # cls.slm_proc.daemon = True # cls.manoconn_pm = ManoBrokerRequestResponseConnection('Son-plugin.SonPluginManager') # cls.manoconn_pm.subscribe(on_register_trigger,'platform.management.plugin.register') # cls.slm_proc.start() #wait until registration process finishes # if not cls.wait_for_first_event.wait(timeout=5): # pass @classmethod def tearDownClass(cls): if cls.slm_proc is not None: cls.slm_proc.terminate() del cls.slm_proc # cls.manoconn_pm.stop_connection() def setUp(self): def on_register_trigger(ch, method, properties, message): return json.dumps({'status': 'OK', 'uuid': self.uuid}) #Generate a new corr_id for every test self.corr_id = str(uuid.uuid4()) #Some threading events that can be used during the tests self.wait_for_first_event = threading.Event() self.wait_for_first_event.clear() self.wait_for_second_event = threading.Event() self.wait_for_second_event.clear() #Deploy SLM and a connection to the broker self.slm_proc = Process(target=ServiceLifecycleManager) self.slm_proc.daemon = True self.manoconn_pm = ManoBrokerRequestResponseConnection( 'son-plugin.SonPluginManager') self.manoconn_pm.subscribe(on_register_trigger, 'platform.management.plugin.register') self.slm_proc.start() #wait until registration process finishes if not self.wait_for_first_event.wait(timeout=5): pass #We make a spy connection to listen to the different topics on the broker self.manoconn_spy = ManoBrokerRequestResponseConnection( 'son-plugin.SonSpy') #we need a connection to simulate messages from the gatekeeper self.manoconn_gk = ManoBrokerRequestResponseConnection( 'son-plugin.SonGateKeeper') #we need a connection to simulate messages from the infrastructure adaptor self.manoconn_ia = ManoBrokerRequestResponseConnection( 'son-plugin.SonInfrastructureAdapter') def tearDown(self): try: self.manoconn_spy.stop_connection() self.manoconn_gk.stop_connection() self.manoconn_ia.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") ######################## #GENERAL ######################## def createGkNewServiceRequestMessage(self, correctlyFormatted=True): """ This method helps creating messages for the service request packets. If it needs to be wrongly formatted, the nsd part of the request is removed. """ path_descriptors = '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/' nsd_descriptor = open(path_descriptors + 'sonata-demo.yml', 'r') vnfd1_descriptor = open(path_descriptors + 'firewall-vnfd.yml', 'r') vnfd2_descriptor = open(path_descriptors + 'iperf-vnfd.yml', 'r') vnfd3_descriptor = open(path_descriptors + 'tcpdump-vnfd.yml', 'r') #import the nsd and vnfds that form the service if correctlyFormatted: service_request = { 'NSD': yaml.load(nsd_descriptor), 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } else: service_request = { 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } return yaml.dump(service_request) #Method that terminates the timer that waits for an event def firstEventFinished(self): self.wait_for_first_event.set() def secondEventFinished(self): self.wait_for_second_event.set() #Method that starts a timer, waiting for an event def waitForFirstEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_first_event.wait(timeout): self.assertEqual(True, False, msg=msg) def waitForSecondEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_second_event.wait(timeout): self.assertEqual(True, False, msg=msg) def dummy(self, ch, method, properties, message): """ Sometimes, we need a cbf for a async_call, without actually needing it. """ return ############################################################# #TEST1: Test Reaction To Correctly Formatted Service Request. ############################################################# def on_slm_infra_adaptor_vim_list_test1(self, ch, method, properties, message): """ This method checks what the SLM sends towards the IA when it receives a valid request from the gk. """ msg = yaml.load(message) #The message should have an empty body and a correlation_id different from the original correlation_id self.assertEqual(msg, {}, msg='message is not empty.') self.assertNotEqual( properties.correlation_id, self.corr_id, msg='message does not contain a new correlation_id.') self.assertEqual(properties.reply_to, 'infrastructure.management.compute.list', msg='not the correct reply_to topic.') self.firstEventFinished() def on_gk_response_to_correct_service_request(self, ch, method, properties, message): """ This method checks whether the SLM responds to a correctly formatted new service request it receives from the GK. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='response to service request is not a dictionary.') self.assertEqual(msg['status'], 'INSTANTIATING', msg='not correct response, should be INSTANTIATING.') self.assertEqual(msg['error'], None, msg='not correct response, should be None.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float') self.assertEqual( properties.correlation_id, self.corr_id, msg='response to async call doesnt have the same correlation_id') self.secondEventFinished() def testReactionToCorrectlyFormattedServiceRequest(self): """ If the gk sends a request on the service.instances.create topic that is correctly formatted, then the SLM should respond by doing 2 things: 1. Replying with the message {'status':'INSTANTIATING', 'error':NULL, 'timestamp':<timestamp>} with the same correlation_id as the one in the request. 2. Requesting the available vims from the IA on the infrastructure.management.compute.list topic with a new correlation id and an empty body. """ self.wait_for_first_event.clear() self.wait_for_second_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test1, 'infrastructure.management.compute.list') #STEP2: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async( self.on_gk_response_to_correct_service_request, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP3: Start waiting for the messages that are triggered by this request self.waitForFirstEvent( timeout=10, msg= 'Wait for message from SLM to IA to request resources timed out.') self.waitForSecondEvent( timeout=10, msg='Wait for reply to request from GK timed out.') ########################################################### #TEST2: Test reaction to wrongly formatted service request. ########################################################### def on_gk_response_to_wrong_service_request(self, ch, method, properties, message): """ This method checks whether the SLM responds to a wrongly formatted new service request it receives from the GK. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='response to service request is not a dictionary.') self.assertEqual(msg['status'], 'ERROR', msg='not correct response, should be ERROR') self.assertTrue(isinstance(msg['error'], str), msg='Error message is not a string.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float') self.assertEqual( properties.correlation_id, self.corr_id, msg='response to async call doesnt have the same correlation_id') self.firstEventFinished() def testReactionToWronglyFormattedServiceRequest(self): """ If the gk sends a request on the service.instances.create topic that is wrongly formatted, then the SLM should respond by replying with the message {'status':'ERROR', 'error':<error message>, 'timestamp':<timestamp>} with the same correlation_id as the one in the request. """ self.wait_for_first_event.clear() #STEP1: Send a wrongly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async( self.on_gk_response_to_wrong_service_request, 'service.instances.create', msg=self.createGkNewServiceRequestMessage( correctlyFormatted=False), content_type='application/yaml', correlation_id=self.corr_id) #STEP2: Start waiting for the messages that are triggered by this request self.waitForFirstEvent( timeout=10, msg='Wait for reply to request from GK timed out.') ############################################################### #TEST3: Test Reaction when SLM receives a valid list of VIMs. ############################################################### def on_slm_infra_adaptor_vim_list_test3(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [{ 'vim_uuid': uuid.uuid4().hex }, { 'vim_uuid': uuid.uuid4().hex }, { 'vim_uuid': uuid.uuid4().hex }] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_infra_adaptor_service_deploy_request_test3( self, ch, method, properties, message): """ This method checks whether the request from the SLM to the IA to deploy a service is correctly formatted. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg="message is not a dictionary.") self.assertIn('vim_uuid', msg.keys(), msg="vim_uuid is not a key in the dictionary.") self.assertIn('nsd', msg.keys(), msg="nsd is not a key in the dictionary.") self.assertIn('vnfds', msg.keys(), msg="vnfds is not a key in the dictionary.") self.assertIn('instance_uuid', msg['nsd'].keys(), msg="instance_uuid is not a key in the dictionary.") for vnfd in msg['vnfds']: self.assertIn('instance_uuid', vnfd.keys(), msg='intance_uuid is not a key in the dictionary.') self.firstEventFinished() def testReactionToCorrectlyFormattedVimList(self): """ This method tests the response of the SLM when it receives a valid VIM list. The SLM should choose a VIM out of the list, and request whether it has enough resources to host the service. """ self.wait_for_first_event.clear() self.wait_for_second_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test3, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the infrastructure adaptor the first time, to request the resource availability. self.manoconn_spy.subscribe( self.on_slm_infra_adaptor_service_deploy_request_test3, 'infrastructure.service.deploy') #STEP3: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async( self.dummy, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP4: Start waiting for the messages that are triggered by this request self.waitForFirstEvent( timeout=10, msg= 'Wait for message from SLM to IA to request resources timed out.') ############################################################### #TEST4: Test Reaction when SLM receives an empty list of VIMs. ############################################################### def on_slm_infra_adaptor_vim_list_test4(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_response_to_gk_with_empty_vim_list(self, ch, method, properties, message): """ This method checks the content of the message send from SLM to the GK to indicate that there are no vims available. """ msg = yaml.load(message) #We don't want to trigger on the first response (the async_call), butonly on the second(the notify) and we don't want to trigger on our outgoing message. if properties.app_id == 'son-plugin.ServiceLifecycleManager': if msg['status'] != 'INSTANTIATING': self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary.') self.assertEqual(msg['status'], 'ERROR', msg='status is not correct.') self.assertEqual(msg['error'], 'No VIM.', msg='error message is not correct.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float.') self.firstEventFinished() def testReactionToWronglyFormattedVimList(self): """ This method tests the response of the SLM when it receives an empty VIM list. The SLM should report back to the gk with an error. """ self.wait_for_first_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test4, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the GK, to indicate that the deployment is stopped due to lack of resources. self.manoconn_spy.subscribe( self.on_slm_response_to_gk_with_empty_vim_list, 'service.instances.create') #STEP3: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async( self.on_slm_response_to_gk_with_empty_vim_list, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP4: Start waiting for the messages that are triggered by this request self.waitForFirstEvent( timeout=10, msg= 'Wait for message from SLM to IA to request resources timed out.') ############################################################################### #TEST7: Test reaction to negative response on deployment message to/from IA ############################################################################### def on_slm_infra_adaptor_vim_list_test7(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [{'vim_uuid': uuid.uuid4().hex}] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_infra_adaptor_service_deploy_request_test7( self, ch, method, properties, message): """ This method fakes a message from the IA to the SLM that indicates that the deployment has failed. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': reply_message = {'request_status': 'failed'} self.manoconn_ia.notify('infrastructure.service.deploy', yaml.dump(reply_message), correlation_id=properties.correlation_id) def on_slm_gk_service_deploy_request_failed(self, ch, method, properties, message): """ This method checks whether the message from the SLM to the GK to indicate that the deployment failed is correctly formatted. """ msg = yaml.load(message) #We don't want to trigger on the first response (the async_call), but only on the second(the notify) and we don't want to trigger on our outgoing message. if properties.app_id == 'son-plugin.ServiceLifecycleManager': if msg['status'] != 'INSTANTIATING': self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary.') self.assertEqual(msg['status'], "ERROR", msg='status is not correct.') self.assertEqual(msg['error'], 'Deployment result: failed', msg='error message is not correct.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float.') self.firstEventFinished() def testReactionToNegativeReplyOnDeploymentFromIA(self): """ When the SLM contacts the IA to request whether enough resources are available, it gets a response from the IA. If this response indicates that the resources are available, the SLM should requestthe deployment of the service to the IA. """ self.wait_for_first_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test7, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the IA the second time, to request the deployment of the service self.manoconn_ia.subscribe( self.on_slm_infra_adaptor_service_deploy_request_test7, 'infrastructure.service.deploy') #STEP3: Spy the topic on which the SLM will contact the GK to respond that the deployment has failed. self.manoconn_gk.subscribe( self.on_slm_gk_service_deploy_request_failed, 'service.instances.create') #STEP4: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async( self.dummy, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP5: Start waiting for the messages that are triggered by this request self.waitForFirstEvent( timeout=15, msg= 'Wait for message from SLM to IA to request deployment timed out.') ############################################################################### #TEST8: Test Monitoring message creation. ############################################################################### def testMonitoringMessageGeneration(self): """ SLM should generate a message for the monitoring module in order to start the monitoring process to the deployed network service. This message is generated from the information existing in NSD, VNFDs, NSRs and VNFs. The test checks that, given the sonata-demo network service, SLM correctly generates the expected message for the monitoring module. """ #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: add ids to NSD and VNFDs (those used in the expected message) gk_request['NSD']['uuid'] = '005606ed-be7d-4ce3-983c-847039e3a5a2' gk_request['VNFD1']['uuid'] = '6a15313f-cb0a-4540-baa2-77cc6b3f5b68' gk_request['VNFD2']['uuid'] = '645db4fa-a714-4cba-9617-4001477d1281' gk_request['VNFD3']['uuid'] = '8a0aa837-ec1c-44e5-9907-898f6401c3ae' #STEP3: load nsr_file, containing both NSR and the list of VNFRs message_from_ia = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) nsr_file = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-nsr.yml', 'r')) vnfrs_file = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-vnfrs.yml', 'r')) #STEP4: call real method message = tools.build_monitoring_message(gk_request, message_from_ia, nsr_file, vnfrs_file) #STEP5: read expected message from descriptor file expected_message = json.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/monitoring-message.json', 'r')) #STEP6: compare that generated message is equals to the expected one self.assertEqual(message, expected_message, "messages are not equals") ############################################################################### #TEST9: Test creation of the message addressed to the Monitoring Repository ############################################################################### def testNsrCreation(self): """ Once the Infrastructure Adapter has deployed the network service, it would build the entire NSR from the information provided by the Infrastructure Adapter. This test checks that, given the sonata-demo network service, the IA is able to build the correct NSR. """ #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: read IA response and the expected NSR ia_nsr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) expected_nsr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-nsr.yml', 'r')) #STEP3: call real method message = tools.build_nsr(gk_request, ia_nsr) #STEP4: comprare the generated message is equals to the expected one self.assertEqual(message, expected_nsr, "Built NSR is not equal to the expected one") ############################################################################### #TEST10: Test creation of the NSR ############################################################################### def testVnfrsCreation(self): #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: read IA response and the expected NSR ia_nsr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) expected_vnfrs = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-vnfrs.yml', 'r')) message = tools.build_vnfrs(gk_request, ia_nsr['vnfrs']) self.assertEqual(message, expected_vnfrs, "Built VNFRs are not equals to the expected ones")
class testSlmRegistrationAndHeartbeat(unittest.TestCase): """ Tests the registration process of the SLM to the broker and the plugin manager, and the heartbeat process. """ def setUp(self): #a new SLM in another process for each test self.slm_proc = Process(target=ServiceLifecycleManager) self.slm_proc.daemon = True #make a new connection with the broker before each test self.manoconn = ManoBrokerRequestResponseConnection('son-plugin.SonPluginManager') #Some threading events that can be used during the tests self.wait_for_event = threading.Event() self.wait_for_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing the slm if self.slm_proc is not None: self.slm_proc.terminate() del self.slm_proc #Killing the connection with the broker try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event #Method that terminates the timer that waits for an event def eventFinished(self): self.wait_for_event.set() #Method that starts a timer, waiting for an event def waitForEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_event.wait(timeout): self.assertEqual(True, False, msg=msg) def testSlmHeartbeat(self): """ TEST: This test verifies whether the SLM sends out a heartbeat as intended, once it is registered and whether this heartbeat message is correctly formatted. """ def on_registration_trigger(ch, method, properties, message): """ When the registration request from the plugin is received, this method replies as if it were the plugin manager """ self.eventFinished() return json.dumps({'status': 'OK', 'uuid': self.uuid}) def on_heartbeat_receive(ch, method, properties, message): """ When the heartbeat message is received, this method checks if it is formatted correctly """ msg = json.loads(str(message)) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg="Message is not a dictionary.") #CHECK: The dictionary should have a key 'uuid'. self.assertTrue("uuid" in msg.keys(), msg="uuid is not a key.") #CHECK: The value of 'uuid' should be a string. self.assertTrue(isinstance(msg["uuid"], str), msg="uuid is not a string.") #CHECK: The uuid in the message should be the same as the assigned uuid. self.assertEqual(self.uuid, msg["uuid"], msg="uuid not correct.") #CHECK: The dictionary should have a key 'state'. self.assertTrue("state" in msg.keys(), msg="state is not a key.") #CHECK: The value of 'state' should be a 'READY', 'RUNNING', 'PAUSED' or 'FAILED'. self.assertTrue(msg["state"] in ["READY", "RUNNING", "PAUSED", "FAILED"], msg="Not a valid state.") #Stop the wait self.eventFinished() #STEP1: subscribe to the correct topics self.manoconn.register_async_endpoint(on_registration_trigger, 'platform.management.plugin.register') self.manoconn.subscribe(on_heartbeat_receive, 'platform.management.plugin.' + self.uuid + '.heartbeat') #STEP2: Start the SLM self.slm_proc.start() #STEP3: Wait until the registration request has been answered self.waitForEvent(msg="No registration request received") self.wait_for_event.clear() #STEP4: Wait until the heartbeat message is received. def testSlmRegistration(self): """ TEST: This test verifies whether the SLM is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. TODO: check properties def on_register_receive(ch, method, properties, message): msg = json.loads(str(message)) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the SLM self.slm_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent(timeout=5, msg="message not received.")
class TestPluginManagerBase(unittest.TestCase): """ Commen functionalities used my many test cases """ pm_proc = None @classmethod def setUpClass(cls): # start the plugin manger in another process so that we can connect to it using its broker interface cls.pm_proc = Process(target=SonPluginManager) cls.pm_proc.daemon = True cls.pm_proc.start() time.sleep(1) # give the plugin manager some time to start @classmethod def tearDownClass(cls): if cls.pm_proc is not None: cls.pm_proc.terminate() del cls.pm_proc def setUp(self): # initialize messaging subsystem self.m = ManoBrokerRequestResponseConnection("pm-client" + self.id()) self.wait_for_reply = threading.Event() self.plugin_uuid = None def tearDown(self): self.m.stop_connection() self.m.stop_threads() del self.m def waitForMessage(self, timeout=5): self.wait_for_reply.clear() if not self.wait_for_reply.wait(timeout): raise Exception("Timeout in wait for reply message.") def messageReceived(self): self.wait_for_reply.set() def register(self): """ Helper: We need this in many tests. :return: """ def on_register_reply(ch, method, properties, message): msg = json.loads(str(message)) assert(msg.get("status") == "OK") assert(len(msg.get("uuid")) > 0) assert(msg.get("error") is None) # set internal state variables self.plugin_uuid = msg.get("uuid") # stop waiting self.messageReceived() # create register request message msg = dict(name="test-plugin", version="v0.01", description="description") # do the registration call self.m.call_async(on_register_reply, "platform.management.plugin.register", json.dumps(msg)) # make our test synchronous: wait self.waitForMessage() def deregister(self): """ Helper: We need this in many tests. :return: """ assert(self.plugin_uuid is not None) def on_deregister_reply(ch, method, properties, message): msg = json.loads(str(message)) assert(msg.get("status") == "OK") # stop waiting self.messageReceived() # create register request message msg = dict(uuid=self.plugin_uuid) # do the registration call self.m.call_async(on_deregister_reply, "platform.management.plugin.deregister", json.dumps(msg)) # make our test synchronous: wait self.waitForMessage()
class testSlmFunctionality(unittest.TestCase): """ Tests the tasks that the SLM should perform in the service life cycle of the network services. """ slm_proc = None manoconn_pm = None uuid = '1' corr_id = '1ba347d6-6210-4de7-9ca3-a383e50d0330' ######################## #SETUP ######################## # @classmethod # def setUpClass(cls): # """ # Starts the SLM instance and takes care if its registration. # """ # def on_register_trigger(ch, method, properties, message): # return json.dumps({'status':'OK','uuid':cls.uuid}) # #Some threading events that can be used during the tests # cls.wait_for_first_event = threading.Event() # cls.wait_for_first_event.clear() # cls.wait_for_second_event = threading.Event() # cls.wait_for_second_event.clear() #Deploy SLM and a connection to the broker # cls.slm_proc = Process(target=ServiceLifecycleManager) # cls.slm_proc.daemon = True # cls.manoconn_pm = ManoBrokerRequestResponseConnection('Son-plugin.SonPluginManager') # cls.manoconn_pm.subscribe(on_register_trigger,'platform.management.plugin.register') # cls.slm_proc.start() #wait until registration process finishes # if not cls.wait_for_first_event.wait(timeout=5): # pass @classmethod def tearDownClass(cls): if cls.slm_proc is not None: cls.slm_proc.terminate() del cls.slm_proc # cls.manoconn_pm.stop_connection() def setUp(self): def on_register_trigger(ch, method, properties, message): return json.dumps({'status': 'OK', 'uuid': self.uuid}) #Generate a new corr_id for every test self.corr_id = str(uuid.uuid4()) #Some threading events that can be used during the tests self.wait_for_first_event = threading.Event() self.wait_for_first_event.clear() self.wait_for_second_event = threading.Event() self.wait_for_second_event.clear() #Deploy SLM and a connection to the broker self.slm_proc = Process(target=ServiceLifecycleManager) self.slm_proc.daemon = True self.manoconn_pm = ManoBrokerRequestResponseConnection('son-plugin.SonPluginManager') self.manoconn_pm.subscribe(on_register_trigger, 'platform.management.plugin.register') self.slm_proc.start() #wait until registration process finishes if not self.wait_for_first_event.wait(timeout=5): pass #We make a spy connection to listen to the different topics on the broker self.manoconn_spy = ManoBrokerRequestResponseConnection('son-plugin.SonSpy') #we need a connection to simulate messages from the gatekeeper self.manoconn_gk = ManoBrokerRequestResponseConnection('son-plugin.SonGateKeeper') #we need a connection to simulate messages from the infrastructure adaptor self.manoconn_ia = ManoBrokerRequestResponseConnection('son-plugin.SonInfrastructureAdapter') def tearDown(self): try: self.manoconn_spy.stop_connection() self.manoconn_gk.stop_connection() self.manoconn_ia.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") ######################## #GENERAL ######################## def createGkNewServiceRequestMessage(self, correctlyFormatted=True): """ This method helps creating messages for the service request packets. If it needs to be wrongly formatted, the nsd part of the request is removed. """ path_descriptors = '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/' nsd_descriptor = open(path_descriptors + 'sonata-demo.yml', 'r') vnfd1_descriptor = open(path_descriptors + 'firewall-vnfd.yml', 'r') vnfd2_descriptor = open(path_descriptors + 'iperf-vnfd.yml', 'r') vnfd3_descriptor = open(path_descriptors + 'tcpdump-vnfd.yml', 'r') #import the nsd and vnfds that form the service if correctlyFormatted: service_request = {'NSD': yaml.load(nsd_descriptor), 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor)} else: service_request = {'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor)} return yaml.dump(service_request) #Method that terminates the timer that waits for an event def firstEventFinished(self): self.wait_for_first_event.set() def secondEventFinished(self): self.wait_for_second_event.set() #Method that starts a timer, waiting for an event def waitForFirstEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_first_event.wait(timeout): self.assertEqual(True, False, msg=msg) def waitForSecondEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_second_event.wait(timeout): self.assertEqual(True, False, msg=msg) def dummy(self, ch, method, properties, message): """ Sometimes, we need a cbf for a async_call, without actually needing it. """ return ############################################################# #TEST1: Test Reaction To Correctly Formatted Service Request. ############################################################# def on_slm_infra_adaptor_vim_list_test1(self, ch, method, properties, message): """ This method checks what the SLM sends towards the IA when it receives a valid request from the gk. """ msg = yaml.load(message) #The message should have an empty body and a correlation_id different from the original correlation_id self.assertEqual(msg, {}, msg='message is not empty.') self.assertNotEqual(properties.correlation_id, self.corr_id, msg='message does not contain a new correlation_id.') self.assertEqual(properties.reply_to, 'infrastructure.management.compute.list', msg='not the correct reply_to topic.') self.firstEventFinished() def on_gk_response_to_correct_service_request(self, ch, method, properties, message): """ This method checks whether the SLM responds to a correctly formatted new service request it receives from the GK. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='response to service request is not a dictionary.') self.assertEqual(msg['status'], 'INSTANTIATING', msg='not correct response, should be INSTANTIATING.') self.assertEqual(msg['error'], None, msg='not correct response, should be None.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float') self.assertEqual(properties.correlation_id, self.corr_id, msg='response to async call doesnt have the same correlation_id') self.secondEventFinished() def testReactionToCorrectlyFormattedServiceRequest(self): """ If the gk sends a request on the service.instances.create topic that is correctly formatted, then the SLM should respond by doing 2 things: 1. Replying with the message {'status':'INSTANTIATING', 'error':NULL, 'timestamp':<timestamp>} with the same correlation_id as the one in the request. 2. Requesting the available vims from the IA on the infrastructure.management.compute.list topic with a new correlation id and an empty body. """ self.wait_for_first_event.clear() self.wait_for_second_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test1, 'infrastructure.management.compute.list') #STEP2: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async(self.on_gk_response_to_correct_service_request, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP3: Start waiting for the messages that are triggered by this request self.waitForFirstEvent(timeout=10, msg='Wait for message from SLM to IA to request resources timed out.') self.waitForSecondEvent(timeout=10, msg='Wait for reply to request from GK timed out.') ########################################################### #TEST2: Test reaction to wrongly formatted service request. ########################################################### def on_gk_response_to_wrong_service_request(self, ch, method, properties, message): """ This method checks whether the SLM responds to a wrongly formatted new service request it receives from the GK. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='response to service request is not a dictionary.') self.assertEqual(msg['status'], 'ERROR', msg='not correct response, should be ERROR') self.assertTrue(isinstance(msg['error'], str), msg='Error message is not a string.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float') self.assertEqual(properties.correlation_id, self.corr_id, msg='response to async call doesnt have the same correlation_id') self.firstEventFinished() def testReactionToWronglyFormattedServiceRequest(self): """ If the gk sends a request on the service.instances.create topic that is wrongly formatted, then the SLM should respond by replying with the message {'status':'ERROR', 'error':<error message>, 'timestamp':<timestamp>} with the same correlation_id as the one in the request. """ self.wait_for_first_event.clear() #STEP1: Send a wrongly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async(self.on_gk_response_to_wrong_service_request, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=False), content_type='application/yaml', correlation_id=self.corr_id) #STEP2: Start waiting for the messages that are triggered by this request self.waitForFirstEvent(timeout=10, msg='Wait for reply to request from GK timed out.') ############################################################### #TEST3: Test Reaction when SLM receives a valid list of VIMs. ############################################################### def on_slm_infra_adaptor_vim_list_test3(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [{'vim_uuid': uuid.uuid4().hex}, {'vim_uuid': uuid.uuid4().hex}, {'vim_uuid': uuid.uuid4().hex}] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_infra_adaptor_service_deploy_request_test3(self, ch, method, properties, message): """ This method checks whether the request from the SLM to the IA to deploy a service is correctly formatted. """ msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg="message is not a dictionary.") self.assertIn('vim_uuid', msg.keys(), msg="vim_uuid is not a key in the dictionary.") self.assertIn('nsd', msg.keys(), msg="nsd is not a key in the dictionary.") self.assertIn('vnfds', msg.keys(), msg="vnfds is not a key in the dictionary.") self.assertIn('instance_uuid', msg['nsd'].keys(), msg="instance_uuid is not a key in the dictionary.") for vnfd in msg['vnfds']: self.assertIn('instance_uuid', vnfd.keys(), msg='intance_uuid is not a key in the dictionary.') self.firstEventFinished() def testReactionToCorrectlyFormattedVimList(self): """ This method tests the response of the SLM when it receives a valid VIM list. The SLM should choose a VIM out of the list, and request whether it has enough resources to host the service. """ self.wait_for_first_event.clear() self.wait_for_second_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test3, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the infrastructure adaptor the first time, to request the resource availability. self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_service_deploy_request_test3, 'infrastructure.service.deploy') #STEP3: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async(self.dummy, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP4: Start waiting for the messages that are triggered by this request self.waitForFirstEvent(timeout=10, msg='Wait for message from SLM to IA to request resources timed out.') ############################################################### #TEST4: Test Reaction when SLM receives an empty list of VIMs. ############################################################### def on_slm_infra_adaptor_vim_list_test4(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_response_to_gk_with_empty_vim_list(self, ch, method, properties, message): """ This method checks the content of the message send from SLM to the GK to indicate that there are no vims available. """ msg = yaml.load(message) #We don't want to trigger on the first response (the async_call), butonly on the second(the notify) and we don't want to trigger on our outgoing message. if properties.app_id == 'son-plugin.ServiceLifecycleManager': if msg['status'] != 'INSTANTIATING': self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary.') self.assertEqual(msg['status'], 'ERROR', msg='status is not correct.') self.assertEqual(msg['error'], 'No VIM.', msg='error message is not correct.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float.') self.firstEventFinished() def testReactionToWronglyFormattedVimList(self): """ This method tests the response of the SLM when it receives an empty VIM list. The SLM should report back to the gk with an error. """ self.wait_for_first_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test4, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the GK, to indicate that the deployment is stopped due to lack of resources. self.manoconn_spy.subscribe(self.on_slm_response_to_gk_with_empty_vim_list, 'service.instances.create') #STEP3: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async(self.on_slm_response_to_gk_with_empty_vim_list, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP4: Start waiting for the messages that are triggered by this request self.waitForFirstEvent(timeout=10, msg='Wait for message from SLM to IA to request resources timed out.') ############################################################################### #TEST7: Test reaction to negative response on deployment message to/from IA ############################################################################### def on_slm_infra_adaptor_vim_list_test7(self, ch, method, properties, message): """ This method replies to a request of the SLM to the IA to get the VIM-list. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': VIM_list = [{'vim_uuid':uuid.uuid4().hex}] self.manoconn_ia.notify('infrastructure.management.compute.list', yaml.dump(VIM_list), correlation_id=properties.correlation_id) def on_slm_infra_adaptor_service_deploy_request_test7(self, ch, method, properties, message): """ This method fakes a message from the IA to the SLM that indicates that the deployment has failed. """ if properties.app_id == 'son-plugin.ServiceLifecycleManager': reply_message = {'request_status':'failed'} self.manoconn_ia.notify('infrastructure.service.deploy', yaml.dump(reply_message), correlation_id=properties.correlation_id) def on_slm_gk_service_deploy_request_failed(self, ch, method, properties, message): """ This method checks whether the message from the SLM to the GK to indicate that the deployment failed is correctly formatted. """ msg = yaml.load(message) #We don't want to trigger on the first response (the async_call), but only on the second(the notify) and we don't want to trigger on our outgoing message. if properties.app_id == 'son-plugin.ServiceLifecycleManager': if msg['status'] != 'INSTANTIATING': self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary.') self.assertEqual(msg['status'], "ERROR", msg='status is not correct.') self.assertEqual(msg['error'], 'Deployment result: failed', msg='error message is not correct.') self.assertTrue(isinstance(msg['timestamp'], float), msg='timestamp is not a float.') self.firstEventFinished() def testReactionToNegativeReplyOnDeploymentFromIA(self): """ When the SLM contacts the IA to request whether enough resources are available, it gets a response from the IA. If this response indicates that the resources are available, the SLM should requestthe deployment of the service to the IA. """ self.wait_for_first_event.clear() #STEP1: Spy the topic on which the SLM will contact the infrastructure adaptor self.manoconn_spy.subscribe(self.on_slm_infra_adaptor_vim_list_test7, 'infrastructure.management.compute.list') #STEP2: Spy the topic on which the SLM will contact the IA the second time, to request the deployment of the service self.manoconn_ia.subscribe(self.on_slm_infra_adaptor_service_deploy_request_test7, 'infrastructure.service.deploy') #STEP3: Spy the topic on which the SLM will contact the GK to respond that the deployment has failed. self.manoconn_gk.subscribe(self.on_slm_gk_service_deploy_request_failed, 'service.instances.create') #STEP4: Send a correctly formatted service request message (from the gk) to the SLM self.manoconn_gk.call_async(self.dummy, 'service.instances.create', msg=self.createGkNewServiceRequestMessage(correctlyFormatted=True), content_type='application/yaml', correlation_id=self.corr_id) #STEP5: Start waiting for the messages that are triggered by this request self.waitForFirstEvent(timeout=15, msg='Wait for message from SLM to IA to request deployment timed out.') ############################################################################### #TEST8: Test Monitoring message creation. ############################################################################### def testMonitoringMessageGeneration(self): """ SLM should generate a message for the monitoring module in order to start the monitoring process to the deployed network service. This message is generated from the information existing in NSD, VNFDs, NSRs and VNFs. The test checks that, given the sonata-demo network service, SLM correctly generates the expected message for the monitoring module. """ #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: add ids to NSD and VNFDs (those used in the expected message) gk_request['NSD']['uuid'] = '005606ed-be7d-4ce3-983c-847039e3a5a2' gk_request['VNFD1']['uuid'] = '6a15313f-cb0a-4540-baa2-77cc6b3f5b68' gk_request['VNFD2']['uuid'] = '645db4fa-a714-4cba-9617-4001477d1281' gk_request['VNFD3']['uuid'] = '8a0aa837-ec1c-44e5-9907-898f6401c3ae' #STEP3: load nsr_file, containing both NSR and the list of VNFRs message_from_ia = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) nsr_file = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-nsr.yml', 'r')) vnfrs_file = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-vnfrs.yml', 'r')) #STEP4: call real method message = tools.build_monitoring_message(gk_request, message_from_ia, nsr_file, vnfrs_file) #STEP5: read expected message from descriptor file expected_message = json.load(open('/plugins/son-mano-service-lifecycle-management/test/test_descriptors/monitoring-message.json', 'r')) #STEP6: compare that generated message is equals to the expected one self.assertEqual(message, expected_message, "messages are not equals") ############################################################################### #TEST9: Test creation of the message addressed to the Monitoring Repository ############################################################################### def testNsrCreation(self): """ Once the Infrastructure Adapter has deployed the network service, it would build the entire NSR from the information provided by the Infrastructure Adapter. This test checks that, given the sonata-demo network service, the IA is able to build the correct NSR. """ #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: read IA response and the expected NSR ia_nsr = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) expected_nsr = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-nsr.yml', 'r')) #STEP3: call real method message = tools.build_nsr(gk_request, ia_nsr) #STEP4: comprare the generated message is equals to the expected one self.assertEqual(message, expected_nsr, "Built NSR is not equal to the expected one") ############################################################################### #TEST10: Test creation of the NSR ############################################################################### def testVnfrsCreation(self): #STEP1: create NSD and VNFD by reading test descriptors. gk_request = yaml.load(self.createGkNewServiceRequestMessage()) #STEP2: read IA response and the expected NSR ia_nsr = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/ia-nsr.yml', 'r')) expected_vnfrs = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/sonata-demo-vnfrs.yml', 'r')) message = tools.build_vnfrs(gk_request, ia_nsr['vnfrs']) self.assertEqual(message, expected_vnfrs, "Built VNFRs are not equals to the expected ones")
class testPLEXRegistration(unittest.TestCase): """ Tests the registration process of the Scaling Executive to the broker and the plugin manager, and the heartbeat process. """ def setUp(self): #a new Scaling Executive in another process for each test self.plex_proc = Process(target=ScalingExecutive) self.plex_proc.daemon = True if 'broker_man_host' in os.environ: self.man_host = os.environ['broker_man_host'] else: self.man_host = 'http://localhost:15672' if 'sm_broker_host' in os.environ: self.sm_host = os.environ['sm_broker_host'] else: self.sm_host = 'http://localhost:15672' url_user = "******".format(self.man_host) url_create = '{0}/api/vhosts/fsm-1234'.format(self.man_host) url_permission = '{0}/api/permissions/fsm-1234/specific-management'.format( self.man_host) self.headers = {'content-type': 'application/json'} data1 = '{"password":"******","tags":"son-sm"}' data2 = '{"configure":".*","write":".*","read":".*"}' res = requests.put(url=url_user, headers=self.headers, data=data1, auth=('guest', 'guest')) LOG.info(res.content) res1 = requests.put(url=url_create, headers=self.headers, auth=('guest', 'guest')) LOG.info(res1.content) res2 = requests.put(url=url_permission, headers=self.headers, data=data2, auth=('guest', 'guest')) LOG.info(res2.content) #make a new connection with the broker before each test url = "{0}/fsm-1234".format(self.sm_host) self.manoconn = ManoBrokerRequestResponseConnection( 'son-plugin.SonPluginManager') self.sm_connection = ManoBrokerRequestResponseConnection( 'son-plugin.FSM', url=url) #Some threading events that can be used during the tests self.wait_for_event1 = threading.Event() self.wait_for_event1.clear() self.wait_for_event2 = threading.Event() self.wait_for_event2.clear() def tearDown(self): #Killing the scaling Executive if self.plex_proc is not None: self.plex_proc.terminate() del self.plex_proc #Killing the connection with the broker try: self.manoconn.stop_connection() self.sm_connection.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") #Clearing the threading helpers del self.wait_for_event1 del self.wait_for_event2 url_user = "******".format(self.man_host) url_vhost = "{0}/api/vhosts/fsm-1234".format(self.man_host) requests.delete(url=url_user, headers=self.headers, auth=('guest', 'guest')) requests.delete(url=url_vhost, headers=self.headers, auth=('guest', 'guest')) #Method that terminates the timer that waits for an event def eventFinished1(self): self.wait_for_event1.set() def eventFinished2(self): self.wait_for_event2.set() #Method that starts a timer, waiting for an event def waitForEvent1(self, timeout=5, msg="Event timed out."): if not self.wait_for_event1.wait(timeout): self.assertEqual(True, False, msg=msg) def waitForEvent2(self, timeout=5, msg="Event timed out."): if not self.wait_for_event2.wait(timeout): self.assertEqual(True, False, msg=msg) def test_1_SCEX_Registration(self): """ TEST: This test verifies whether the Scaling Executive is sending out a message, and whether it contains all the needed info on the platform.management.plugin.register topic to register to the plugin manager. """ #STEP3a: When receiving the message, we need to check whether all fields present. def on_register_receive(ch, method, properties, message): msg = yaml.load(message) #CHECK: The message should be a dictionary. self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') #CHECK: The dictionary should have a key 'name'. self.assertIn('name', msg.keys(), msg='No name provided in message.') if isinstance(msg['name'], str): #CHECK: The value of 'name' should not be an empty string. self.assertTrue(len(msg['name']) > 0, msg='empty name provided.') else: #CHECK: The value of 'name' should be a string self.assertEqual(True, False, msg='name is not a string') #CHECK: The dictionary should have a key 'version'. self.assertIn('version', msg.keys(), msg='No version provided in message.') if isinstance(msg['version'], str): #CHECK: The value of 'version' should not be an empty string. self.assertTrue(len(msg['version']) > 0, msg='empty version provided.') else: #CHECK: The value of 'version' should be a string self.assertEqual(True, False, msg='version is not a string') #CHECK: The dictionary should have a key 'description' self.assertIn('description', msg.keys(), msg='No description provided in message.') if isinstance(msg['description'], str): #CHECK: The value of 'description' should not be an empty string. self.assertTrue(len(msg['description']) > 0, msg='empty description provided.') else: #CHECK: The value of 'description' should be a string self.assertEqual(True, False, msg='description is not a string') # stop waiting self.eventFinished1() #STEP1: Listen to the platform.management.plugin.register topic self.manoconn.subscribe(on_register_receive, 'platform.management.plugin.register') #STEP2: Start the Scaling Executive self.plex_proc.start() #STEP3b: When not receiving the message, the test failed self.waitForEvent1(timeout=5, msg="message not received.") def test_2_SCEX_request_response(self): def on_request_send(ch, method, properties, message): if properties.app_id == "son-plugin.ScalingExecutive": msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') self.assertIn('uuid', msg.keys(), msg='No uuid provided in message.') if isinstance(msg['uuid'], str): self.assertTrue(msg['uuid'] == '1234', msg='empty uuid provided.') self.assertNotIn('scale', msg.keys(), msg='wrong message!') res_payload = yaml.dump({'uuid': '1234', 'scale': '2'}) self.eventFinished1() return res_payload def on_response_send(ch, method, properties, message): if properties.app_id == "son-plugin.ScalingExecutive": msg = yaml.load(message) self.assertTrue(isinstance(msg, dict), msg='message is not a dictionary') self.assertIn('uuid', msg.keys(), msg='No uuid provided in message.') if isinstance(msg['uuid'], str): self.assertTrue(msg['uuid'] == '1234', msg='empty uuid provided.') self.assertIn('scale', msg.keys(), msg='No scale provided in message.') if isinstance(msg['scale'], str): self.assertTrue(msg['scale'] == '2', msg='empty uuid provided.') self.eventFinished2() self.plex_proc.start() time.sleep(2) self.manoconn.subscribe(on_response_send, 'scaling.executive.request') self.sm_connection.register_async_endpoint(on_request_send, 'scaling.fsm.1234') req_payload = yaml.dump({'uuid': '1234'}) self.manoconn.publish("scaling.executive.request", message=req_payload) self.waitForEvent1(timeout=5, msg="response message not received.") self.waitForEvent2(timeout=5, msg="request message not received.")
class test_SMR_functionalities(unittest.TestCase): @classmethod def setUpClass(self): def wait_for_smr(ch, method, properties, message): LOG.info("PM status message received") status = json.loads(message) plugin_dict = status['plugin_dict'] for uuid in plugin_dict.keys(): if plugin_dict[uuid]['name'] == 'son-plugin.SpecificManagerRegistry': LOG.info("SMR detected") self.smr_active = True print("SetUpClass triggered") self.smr_active = False self.manoconn = ManoBrokerRequestResponseConnection('smr-unittest') self.manoconn.subscribe(wait_for_smr, 'platform.management.plugin.status') self.smr_proc = Process(target=SpecificManagerRegistry) self.smr_proc.daemon = True self.smr_proc.start() self.wait_for_ssm_event = threading.Event() self.wait_for_ssm_event.clear() self.wait_for_fsm_event = threading.Event() self.wait_for_fsm_event.clear() self.event1 = False self.event2 = False while not self.smr_active: LOG.info("SMR not active yet, sleeping...") time.sleep(1) LOG.info('SMR is active') @classmethod def tearDownClass(self): if self.smr_proc is not None: self.smr_proc.terminate() del self.smr_proc try: self.manoconn.stop_connection() except Exception as e: LOG.exception("Stop connection exception.") del self.wait_for_fsm_event del self.wait_for_ssm_event def ssm_eventFinished(self): self.wait_for_ssm_event.set() def waitForSSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_ssm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def fsm_eventFinished(self): self.wait_for_fsm_event.set() def waitForFSMEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_fsm_event.wait(timeout): self.assertEqual(True, False, msg=msg) def test_1_SMR_onboard(self): self.event1 = False self.event2 = False def on_ssm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1','sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['error'] == 'None', msg='error in onbording sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_onboarding_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1dumb1'], msg='not all FSMs results in VNFD1 received') self.assertTrue(result['sonfsmservice1function1dumb1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in onbording sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1']or list(result.keys()) == ['sonfsmservice1firewallconfiguration1','sonfsmservice1function1monitoring1'] , msg='not all FSMs results in VNFD2 received') self.assertTrue(result['sonfsmservice1function1monitoring1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1function1monitoring1']['error'] == 'None', msg='error in onbording sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['status'] == 'On-boarded', msg='error in onbording sonssmservice1dumb1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg='error in onbording sonfsmservice1firewallconfiguration1') self.event2 = True if self.event1 and self.event2 == True: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_onboarding_result, 'specific.manager.registry.ssm.on-board') self.manoconn.subscribe(on_fsm_onboarding_result, 'specific.manager.registry.fsm.on-board') onboaring_proc = Process(target=fakeslm_onboarding) onboaring_proc.daemon = True onboaring_proc.start() self.waitForSSMEvent(timeout=70 , msg='SSM Onboarding request not received.') self.waitForFSMEvent(timeout=70, msg='FSM Onboarding request not received.') self.wait_for_fsm_event.clear() self.wait_for_ssm_event.clear() onboaring_proc.terminate() del onboaring_proc def test_2_SMR_instantiation(self): self.event1 = False self.event2 = False def on_ssm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) self.assertTrue(list(result.keys()) == ['sonssmservice1dumb1', 'sonssmservice1placement1'] or list(result.keys()) == ['sonssmservice1placement1', 'sonssmservice1dumb1'], msg='not all SSMs results received') self.assertTrue(result['sonssmservice1dumb1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1dumb1') self.assertTrue(result['sonssmservice1dumb1']['error'] == 'None', msg='error in instantiation sonssmservice1dumb1') self.assertTrue(result['sonssmservice1placement1']['status'] == 'Instantiated', msg='error in instantiation sonssmservice1placement1') self.assertTrue(result['sonssmservice1placement1']['error'] == 'None', msg='error in instantiation sonssmservice1placement1') self.ssm_eventFinished() def on_fsm_instantiation_result(ch, method, properties, message): if properties.app_id == 'son-plugin.SpecificManagerRegistry': result = yaml.load(message) if list(result.keys()) == ['sonfsmservice1function1dumb1']: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1dumb1'], msg='not all FSMs instantiation results in VNFD1 received') self.assertTrue(result['sonfsmservice1function1dumb1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1function1dumb1') self.assertTrue(result['sonfsmservice1function1dumb1']['error'] == 'None', msg='error in instantiation sonfsmservice1function1dumb1') self.event1 = True else: self.assertTrue(list(result.keys()) == ['sonfsmservice1function1monitoring1', 'sonfsmservice1firewallconfiguration1'] or list(result.keys()) == ['sonfsmservice1firewallconfiguration1', 'sonfsmservice1function1monitoring1'] , msg='not all FSMs instantiation results in VNFD2 received') self.assertTrue(result['sonfsmservice1function1monitoring1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1function1monitoring1']['error'] == 'None', msg='error in instantiation sonfsmservice1function1monitoring1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['status'] == 'Instantiated', msg='error in instantiation sonfsmservice1firewallconfiguration1') self.assertTrue(result['sonfsmservice1firewallconfiguration1']['error'] == 'None', msg='error in instantiation sonfsmservice1firewallconfiguration1') self.event2 = True if self.event1 and self.event2: self.fsm_eventFinished() self.manoconn.subscribe(on_ssm_instantiation_result, 'specific.manager.registry.ssm.instantiate') self.manoconn.subscribe(on_fsm_instantiation_result, 'specific.manager.registry.fsm.instantiate') instantiation_proc = Process(target=fakeslm_instantiation) instantiation_proc.daemon = True instantiation_proc.start() self.waitForSSMEvent(timeout=70, msg='SSM instantiation request not received.') self.waitForFSMEvent(timeout=70, msg='FSM instantiation request not received.') self.wait_for_ssm_event.clear() self.wait_for_fsm_event.clear() instantiation_proc.terminate() del instantiation_proc
class testSlmFunctionality(unittest.TestCase): """ Tests the tasks that the SLM should perform in the service life cycle of the network services. """ slm_proc = None uuid = '1' corr_id = '1ba347d6-6210-4de7-9ca3-a383e50d0330' ######################## #SETUP ######################## def setUp(self): def on_register_trigger(ch, method, properties, message): return json.dumps({'status': 'OK', 'uuid': self.uuid}) #vnfcounter for when needed self.vnfcounter = 0 #Generate a new corr_id for every test self.corr_id = str(uuid.uuid4()) #a new SLM in another process for each test self.slm_proc = ServiceLifecycleManager(auto_register=False, start_running=False) #We make a spy connection to listen to the different topics on the broker self.manoconn_spy = ManoBrokerRequestResponseConnection('son-plugin.SonSpy') #we need a connection to simulate messages from the gatekeeper self.manoconn_gk = ManoBrokerRequestResponseConnection('son-plugin.SonGateKeeper') #we need a connection to simulate messages from the infrastructure adaptor self.manoconn_ia = ManoBrokerRequestResponseConnection('son-plugin.SonInfrastructureAdapter') #Some threading events that can be used during the tests self.wait_for_first_event = threading.Event() self.wait_for_first_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing the slm self.slm_proc.manoconn.stop_connection() self.slm_proc.manoconn.stop_threads() try: del self.slm_proc except: pass #Killing the connection with the broker self.manoconn_spy.stop_connection() self.manoconn_gk.stop_connection() self.manoconn_ia.stop_connection() self.manoconn_spy.stop_threads() self.manoconn_gk.stop_threads() self.manoconn_ia.stop_threads() del self.manoconn_spy del self.manoconn_gk del self.manoconn_ia del self.wait_for_first_event ######################## #GENERAL ######################## def createGkNewServiceRequestMessage(self, correctlyFormatted=True): """ This method helps creating messages for the service request packets. If it needs to be wrongly formatted, the nsd part of the request is removed. """ path_descriptors = '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/' nsd_descriptor = open(path_descriptors + 'sonata-demo.yml', 'r') vnfd1_descriptor = open(path_descriptors + 'firewall-vnfd.yml', 'r') vnfd2_descriptor = open(path_descriptors + 'iperf-vnfd.yml', 'r') vnfd3_descriptor = open(path_descriptors + 'tcpdump-vnfd.yml', 'r') #import the nsd and vnfds that form the service if correctlyFormatted: service_request = {'NSD': yaml.load(nsd_descriptor), 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor)} else: service_request = {'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor)} return yaml.dump(service_request) #Method that terminates the timer that waits for an event def firstEventFinished(self): self.wait_for_first_event.set() #Method that starts a timer, waiting for an event def waitForFirstEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_first_event.wait(timeout): self.assertEqual(True, False, msg=msg) def dummy(self, ch, method, properties, message): """ Sometimes, we need a cbf for a async_call, without actually using it. """ return ############################################################# #TEST1: test validate_deploy_request ############################################################# def test_validate_deploy_request(self): """ The method validate_deploy_request is used to check whether the received message that requests the deployment of a new service is correctly formatted. """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'original_corr_id':corr_id} #SUBTEST1: Check a correctly formatted message message = self.createGkNewServiceRequestMessage() service_dict[service_id]['payload'] = yaml.load(message) self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() self.assertEqual({'status': result[service_id]['status'], 'error': result[service_id]['error']}, {'status': 'INSTANTIATING', 'error': None}, msg="outcome and expected result not equal SUBTEST1.") #SUBTEST2: Check a message that is not a dictionary message = "test message" service_dict[service_id]['payload'] = message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": payload is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual({'status': result[service_id]['status'], 'error': result[service_id]['error']}, expected_response, msg="outcome and expected result not equal SUBTEST2.") #SUBTEST3: Check a message that contains no NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) del loaded_message['NSD'] service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": NSD is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual({'status': result[service_id]['status'], 'error': result[service_id]['error']}, expected_response, msg="outcome and expected result not equal SUBTEST3.") #SUBTEST4: The number of VNFDs must be the same as listed in the NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['NSD']['network_functions'].append({}) service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": # of VNFDs doesn't match NSD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual({'status': result[service_id]['status'], 'error': result[service_id]['error']}, expected_response, msg="outcome and expected result not equal SUBTEST4.") #SUBTEST5: VNFDs can not be empty message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['VNFD1'] = None service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": empty VNFD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual({'status': result[service_id]['status'], 'error': result[service_id]['error']}, expected_response, msg="outcome and expected result not equal SUBTEST5.") ########################################################### #TEST2: Test start_next_task ########################################################### def test_start_next_task(self): """ This method tests the start_next_task method """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = {'corr_id':corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': True, 'kill_chain': False} #SUBTEST1: Check if next task is correctly called message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = ['validate_deploy_request'] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result generated_response = {'status': result[service_id]['status'], 'error': result[service_id]['error']} expected_response = {'status': 'INSTANTIATING', 'error': None} self.assertEqual(generated_response, expected_response, msg="outcome and expected result not equal SUBTEST1.") #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = {'corr_id':corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': False, 'kill_chain': False} #SUBTEST2: Check behavior if there is no next task message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = [] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result: if successful, service_id will not be a key in result self.assertFalse(service_id in result.keys(), msg="key is part of ledger in SUBTEST2.") # ############################################################### # #TEST3: Test service_instance_create # ############################################################### # def test_service_instance_create(self): # """ # This method tests the service_instance_create method of the SLM # """ # #Setup # message = self.createGkNewServiceRequestMessage() # corr_id = str(uuid.uuid4()) # topic = "service.instances.create" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': "Gatekeeper"} # properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) # schedule = self.slm_proc.service_instance_create('foo', # 'bar', # properties, # message) # #Check result: since we don't know how many of the tasks # #were completed by the time we got the result, we only check # #the final elements in the tasklist # #The last 7 elements from the generated result # generated_result = schedule[-7:] # #The expected last 7 elements in the list # expected_result = ['SLM_mapping', 'ia_prepare', 'vnf_deploy', # 'vnf_chain', 'wan_configure', # 'instruct_monitoring', 'inform_gk'] # self.assertEqual(generated_result, # expected_result, # msg='lists are not equal') ############################################################### #TEST4: Test resp_topo ############################################################### # def test_resp_topo(self): # """ # This method tests the resp_topo method. # """ # #Setup # #Create topology message # first = {'vim_uuid':str(uuid.uuid4()), 'memory_used':5, 'memory_total':12, 'core_used':4, 'core_total':6} # second = {'vim_uuid':str(uuid.uuid4()), 'memory_used':3, 'memory_total':5, 'core_used':4, 'core_total':5} # third = {'vim_uuid':str(uuid.uuid4()), 'memory_used':6, 'memory_total':7, 'core_used':2, 'core_total':12} # topology_message = [first, second, third] # payload = yaml.dump(topology_message) # #Create ledger # service_dict = {} # service_id = str(uuid.uuid4()) # corr_id = str(uuid.uuid4()) # service_dict[service_id] = {'act_corr_id':corr_id, # 'infrastructure': {'topology':None}, # 'schedule': ['get_ledger'], # 'original_corr_id':corr_id, # 'pause_chain': True, # 'kill_chain': False} # self.slm_proc.set_services(service_dict) # #Create properties # topic = "infrastructure.management.compute.list" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': 'InfrastructureAdaptor'} # properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) # #Run method # self.slm_proc.resp_topo('foo', 'bar', properties, payload) # #Check result # result = self.slm_proc.get_services() # self.assertEqual(topology_message, # result[service_id]['infrastructure']['topology'], # msg="Dictionaries are not equal") ############################################################### #TEST5: Test resp_vnf_depl ############################################################### def test_resp_vnf_depl(self): """ This method tests the resp_vnf_depl method. """ #SUBTEST1: Only one VNFD in the service #Setup #Create the message vnfr = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = {'status': 'DEPLOYED', 'error': None, 'ip_mapping': [], 'vnfr': vnfr} payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'act_corr_id':corr_id, 'function': [{'id': vnfr['id']}], 'vnfs_to_resp': 1, 'ip_mapping': [], 'schedule': ['get_ledger'], 'original_corr_id':corr_id, 'pause_chain': True, 'kill_chain': False} self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = {'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager'} properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 1") self.assertEqual(result[service_id]['vnfs_to_resp'], 0, msg="Values not equal SUBTEST 1") #SUBTEST2: Two VNFDs in the service #Setup #Create the message vnfr = yaml.load(open('/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = {'status': 'DEPLOYED', 'error': None, 'ip_mapping': [], 'vnfr': vnfr} payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'act_corr_id':corr_id, 'function': [{'id': vnfr['id']}], 'vnfs_to_resp': 2, 'ip_mapping': [], 'schedule': ['get_ledger'], 'original_corr_id':corr_id, 'pause_chain': True, 'kill_chain': False} self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = {'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager'} properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 2") self.assertEqual(result[service_id]['vnfs_to_resp'], 1, msg="Values not equal SUBTEST 2") self.assertEqual(result[service_id]['schedule'], ['get_ledger'], msg="Lists not equal SUBTEST 2") ############################################################### #TEST6: Test resp_prepare ############################################################### def test_resp_prepare(self): """ This method tests the resp_prepare method. """ #SUBTEST 1: Successful response message #Setup #Create the message message = {'request_status': 'COMPLETED', 'error': None, } payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'act_corr_id':corr_id, 'schedule': ['get_ledger'], 'original_corr_id':corr_id, 'pause_chain': True, 'current_workflow': 'instantiation', 'kill_chain': False} self.slm_proc.set_services(service_dict) #Create properties topic = "infrastructure.service.prepare" prop_dict = {'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'InfrastructureAdaptor'} properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_prepare('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertFalse('status' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1") self.assertFalse('error' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1") # #SUBTEST 2: Failed response message # def on_test_resp_prepare_subtest2(ch, mthd, prop, payload): # message = yaml.load(payload) # self.assertEqual(message['status'], # 'ERROR', # msg="Status not correct in SUBTEST 1") # self.assertEqual(message['error'], # 'BAR', # msg="Error not correct in SUBTEST 1") # self.assertTrue('timestamp' in message.keys(), # msg="Timestamp missing in SUBTEST 1") # self.assertEqual(len(message.keys()), # 3, # msg="Number of keys not correct in SUBTEST1") # self.firstEventFinished() # #Setup # #Create the message # message = {'request_status': 'FOO', # 'message': 'BAR', # } # payload = yaml.dump(message) # #Listen on feedback topic # self.manoconn_gk.subscribe(on_test_resp_prepare_subtest2,'service.instances.create') # #Create ledger # service_dict = {} # service_id = str(uuid.uuid4()) # corr_id = str(uuid.uuid4()) # service_dict[service_id] = {'act_corr_id':corr_id, # 'schedule': ['get_ledger'], # 'original_corr_id':corr_id, # 'pause_chain': True, # 'current_workflow': 'instantiation', # 'kill_chain': False} # self.slm_proc.set_services(service_dict) # #Create properties # topic = "infrastructure.service.prepare" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': 'InfrastructureAdaptor'} # properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) # #Run method # self.slm_proc.resp_prepare('foo', 'bar', properties, payload) # #Wait for the test to finish # self.waitForFirstEvent(timeout=5) ############################################################### #TEST7: test contact_gk ############################################################### def test_contact_gk(self): """ This method tests the contact_gk method. """ #Check result SUBTEST 1 def on_contact_gk_subtest1(ch, mthd, prop, payload): message = yaml.load(payload) self.assertEqual(message['status'], 'FOO', msg="Status not correct in SUBTEST 1") self.assertEqual(message['error'], 'BAR', msg="Error not correct in SUBTEST 1") self.assertTrue('timestamp' in message.keys(), msg="Timestamp missing in SUBTEST 1") self.assertEqual(len(message.keys()), 3, msg="Number of keys not correct in SUBTEST1") self.firstEventFinished() #Check result SUBTEST2 def on_contact_gk_subtest2(ch, mthd, prop, payload): self.firstEventFinished() message = yaml.load(payload) self.assertEqual(message['status'], 'FOO', msg="Status not correct in SUBTEST 2") self.assertEqual(message['error'], 'BAR', msg="Error not correct in SUBTEST 2") self.assertEqual(message['FOO'], 'BAR', msg="Error not correct in SUBTEST 2") self.assertTrue('timestamp' in message.keys(), msg="Timestamp missing in SUBTEST 2") self.assertEqual(len(message.keys()), 4, msg="Number of keys not correct in SUBTEST2") #SUBTEST1: Without additional content #Setup #Create the ledger self.wait_for_first_event.clear() service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'schedule': ['get_ledger'], 'original_corr_id':corr_id, 'pause_chain': True, 'status': 'FOO', 'error': 'BAR', 'kill_chain': False, 'topic': 'service.instances.create'} #Set the ledger self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_spy.subscribe(on_contact_gk_subtest1, 'service.instances.create') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.contact_gk(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5) #SUBTEST2: With additional content #Setup self.wait_for_first_event.clear() #Create the ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) add_content = {'FOO': 'BAR'} service_dict[service_id] = {'schedule': ['get_ledger'], 'original_corr_id':corr_id, 'pause_chain': True, 'status': 'FOO', 'error': 'BAR', 'add_content': add_content, 'topic': 'service.instances.create'} self.slm_proc.set_services(service_dict) #Spy the message bus self.manoconn_gk.subscribe(on_contact_gk_subtest2, 'service.instances.create') #Wait until subscription is completed time.sleep(0.1) #Run the method self.slm_proc.contact_gk(service_id) #Wait for the test to finish self.waitForFirstEvent(timeout=5)
class testSlmFunctionality(unittest.TestCase): """ Tests the tasks that the SLM should perform in the service life cycle of the network services. """ slm_proc = None uuid = '1' corr_id = '1ba347d6-6210-4de7-9ca3-a383e50d0330' ######################## #SETUP ######################## def setUp(self): def on_register_trigger(ch, method, properties, message): return json.dumps({'status': 'OK', 'uuid': self.uuid}) #vnfcounter for when needed self.vnfcounter = 0 #Generate a new corr_id for every test self.corr_id = str(uuid.uuid4()) #a new SLM in another process for each test self.slm_proc = ServiceLifecycleManager(start_running=False) #We make a spy connection to listen to the different topics on the broker self.manoconn_spy = ManoBrokerRequestResponseConnection( 'son-plugin.SonSpy') #we need a connection to simulate messages from the gatekeeper self.manoconn_gk = ManoBrokerRequestResponseConnection( 'son-plugin.SonGateKeeper') #we need a connection to simulate messages from the infrastructure adaptor self.manoconn_ia = ManoBrokerRequestResponseConnection( 'son-plugin.SonInfrastructureAdapter') #Some threading events that can be used during the tests self.wait_for_first_event = threading.Event() self.wait_for_first_event.clear() #The uuid that can be assigned to the plugin self.uuid = '1' def tearDown(self): #Killing the slm self.slm_proc.manoconn.stop_connection() self.slm_proc.manoconn.stop_threads() try: del self.slm_proc except: pass #Killing the connection with the broker self.manoconn_spy.stop_connection() self.manoconn_gk.stop_connection() self.manoconn_ia.stop_connection() self.manoconn_spy.stop_threads() self.manoconn_gk.stop_threads() self.manoconn_ia.stop_threads() del self.manoconn_spy del self.manoconn_gk del self.manoconn_ia del self.wait_for_first_event ######################## #GENERAL ######################## def createGkNewServiceRequestMessage(self, correctlyFormatted=True): """ This method helps creating messages for the service request packets. If it needs to be wrongly formatted, the nsd part of the request is removed. """ path_descriptors = '/plugins/son-mano-service-lifecycle-management/test/test_descriptors/' nsd_descriptor = open(path_descriptors + 'sonata-demo.yml', 'r') vnfd1_descriptor = open(path_descriptors + 'firewall-vnfd.yml', 'r') vnfd2_descriptor = open(path_descriptors + 'iperf-vnfd.yml', 'r') vnfd3_descriptor = open(path_descriptors + 'tcpdump-vnfd.yml', 'r') #import the nsd and vnfds that form the service if correctlyFormatted: service_request = { 'NSD': yaml.load(nsd_descriptor), 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } else: service_request = { 'VNFD1': yaml.load(vnfd1_descriptor), 'VNFD2': yaml.load(vnfd2_descriptor), 'VNFD3': yaml.load(vnfd3_descriptor) } return yaml.dump(service_request) #Method that terminates the timer that waits for an event def firstEventFinished(self): self.wait_for_first_event.set() #Method that starts a timer, waiting for an event def waitForFirstEvent(self, timeout=5, msg="Event timed out."): if not self.wait_for_first_event.wait(timeout): self.assertEqual(True, False, msg=msg) def dummy(self, ch, method, properties, message): """ Sometimes, we need a cbf for a async_call, without actually using it. """ return ############################################################# #TEST1: test validate_deploy_request ############################################################# def test_validate_deploy_request(self): """ The method validate_deploy_request is used to check whether the received message that requests the deployment of a new service is correctly formatted. """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = {'original_corr_id': corr_id} # #SUBTEST1: Check a correctly formatted message # message = self.createGkNewServiceRequestMessage() # service_dict[service_id]['payload'] = yaml.load(message) # self.slm_proc.set_services(service_dict) # self.slm_proc.validate_deploy_request(service_id) # result = self.slm_proc.get_services() # self.assertEqual({'status': result[service_id]['status'], # 'error': result[service_id]['error']}, # {'status': 'INSTANTIATING', 'error': None}, # msg="outcome and expected result not equal SUBTEST1.") #SUBTEST2: Check a message that is not a dictionary message = "test message" service_dict[service_id]['payload'] = message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": payload is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST2.") #SUBTEST3: Check a message that contains no NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) del loaded_message['NSD'] service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": NSD is not a dict." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST3.") #SUBTEST4: The number of VNFDs must be the same as listed in the NSD message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['NSD']['network_functions'].append({}) service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": # of VNFDs doesn't match NSD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST4.") #SUBTEST5: VNFDs can not be empty message = self.createGkNewServiceRequestMessage() loaded_message = yaml.load(message) loaded_message['VNFD1'] = None service_dict[service_id]['payload'] = loaded_message self.slm_proc.set_services(service_dict) self.slm_proc.validate_deploy_request(service_id) result = self.slm_proc.get_services() expected_message = "Request " + corr_id + ": empty VNFD." expected_response = {'status': 'ERROR', 'error': expected_message} self.assertEqual( { 'status': result[service_id]['status'], 'error': result[service_id]['error'] }, expected_response, msg="outcome and expected result not equal SUBTEST5.") ########################################################### #TEST2: Test start_next_task ########################################################### def test_start_next_task(self): """ This method tests the start_next_task method """ #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'corr_id': corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': True, 'kill_chain': False } #SUBTEST1: Check if next task is correctly called message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = ['validate_deploy_request'] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result generated_response = { 'status': result[service_id]['status'], 'error': result[service_id]['error'] } expected_response = {'status': 'INSTANTIATING', 'error': None} self.assertEqual(generated_response, expected_response, msg="outcome and expected result not equal SUBTEST1.") #Setup service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) orig_corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'corr_id': corr_id, 'original_corr_id': orig_corr_id, 'pause_chain': False, 'kill_chain': False } #SUBTEST2: Check behavior if there is no next task message = self.createGkNewServiceRequestMessage() #Add a task to the list task_list = [] #Create the ledger service_dict[service_id]['schedule'] = task_list service_dict[service_id]['payload'] = yaml.load(message) #Run the method self.slm_proc.set_services(service_dict) self.slm_proc.start_next_task(service_id) #wait for the task to finish time.sleep(0.1) result = self.slm_proc.get_services() #Check result: if successful, service_id will not be a key in result self.assertFalse(service_id in result.keys(), msg="key is part of ledger in SUBTEST2.") # ############################################################### # #TEST3: Test service_instance_create # ############################################################### # def test_service_instance_create(self): # """ # This method tests the service_instance_create method of the SLM # """ # #Setup # message = self.createGkNewServiceRequestMessage() # corr_id = str(uuid.uuid4()) # topic = "service.instances.create" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': "Gatekeeper"} # properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) # schedule = self.slm_proc.service_instance_create('foo', # 'bar', # properties, # message) # #Check result: since we don't know how many of the tasks # #were completed by the time we got the result, we only check # #the final elements in the tasklist # #The last 7 elements from the generated result # generated_result = schedule[-7:] # #The expected last 7 elements in the list # expected_result = ['SLM_mapping', 'ia_prepare', 'vnf_deploy', # 'vnf_chain', 'wan_configure', # 'instruct_monitoring', 'inform_gk'] # self.assertEqual(generated_result, # expected_result, # msg='lists are not equal') ############################################################### #TEST4: Test resp_topo ############################################################### # def test_resp_topo(self): # """ # This method tests the resp_topo method. # """ # #Setup # #Create topology message # first = {'vim_uuid':str(uuid.uuid4()), 'memory_used':5, 'memory_total':12, 'core_used':4, 'core_total':6} # second = {'vim_uuid':str(uuid.uuid4()), 'memory_used':3, 'memory_total':5, 'core_used':4, 'core_total':5} # third = {'vim_uuid':str(uuid.uuid4()), 'memory_used':6, 'memory_total':7, 'core_used':2, 'core_total':12} # topology_message = [first, second, third] # payload = yaml.dump(topology_message) # #Create ledger # service_dict = {} # service_id = str(uuid.uuid4()) # corr_id = str(uuid.uuid4()) # service_dict[service_id] = {'act_corr_id':corr_id, # 'infrastructure': {'topology':None}, # 'schedule': ['get_ledger'], # 'original_corr_id':corr_id, # 'pause_chain': True, # 'kill_chain': False} # self.slm_proc.set_services(service_dict) # #Create properties # topic = "infrastructure.management.compute.list" # prop_dict = {'reply_to': topic, # 'correlation_id': corr_id, # 'app_id': 'InfrastructureAdaptor'} # properties = namedtuple('properties', prop_dict.keys())(*prop_dict.values()) # #Run method # self.slm_proc.resp_topo('foo', 'bar', properties, payload) # #Check result # result = self.slm_proc.get_services() # self.assertEqual(topology_message, # result[service_id]['infrastructure']['topology'], # msg="Dictionaries are not equal") ############################################################### #TEST5: Test resp_vnf_depl ############################################################### def test_resp_vnf_depl(self): """ This method tests the resp_vnf_depl method. """ #SUBTEST1: Only one VNFD in the service #Setup #Create the message vnfr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = { 'status': 'DEPLOYED', 'error': None, 'ip_mapping': [], 'vnfr': vnfr } payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'function': [{ 'id': vnfr['id'] }], 'vnfs_to_resp': 1, 'ip_mapping': [], 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 1") self.assertEqual(result[service_id]['vnfs_to_resp'], 0, msg="Values not equal SUBTEST 1") #SUBTEST2: Two VNFDs in the service #Setup #Create the message vnfr = yaml.load( open( '/plugins/son-mano-service-lifecycle-management/test/test_records/expected_vnfr_iperf.yml', 'r')) message = { 'status': 'DEPLOYED', 'error': None, 'ip_mapping': [], 'vnfr': vnfr } payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'function': [{ 'id': vnfr['id'] }], 'vnfs_to_resp': 2, 'ip_mapping': [], 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "mano.function.deploy" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'FunctionLifecycleManager' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_vnf_depl('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertEqual(vnfr, result[service_id]['function'][0]['vnfr'], msg="Dictionaries are not equal SUBTEST 2") self.assertEqual(result[service_id]['vnfs_to_resp'], 1, msg="Values not equal SUBTEST 2") self.assertEqual(result[service_id]['schedule'], ['get_ledger'], msg="Lists not equal SUBTEST 2") ############################################################### #TEST6: Test resp_prepare ############################################################### def test_resp_prepare(self): """ This method tests the resp_prepare method. """ #SUBTEST 1: Successful response message #Setup #Create the message message = { 'request_status': 'COMPLETED', 'error': None, } payload = yaml.dump(message) #Create ledger service_dict = {} service_id = str(uuid.uuid4()) corr_id = str(uuid.uuid4()) service_dict[service_id] = { 'act_corr_id': corr_id, 'schedule': ['get_ledger'], 'original_corr_id': corr_id, 'pause_chain': True, 'current_workflow': 'instantiation', 'kill_chain': False } self.slm_proc.set_services(service_dict) #Create properties topic = "infrastructure.service.prepare" prop_dict = { 'reply_to': topic, 'correlation_id': corr_id, 'app_id': 'InfrastructureAdaptor' } properties = namedtuple('props', prop_dict.keys())(*prop_dict.values()) #Run method self.slm_proc.resp_prepare('foo', 'bar', properties, payload) #Check result result = self.slm_proc.get_services() self.assertFalse('status' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1") self.assertFalse('error' in result[service_id].keys(), msg="Key in dictionary SUBTEST 1")