summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormaopengzhang <zhang.maopeng1@zte.com.cn>2018-09-17 16:55:34 +0800
committermaopengzhang <zhang.maopeng1@zte.com.cn>2018-09-17 20:52:00 +0800
commitdb610a8280b3922b64eef965e3707444885f8002 (patch)
tree09bc36d551dd53b652867d10dede89015734e603
parent48f7b3d0d6fc76f6949b0608465267325237c00c (diff)
Support PNF In NSLCM
Support PNF in NSLCM Change-Id: I0e1d28d8f574ca38c6e99c74617e6dc91c6403ad Issue-ID: VFC-1102 Signed-off-by: maopengzhang <zhang.maopeng1@zte.com.cn>
-rw-r--r--lcm/ns_pnfs/__init__.py13
-rw-r--r--lcm/ns_pnfs/biz/__init__.py13
-rw-r--r--lcm/ns_pnfs/biz/active_pnf.py27
-rw-r--r--lcm/ns_pnfs/biz/create_pnf.py71
-rw-r--r--lcm/ns_pnfs/biz/delete_pnf.py34
-rw-r--r--lcm/ns_pnfs/biz/get_pnf.py33
-rw-r--r--lcm/ns_pnfs/serializers/__init__.py13
-rw-r--r--lcm/ns_pnfs/serializers/pnf_serializer.py28
-rw-r--r--lcm/ns_pnfs/tests/__init__.py13
-rw-r--r--lcm/ns_pnfs/tests/test_create_pnf.py90
-rw-r--r--lcm/ns_pnfs/tests/test_delete_pnf.py58
-rw-r--r--lcm/ns_pnfs/tests/test_get_pnf.py99
-rw-r--r--lcm/ns_pnfs/urls.py24
-rw-r--r--lcm/ns_pnfs/views/__init__.py13
-rw-r--r--lcm/ns_pnfs/views/pnf_view.py119
-rw-r--r--lcm/pub/database/models.py14
-rw-r--r--lcm/pub/msapi/emsdriver.py31
-rw-r--r--lcm/pub/msapi/extsys.py28
-rw-r--r--lcm/pub/msapi/sdc_run_catalog.py12
-rw-r--r--lcm/urls.py1
20 files changed, 734 insertions, 0 deletions
diff --git a/lcm/ns_pnfs/__init__.py b/lcm/ns_pnfs/__init__.py
new file mode 100644
index 00000000..342c2a8c
--- /dev/null
+++ b/lcm/ns_pnfs/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/lcm/ns_pnfs/biz/__init__.py b/lcm/ns_pnfs/biz/__init__.py
new file mode 100644
index 00000000..342c2a8c
--- /dev/null
+++ b/lcm/ns_pnfs/biz/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/lcm/ns_pnfs/biz/active_pnf.py b/lcm/ns_pnfs/biz/active_pnf.py
new file mode 100644
index 00000000..3a7ff860
--- /dev/null
+++ b/lcm/ns_pnfs/biz/active_pnf.py
@@ -0,0 +1,27 @@
+# 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 lcm.pub.msapi.emsdriver import send_active_pnf_request
+
+
+class ActivePnf(object):
+ def __init__(self, ems_id, pnf_id, active_data):
+ self.ems_id = ems_id
+ self.pnf_id = pnf_id
+ self.data = active_data
+
+ def do_biz(self):
+ self.active_pnf()
+
+ def active_pnf(self):
+ return send_active_pnf_request(self.ems_id, self.pnf_id, self.data)
diff --git a/lcm/ns_pnfs/biz/create_pnf.py b/lcm/ns_pnfs/biz/create_pnf.py
new file mode 100644
index 00000000..c9207135
--- /dev/null
+++ b/lcm/ns_pnfs/biz/create_pnf.py
@@ -0,0 +1,71 @@
+# 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.
+
+import logging
+from lcm.pub.database.models import PNFInstModel
+from lcm.pub.exceptions import NSLCMException
+from lcm.pub.msapi.sdc_run_catalog import query_pnf_descriptor
+from lcm.ns_pnfs.biz.get_pnf import GetPnf
+
+logger = logging.getLogger(__name__)
+
+
+class CreatePnf(object):
+ def __init__(self, data):
+ self.pnfId = data.get("pnfId"),
+ self.pnfName = data.get("pnfName"),
+ self.pnfdId = data.get("pnfdId"),
+ self.pnfdInfoId = data.get("pnfdInfoId"),
+ self.pnfProfileId = data.get("pnfProfileId"),
+ self.cpInfo = data.get("cpInfo", "")
+ self.emsId = data.get("emsId", "")
+ self.nsInstances = data.get("nsInstances")
+
+ def do_biz(self):
+ self.check_pnfd_valid()
+ self.build_cpInfo()
+ self.build_emsId()
+ self.create_pnf_inst()
+ logger.debug("CreatePnf::do_biz::pnfId=%s" % self.pnfId)
+ return GetPnf({"pnfId": self.pnfId}, True).do_biz()
+
+ def check_pnfd_valid(self):
+ pnf_package_info = query_pnf_descriptor({"pnfId": self.pnfdInfoId})
+ if not pnf_package_info:
+ raise NSLCMException("Pnfd(%s) does not exist." % self.pnfdInfoId)
+
+ def build_cpInfo(self):
+ # todo
+ pass
+
+ def build_emsId(self):
+ # todo
+ pass
+
+ def create_pnf_inst(self):
+ pnfInstances = PNFInstModel.objects.filter(pnfId=self.pnfId)
+ if pnfInstances:
+ if not pnfInstances.filter(nsInstances__contains=self.nsInstances):
+ for pnfInstance in pnfInstances:
+ new_nsInstances = pnfInstance.nsInstances + "," + self.nsInstances
+ pnfInstance.update(nsInstances=new_nsInstances)
+ else:
+ PNFInstModel(pnfId=self.pnfId,
+ pnfName=self.pnfName,
+ pnfdId=self.pnfdId,
+ pnfdInfoId=self.pnfdInfoId,
+ pnfProfileId=self.pnfProfileId,
+ cpInfo=self.cpInfo,
+ emsId=self.emsId,
+ nsInstances=self.nsInstances).save()
diff --git a/lcm/ns_pnfs/biz/delete_pnf.py b/lcm/ns_pnfs/biz/delete_pnf.py
new file mode 100644
index 00000000..513fd97e
--- /dev/null
+++ b/lcm/ns_pnfs/biz/delete_pnf.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.
+
+import logging
+from lcm.pub.database.models import PNFInstModel
+
+logger = logging.getLogger(__name__)
+
+
+class DeletePnf(object):
+ def __init__(self, pnf_id):
+ self.pnfId = pnf_id
+
+ def do_biz(self):
+ self.check_pnf_used()
+ self.delete_pnf()
+
+ def check_pnf_used(self):
+ pass # todo check whether the PNF is used in NS Instances
+
+ def delete_pnf(self):
+ logger.debug("delele PnfInstModel(%s)", self.pnfId)
+ PNFInstModel.objects.filter(pnfId=self.pnfId).delete()
diff --git a/lcm/ns_pnfs/biz/get_pnf.py b/lcm/ns_pnfs/biz/get_pnf.py
new file mode 100644
index 00000000..a01abad6
--- /dev/null
+++ b/lcm/ns_pnfs/biz/get_pnf.py
@@ -0,0 +1,33 @@
+# 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 lcm.pub.database.models import PNFInstModel
+
+
+class GetPnf(object):
+ def __init__(self, filter=None, isIndividual=False):
+ self.filter = filter
+ self.isIndividual = isIndividual
+
+ def do_biz(self):
+ if self.filter and "pnfId" in self.filter:
+ pnf_instances = PNFInstModel.objects.filter(pnfId=self.filter["pnfId"])
+ if pnf_instances and self.isIndividual:
+ return pnf_instances[0]
+ else:
+ return pnf_instances
+ elif self.filter and "nsInstanceId" in self.filter:
+ return PNFInstModel.objects.filter(nsInstances__contains=self.filter["nsInstanceId"])
+ else:
+ return PNFInstModel.objects.all()
diff --git a/lcm/ns_pnfs/serializers/__init__.py b/lcm/ns_pnfs/serializers/__init__.py
new file mode 100644
index 00000000..342c2a8c
--- /dev/null
+++ b/lcm/ns_pnfs/serializers/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/lcm/ns_pnfs/serializers/pnf_serializer.py b/lcm/ns_pnfs/serializers/pnf_serializer.py
new file mode 100644
index 00000000..b3d7410b
--- /dev/null
+++ b/lcm/ns_pnfs/serializers/pnf_serializer.py
@@ -0,0 +1,28 @@
+# 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
+
+
+class PnfInstanceSerializer(serializers.Serializer):
+ pnfId = serializers.CharField(help_text="Identifier of the PNF.", required=True, allow_null=False)
+ pnfName = serializers.CharField(help_text="Name of the PNF.", required=True, allow_null=True)
+ pnfdId = serializers.CharField(help_text="Identifier of the PNFD on which the PNF is based.", required=True, allow_null=True)
+ pnfdInfoId = serializers.CharField(help_text="Identifier of the PNFD information object related to this PNF.", required=True, allow_null=True)
+ pnfProfileId = serializers.CharField(help_text="Identifier of the related PnfProfile in the NSD on which the PNF is based.", required=True, allow_null=True)
+ cpInfo = serializers.CharField(help_text="Information on the external CP of the PNF.", required=True, allow_null=True)
+
+
+class PnfInstancesSerializer(serializers.ListSerializer):
+ child = PnfInstanceSerializer()
diff --git a/lcm/ns_pnfs/tests/__init__.py b/lcm/ns_pnfs/tests/__init__.py
new file mode 100644
index 00000000..342c2a8c
--- /dev/null
+++ b/lcm/ns_pnfs/tests/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/lcm/ns_pnfs/tests/test_create_pnf.py b/lcm/ns_pnfs/tests/test_create_pnf.py
new file mode 100644
index 00000000..c248ecb5
--- /dev/null
+++ b/lcm/ns_pnfs/tests/test_create_pnf.py
@@ -0,0 +1,90 @@
+# 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.
+
+import uuid
+import mock
+import json
+from django.test import TestCase, Client
+from rest_framework import status
+from lcm.ns_pnfs.biz.create_pnf import CreatePnf
+from lcm.pub.utils import restcall
+
+
+class TestCreatePnfViews(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ def tearDown(self):
+ pass
+
+ @mock.patch.object(restcall, 'call_req')
+ def test_do_biz(self, mock_call_req):
+ mock_call_req.return_value = [0, json.JSONEncoder().encode({
+ 'id': str(uuid.uuid4()),
+ 'pnfdId': 'test',
+ 'pnfdName': 'test',
+ 'pnfdVersion': 'v1.1.0',
+ 'pnfdProvider': 'ZTE',
+ 'pnfdInvariantId': str(uuid.uuid4())
+ }), '200']
+ id = str(uuid.uuid4())
+ data = {
+ "pnfId": id,
+ "pnfName": "Test PNF",
+ "pnfdId": str(uuid.uuid4()),
+ "pnfdInfoId": str(uuid.uuid4()),
+ "pnfProfileId": str(uuid.uuid4()),
+ "cpInfo": [
+ {
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }
+ ],
+ "emsId": str(uuid.uuid4()),
+ "nsInstances": str(uuid.uuid4()) + "," + str(uuid.uuid4())
+ }
+ ret = CreatePnf(data).do_biz()
+ self.assertIsNotNone(ret)
+
+ @mock.patch.object(restcall, 'call_req')
+ def test_rest_api(self, mock_call_req):
+ mock_call_req.return_value = [0, json.JSONEncoder().encode({
+ 'id': str(uuid.uuid4()),
+ 'pnfdId': 'test',
+ 'pnfdName': 'test',
+ 'pnfdVersion': 'v1.1.0',
+ 'pnfdProvider': 'ZTE',
+ 'pnfdInvariantId': str(uuid.uuid4())
+ }), '200']
+ id = str(uuid.uuid4())
+ data = {
+ "pnfId": id,
+ "pnfName": "Test PNF",
+ "pnfdId": str(uuid.uuid4()),
+ "pnfdInfoId": str(uuid.uuid4()),
+ "pnfProfileId": str(uuid.uuid4()),
+ "cpInfo": [
+ {
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }
+ ],
+ "emsId": str(uuid.uuid4()),
+ "nsInstances": str(uuid.uuid4()) + "," + str(uuid.uuid4())
+ }
+
+ response = self.client.post("/api/nslcm/v1/pnfs", data=data, format='json')
+ self.assertEqual(status.HTTP_201_CREATED, response.status_code)
diff --git a/lcm/ns_pnfs/tests/test_delete_pnf.py b/lcm/ns_pnfs/tests/test_delete_pnf.py
new file mode 100644
index 00000000..1cf431e6
--- /dev/null
+++ b/lcm/ns_pnfs/tests/test_delete_pnf.py
@@ -0,0 +1,58 @@
+# 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.
+
+import uuid
+from django.test import TestCase, Client
+from rest_framework import status
+from lcm.ns_pnfs.biz.delete_pnf import DeletePnf
+from lcm.pub.database.models import PNFInstModel
+
+
+class TestDeletePnfViews(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ def tearDown(self):
+ pass
+
+ def test_do_biz(self):
+ pnfId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }]).save()
+ DeletePnf(pnfId).do_biz()
+ pnfInst = PNFInstModel.objects.filter(pnfId=pnfId)
+ self.assertEqual(0, len(pnfInst))
+
+ def test_rest_api(self):
+ pnfId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }]).save()
+ response = self.client.delete("/api/nslcm/v1/pnfs/%s" % pnfId)
+ self.assertEqual(status.HTTP_204_NO_CONTENT, response.status_code)
diff --git a/lcm/ns_pnfs/tests/test_get_pnf.py b/lcm/ns_pnfs/tests/test_get_pnf.py
new file mode 100644
index 00000000..e5688733
--- /dev/null
+++ b/lcm/ns_pnfs/tests/test_get_pnf.py
@@ -0,0 +1,99 @@
+# 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.
+
+import uuid
+from django.test import TestCase, Client
+from rest_framework import status
+from lcm.ns_pnfs.biz.get_pnf import GetPnf
+from lcm.pub.database.models import PNFInstModel
+
+
+class TestGetPnfViews(TestCase):
+ def setUp(self):
+ self.client = Client()
+
+ def tearDown(self):
+ pass
+
+ def test_pnfid_filter(self):
+ pnfId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }]).save()
+ pnfInst = GetPnf({"pnfId": pnfId}).do_biz()
+ self.assertEqual("Test PNF", pnfInst[0].pnfName)
+
+ def test_nsInstanceid_filter(self):
+ pnfId = str(uuid.uuid4())
+ nsInstanceId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }],
+ emsId=str(uuid.uuid4()),
+ nsInstances=nsInstanceId
+ ).save()
+ pnfInst = GetPnf({"nsInstanceId": nsInstanceId}).do_biz()
+ self.assertEqual("Test PNF", pnfInst[0].pnfName)
+
+ def test_get_instances_restapi(self):
+ pnfId = str(uuid.uuid4())
+ nsInstanceId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }],
+ emsId=str(uuid.uuid4()),
+ nsInstances=nsInstanceId
+ ).save()
+ response = self.client.get("/api/nslcm/v1/pnfs")
+ self.assertEqual(status.HTTP_200_OK, response.status_code)
+
+ def test_get_individual_instance_restapi(self):
+ pnfId = str(uuid.uuid4())
+ nsInstanceId = str(uuid.uuid4())
+ PNFInstModel(pnfId=pnfId,
+ pnfName="Test PNF",
+ pnfdId=str(uuid.uuid4()),
+ pnfdInfoId=str(uuid.uuid4()),
+ pnfProfileId=str(uuid.uuid4()),
+ cpInfo=[{
+ "cpInstanceId": str(uuid.uuid4()),
+ "cpdId": "pnf_ext_cp01",
+ "cpProtocolData": []
+ }],
+ emsId=str(uuid.uuid4()),
+ nsInstances=nsInstanceId
+ ).save()
+ response = self.client.get("/api/nslcm/v1/pnfs/%s" % pnfId)
+ self.assertEqual(status.HTTP_200_OK, response.status_code)
diff --git a/lcm/ns_pnfs/urls.py b/lcm/ns_pnfs/urls.py
new file mode 100644
index 00000000..8237b640
--- /dev/null
+++ b/lcm/ns_pnfs/urls.py
@@ -0,0 +1,24 @@
+# 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 django.conf.urls import url
+from rest_framework.urlpatterns import format_suffix_patterns
+from lcm.ns_pnfs.views.pnf_view import PnfView, IndividualPnfView
+
+urlpatterns = [
+ url(r'^api/nslcm/v1/pnfs$', PnfView.as_view()),
+ url(r'^api/nslcm/v1/pnfs/(?P<pnf_id>[0-9a-zA-Z_-]+)$', IndividualPnfView.as_view()),
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns)
diff --git a/lcm/ns_pnfs/views/__init__.py b/lcm/ns_pnfs/views/__init__.py
new file mode 100644
index 00000000..342c2a8c
--- /dev/null
+++ b/lcm/ns_pnfs/views/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/lcm/ns_pnfs/views/pnf_view.py b/lcm/ns_pnfs/views/pnf_view.py
new file mode 100644
index 00000000..0e1ae6fe
--- /dev/null
+++ b/lcm/ns_pnfs/views/pnf_view.py
@@ -0,0 +1,119 @@
+# 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.
+
+import logging
+import traceback
+
+from drf_yasg.utils import swagger_auto_schema
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.views import APIView
+from lcm.ns_pnfs.serializers.pnf_serializer import PnfInstanceSerializer, PnfInstancesSerializer
+from lcm.ns_pnfs.biz.create_pnf import CreatePnf
+from lcm.ns_pnfs.biz.delete_pnf import DeletePnf
+from lcm.ns_pnfs.biz.get_pnf import GetPnf
+from lcm.pub.exceptions import NSLCMException
+
+logger = logging.getLogger(__name__)
+
+
+class PnfView(APIView):
+ @swagger_auto_schema(
+ request_body=PnfInstanceSerializer(),
+ responses={
+ status.HTTP_201_CREATED: PnfInstanceSerializer()
+ }
+ )
+ def post(self, request):
+ logger.debug("PnfView--post::> %s" % request.data)
+
+ req_serializer = PnfInstanceSerializer(data=request.data)
+ if not req_serializer.is_valid():
+ logger.error(req_serializer.errors)
+ resp = {"result": 1, "detail": req_serializer.errors, "pnfId": ""}
+ return Response(data=resp, status=status.HTTP_201_CREATED)
+
+ pnfInstData = CreatePnf(request.data).do_biz()
+ resp_serializer = PnfInstanceSerializer(data=pnfInstData.__dict__)
+ if not resp_serializer.is_valid():
+ logger.error(resp_serializer.errors)
+ resp = {"result": 1, "detail": resp_serializer.errors, "pnfId": ""}
+ return Response(data=resp, status=status.HTTP_201_CREATED)
+
+ return Response(data=resp_serializer.data, status=status.HTTP_201_CREATED)
+
+ @swagger_auto_schema(
+ request_body="None",
+ responses={
+ status.HTTP_200_OK: PnfInstancesSerializer(help_text="Pnf instances", many=True),
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Inner error"
+ }
+ )
+ def get(self, request):
+ try:
+ logger.debug("PnfView::get")
+ pnfInstDataSet = GetPnf().do_biz()
+ logger.debug("PnfView::get::ret=%s", pnfInstDataSet)
+ resp_serializer = PnfInstancesSerializer(data=[pnfInstData.__dict__ for pnfInstData in pnfInstDataSet])
+ if not resp_serializer.is_valid():
+ raise NSLCMException(resp_serializer.errors)
+ return Response(data=resp_serializer.data, status=status.HTTP_200_OK)
+ except Exception as e:
+ logger.error(traceback.format_exc())
+ logger.error("Exception in GetPnf: %s", e.message)
+ return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class IndividualPnfView(APIView):
+ @swagger_auto_schema(
+ request_body="None",
+ responses={
+ status.HTTP_204_NO_CONTENT: 'successful',
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Inner error"
+ }
+ )
+ def delete(self, request, pnf_id):
+ try:
+ logger.debug("Enter IndividualPnfView::delete pnf(%s)", pnf_id)
+ DeletePnf(pnf_id).do_biz()
+ return Response(data={}, status=status.HTTP_204_NO_CONTENT)
+ except Exception as e:
+ logger.error(traceback.format_exc())
+ logger.error("Exception in delete pnf: %s", e.message)
+ return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+ @swagger_auto_schema(
+ request_body="None",
+ responses={
+ status.HTTP_200_OK: PnfInstanceSerializer(help_text="Pnf instance", many=True),
+ status.HTTP_500_INTERNAL_SERVER_ERROR: "Inner error",
+ status.HTTP_404_NOT_FOUND: "Pnf instance does not exist"
+ }
+ )
+ def get(self, request, pnf_id):
+ try:
+ logger.debug("Enter IndividualPnfView::get pnf(%s)", pnf_id)
+ pnf_filter = {"pnfId": pnf_id}
+ pnfInstData = GetPnf(pnf_filter, True).do_biz()
+ if not pnfInstData:
+ return Response(status=status.HTTP_404_NOT_FOUND)
+ logger.debug("Leave IndividualPnfView::get::ret=%s", pnfInstData)
+ resp_serializer = PnfInstanceSerializer(data=pnfInstData.__dict__)
+ if not resp_serializer.is_valid():
+ raise NSLCMException(resp_serializer.errors)
+ return Response(data=resp_serializer.data, status=status.HTTP_200_OK)
+ except Exception as e:
+ logger.error(traceback.format_exc())
+ logger.error("Exception in IndividualPnfView: %s", e.message)
+ return Response(data={'error': e.message}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
diff --git a/lcm/pub/database/models.py b/lcm/pub/database/models.py
index f1aa57ab..1e70dbc7 100644
--- a/lcm/pub/database/models.py
+++ b/lcm/pub/database/models.py
@@ -343,3 +343,17 @@ class SubscriptionModel(models.Model):
operation_states = models.TextField(db_column='OPERATIONSTATES', null=True)
callback_uri = models.CharField(db_column='CALLBACKURI', max_length=255)
links = models.TextField(db_column='LINKS', max_length=20000)
+
+
+class PNFInstModel(models.Model):
+ class Meta:
+ db_table = 'NFVO_PNFINST'
+
+ pnfId = models.CharField(db_column='PNFID', primary_key=True, max_length=255)
+ pnfName = models.CharField(db_column='PNFNAME', max_length=255)
+ pnfdId = models.CharField(db_column='PNFDID', max_length=50)
+ pnfdInfoId = models.CharField(db_column='PNFDINFOID', max_length=100)
+ pnfProfileId = models.CharField(db_column='PNFPROFILEID', max_length=255)
+ cpInfo = models.TextField(db_column='CPINFO', max_length=255, null=True, blank=True)
+ emsId = models.CharField(db_column='EMSID', null=True, max_length=255)
+ nsInstances = models.TextField(db_column='NSINSTANCES', max_length=1000, null=True, blank=True)
diff --git a/lcm/pub/msapi/emsdriver.py b/lcm/pub/msapi/emsdriver.py
new file mode 100644
index 00000000..a4188454
--- /dev/null
+++ b/lcm/pub/msapi/emsdriver.py
@@ -0,0 +1,31 @@
+# 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.
+import json
+import logging
+
+from lcm.pub.exceptions import NSLCMException
+from lcm.pub.msapi.extsys import get_ems_by_id
+from lcm.pub.utils.restcall import req_by_msb
+
+logger = logging.getLogger(__name__)
+
+
+def send_active_pnf_request(ems_inst_id, pnf_id, req_param):
+ ems = get_ems_by_id(ems_inst_id)
+ uri = '/api/%s/v1/%s/pnfs/%s/active' % (ems["type"], ems_inst_id, pnf_id)
+ ret = req_by_msb(uri, "POST", req_param)
+ if ret[0] != 0:
+ logger.error("Failed to send nf init req:%s,%s", ret[2], ret[1])
+ raise NSLCMException('Failed to send nf init request to VNFM(%s)' % ems_inst_id)
+ return json.JSONDecoder().decode(ret[1])
diff --git a/lcm/pub/msapi/extsys.py b/lcm/pub/msapi/extsys.py
index 9b6d0344..019f0825 100644
--- a/lcm/pub/msapi/extsys.py
+++ b/lcm/pub/msapi/extsys.py
@@ -173,3 +173,31 @@ def select_vnfm(vnfm_type, vim_id):
if vnfmtype == vnfm_type and vimid == vim_id:
return vnfm_info
raise NSLCMException('No vnfm found with %s in vim(%s)' % (vnfm_type, vim_id))
+
+
+def get_ems_by_id(ems_inst_id):
+ uri = "/external-system/esr-ems-list/esr-ems/%s?depth=all" % ems_inst_id
+ ret = call_aai(uri, "GET")
+ if ret[0] > 0:
+ logger.error('Send get EMS information request to extsys failed.')
+ raise NSLCMException('Send get EMS information request to extsys failed.')
+ # convert vnfm_info_aai to internal vnfm_info
+ ems_info_aai = json.JSONDecoder().decode(ret[1])
+ ems_info = convert_ems_info(ems_info_aai)
+ logger.debug("ems_inst_id=%s, ems_info=%s", ems_inst_id, ems_info)
+ return ems_info
+
+
+def convert_ems_info(ems_info_aai):
+ esr_system_info = ignore_case_get(ignore_case_get(ems_info_aai, "esr-system-info-list"), "esr-system-info")
+ ems_info_aai = {
+ "emsId": ems_info_aai["ems-id"],
+ "type": ignore_case_get(esr_system_info[0], "type"),
+ "vendor": ignore_case_get(esr_system_info[0], "vendor"),
+ "version": ignore_case_get(esr_system_info[0], "version"),
+ "url": ignore_case_get(esr_system_info[0], "service-url"),
+ "userName": ignore_case_get(esr_system_info[0], "user-name"),
+ "password": ignore_case_get(esr_system_info[0], "password"),
+ "createTime": ""
+ }
+ return ems_info_aai
diff --git a/lcm/pub/msapi/sdc_run_catalog.py b/lcm/pub/msapi/sdc_run_catalog.py
index e12c2142..547a542b 100644
--- a/lcm/pub/msapi/sdc_run_catalog.py
+++ b/lcm/pub/msapi/sdc_run_catalog.py
@@ -55,3 +55,15 @@ def query_vnfpackage_by_id(csar_id):
logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
raise NSLCMException("Failed to query vnf CSAR(%s) from catalog." % csar_id)
return json.JSONDecoder().decode(ret[1])
+
+
+def query_pnf_descriptor(filter=None):
+ if filter:
+ pnfdInfoId = filter.get("pnfdInfoId")
+ ret = req_by_msb("/api/catalog/v1/pnf_descriptors/%s" % pnfdInfoId, "GET")
+ else:
+ ret = req_by_msb("/api/catalog/v1/pnf_descriptors", "GET")
+ if ret[0] != 0:
+ logger.error("Status code is %s, detail is %s.", ret[2], ret[1])
+ raise NSLCMException("Failed to query pnf descriptor(%s) from catalog." % pnfdInfoId)
+ return json.JSONDecoder().decode(ret[1])
diff --git a/lcm/urls.py b/lcm/urls.py
index 44b79f55..9c14ede8 100644
--- a/lcm/urls.py
+++ b/lcm/urls.py
@@ -21,6 +21,7 @@ from lcm.pub.config.config import REG_TO_MSB_WHEN_START, REG_TO_MSB_REG_URL, REG
urlpatterns = [
url(r'^', include('lcm.samples.urls')),
url(r'^', include('lcm.ns_vnfs.urls')),
+ url(r'^', include('lcm.ns_pnfs.urls')),
url(r'^', include('lcm.ns_vls.urls')),
url(r'^', include('lcm.ns_sfcs.urls')),
url(r'^', include('lcm.ns.urls')),