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 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 self.manoconn.stop_connection() self.manoconn.stop_threads() del self.manoconn #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 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 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, '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")