From 8246f98e0c9e694a06661d3f9d67cfe8de1dfff3 Mon Sep 17 00:00:00 2001 From: peusterm Date: Thu, 6 Jun 2019 17:43:34 +0200 Subject: [PATCH] 5GTANGO LLCM: Made APIs compatible with tng-cli Change-Id: I4f9b42e8c0db5323ee62495855618c449056edb0 Signed-off-by: peusterm --- devops-stages/stage-test.sh | 2 +- pipeline_local.sh | 4 +- src/emuvim/api/tango/llcm.py | 75 +++++++++++++++++--- src/emuvim/test/unittests/test_tango_llcm.py | 27 ++++--- 4 files changed, 81 insertions(+), 27 deletions(-) diff --git a/devops-stages/stage-test.sh b/devops-stages/stage-test.sh index e464b27..67a1f5a 100755 --- a/devops-stages/stage-test.sh +++ b/devops-stages/stage-test.sh @@ -43,7 +43,7 @@ cd /son-emu/ echo "flake8 version:" flake8 --version echo "Doing flake8 style check ..." -flake8 --exclude=.eggs,devops,examples/charms --ignore=E501,W605,W504 . +flake8 --exclude=.eggs,devops,build,examples/charms --ignore=E501,W605,W504 . echo "done." # trigger the tests echo "Running unit tests ..." diff --git a/pipeline_local.sh b/pipeline_local.sh index 620d23b..4b34ea6 100755 --- a/pipeline_local.sh +++ b/pipeline_local.sh @@ -3,7 +3,7 @@ set -e # trigger pep8 style check echo "Doing flake8 style check ..." -flake8 --exclude=.eggs,devops,examples/charms --ignore=E501,W605,W504 . +flake8 --exclude=.eggs,build,devops,examples/charms --ignore=E501,W605,W504 . echo "done." # trigger the tests echo "Running unit tests ..." @@ -11,5 +11,5 @@ sudo pytest -v # do everything in Docker, like it is done by Jenkins docker build -t vim-emu-loc-test . docker run --rm --privileged --pid='host' -v /var/run/docker.sock:/var/run/docker.sock vim-emu-loc-test pytest -v -docker run --rm --privileged --pid='host' -v /var/run/docker.sock:/var/run/docker.sock vim-emu-loc-test flake8 --exclude=.eggs,devops,examples/charms --ignore=E501,W605,W504 . +docker run --rm --privileged --pid='host' -v /var/run/docker.sock:/var/run/docker.sock vim-emu-loc-test flake8 --exclude=.eggs,devopsi,build,examples/charms --ignore=E501,W605,W504 . echo "done." diff --git a/src/emuvim/api/tango/llcm.py b/src/emuvim/api/tango/llcm.py index f0caf56..0a62485 100755 --- a/src/emuvim/api/tango/llcm.py +++ b/src/emuvim/api/tango/llcm.py @@ -1,3 +1,4 @@ + # Copyright (c) 2018 SONATA-NFV, 5GTANGO and Paderborn University # ALL RIGHTS RESERVED. # @@ -36,6 +37,7 @@ import hashlib import zipfile import yaml import threading +import datetime from docker import DockerClient from flask import Flask, request import flask_restful as fr @@ -141,6 +143,7 @@ class Service(object): self.remote_docker_image_urls = dict() self.instances = dict() self._instance_counter = 0 + self.created_at = str(datetime.datetime.now()) def onboard(self): """ @@ -193,6 +196,7 @@ class Service(object): self.instances[instance_uuid]["ssiid"] = self._instance_counter self.instances[instance_uuid]["name"] = get_triple_id(self.nsd) self.instances[instance_uuid]["vnf_instances"] = list() + self.instances[instance_uuid]["created_at"] = str(datetime.datetime.now()) # increase for next instance self._instance_counter += 1 @@ -952,11 +956,44 @@ class Packages(fr.Resource): def get(self): """ - Return a list of UUID's of uploaded service packages. - :return: dict/list + Return a list of package descriptor headers. + Fakes the behavior of 5GTANGO's GK API to be + compatible with tng-cli. + :return: list """ LOG.info("GET /packages") - return {"service_uuid_list": list(GK.services.iterkeys())} + result = list() + for suuid, sobj in GK.services.iteritems(): + pkg = dict() + pkg["pd"] = dict() + pkg["uuid"] = suuid + pkg["pd"]["name"] = sobj.manifest.get("name") + pkg["pd"]["version"] = sobj.manifest.get("version") + pkg["created_at"] = sobj.created_at + result.append(pkg) + return result, 200 + + +class Services(fr.Resource): + + def get(self): + """ + Return a list of services. + Fakes the behavior of 5GTANGO's GK API to be + compatible with tng-cli. + :return: list + """ + LOG.info("GET /services") + result = list() + for suuid, sobj in GK.services.iteritems(): + service = dict() + service["nsd"] = dict() + service["uuid"] = suuid + service["nsd"]["name"] = sobj.nsd.get("name") + service["nsd"]["version"] = sobj.nsd.get("version") + service["created_at"] = sobj.created_at + result.append(service) + return result, 200 class Instantiations(fr.Resource): @@ -972,7 +1009,9 @@ class Instantiations(fr.Resource): json_data = request.get_json(force=True) service_uuid = json_data.get("service_uuid") service_name = json_data.get("service_name") - + if service_name is None: + # lets be fuzzy + service_name = service_uuid # first try to find by service_name if service_name is not None: for s_uuid, s in GK.services.iteritems(): @@ -990,7 +1029,10 @@ class Instantiations(fr.Resource): # ok, we have a service uuid, lets start the service service_instance_uuid = GK.services.get( service_uuid).start_service() - return {"service_instance_uuid": service_instance_uuid}, 201 + # multiple ID fields to be compatible with tng-bench and tng-cli + return ({"service_instance_uuid": service_instance_uuid, + "id": service_instance_uuid}, 201) + LOG.error("Service not found: {}/{}".format(service_uuid, service_name)) return "Service not found", 404 def get(self): @@ -998,9 +1040,20 @@ class Instantiations(fr.Resource): Returns a list of UUIDs containing all running services. :return: dict / list """ - LOG.info("GET /instantiations") - return {"service_instantiations_list": [ - list(s.instances.iterkeys()) for s in GK.services.itervalues()]} + LOG.info("GET /instantiations or /api/v3/records/services") + # return {"service_instantiations_list": [ + # list(s.instances.iterkeys()) for s in GK.services.itervalues()]} + result = list() + for suuid, sobj in GK.services.iteritems(): + for iuuid, iobj in sobj.instances.iteritems(): + inst = dict() + inst["uuid"] = iobj.get("uuid") + inst["instance_name"] = "{}-inst.{}".format( + iobj.get("name"), iobj.get("ssiid")) + inst["status"] = "running" + inst["created_at"] = iobj.get("created_at") + result.append(inst) + return result, 200 def delete(self): """ @@ -1078,9 +1131,11 @@ app = Flask(__name__) app.config['MAX_CONTENT_LENGTH'] = 512 * 1024 * 1024 # 512 MB max upload api = fr.Api(app) # define endpoints -api.add_resource(Packages, '/packages', '/api/v2/packages') +api.add_resource(Packages, '/packages', '/api/v2/packages', '/api/v3/packages') +api.add_resource(Services, '/services', '/api/v2/services', '/api/v3/services') api.add_resource(Instantiations, '/instantiations', - '/api/v2/instantiations', '/api/v2/requests') + '/api/v2/instantiations', '/api/v2/requests', '/api/v3/requests', + '/api/v3/records/services') api.add_resource(Exit, '/emulator/exit') diff --git a/src/emuvim/test/unittests/test_tango_llcm.py b/src/emuvim/test/unittests/test_tango_llcm.py index da5c6c3..fc426f5 100644 --- a/src/emuvim/test/unittests/test_tango_llcm.py +++ b/src/emuvim/test/unittests/test_tango_llcm.py @@ -44,6 +44,7 @@ class testTangoLLCM(SimpleTestTopology): # @unittest.skip("disabled") def test_tango_llcm_start_service(self): + initialize_GK() # create network self.createNet(nswitches=0, ndatacenter=2, nhosts=2, ndockers=0, enable_learning=True) @@ -79,15 +80,14 @@ class testTangoLLCM(SimpleTestTopology): # check get request APIs r3 = requests.get("http://127.0.0.1:56000/packages") - self.assertEqual(len(json.loads(r3.text).get("service_uuid_list")), 1) + self.assertEqual(len(json.loads(r3.text)), 1) r4 = requests.get("http://127.0.0.1:56000/instantiations") - self.assertEqual(len(json.loads(r4.text).get( - "service_instantiations_list")), 1) + self.assertEqual(len(json.loads(r4.text)), 1) # check number of running nodes - self.assertTrue(len(self.getContainernetContainers()) == 2) - self.assertTrue(len(self.net.hosts) == 4) - self.assertTrue(len(self.net.switches) == 2) + self.assertEqual(len(self.getContainernetContainers()), 2) + self.assertEqual(len(self.net.hosts), 4) + self.assertEqual(len(self.net.switches), 2) # check compute list result (considering placement) self.assertEqual(len(self.dc[0].listCompute()), 1) self.assertEqual(len(self.dc[1].listCompute()), 1) @@ -163,6 +163,7 @@ class testTangoLLCM(SimpleTestTopology): # @unittest.skip("disabled") def test_tango_llcm_stop_service(self): + initialize_GK() # create network self.createNet(ndatacenter=2, nhosts=2) # setup links @@ -198,15 +199,14 @@ class testTangoLLCM(SimpleTestTopology): # check get request APIs r3 = requests.get("http://127.0.0.1:56001/packages") - self.assertEqual(len(json.loads(r3.text).get("service_uuid_list")), 1) + self.assertEqual(len(json.loads(r3.text)), 1) r4 = requests.get("http://127.0.0.1:56001/instantiations") - self.assertEqual(len(json.loads(r4.text).get( - "service_instantiations_list")), 1) + self.assertEqual(len(json.loads(r4.text)), 1) # check number of running nodes - self.assertTrue(len(self.getContainernetContainers()) == 2) - self.assertTrue(len(self.net.hosts) == 4) - self.assertTrue(len(self.net.switches) == 2) + self.assertEqual(len(self.getContainernetContainers()), 2) + self.assertEqual(len(self.net.hosts), 4) + self.assertEqual(len(self.net.switches), 2) # check compute list result (considering placement) self.assertEqual(len(self.dc[0].listCompute()), 1) self.assertEqual(len(self.dc[1].listCompute()), 1) @@ -220,8 +220,7 @@ class testTangoLLCM(SimpleTestTopology): r5 = requests.get("http://127.0.0.1:56001/instantiations") # note that there was 1 instance before - self.assertTrue(len(json.loads(r5.text).get( - "service_instantiations_list")), 0) + self.assertEqual(len(json.loads(r5.text)), 0) # stop Mininet network self.stopNet() -- 2.17.1