From bf82cec0dc9d73c05d1011f47bb696f6010dea57 Mon Sep 17 00:00:00 2001 From: Shobana Jothi Date: Fri, 7 Sep 2018 19:56:37 +0530 Subject: Heal api in Gvnfm Driver Change-Id: I674cc0231c172f9fb0985bd6b1182138182c07dc Issue-ID: VFC-1050 Signed-off-by: Shobana Jothi --- .../driver/interfaces/serializers/heal_request.py | 34 +++++++ gvnfmadapter/driver/interfaces/tests.py | 100 +++++++++++++++++++++ gvnfmadapter/driver/interfaces/urls.py | 4 +- gvnfmadapter/driver/interfaces/views.py | 51 +++++++++++ 4 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 gvnfmadapter/driver/interfaces/serializers/heal_request.py (limited to 'gvnfmadapter') diff --git a/gvnfmadapter/driver/interfaces/serializers/heal_request.py b/gvnfmadapter/driver/interfaces/serializers/heal_request.py new file mode 100644 index 0000000..c212769 --- /dev/null +++ b/gvnfmadapter/driver/interfaces/serializers/heal_request.py @@ -0,0 +1,34 @@ +# Copyright (C) 2018 Verizon. All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from rest_framework import serializers + + +class AffectedVm(serializers.Serializer): + vmid = serializers.CharField(help_text="Vm id", required=True) + vduid = serializers.CharField(help_text="Vdu id", required=True) + vmname = serializers.CharField(help_text="Vm name", required=True) + +class VnfHealRequestSerializer(serializers.Serializer): + action = serializers.CharField(help_text="Action for NS heal", required=True, allow_null=True) + affectedvm = AffectedVm(help_text="Get the vm information to be healed", required=True) + +class HealVnfRequestSerializerToVnfm(serializers.Serializer): + cause = serializers.CharField(help_text="Cause of NS heal", required=False, allow_null=True) + additionalParams = serializers.DictField( + help_text="Additional input parameters for the healing process, \ + specific to the VNF being healed, \ + as declared in the VNFD as part of HealVnfOpConfig.", + required=False, + allow_null=True) diff --git a/gvnfmadapter/driver/interfaces/tests.py b/gvnfmadapter/driver/interfaces/tests.py index 7196f3a..c062c7c 100644 --- a/gvnfmadapter/driver/interfaces/tests.py +++ b/gvnfmadapter/driver/interfaces/tests.py @@ -818,3 +818,103 @@ class InterfacesTest(TestCase): self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code) self.assertEqual(None, response.data) self.assertEqual("/vnf_lc_ops/NF-OPERATE-12-2a3be946-b01d-11e8-9302-08002705b121", response['Location']) + +# Heal API + @mock.patch.object(restcall, 'call_req') + def test_heal_vnf_404_NotFound(self, mock_call_req): + vnfm_info = { + "vnfmId": "19ecbb3a-3242-4fa3-9926-8dfb7ddc29ee", + "name": "g_vnfm", + "type": "gvnfmdriver", + "vimId": "", + "vendor": "vendor1", + "version": "v1.0", + "description": "vnfm", + "certificateUrl": "", + "url": "http://10.74.44.11", + "userName": "admin", + "password": "admin", + "createTime": "2016-07-06 15:33:18" + } + req_data = { + "action": "vmReset", + "affectedvm": { + "vmid": "1", + "vduid": "vdu1Id", + "vmname": "vduinstname" + } + } + probDetail = {"status": 404, "detail": "VNF Instance not found"} + r1 = [0, json.JSONEncoder().encode(vnfm_info), "200", ""] + r2 = [1, json.JSONEncoder().encode(probDetail), "404", ""] + mock_call_req.side_effect = [r1, r2] + response = self.client.post("/api/gvnfmdriver/v1/vnfmid/vnfs/2/heal", + data=json.dumps(req_data), content_type="application/json") + self.assertEqual(status.HTTP_404_NOT_FOUND, response.status_code) + self.assertEqual(probDetail, response.data) + + @mock.patch.object(restcall, 'call_req') + def test_heal_vnf_409_Conflict(self, mock_call_req): + vnfm_info = { + "vnfmId": "19ecbb3a-3242-4fa3-9926-8dfb7ddc29ee", + "name": "g_vnfm", + "type": "gvnfmdriver", + "vimId": "", + "vendor": "vendor1", + "version": "v1.0", + "description": "vnfm", + "certificateUrl": "", + "url": "http://10.74.44.11", + "userName": "admin", + "password": "admin", + "createTime": "2016-07-06 15:33:18" + } + req_data = { + "action": "vmReset", + "affectedvm": { + "vmid": "1", + "vduid": "vdu1Id", + "vmname": "vduinstname" + } + } + probDetail = {"status": 409, "detail": "VNF Instance not in Instantiated State"} + r1 = [0, json.JSONEncoder().encode(vnfm_info), "200", ""] + r2 = [1, json.JSONEncoder().encode(probDetail), "409", ""] + mock_call_req.side_effect = [r1, r2] + response = self.client.post("/api/gvnfmdriver/v1/vnfmid/vnfs/2/heal", + data=json.dumps(req_data), content_type="application/json") + self.assertEqual(status.HTTP_409_CONFLICT, response.status_code) + self.assertEqual(probDetail, response.data) + + @mock.patch.object(restcall, 'call_req') + def test_heal_vnf_success(self, mock_call_req): + vnfm_info = { + "vnfmId": "19ecbb3a-3242-4fa3-9926-8dfb7ddc29ee", + "name": "g_vnfm", + "type": "gvnfmdriver", + "vimId": "", + "vendor": "vendor1", + "version": "v1.0", + "description": "vnfm", + "certificateUrl": "", + "url": "http://10.74.44.11", + "userName": "admin", + "password": "admin", + "createTime": "2016-07-06 15:33:18" + } + req_data = { + "action": "vmReset", + "affectedvm": { + "vmid": "1", + "vduid": "vdu1Id", + "vmname": "vduinstname" + } + } + r1 = [0, json.JSONEncoder().encode(vnfm_info), "200"] + r2 = [0, json.JSONEncoder().encode(''), "202", "/vnf_lc_ops/NF-HEAL-12-2a3be946-b01d-11e8-9302-08002705b121"] + mock_call_req.side_effect = [r1, r2] + response = self.client.post("/api/gvnfmdriver/v1/vnfmid/vnfs/2/heal", + data=json.dumps(req_data), content_type="application/json") + self.assertEqual(status.HTTP_202_ACCEPTED, response.status_code) + self.assertEqual(None, response.data) + self.assertEqual("/vnf_lc_ops/NF-HEAL-12-2a3be946-b01d-11e8-9302-08002705b121", response['Location']) diff --git a/gvnfmadapter/driver/interfaces/urls.py b/gvnfmadapter/driver/interfaces/urls.py index b615d9b..9a36463 100644 --- a/gvnfmadapter/driver/interfaces/urls.py +++ b/gvnfmadapter/driver/interfaces/urls.py @@ -15,7 +15,7 @@ from django.conf.urls import url from driver.interfaces.views import VnfInstInfo, VnfTermInfo, VnfQueryInfo, VnfOperInfo from driver.interfaces.views import Subscription -from driver.interfaces.views import VnfPkgsInfo, VnfGrantInfo, VnfNotifyInfo, QuerySingleVnfLcmOpOcc, VnfOperateView +from driver.interfaces.views import VnfPkgsInfo, VnfGrantInfo, VnfNotifyInfo, QuerySingleVnfLcmOpOcc, VnfOperateView, VnfHealView urlpatterns = [ url(r'^api/(?P[0-9a-zA-Z\-\_]+)/v1/(?P[0-9a-zA-Z\-\_]+)/vnfs$', VnfInstInfo.as_view()), @@ -30,4 +30,6 @@ urlpatterns = [ url(r'^api/(?P[0-9a-zA-Z\-\_]+)/v1/(?P[0-9a-zA-Z\-\_]+)/vnf_lcm_op_occs/(?P[0-9a-zA-Z_-]+)$', QuerySingleVnfLcmOpOcc.as_view()), url(r'^api/(?P[0-9a-zA-Z\-\_]+)/v1/(?P[0-9a-zA-Z\-\_]+)/vnfs/(?P' r'[0-9a-zA-Z\-\_]+)/operate$', VnfOperateView.as_view()), + url(r'^api/(?P[0-9a-zA-Z\-\_]+)/v1/(?P[0-9a-zA-Z\-\_]+)/vnfs/(?P' + r'[0-9a-zA-Z\-\_]+)/heal$', VnfHealView.as_view()), ] diff --git a/gvnfmadapter/driver/interfaces/views.py b/gvnfmadapter/driver/interfaces/views.py index b32aa8c..3a62b24 100644 --- a/gvnfmadapter/driver/interfaces/views.py +++ b/gvnfmadapter/driver/interfaces/views.py @@ -35,6 +35,7 @@ from driver.pub.exceptions import GvnfmDriverException from driver.pub.utils import restcall from driver.pub.utils.restcall import req_by_msb from driver.interfaces.serializers.operate_request import VnfOperateRequestSerializer +from driver.interfaces.serializers.heal_request import HealVnfRequestSerializerToVnfm, VnfHealRequestSerializer from driver.interfaces.serializers.response import ProblemDetailsSerializer logger = logging.getLogger(__name__) @@ -341,6 +342,56 @@ class VnfOperateView(APIView): return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) +class VnfHealView(APIView): + @swagger_auto_schema( + request_body=VnfHealRequestSerializer(), + responses={ + status.HTTP_202_ACCEPTED: "Success", + status.HTTP_404_NOT_FOUND: ProblemDetailsSerializer(), + status.HTTP_409_CONFLICT: ProblemDetailsSerializer(), + status.HTTP_500_INTERNAL_SERVER_ERROR: "Internal error" + } + ) + def post(self, request, vnfmtype, vnfmid, vnfInstanceId): + logger.debug("Heal_vnf--post::> %s" % request.data) + logger.debug("Heal vnf begin!") + try: + requestSerializer = VnfHealRequestSerializer(data=request.data) + request_isValid = requestSerializer.is_valid() + if not request_isValid: + raise Exception(requestSerializer.errors) + healdata = { + u"additionalParams": { + u"action": ignorcase_get(request.data, "action"), + u"affectedvm": ignorcase_get(request.data, "affectedvm") + } + } + input_data = HealVnfRequestSerializerToVnfm(data=healdata) + resp_isvalid = input_data.is_valid() + if not resp_isvalid: + raise GvnfmDriverException(input_data.errors) + logger.debug("Heal vnf start!") + logger.debug("do_heal: vnfmid=[%s],vnfInstanceId=[%s],request data=[%s]", + vnfmid, vnfInstanceId, input_data) + statusCode, resp, location = do_lcmVnf(vnfmid, vnfInstanceId, input_data.data, "heal") + logger.debug("do_heal: response data=[%s]", resp) + logger.debug("Heal vnf end!") + ret = int(statusCode) + if ret == status.HTTP_404_NOT_FOUND: + return Response(data=resp, status=status.HTTP_404_NOT_FOUND) + elif ret == status.HTTP_409_CONFLICT: + return Response(data=resp, status=status.HTTP_409_CONFLICT) + response = Response(data=None, status=status.HTTP_202_ACCEPTED) + response["Location"] = location + return response + except GvnfmDriverException as e: + logger.error('Heal vnf failed, detail message: %s' % e.message) + return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except: + logger.error(traceback.format_exc()) + return Response(data={'error': 'unexpected exception'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + class VnfPkgsInfo(APIView): def get(request, *args, **kwargs): try: -- cgit 1.2.3-korg