summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlaili <lai.li@zte.com.cn>2018-09-13 20:13:29 +0800
committerFu Jinhua <fu.jinhua@zte.com.cn>2018-09-14 00:30:07 +0000
commit261eb147ac54ecfb9b41c643658e1f07c83b4401 (patch)
tree5afa69bc4424cfaa76bbff1f0c06d9db02a1e6cc
parentf8167ebe3cb0b8894c9b4f6bd9d532927c366adf (diff)
Add a subscription api on gvnfmdriver.
Add serializers, view, and tests supscription. Change-Id: I64cf560520038d9396c810307ac022d303f9ddfe Issue-ID: VFC-1118 Signed-off-by: laili <lai.li@zte.com.cn>
-rw-r--r--gvnfmadapter/driver/interfaces/serializers/lccn_subscription.py47
-rw-r--r--gvnfmadapter/driver/interfaces/serializers/lccn_subscription_request.py34
-rw-r--r--gvnfmadapter/driver/interfaces/tests.py61
-rw-r--r--gvnfmadapter/driver/interfaces/urls.py19
-rw-r--r--gvnfmadapter/driver/interfaces/views.py44
5 files changed, 193 insertions, 12 deletions
diff --git a/gvnfmadapter/driver/interfaces/serializers/lccn_subscription.py b/gvnfmadapter/driver/interfaces/serializers/lccn_subscription.py
new file mode 100644
index 0000000..829c927
--- /dev/null
+++ b/gvnfmadapter/driver/interfaces/serializers/lccn_subscription.py
@@ -0,0 +1,47 @@
+# Copyright 2018 ZTE Corporation.
+#
+# 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
+
+from driver.interfaces.serializers.link import LinkSerializer
+from driver.interfaces.serializers.lccn_filter import LifeCycleChangeNotificationsFilterSerializer
+
+
+class _LinkSerializer(serializers.Serializer):
+ self = LinkSerializer(
+ help_text="URI of this resource.",
+ required=True,
+ allow_null=False)
+
+
+class LccnSubscriptionSerializer(serializers.Serializer):
+ id = serializers.CharField(
+ help_text="Identifier of this subscription resource.",
+ max_length=255,
+ required=True
+ )
+ callbackUri = serializers.CharField(
+ help_text="The URI of the endpoint to send the notification to.",
+ max_length=255,
+ required=True
+ )
+ filter = LifeCycleChangeNotificationsFilterSerializer(
+ help_text="Filter settings for this subscription, to define the " +
+ "of all notifications this subscription relates to.",
+ required=False
+ )
+ _links = _LinkSerializer(
+ help_text="Links to resources related to this resource.",
+ required=True
+ )
diff --git a/gvnfmadapter/driver/interfaces/serializers/lccn_subscription_request.py b/gvnfmadapter/driver/interfaces/serializers/lccn_subscription_request.py
new file mode 100644
index 0000000..88797bc
--- /dev/null
+++ b/gvnfmadapter/driver/interfaces/serializers/lccn_subscription_request.py
@@ -0,0 +1,34 @@
+# Copyright 2018 ZTE Corporation.
+#
+# 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
+
+from driver.interfaces.serializers.lccn_filter import LifeCycleChangeNotificationsFilterSerializer
+from driver.interfaces.serializers.subscription_authentication import SubscriptionAuthenticationSerializer
+
+class LccnSubscriptionRequestSerializer(serializers.Serializer):
+ callbackUri = serializers.URLField(
+ help_text="The URI of the endpoint to send the notification to.",
+ required=True,
+ allow_null=False)
+ filter = LifeCycleChangeNotificationsFilterSerializer(
+ help_text="Filter settings for the subscription, to define the subset of all " +
+ "notifications this subscription relates to.",
+ required=False,
+ allow_null=True)
+ authentication = SubscriptionAuthenticationSerializer(
+ help_text="Authentication parameters to configure the use of Authorization when sending " +
+ "notifications corresponding to this subscription.",
+ required=False,
+ allow_null=True)
diff --git a/gvnfmadapter/driver/interfaces/tests.py b/gvnfmadapter/driver/interfaces/tests.py
index 9c50466..4d58137 100644
--- a/gvnfmadapter/driver/interfaces/tests.py
+++ b/gvnfmadapter/driver/interfaces/tests.py
@@ -40,7 +40,7 @@ class InterfacesTest(TestCase):
'vnfmId': 'b0797c9b-3da9-459c-b25c-3813e9d8fd70',
'password': 'admin',
'type': 'gvnfmdriver',
- 'createTime': '2016-10-3111: 08: 39',
+ 'createTime': '2016-10-3T11:08:39',
'description': ''
}
create_vnf_resp = {
@@ -583,7 +583,7 @@ class InterfacesTest(TestCase):
"url": "http://10.74.44.11",
"userName": "admin",
"password": "admin",
- "createTime": "2016-07-06 15:33:18"
+ "createTime": "2016-07-06T15:33:18"
}
dummy_single_vnf_lcm_op = {
"id": vnfLcmOpOccId,
@@ -633,3 +633,60 @@ class InterfacesTest(TestCase):
mock_call_req.return_value = [1, json.JSONEncoder().encode({}), status.HTTP_500_INTERNAL_SERVER_ERROR]
resp = self.client.get("/api/gvnfmdriver/v1/%s/vnf_lcm_op_occs/%s" % (vnfm_info['vnfmId'], vnfLcmOpOccId))
self.assertEqual(status.HTTP_500_INTERNAL_SERVER_ERROR, resp.status_code)
+
+ @mock.patch.object(restcall, 'call_req')
+ def test_subscribe_successfully(self, mock_call_req):
+ lccn_subscription_request_data = {
+ "filter": {
+ "notificationTypes": ["VnfLcmOperationOccurrenceNotification"],
+ "operationTypes": ["INSTANTIATE"],
+ "operationStates": ["STARTING"],
+ },
+ "callbackUri": "http://aurl.com",
+ "authentication": {
+ "authType": ["BASIC"],
+ "paramsBasic": {
+ "username": "username",
+ "password": "password"
+ }
+ }
+ }
+ lccn_subscription_data = {
+ "id": "cd552c9c-ab6f-11e8-b354-236c32aa91a1",
+ "callbackUri": "http://aurl.com",
+ "filter": {
+ "notificationTypes": ["VnfLcmOperationOccurrenceNotification"],
+ "operationTypes": ["INSTANTIATE"],
+ "operationStates": ["STARTING"]
+ },
+ "_links": {
+ "self": {"href": "URI of this resource."}
+ },
+ }
+ mock_call_req.return_value = [0, json.JSONEncoder().encode(lccn_subscription_data), status.HTTP_201_CREATED]
+ response = self.client.post("/api/gvnfmdriver/v1/subscriptions", json.dumps(lccn_subscription_request_data),
+ content_type='application/json')
+ self.assertEqual(status.HTTP_201_CREATED, response.status_code)
+ self.assertEqual(lccn_subscription_data, response.data)
+
+ @mock.patch.object(restcall, 'call_req')
+ def test_subscribe_failed(self, mock_call_req):
+ lccn_subscription_request_data = {
+ "filter": {
+ "notificationTypes": ["VnfLcmOperationOccurrenceNotification"],
+ "operationTypes": ["INSTANTIATE"],
+ "operationStates": ["STARTING"],
+ },
+ "callbackUri": "http://aurl.com",
+ "authentication": {
+ "authType": ["BASIC"],
+ "paramsBasic": {
+ "username": "username",
+ "password": "password"
+ }
+ }
+ }
+ mock_call_req.return_value = [1, None, status.HTTP_303_SEE_OTHER]
+ response = self.client.post("/api/gvnfmdriver/v1/subscriptions", json.dumps(lccn_subscription_request_data),
+ content_type='application/json')
+ self.assertEqual(status.HTTP_500_INTERNAL_SERVER_ERROR, response.status_code)
diff --git a/gvnfmadapter/driver/interfaces/urls.py b/gvnfmadapter/driver/interfaces/urls.py
index 6adb6f9..40b8f3b 100644
--- a/gvnfmadapter/driver/interfaces/urls.py
+++ b/gvnfmadapter/driver/interfaces/urls.py
@@ -14,20 +14,19 @@
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
urlpatterns = [
url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnfs$', VnfInstInfo.as_view()),
- url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnfs/(?P<vnfInstanceId>'
- r'[0-9a-zA-Z\-\_]+)/terminate$', VnfTermInfo.as_view()),
- url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnfs/(?P<vnfInstanceId>'
- r'[0-9a-zA-Z\-\_]+)$', VnfQueryInfo.as_view()),
- url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/jobs/(?P<jobid>[0-9a-zA-Z\-\_]+)$',
- VnfOperInfo.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnfs/(?P<vnfInstanceId>[0-9a-zA-Z\-\_]+)/terminate$', VnfTermInfo.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnfs/(?P<vnfInstanceId>[0-9a-zA-Z\-\_]+)$', VnfQueryInfo.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/jobs/(?P<jobid>[0-9a-zA-Z\-\_]+)$', VnfOperInfo.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/subscriptions$', Subscription.as_view()),
+
+
url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/vnfpackages$', VnfPkgsInfo.as_view()),
url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/resource/grant$', VnfGrantInfo.as_view()),
- url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/vnfs/lifecyclechangesnotification$',
- VnfNotifyInfo.as_view()),
- url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnf_lcm_op_occs/(?P<lcmopoccid>[0-9a-zA-Z_-]+)$',
- QuerySingleVnfLcmOpOcc.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/vnfs/lifecyclechangesnotification$', VnfNotifyInfo.as_view()),
+ url(r'^api/(?P<vnfmtype>[0-9a-zA-Z\-\_]+)/v1/(?P<vnfmid>[0-9a-zA-Z\-\_]+)/vnf_lcm_op_occs/(?P<lcmopoccid>[0-9a-zA-Z_-]+)$', QuerySingleVnfLcmOpOcc.as_view()),
]
diff --git a/gvnfmadapter/driver/interfaces/views.py b/gvnfmadapter/driver/interfaces/views.py
index 362fe12..1cf6fa2 100644
--- a/gvnfmadapter/driver/interfaces/views.py
+++ b/gvnfmadapter/driver/interfaces/views.py
@@ -29,6 +29,8 @@ from driver.interfaces.serializers.serializers import VnfOperRespSerializer
from driver.interfaces.serializers.serializers import VnfTermReqSerializer, VnfQueryRespSerializer
from driver.interfaces.serializers.grant_request import GrantRequestSerializer
from driver.interfaces.serializers.grant import GrantSerializer
+from driver.interfaces.serializers.lccn_subscription import LccnSubscriptionSerializer
+from driver.interfaces.serializers.lccn_subscription_request import LccnSubscriptionRequestSerializer
from driver.pub.exceptions import GvnfmDriverException
from driver.pub.utils import restcall
from driver.pub.utils.restcall import req_by_msb
@@ -345,6 +347,38 @@ class QuerySingleVnfLcmOpOcc(APIView):
return Response(data={'error': traceback.format_exc()}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+class Subscription(APIView):
+ @swagger_auto_schema(
+ request_body=LccnSubscriptionRequestSerializer(),
+ responses={
+ status.HTTP_201_CREATED: LccnSubscriptionSerializer(),
+ status.HTTP_303_SEE_OTHER: None,
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "INTERNAL_SERVER_ERROR"
+ }
+ )
+ def post(self, request, vnfmtype):
+ logger.debug("Subscription--post::> %s" % request.data)
+ logger.debug("Subscription begin!")
+ try:
+ lccn_subscription_request_serializer = LccnSubscriptionRequestSerializer(data=request.data)
+ if not lccn_subscription_request_serializer.is_valid():
+ raise GvnfmDriverException(lccn_subscription_request_serializer.error_messages)
+ resp_data = do_subscription(request.data)
+ lccn_subscription_serializer = LccnSubscriptionSerializer(data=resp_data)
+ if not lccn_subscription_serializer.is_valid():
+ logger.debug("[%s]resp_data=%s" % (fun_name(), resp_data))
+ raise GvnfmDriverException(lccn_subscription_serializer.errors)
+ logger.debug("Subscription end!")
+ return Response(data=lccn_subscription_serializer.data, status=status.HTTP_201_CREATED)
+ except GvnfmDriverException as e:
+ logger.error(e.message)
+ return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+ except Exception as e:
+ logger.error(e.message)
+ logger.error(traceback.format_exc())
+ return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
def call_vnfm(resource, method, vnfm_info, data=""):
ret = restcall.call_req(
base_url=ignorcase_get(vnfm_info, "url"),
@@ -493,3 +527,13 @@ def do_queryvnf(data, vnfm_id, vnfInstanceId):
logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
raise GvnfmDriverException('Failed to query vnf.')
return json.JSONDecoder().decode(ret[1])
+
+
+def do_subscription(data):
+ logger.debug("[%s] request.data=%s", fun_name(), data)
+ ret = req_by_msb("api/vnflcm/v1/subscriptions", "POST", json.JSONEncoder().encode(data))
+ logger.debug("[%s] call_req ret=%s", fun_name(), ret)
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise GvnfmDriverException('Failed to subscribe.')
+ return json.JSONDecoder().decode(ret[1])