def testDeleteVim(api, broker: Connection, reraise): id = str(uuid4()) vimAdaptorResponse = {"request_status": "SUCCESS"} # Mock vim adaptor def onDeleteVimRequest(message: Message): with reraise(catch=True): assert {"id": id} == message.payload return vimAdaptorResponse broker.register_async_endpoint(onDeleteVimRequest, "infrastructure.management.compute.remove") # Test successful deletion assert 204 == api.delete("/api/v3/vims/" + id).status_code # Test vim adaptor error response vimAdaptorResponse = { "request_status": "ERROR", "message": "error message" } reply = api.delete("/api/v3/vims/" + id) assert 500 == reply.status_code assert "error message" == reply.get_json()["detail"]
def test_registration_and_heartbeat(connection: Connection, reraise): registration_request_received = Event() def on_registration_request(message: Message): """ When the registration request from the plugin is received, this method replies as if it were the plugin manager """ with reraise: non_empty_string = All(str, Length(min=1)) assert (S({ "name": non_empty_string, "version": non_empty_string, "description": non_empty_string, }) == message.payload) return {"status": "OK", "uuid": PLUGIN_UUID} heartbeat_received = Event() def on_heartbeat(message: Message): with reraise: assert (S({ "uuid": PLUGIN_UUID, "state": In(("READY", "RUNNING", "PAUSED", "FAILED")), }) == message.payload) heartbeat_received.set() connection.register_async_endpoint(on_registration_request, "platform.management.plugin.register") connection.subscribe( on_heartbeat, "platform.management.plugin." + PLUGIN_UUID + ".heartbeat", ) plugin = ManoBasePlugin( use_loopback_connection=True, version="1.2.3", description="Test Plugin", ) try: registration_request_received.wait(1) heartbeat_received.wait(1) assert plugin.uuid == PLUGIN_UUID finally: plugin.conn.close()
def testGetVims(api, broker: Connection): # Mock vim adaptor broker.register_async_endpoint( lambda message: [{ "id": "id", "name": "name", "country": "country", "city": "city", "type": "type", "cores": { "total": 4, "used": 3 }, "memory": { "total": 2, "used": 1 }, }], "infrastructure.management.compute.list", ) response = api.get("/api/v3/vims") assert 200 == response.status_code assert [{ "id": "id", "name": "name", "country": "country", "city": "city", "type": "type", "cores": { "total": 4, "used": 3 }, "memory": { "total": 2, "used": 1 }, }] == response.get_json()
def testAddVim(api, broker: Connection, reraise): id = str(uuid4()) # VIM uuid returned by the vim-adaptor mock baseVimData = { "city": "my city", "country": "my country", "name": "my name", } vimData = { "aws": { **baseVimData, "type": "aws", "accessKey": "access key", "secretKey": "secret key", "region": "region", }, "kubernetes": { **baseVimData, "type": "kubernetes", "serviceToken": "service token", "address": "address", "port": 1234, "ccc": "ccc", }, "openstack": { **baseVimData, "type": "openstack", "address": "address", "tenant": { "id": "tenant id", "externalNetworkId": "tenant external network id", "externalRouterId": "tenant external router id", }, "username": "******", "password": "******", }, } vimAdaptorResponse = {"request_status": "COMPLETED", "id": id} # Mock vim adaptor def onAddVimRequest(message: Message): with reraise(catch=True): # baseVimData should be contained in the payload assert S(baseVimData) <= message.payload return vimAdaptorResponse broker.register_async_endpoint(onAddVimRequest, "infrastructure.management.compute.add") # Add all types of vims for data in vimData.values(): reply = api.post("/api/v3/vims", json=data) assert 201 == reply.status_code assert {"id": id} == reply.get_json() # Let the mock vim adaptor reply with an error vimAdaptorResponse = { "request_status": "ERROR", "message": "error message" } reply = api.post("/api/v3/vims", json=vimData["aws"]) assert 500 == reply.status_code assert "error message" == reply.get_json()["detail"]
class testPLEXRegistration(unittest.TestCase): """ Tests the registration process of the Placement Executive to the broker and the plugin manager, and the heartbeat process. """ def setUp(self): #a new Placement Executive in another process for each test self.plex_proc = Process(target=PlacementExecutive) 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/ssm-1234'.format(self.man_host) url_permission = '{0}/api/permissions/ssm-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}/ssm-1234".format(self.sm_host) self.manoconn = ManoBrokerRequestResponseConnection( 'son-plugin.SonPluginManager') self.sm_connection = ManoBrokerRequestResponseConnection( 'son-plugin.SSM', 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 Placement 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/ssm-1234".format(self.man_host) res1 = requests.delete(url=url_user, headers=self.headers, auth=('guest', 'guest')) LOG.info(res1.content) res1 = requests.delete(url=url_vhost, headers=self.headers, auth=('guest', 'guest')) LOG.info(res1.content) #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_PLEX_Registration(self): """ TEST: This test verifies whether the Placement 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 Placement 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_PLEX_request_response(self): def on_request_send(ch, method, properties, message): if properties.app_id == "son-plugin.PlacementExecutive": 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('place', msg.keys(), msg='wrong message.') res_payload = yaml.dump({'uuid': '1234', 'place': '2'}) self.eventFinished1() return res_payload def on_response_send(ch, method, properties, message): if properties.app_id == "son-plugin.PlacementExecutive": 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('place', msg.keys(), msg='No place provided in message.') if isinstance(msg['place'], str): self.assertTrue(msg['place'] == '2', msg='empty uuid provided.') self.eventFinished2() self.plex_proc.start() time.sleep(2) self.manoconn.subscribe(on_response_send, 'placement.executive.request') self.sm_connection.register_async_endpoint(on_request_send, 'placement.ssm.1234') req_payload = yaml.dump({'uuid': '1234'}) self.manoconn.publish("placement.executive.request", message=req_payload) self.waitForEvent1(timeout=5, msg="response message not received.") self.waitForEvent2(timeout=5, msg="request message not received.")