add occurrence api in lcm 82/78982/1
authoryangyan <yangyanyj@chinamobile.com>
Fri, 22 Feb 2019 02:33:01 +0000 (10:33 +0800)
committeryangyan <yangyanyj@chinamobile.com>
Fri, 22 Feb 2019 02:33:01 +0000 (10:33 +0800)
Change-Id: I637a22ee9a19d6335f8e4d906f5df60f610d237b
Signed-off-by: yangyan <yangyanyj@chinamobile.com>
Issue-ID: VFC-1262

30 files changed:
lcm/ns/biz/affected_nss.py [new file with mode: 0644]
lcm/ns/biz/affected_pnfs.py [new file with mode: 0644]
lcm/ns/biz/affected_saps.py [new file with mode: 0644]
lcm/ns/biz/affected_vls.py [new file with mode: 0644]
lcm/ns/biz/affected_vnffgs.py [new file with mode: 0644]
lcm/ns/biz/affected_vnfs.py [new file with mode: 0644]
lcm/ns/biz/ext_link_port_info.py [new file with mode: 0644]
lcm/ns/biz/ext_virtual_link_info.py [new file with mode: 0644]
lcm/ns/biz/modify_vnf_info_data.py [new file with mode: 0644]
lcm/ns/biz/ns_lcm_op_occ.py [new file with mode: 0644]
lcm/ns/biz/ns_lcm_op_occs.py [new file with mode: 0644]
lcm/ns/biz/query_ns_lcm_op_occ.py [new file with mode: 0644]
lcm/ns/biz/resource_handle.py [new file with mode: 0644]
lcm/ns/const.py
lcm/ns/serializers/affected_nss.py [new file with mode: 0644]
lcm/ns/serializers/affected_pnfs.py [new file with mode: 0644]
lcm/ns/serializers/affected_saps.py [new file with mode: 0644]
lcm/ns/serializers/affected_vls.py [new file with mode: 0644]
lcm/ns/serializers/affected_vnffgs.py [new file with mode: 0644]
lcm/ns/serializers/affected_vnfs.py [new file with mode: 0644]
lcm/ns/serializers/ext_link_port_info.py [new file with mode: 0644]
lcm/ns/serializers/ext_virtual_link_info.py [new file with mode: 0644]
lcm/ns/serializers/modify_vnf_info_data.py [new file with mode: 0644]
lcm/ns/serializers/ns_lcm_op_occ.py [new file with mode: 0644]
lcm/ns/serializers/ns_lcm_op_occs.py [new file with mode: 0644]
lcm/ns/serializers/resource_handle.py [new file with mode: 0644]
lcm/ns/tests/test_query_ns_lcm_op.py [new file with mode: 0644]
lcm/ns/urls.py
lcm/ns/views/lcm_op_occs_view.py [new file with mode: 0644]
lcm/pub/database/models.py

diff --git a/lcm/ns/biz/affected_nss.py b/lcm/ns/biz/affected_nss.py
new file mode 100644 (file)
index 0000000..208e311
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.TERMINATE,
+    const.CHANGE_TYPES.SCALE,
+    const.CHANGE_TYPES.UPDATE,
+    const.CHANGE_TYPES.HEAL
+]
+
+CHANGE_RESULT = [
+    const.CHANGE_RESULTS.COMPLETED,
+    const.CHANGE_RESULTS.ROLLED_BACK,
+    const.CHANGE_RESULTS.FAILED,
+    const.CHANGE_RESULTS.PARTIALLY_COMPLETED
+]
+
+
+class AffectedNssSerializer(serializers.Serializer):
+    nsInstanceId = serializers.UUIDField(
+        help_text="Identifier of the nested NS instance.",
+        required=True
+    )
+    nsdId = serializers.UUIDField(
+        help_text="Identifier of the NSD of the nested NS instance.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/biz/affected_pnfs.py b/lcm/ns/biz/affected_pnfs.py
new file mode 100644 (file)
index 0000000..4b01f6d
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.REMOVE,
+    CHANGE_TYPES.MODIFY
+]
+
+
+class AffectedPnfsSerializer(serializers.Serializer):
+    pnfId = serializers.UUIDField(
+        help_text="Identifier of the affected PNF. This identifier is allocated by the OSS/BSS. ",
+        required=True
+    )
+    pnfdId = serializers.UUIDField(
+        help_text="Identifier of the PNFD on which the PNF is based.",
+        required=True
+    )
+    pnfProfileId = serializers.UUIDField(
+        help_text="Identifier of the VNF profile of the NSD.",
+        required=True
+    )
+    pnfName = serializers.CharField(
+        help_text="Name of the PNF.",
+        required=True)
+    cpInstanceId = serializers.UUIDField(
+        help_text="Identifier of the NS profile of the NSD.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/biz/affected_saps.py b/lcm/ns/biz/affected_saps.py
new file mode 100644 (file)
index 0000000..eadd287
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.MODIFY
+]
+
+CHANGE_RESULT = [
+    const.CHANGE_RESULTS.COMPLETED,
+    const.CHANGE_RESULTS.ROLLED_BACK,
+    const.CHANGE_RESULTS.FAILED
+]
+
+
+class AffectedSapsSerializer(serializers.Serializer):
+    sapInstanceId = serializers.UUIDField(
+        help_text="Identifier of the SAP instance.",
+        required=True
+    )
+    sapdId = serializers.UUIDField(
+        help_text="Identifier of the SAPD for this SAP.",
+        required=True
+    )
+    sapName = serializers.CharField(
+        help_text="Human readable name for the SAP.",
+        required=True)
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/biz/affected_vls.py b/lcm/ns/biz/affected_vls.py
new file mode 100644 (file)
index 0000000..26e0c9b
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.DELETE,
+    CHANGE_TYPES.MODIFY,
+    CHANGE_TYPES.ADD_LINK_PORT,
+    CHANGE_TYPES.REMOVE_LINK_PORT
+]
+
+
+class AffectedVLsSerializer(serializers.Serializer):
+    id = serializers.UUIDField(
+        help_text="Identifier of the VL Instance.",
+        required=True
+    )
+    virtualLinkDescId = serializers.UUIDField(
+        help_text="Identifier of the VLD in the NSD for this VL.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the result of change identified by the 'changeType' attribute.",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/biz/affected_vnffgs.py b/lcm/ns/biz/affected_vnffgs.py
new file mode 100644 (file)
index 0000000..63e9027
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.MODIFY
+]
+
+
+class AffectedVnffgsSerializer(serializers.Serializer):
+    vnffgInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNFFG instance.",
+        required=True
+    )
+    vnffgdId = serializers.UUIDField(
+        help_text="Identifier of the VNFFGD of the VNFFG instance.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=const.CHANGE_RESULT
+    )
diff --git a/lcm/ns/biz/affected_vnfs.py b/lcm/ns/biz/affected_vnfs.py
new file mode 100644 (file)
index 0000000..4d5594f
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 modify_vnf_info_data import ModifyVnfInfoDataSerializer
+from ext_virtual_link_info import ExtVirtualLinkInfoSerializer
+
+from lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.REMOVE,
+    CHANGE_TYPES.INSTANTIATE,
+    CHANGE_TYPES.TERMINATE,
+    CHANGE_TYPES.SCALE,
+    CHANGE_TYPES.CHANGE_FLAVOUR,
+    CHANGE_TYPES.HEAL,
+    CHANGE_TYPES.OPERATE,
+    CHANGE_TYPES.MODIFY_INFORMATION,
+    CHANGE_TYPES.CHANGE_EXTERNAL_VNF_CONNECTIVITY
+]
+
+
+class ChangedInfoSerializer(serializers.Serializer):
+    changedVnfInfo = ModifyVnfInfoDataSerializer(
+        help_text="Information about the changed VNF instance information, including configurable properties",
+        required=False)
+    changedExtConnectivity = ExtVirtualLinkInfoSerializer(
+        help_text="Link to the task resource that represents the 'fail' Information about changed external "
+                  "connectivity, if applicable.",
+        required=False)
+
+
+class AffectedVnfsSerializer(serializers.Serializer):
+    vnfInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNF instance.",
+        required=True
+    )
+    vnfdId = serializers.UUIDField(
+        help_text="Identifier of the VNFD of the VNF Instance..",
+        required=True
+    )
+    vnfProfileId = serializers.UUIDField(
+        help_text="Identifier of the VNF profile of the NSD.",
+        required=True
+    )
+    vnfName = serializers.CharField(
+        help_text="Name of the VNF Instance.",
+        required=True)
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
+    changedInfo = ChangedInfoSerializer(
+        help_text="Links to resources related to this resource.",
+        required=False)
diff --git a/lcm/ns/biz/ext_link_port_info.py b/lcm/ns/biz/ext_link_port_info.py
new file mode 100644 (file)
index 0000000..e2ca15b
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 resource_handle import ResourceHandleSerializer
+
+
+class ExtlinkPortInfoSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of this link port as provided by the entity that has created the link port.",
+        max_length=255,
+        required=True,
+        allow_blank=False,
+        allow_null=False)
+    resourceHandle = ResourceHandleSerializer(
+        help_text="Reference to the virtualised resource realizing this link port.",
+        required=True,
+        allow_null=False)
+    cpInstanceId = serializers.CharField(
+        help_text="Identifier of the external CP of the VNFconnected to this link port.",
+        max_length=255,
+        required=False,
+        allow_blank=True,
+        allow_null=True)
diff --git a/lcm/ns/biz/ext_virtual_link_info.py b/lcm/ns/biz/ext_virtual_link_info.py
new file mode 100644 (file)
index 0000000..7e67e6f
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 resource_handle import ResourceHandleSerializer
+from ext_link_port_info import ExtlinkPortInfoSerializer
+
+
+class ExtVirtualLinkInfoSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of the external VL and the related external VL information instance.",
+        required=True,
+        max_length=255,
+        allow_null=False,
+        allow_blank=False)
+    resourceHandle = ResourceHandleSerializer(
+        help_text="Reference to the resource realizing this VL.",
+        required=True,
+        allow_null=False)
+    extlinkPorts = ExtlinkPortInfoSerializer(
+        help_text="Link ports of this VL.",
+        many=True,
+        required=False,
+        allow_null=True)
diff --git a/lcm/ns/biz/modify_vnf_info_data.py b/lcm/ns/biz/modify_vnf_info_data.py
new file mode 100644 (file)
index 0000000..546fc6b
--- /dev/null
@@ -0,0 +1,52 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ModifyVnfInfoDataSerializer(serializers.Serializer):
+    vnfInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNF instance."
+    )
+    vnfInstanceName = serializers.CharField(
+        help_text="New value of the 'vnfInstanceName' attribute in 'VnfInstance', or 'null' to remove the attribute.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    vnfInstanceDescription = serializers.CharField(
+        help_text="If present, this attribute signals modifications of the 'vnfInstanceDescription' attribute in "
+                  "'VnfInstance'",
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    vnfPkgId = serializers.UUIDField(
+        help_text="New value of the 'vnfPkgId' attribute in 'VnfInstance' The value 'null' is not permitted.."
+    )
+    vnfConfigurableProperties = serializers.DictField(
+        help_text="Modifications to entries in the 'vnfConfigurableProperties' list, as defined below this Table.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
+    metaData = serializers.DictField(
+        help_text="If present, this attribute signals modifications of certain 'metadata' attribute in 'vnfInstance'.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
+    extensions = serializers.DictField(
+        help_text="If present,this attribute signals modifications of certain 'extensions' attribute in 'vnfInstance'.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
diff --git a/lcm/ns/biz/ns_lcm_op_occ.py b/lcm/ns/biz/ns_lcm_op_occ.py
new file mode 100644 (file)
index 0000000..02c7cf9
--- /dev/null
@@ -0,0 +1,155 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 affected_vnfs import AffectedVnfsSerializer
+from affected_pnfs import AffectedPnfsSerializer
+from affected_vls import AffectedVLsSerializer
+from affected_vnffgs import AffectedVnffgsSerializer
+from affected_nss import AffectedNssSerializer
+from affected_saps import AffectedSapsSerializer
+
+from link import LinkSerializer
+from response import ProblemDetailsSerializer
+from lcm.ns import const
+
+
+class ResourceChangesSerializer(serializers.Serializer):
+    affectedVnfs = AffectedVnfsSerializer(
+        help_text="Information about VNFC instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedPnfs = AffectedPnfsSerializer(
+        help_text="Information about the PNF instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedVls = AffectedVLsSerializer(
+        help_text="Information about the VL instances that were affected during the lifecycle operation",
+        required=False,
+        many=True
+    )
+    affectedVnffgs = AffectedVnffgsSerializer(
+        help_text="Information about the VNFFG instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedNss = AffectedNssSerializer(
+        help_text="Information about the nested NS instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedSaps = AffectedSapsSerializer(
+        help_text="Information about the SAP instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+
+
+class LcmOpLinkSerializer(serializers.Serializer):
+    self = LinkSerializer(
+        help_text="URI of this resource.",
+        required=True,
+        allow_null=False)
+    nsInstance = serializers.CharField(
+        help_text="Link to the NS instance that the operation applies to.",
+        required=True)
+    cancel = serializers.CharField(
+        help_text="Link to the task resource that represents the 'cancel' operation for this LCM operation occurrence.",
+        required=False)
+    retry = serializers.CharField(
+        help_text="Link to the task resource that represents the 'retry' operation for this LCM operation occurrence, "
+                  "if retrying is currently allowed",
+        required=False)
+    rollback = serializers.CharField(
+        help_text="Link to the task resource that represents the 'cancel' operation for this LCM operation occurrence.",
+        required=False)
+    fail = serializers.CharField(
+        help_text="Link to the task resource that represents the 'fail' operation for this LCM operation occurrence.",
+        required=False)
+
+
+class NSLCMOpOccSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of this NS lifecycle management operation occurrence,",
+        max_length=255,
+        required=True,
+        allow_null=False
+    )
+    operationState = serializers.ChoiceField(
+        help_text="The state of the VNF LCM operation occurrence. ",
+        required=True,
+        choices=const.LCM_OPERATION_STATE_TYPES
+    )
+    stateEnteredTime = serializers.CharField(
+        help_text="Date-time when the current state was entered.",
+        max_length=50
+    )
+    startTime = serializers.CharField(
+        help_text="Date-time of the start of the operation.",
+        max_length=50
+    )
+    nsInstanceId = serializers.UUIDField(
+        help_text="Identifier of the ns instance to which the operation applies"
+    )
+    operation = serializers.ChoiceField(
+        help_text="The lifecycle management operation",
+        required=True,
+        choices=const.NS_LCM_OP_TYPES
+    )
+    isAutomaticInvocation = serializers.BooleanField(
+        help_text="Set to true if this NS LCM operation occurrence has been automatically triggered by the NFVO.",
+        default=False
+    )
+    operationParams = serializers.DictField(
+        help_text="Input parameters of the LCM operation. This attribute shall be formatted according to the request "
+                  "data type of the related LCM operation. The following mapping between operationType and the data "
+                  "type of this attribute shall apply: "
+                  "1. INSTANTIATE: InstantiateVnfRequest "
+                  "2. SCALE: ScaleVnfRequest "
+                  "3. CHANGE_FLAVOUR: ChangeVnfFlavourRequest"
+                  "4. HEAL: HealVnfRequest "
+                  "5. TERMINATE: TerminateVnfRequest ",
+        required=True,
+        allow_null=False
+    )
+    isCancelPending = serializers.BooleanField(
+        help_text="If the NS LCM operation occurrence is in 'STARTING' or 'PROCESSING' or 'ROLLING_BACK' state and "
+                  "the operation is being cancelled, this attribute shall be set to True. Otherwise, it shall be set "
+                  "to False.",
+        required=True
+    )
+    cancelMode = serializers.CharField(
+        help_text="The mode of an ongoing cancellation. Shall be present when isCancelPending=true, and shall be None "
+                  "otherwise.",
+        allow_null=True,
+        required=False
+    )
+    error = ProblemDetailsSerializer(
+        help_text="If 'operationState' is 'FAILED_TEMP' or 'FAILED' or PROCESSING' or 'ROLLING_BACK' and previous "
+                  "value of 'operationState' was 'FAILED_TEMP'  this attribute shall be present ",
+        allow_null=True,
+        required=False
+    )
+    resourceChanges = ResourceChangesSerializer(
+        help_text="It contains information about the cumulative changes to virtualised resources that were performed "
+                  "so far by the LCM operation since its start, if applicable.",
+        required=False,
+        allow_null=True)
+    _links = LcmOpLinkSerializer(
+        help_text="Links to resources related to this resource.",
+        required=True)
diff --git a/lcm/ns/biz/ns_lcm_op_occs.py b/lcm/ns/biz/ns_lcm_op_occs.py
new file mode 100644 (file)
index 0000000..cede4e3
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ns_lcm_op_occ import NSLCMOpOccSerializer
+
+
+class NSLCMOpOccsSerializer(serializers.ListSerializer):
+    child = NSLCMOpOccSerializer()
diff --git a/lcm/ns/biz/query_ns_lcm_op_occ.py b/lcm/ns/biz/query_ns_lcm_op_occ.py
new file mode 100644 (file)
index 0000000..e4e9d92
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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.database.models import NSLcmOpOccModel
+from lcm.pub.exceptions import NSLCMException
+
+logger = logging.getLogger(__name__)
+FILTERS = {
+    'id': 'id',
+    'operationState': 'operation_state',
+    'stateEnteredTime': 'state_entered_time',
+    'startTime': 'start_time',
+    'nsInstanceId': 'ns_instance_id',
+    'operation': 'operation'
+}
+
+
+class QueryNsLcmOpOcc:
+    def __init__(self, data, lcm_op_occ_id=''):
+        self.ns_lcm_op_occ_id = lcm_op_occ_id
+        self.params = data
+
+    def query_multi_ns_lcm_op_occ(self):
+        query_data = {}
+        logger.debug("QueryMultiNsLcmOpOccs--get--biz::> Check for filters in query params" % self.params)
+        for query, value in self.params.iteritems():
+            if query in FILTERS:
+                query_data[FILTERS[query]] = value
+        # Query the database with filters if the request has fields in request params, else fetch all records
+        if query_data:
+            lcm_ops = NSLcmOpOccModel.objects.filter(**query_data)
+        else:
+            lcm_ops = NSLcmOpOccModel.objects.all()
+        if not lcm_ops.exists():
+            raise NSLCMException('LCM Operation Occurances do not exist')
+        return [self.fill_resp_data(lcm_op) for lcm_op in lcm_ops]
+
+    def fill_resp_data(self, lcm_op):
+        resp_data = {
+            'id': lcm_op.id,
+            'operationState': lcm_op.operation_state,
+            'stateEnteredTime': lcm_op.state_entered_time,
+            'startTime': lcm_op.start_time,
+            'nsInstanceId': lcm_op.ns_instance_id,
+            'operation': lcm_op.operation,
+            'isAutomaticInvocation': lcm_op.is_automatic_invocation,
+            'operationParams': json.loads(lcm_op.operation_params),
+            'isCancelPending': lcm_op.is_cancel_pending,
+            'cancelMode': lcm_op.cancel_mode,
+            'error': None if not lcm_op.error else json.loads(lcm_op.error),
+            'resourceChanges': None if not lcm_op.resource_changes else json.loads(lcm_op.resource_changes),
+            '_links': json.loads(lcm_op.links)
+        }
+        return resp_data
+
+    def query_single_ns_lcm_op_occ(self):
+        lcm_op = NSLcmOpOccModel.objects.filter(id=self.ns_lcm_op_occ_id)
+        if not lcm_op.exists():
+            raise NSLCMException('LCM Operation Occurance does not exist')
+        resp_data = self.fill_resp_data(lcm_op[0])
+        return resp_data
diff --git a/lcm/ns/biz/resource_handle.py b/lcm/ns/biz/resource_handle.py
new file mode 100644 (file)
index 0000000..79ec53b
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ResourceHandleSerializer(serializers.Serializer):
+    vimConnectionId = serializers.CharField(
+        help_text="Identifier of the VIM connection to manage the resource.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    resourceProviderId = serializers.CharField(
+        help_text="Identifier of the entity responsible for the management of the resource.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    resourceId = serializers.CharField(
+        help_text="Identifier of the resource in the scope of the VIM or the resource provider.",
+        required=True,
+        max_length=255,
+        allow_null=False,
+        allow_blank=False)
+    vimLevelResourceType = serializers.CharField(
+        help_text="String, type of the resource in the scope of the VIM or the resource provider.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
index bf15894..c5231be 100644 (file)
@@ -16,16 +16,15 @@ from lcm.pub.utils.enumutil import enum
 OWNER_TYPE = enum(VNF=0, VNFM=1, NS=2)
 
 NS_INST_STATUS = enum(EMPTY='empty', INSTANTIATING='instantiating', TERMINATING='terminating',
-                      ACTIVE='active', FAILED='failed', INACTIVE='inactive', UPDATING='updating',
-                      SCALING='scaling', HEALING='healing')
+                      ACTIVE='active', FAILED='failed', INACTIVE='inactive', UPDATING='updating', SCALING='scaling',
+                      HEALING='healing')
 
 SERVICE_TYPE = 'NetworkService'
 SERVICE_ROLE = 'NetworkService'
 
 HEAL_ACTION_TYPE = enum(START="vmCreate", RESTART="vmReset")
 ACTION_TYPE = enum(START=1, STOP=2, REBOOT=3)
-GRANT_TYPE = enum(INSTANTIATE="INSTANTIATE", TERMINATE="TERMINATE", HEAL_CREATE="Heal Create",
-                  HEAL_RESTART="Heal Restart", OPERATE="OPERATE")
+GRANT_TYPE = enum(INSTANTIATE="INSTANTIATE", TERMINATE="TERMINATE", HEAL_CREATE="Heal Create", HEAL_RESTART="Heal Restart", OPERATE="OPERATE")
 VNF_STATUS = enum(NULL='null', INSTANTIATING="instantiating", INACTIVE='inactive', ACTIVE="active",
                   FAILED="failed", TERMINATING="terminating", SCALING="scaling", OPERATING="operating",
                   UPDATING="updating", HEALING="healing")
@@ -76,25 +75,38 @@ BASIC = "BASIC"
 
 OAUTH2_CLIENT_CREDENTIALS = "OAUTH2_CLIENT_CREDENTIALS"
 
-# CHANGE_TYPE = enum(
-#     ADDED='ADDED',
-#     REMOVED='REMOVED',
-#     MODIFIED='MODIFIED',
-#     TEMPORARY='TEMPORARY',
-#     LINK_PORT_ADDED='LINK_PORT_ADDED',
-#     LINK_PORT_REMOVED='LINK_PORT_REMOVED'
-# )
+CHANGE_TYPES = enum(
+    ADD='ADD',
+    DELETE='DELETE',
+    REMOVE='REMOVE',
+    INSTANTIATE='INSTANTIATE',
+    TERMINATE='TERMINATE',
+    SCALE='SCALE',
+    UPDATE='UPDATE',
+    CHANGE_FLAVOUR='CHANGE_FLAVOUR',
+    HEAL='HEAL',
+    OPERATE='OPERATE',
+    MODIFY='MODIFY',
+    MODIFY_INFORMATION='MODIFY_INFORMATION',
+    CHANGE_EXTERNAL_VNF_CONNECTIVITY='CHANGE_EXTERNAL_VNF_CONNECTIVITY',
+    ADD_LINK_PORT='ADD_LINK_PORT',
+    REMOVE_LINK_PORT='REMOVE_LINK_PORT'
+)
+
+CHANGE_RESULTS = enum(
+    COMPLETED='COMPLETED',
+    ROLLED_BACK='ROLLED_BACK',
+    FAILED='FAILED',
+    PARTIALLY_COMPLETED='PARTIALLY_COMPLETED'
+)
 
-# RESOURCE_MAP = {'Storage': 'volumn', 'Network': 'network', 'SubNetwork': 'subnet', 'Port': 'port',
-#                 'Flavour': 'flavor', 'Vm': 'vm'}
 
 ROOT_URI = "api/nslcm/v1/subscriptions/"
 
 LCCNNOTIFICATION = "NsLcmOperationOccurrenceNotification"
 
 NOTIFICATION_TYPES = [
-    "NsLcmOperationOccurrenceNotification", "NsIdentifierCreationNotification",
-    "NsIdentifierDeletionNotification",
+    "NsLcmOperationOccurrenceNotification", "NsIdentifierCreationNotification", "NsIdentifierDeletionNotification",
     "NsChangeNotification",
 ]
 
@@ -147,3 +159,10 @@ LCM_OpOcc_Status_For_ChangeNotification_Type = [
     OpOcc_Status_For_ChangeNotification_Type.FAILED,
     OpOcc_Status_For_ChangeNotification_Type.ROLLED_BACK,
 ]
+
+
+CHANGE_RESULT = [
+    CHANGE_RESULTS.COMPLETED,
+    CHANGE_RESULTS.ROLLED_BACK,
+    CHANGE_RESULTS.FAILED
+]
diff --git a/lcm/ns/serializers/affected_nss.py b/lcm/ns/serializers/affected_nss.py
new file mode 100644 (file)
index 0000000..208e311
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.TERMINATE,
+    const.CHANGE_TYPES.SCALE,
+    const.CHANGE_TYPES.UPDATE,
+    const.CHANGE_TYPES.HEAL
+]
+
+CHANGE_RESULT = [
+    const.CHANGE_RESULTS.COMPLETED,
+    const.CHANGE_RESULTS.ROLLED_BACK,
+    const.CHANGE_RESULTS.FAILED,
+    const.CHANGE_RESULTS.PARTIALLY_COMPLETED
+]
+
+
+class AffectedNssSerializer(serializers.Serializer):
+    nsInstanceId = serializers.UUIDField(
+        help_text="Identifier of the nested NS instance.",
+        required=True
+    )
+    nsdId = serializers.UUIDField(
+        help_text="Identifier of the NSD of the nested NS instance.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/serializers/affected_pnfs.py b/lcm/ns/serializers/affected_pnfs.py
new file mode 100644 (file)
index 0000000..4b01f6d
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.REMOVE,
+    CHANGE_TYPES.MODIFY
+]
+
+
+class AffectedPnfsSerializer(serializers.Serializer):
+    pnfId = serializers.UUIDField(
+        help_text="Identifier of the affected PNF. This identifier is allocated by the OSS/BSS. ",
+        required=True
+    )
+    pnfdId = serializers.UUIDField(
+        help_text="Identifier of the PNFD on which the PNF is based.",
+        required=True
+    )
+    pnfProfileId = serializers.UUIDField(
+        help_text="Identifier of the VNF profile of the NSD.",
+        required=True
+    )
+    pnfName = serializers.CharField(
+        help_text="Name of the PNF.",
+        required=True)
+    cpInstanceId = serializers.UUIDField(
+        help_text="Identifier of the NS profile of the NSD.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/serializers/affected_saps.py b/lcm/ns/serializers/affected_saps.py
new file mode 100644 (file)
index 0000000..eadd287
--- /dev/null
@@ -0,0 +1,55 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.MODIFY
+]
+
+CHANGE_RESULT = [
+    const.CHANGE_RESULTS.COMPLETED,
+    const.CHANGE_RESULTS.ROLLED_BACK,
+    const.CHANGE_RESULTS.FAILED
+]
+
+
+class AffectedSapsSerializer(serializers.Serializer):
+    sapInstanceId = serializers.UUIDField(
+        help_text="Identifier of the SAP instance.",
+        required=True
+    )
+    sapdId = serializers.UUIDField(
+        help_text="Identifier of the SAPD for this SAP.",
+        required=True
+    )
+    sapName = serializers.CharField(
+        help_text="Human readable name for the SAP.",
+        required=True)
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/serializers/affected_vls.py b/lcm/ns/serializers/affected_vls.py
new file mode 100644 (file)
index 0000000..26e0c9b
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.DELETE,
+    CHANGE_TYPES.MODIFY,
+    CHANGE_TYPES.ADD_LINK_PORT,
+    CHANGE_TYPES.REMOVE_LINK_PORT
+]
+
+
+class AffectedVLsSerializer(serializers.Serializer):
+    id = serializers.UUIDField(
+        help_text="Identifier of the VL Instance.",
+        required=True
+    )
+    virtualLinkDescId = serializers.UUIDField(
+        help_text="Identifier of the VLD in the NSD for this VL.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the result of change identified by the 'changeType' attribute.",
+        required=True,
+        choices=CHANGE_RESULT
+    )
diff --git a/lcm/ns/serializers/affected_vnffgs.py b/lcm/ns/serializers/affected_vnffgs.py
new file mode 100644 (file)
index 0000000..63e9027
--- /dev/null
@@ -0,0 +1,46 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 lcm.ns import const
+
+
+CHANGE_TYPE = [
+    const.CHANGE_TYPES.ADD,
+    const.CHANGE_TYPES.REMOVE,
+    const.CHANGE_TYPES.MODIFY
+]
+
+
+class AffectedVnffgsSerializer(serializers.Serializer):
+    vnffgInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNFFG instance.",
+        required=True
+    )
+    vnffgdId = serializers.UUIDField(
+        help_text="Identifier of the VNFFGD of the VNFFG instance.",
+        required=True
+    )
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=const.CHANGE_RESULT
+    )
diff --git a/lcm/ns/serializers/affected_vnfs.py b/lcm/ns/serializers/affected_vnfs.py
new file mode 100644 (file)
index 0000000..4d5594f
--- /dev/null
@@ -0,0 +1,75 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 modify_vnf_info_data import ModifyVnfInfoDataSerializer
+from ext_virtual_link_info import ExtVirtualLinkInfoSerializer
+
+from lcm.ns.const import CHANGE_TYPES, CHANGE_RESULT
+
+
+CHANGE_TYPE = [
+    CHANGE_TYPES.ADD,
+    CHANGE_TYPES.REMOVE,
+    CHANGE_TYPES.INSTANTIATE,
+    CHANGE_TYPES.TERMINATE,
+    CHANGE_TYPES.SCALE,
+    CHANGE_TYPES.CHANGE_FLAVOUR,
+    CHANGE_TYPES.HEAL,
+    CHANGE_TYPES.OPERATE,
+    CHANGE_TYPES.MODIFY_INFORMATION,
+    CHANGE_TYPES.CHANGE_EXTERNAL_VNF_CONNECTIVITY
+]
+
+
+class ChangedInfoSerializer(serializers.Serializer):
+    changedVnfInfo = ModifyVnfInfoDataSerializer(
+        help_text="Information about the changed VNF instance information, including configurable properties",
+        required=False)
+    changedExtConnectivity = ExtVirtualLinkInfoSerializer(
+        help_text="Link to the task resource that represents the 'fail' Information about changed external "
+                  "connectivity, if applicable.",
+        required=False)
+
+
+class AffectedVnfsSerializer(serializers.Serializer):
+    vnfInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNF instance.",
+        required=True
+    )
+    vnfdId = serializers.UUIDField(
+        help_text="Identifier of the VNFD of the VNF Instance..",
+        required=True
+    )
+    vnfProfileId = serializers.UUIDField(
+        help_text="Identifier of the VNF profile of the NSD.",
+        required=True
+    )
+    vnfName = serializers.CharField(
+        help_text="Name of the VNF Instance.",
+        required=True)
+    changeType = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_TYPE
+    )
+    changeResult = serializers.ChoiceField(
+        help_text="Signals the type of change",
+        required=True,
+        choices=CHANGE_RESULT
+    )
+    changedInfo = ChangedInfoSerializer(
+        help_text="Links to resources related to this resource.",
+        required=False)
diff --git a/lcm/ns/serializers/ext_link_port_info.py b/lcm/ns/serializers/ext_link_port_info.py
new file mode 100644 (file)
index 0000000..e2ca15b
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 resource_handle import ResourceHandleSerializer
+
+
+class ExtlinkPortInfoSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of this link port as provided by the entity that has created the link port.",
+        max_length=255,
+        required=True,
+        allow_blank=False,
+        allow_null=False)
+    resourceHandle = ResourceHandleSerializer(
+        help_text="Reference to the virtualised resource realizing this link port.",
+        required=True,
+        allow_null=False)
+    cpInstanceId = serializers.CharField(
+        help_text="Identifier of the external CP of the VNFconnected to this link port.",
+        max_length=255,
+        required=False,
+        allow_blank=True,
+        allow_null=True)
diff --git a/lcm/ns/serializers/ext_virtual_link_info.py b/lcm/ns/serializers/ext_virtual_link_info.py
new file mode 100644 (file)
index 0000000..7e67e6f
--- /dev/null
@@ -0,0 +1,36 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 resource_handle import ResourceHandleSerializer
+from ext_link_port_info import ExtlinkPortInfoSerializer
+
+
+class ExtVirtualLinkInfoSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of the external VL and the related external VL information instance.",
+        required=True,
+        max_length=255,
+        allow_null=False,
+        allow_blank=False)
+    resourceHandle = ResourceHandleSerializer(
+        help_text="Reference to the resource realizing this VL.",
+        required=True,
+        allow_null=False)
+    extlinkPorts = ExtlinkPortInfoSerializer(
+        help_text="Link ports of this VL.",
+        many=True,
+        required=False,
+        allow_null=True)
diff --git a/lcm/ns/serializers/modify_vnf_info_data.py b/lcm/ns/serializers/modify_vnf_info_data.py
new file mode 100644 (file)
index 0000000..546fc6b
--- /dev/null
@@ -0,0 +1,52 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ModifyVnfInfoDataSerializer(serializers.Serializer):
+    vnfInstanceId = serializers.UUIDField(
+        help_text="Identifier of the VNF instance."
+    )
+    vnfInstanceName = serializers.CharField(
+        help_text="New value of the 'vnfInstanceName' attribute in 'VnfInstance', or 'null' to remove the attribute.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    vnfInstanceDescription = serializers.CharField(
+        help_text="If present, this attribute signals modifications of the 'vnfInstanceDescription' attribute in "
+                  "'VnfInstance'",
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    vnfPkgId = serializers.UUIDField(
+        help_text="New value of the 'vnfPkgId' attribute in 'VnfInstance' The value 'null' is not permitted.."
+    )
+    vnfConfigurableProperties = serializers.DictField(
+        help_text="Modifications to entries in the 'vnfConfigurableProperties' list, as defined below this Table.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
+    metaData = serializers.DictField(
+        help_text="If present, this attribute signals modifications of certain 'metadata' attribute in 'vnfInstance'.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
+    extensions = serializers.DictField(
+        help_text="If present,this attribute signals modifications of certain 'extensions' attribute in 'vnfInstance'.",
+        child=serializers.CharField(help_text="KeyValue Pairs", allow_blank=True),
+        required=False,
+        allow_null=True)
diff --git a/lcm/ns/serializers/ns_lcm_op_occ.py b/lcm/ns/serializers/ns_lcm_op_occ.py
new file mode 100644 (file)
index 0000000..02c7cf9
--- /dev/null
@@ -0,0 +1,155 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 affected_vnfs import AffectedVnfsSerializer
+from affected_pnfs import AffectedPnfsSerializer
+from affected_vls import AffectedVLsSerializer
+from affected_vnffgs import AffectedVnffgsSerializer
+from affected_nss import AffectedNssSerializer
+from affected_saps import AffectedSapsSerializer
+
+from link import LinkSerializer
+from response import ProblemDetailsSerializer
+from lcm.ns import const
+
+
+class ResourceChangesSerializer(serializers.Serializer):
+    affectedVnfs = AffectedVnfsSerializer(
+        help_text="Information about VNFC instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedPnfs = AffectedPnfsSerializer(
+        help_text="Information about the PNF instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedVls = AffectedVLsSerializer(
+        help_text="Information about the VL instances that were affected during the lifecycle operation",
+        required=False,
+        many=True
+    )
+    affectedVnffgs = AffectedVnffgsSerializer(
+        help_text="Information about the VNFFG instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedNss = AffectedNssSerializer(
+        help_text="Information about the nested NS instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+    affectedSaps = AffectedSapsSerializer(
+        help_text="Information about the SAP instances that were affected during the lifecycle operation.",
+        required=False,
+        many=True
+    )
+
+
+class LcmOpLinkSerializer(serializers.Serializer):
+    self = LinkSerializer(
+        help_text="URI of this resource.",
+        required=True,
+        allow_null=False)
+    nsInstance = serializers.CharField(
+        help_text="Link to the NS instance that the operation applies to.",
+        required=True)
+    cancel = serializers.CharField(
+        help_text="Link to the task resource that represents the 'cancel' operation for this LCM operation occurrence.",
+        required=False)
+    retry = serializers.CharField(
+        help_text="Link to the task resource that represents the 'retry' operation for this LCM operation occurrence, "
+                  "if retrying is currently allowed",
+        required=False)
+    rollback = serializers.CharField(
+        help_text="Link to the task resource that represents the 'cancel' operation for this LCM operation occurrence.",
+        required=False)
+    fail = serializers.CharField(
+        help_text="Link to the task resource that represents the 'fail' operation for this LCM operation occurrence.",
+        required=False)
+
+
+class NSLCMOpOccSerializer(serializers.Serializer):
+    id = serializers.CharField(
+        help_text="Identifier of this NS lifecycle management operation occurrence,",
+        max_length=255,
+        required=True,
+        allow_null=False
+    )
+    operationState = serializers.ChoiceField(
+        help_text="The state of the VNF LCM operation occurrence. ",
+        required=True,
+        choices=const.LCM_OPERATION_STATE_TYPES
+    )
+    stateEnteredTime = serializers.CharField(
+        help_text="Date-time when the current state was entered.",
+        max_length=50
+    )
+    startTime = serializers.CharField(
+        help_text="Date-time of the start of the operation.",
+        max_length=50
+    )
+    nsInstanceId = serializers.UUIDField(
+        help_text="Identifier of the ns instance to which the operation applies"
+    )
+    operation = serializers.ChoiceField(
+        help_text="The lifecycle management operation",
+        required=True,
+        choices=const.NS_LCM_OP_TYPES
+    )
+    isAutomaticInvocation = serializers.BooleanField(
+        help_text="Set to true if this NS LCM operation occurrence has been automatically triggered by the NFVO.",
+        default=False
+    )
+    operationParams = serializers.DictField(
+        help_text="Input parameters of the LCM operation. This attribute shall be formatted according to the request "
+                  "data type of the related LCM operation. The following mapping between operationType and the data "
+                  "type of this attribute shall apply: "
+                  "1. INSTANTIATE: InstantiateVnfRequest "
+                  "2. SCALE: ScaleVnfRequest "
+                  "3. CHANGE_FLAVOUR: ChangeVnfFlavourRequest"
+                  "4. HEAL: HealVnfRequest "
+                  "5. TERMINATE: TerminateVnfRequest ",
+        required=True,
+        allow_null=False
+    )
+    isCancelPending = serializers.BooleanField(
+        help_text="If the NS LCM operation occurrence is in 'STARTING' or 'PROCESSING' or 'ROLLING_BACK' state and "
+                  "the operation is being cancelled, this attribute shall be set to True. Otherwise, it shall be set "
+                  "to False.",
+        required=True
+    )
+    cancelMode = serializers.CharField(
+        help_text="The mode of an ongoing cancellation. Shall be present when isCancelPending=true, and shall be None "
+                  "otherwise.",
+        allow_null=True,
+        required=False
+    )
+    error = ProblemDetailsSerializer(
+        help_text="If 'operationState' is 'FAILED_TEMP' or 'FAILED' or PROCESSING' or 'ROLLING_BACK' and previous "
+                  "value of 'operationState' was 'FAILED_TEMP'  this attribute shall be present ",
+        allow_null=True,
+        required=False
+    )
+    resourceChanges = ResourceChangesSerializer(
+        help_text="It contains information about the cumulative changes to virtualised resources that were performed "
+                  "so far by the LCM operation since its start, if applicable.",
+        required=False,
+        allow_null=True)
+    _links = LcmOpLinkSerializer(
+        help_text="Links to resources related to this resource.",
+        required=True)
diff --git a/lcm/ns/serializers/ns_lcm_op_occs.py b/lcm/ns/serializers/ns_lcm_op_occs.py
new file mode 100644 (file)
index 0000000..cede4e3
--- /dev/null
@@ -0,0 +1,20 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ns_lcm_op_occ import NSLCMOpOccSerializer
+
+
+class NSLCMOpOccsSerializer(serializers.ListSerializer):
+    child = NSLCMOpOccSerializer()
diff --git a/lcm/ns/serializers/resource_handle.py b/lcm/ns/serializers/resource_handle.py
new file mode 100644 (file)
index 0000000..79ec53b
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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 ResourceHandleSerializer(serializers.Serializer):
+    vimConnectionId = serializers.CharField(
+        help_text="Identifier of the VIM connection to manage the resource.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    resourceProviderId = serializers.CharField(
+        help_text="Identifier of the entity responsible for the management of the resource.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
+    resourceId = serializers.CharField(
+        help_text="Identifier of the resource in the scope of the VIM or the resource provider.",
+        required=True,
+        max_length=255,
+        allow_null=False,
+        allow_blank=False)
+    vimLevelResourceType = serializers.CharField(
+        help_text="String, type of the resource in the scope of the VIM or the resource provider.",
+        max_length=255,
+        required=False,
+        allow_null=True,
+        allow_blank=True)
diff --git a/lcm/ns/tests/test_query_ns_lcm_op.py b/lcm/ns/tests/test_query_ns_lcm_op.py
new file mode 100644 (file)
index 0000000..723553e
--- /dev/null
@@ -0,0 +1,172 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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
+
+from django.test import TestCase, Client
+from rest_framework import status
+
+from lcm.pub.database.models import NSLcmOpOccModel
+
+
+class TestNSLcmOpOccs(TestCase):
+    def setUp(self):
+        self.client = Client()
+        self.ns_lcm_op_occ_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        NSLcmOpOccModel.objects.all().delete()
+        self.test_single_ns_lcm_op = {
+            "id": "99442b18-a5c7-11e8-998c-bf1755941f16",
+            "operationState": "STARTING",
+            "stateEnteredTime": "2019-01-01",
+            "startTime": "2019-01-01",
+            "nsInstanceId": "cd552c9c-ab6f-11e8-b354-236c32aa91a1",
+            "operation": "SCALE",
+            "isAutomaticInvocation": False,
+            "operationParams": {},
+            "isCancelPending": False,
+            "cancelMode": None,
+            "error": None,
+            "resourceChanges": None,
+            "_links": {
+                "self": {
+                    "href": "demo"
+                },
+                "nsInstance": "demo"
+            }
+        }
+        self.test_nslcmop_with_exclude_default = [{
+            "id": "99442b18-a5c7-11e8-998c-bf1755941f16",
+            "operationState": "STARTING",
+            "stateEnteredTime": "2019-01-01",
+            "startTime": "2019-01-01",
+            "nsInstanceId": "cd552c9c-ab6f-11e8-b354-236c32aa91a1",
+            "operation": "SCALE",
+            "isAutomaticInvocation": False,
+            "isCancelPending": False,
+            "cancelMode": None,
+            "_links": {
+                "self": {
+                    "href": "demo"
+                },
+                "nsInstance": "demo"
+            }
+        }]
+
+        self.test_multiple_ns_lcm_op = [{
+            "id": "a6b9415c-ab99-11e8-9d37-dbb5e0378955",
+            "operationState": "STARTING",
+            "stateEnteredTime": "2019-01-01",
+            "startTime": "2019-01-01",
+            "nsInstanceId": "cd552c9c-ab6f-11e8-b354-236c32aa91a1",
+            "operation": "INSTANTIATE",
+            "isAutomaticInvocation": False,
+            "operationParams": {},
+            "isCancelPending": False,
+            "cancelMode": None,
+            "error": None,
+            "resourceChanges": None,
+            "_links": {
+                "self": {
+                    "href": "demo"
+                },
+                "nsInstance": "demo"
+            }
+        }]
+        self.test_multiple_ns_lcm_op.append(
+            self.test_single_ns_lcm_op)
+
+    def tearDown(self):
+        pass
+
+    def test_get_nslcmopoccs(self):
+        lcm_op_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        ns_instance_id = "cd552c9c-ab6f-11e8-b354-236c32aa91a1"
+        NSLcmOpOccModel(id=lcm_op_id, operation_state="STARTING", state_entered_time="2019-01-01",
+                        start_time="2019-01-01", ns_instance_id=ns_instance_id, operation="SCALE",
+                        is_automatic_invocation=False, operation_params='{}', is_cancel_pending=False,
+                        cancel_mode=None, error=None, resource_changes=None,
+                        links=json.dumps({"self": {"href": "demo"}, "nsInstance": "demo"})).save()
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs", format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual([self.test_single_ns_lcm_op], response.data)
+
+    def test_get_nslcmopoccs_with_id_not_exist(self):
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs?id=dummy", format='json')
+        self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
+        expected_data = {
+            "status": 500,
+            "detail": "LCM Operation Occurances do not exist"
+        }
+        self.assertEqual(expected_data, response.data)
+
+    def test_get_nslcmopoccs_with_filters(self):
+        lcm_op_id = "a6b9415c-ab99-11e8-9d37-dbb5e0378955"
+        ns_instance_id = "cd552c9c-ab6f-11e8-b354-236c32aa91a1"
+        NSLcmOpOccModel(id=lcm_op_id, operation_state="STARTING",
+                        state_entered_time="2019-01-01", start_time="2019-01-01", ns_instance_id=ns_instance_id,
+                        operation="INSTANTIATE", is_automatic_invocation=False, operation_params='{}',
+                        is_cancel_pending=False, cancel_mode=None, error=None, resource_changes=None,
+                        links=json.dumps({"self": {"href": "demo"}, "nsInstance": "demo"})).save()
+
+        lcm_op_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        NSLcmOpOccModel(id=lcm_op_id, operation_state="STARTING", state_entered_time="2019-01-01",
+                        start_time="2019-01-01", ns_instance_id=ns_instance_id, operation="SCALE",
+                        is_automatic_invocation=False, operation_params='{}', is_cancel_pending=False,
+                        cancel_mode=None, error=None, resource_changes=None,
+                        links=json.dumps({"self": {"href": "demo"}, "nsInstance": "demo"})).save()
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs", format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(self.test_multiple_ns_lcm_op, response.data)
+
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs?operation=SCALE", format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual([self.test_single_ns_lcm_op], response.data)
+
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs?nsInstanceId=%s" % ns_instance_id, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(self.test_multiple_ns_lcm_op, response.data)
+
+    def test_get_nslcmopoccs_with_extra_flags(self):
+        lcm_op_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        ns_instance_id = "cd552c9c-ab6f-11e8-b354-236c32aa91a1"
+        NSLcmOpOccModel(id=lcm_op_id, operation_state="STARTING", state_entered_time="2019-01-01",
+                        start_time="2019-01-01", ns_instance_id=ns_instance_id, operation="SCALE",
+                        is_automatic_invocation=False, operation_params='{}', is_cancel_pending=False,
+                        cancel_mode=None, error=None, resource_changes=None,
+                        links=json.dumps({"self": {"href": "demo"}, "nsInstance": "demo"})).save()
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs?exclude_default", format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(self.test_nslcmop_with_exclude_default, response.data)
+
+    def test_get_nslcmopocc_with_id(self):
+        lcm_op_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        ns_instance_id = "cd552c9c-ab6f-11e8-b354-236c32aa91a1"
+        NSLcmOpOccModel(id=lcm_op_id, operation_state="STARTING", state_entered_time="2019-01-01",
+                        start_time="2019-01-01", ns_instance_id=ns_instance_id, operation="SCALE",
+                        is_automatic_invocation=False, operation_params='{}', is_cancel_pending=False, cancel_mode=None,
+                        error=None, resource_changes=None,
+                        links=json.dumps({"self": {"href": "demo"}, "nsInstance": "demo"})).save()
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs/" + lcm_op_id, format='json')
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        self.assertEqual(self.test_single_ns_lcm_op, response.data)
+
+    def test_single_nslcmopocc_with_unknown_id(self):
+        lcm_op_id = "99442b18-a5c7-11e8-998c-bf1755941f16"
+        response = self.client.get("/api/nslcm/v1/ns_lcm_op_occs/" + lcm_op_id, format='json')
+        self.assertEqual(response.status_code, status.HTTP_500_INTERNAL_SERVER_ERROR)
+        expected_data = {
+            "status": 500,
+            "detail": "LCM Operation Occurance does not exist"
+        }
+        self.assertEqual(expected_data, response.data)
index 441d522..d9efa61 100644 (file)
@@ -23,6 +23,7 @@ from lcm.ns.views.get_del_ns_view import NSDetailView
 from lcm.ns.views.inst_ns_post_deal_view import NSInstPostDealView
 from lcm.ns.views.scale_ns_views import NSManualScaleView
 from lcm.ns.views.subscriptions_view import SubscriptionsView
+from lcm.ns.views.lcm_op_occs_view import QueryMultiNsLcmOpOccs, QuerySingleNsLcmOpOcc
 
 urlpatterns = [
     # API will be deprecated in the future release
@@ -34,6 +35,8 @@ urlpatterns = [
     url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/postdeal$', NSInstPostDealView.as_view()),
     url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/scale$', NSManualScaleView.as_view()),
     url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/heal$', NSHealView.as_view()),
+    url(r'^api/nslcm/v1/ns_lcm_op_occs$', QueryMultiNsLcmOpOccs.as_view()),
+    url(r'^api/nslcm/v1/ns_lcm_op_occs/(?P<lcmopoccid>[0-9a-zA-Z_-]+)$', QuerySingleNsLcmOpOcc.as_view()),
 
     # SOL005 URL API definition TODO
     url(r'^api/nslcm/v1/ns/(?P<ns_instance_id>[0-9a-zA-Z_-]+)/update$',
diff --git a/lcm/ns/views/lcm_op_occs_view.py b/lcm/ns/views/lcm_op_occs_view.py
new file mode 100644 (file)
index 0000000..e2feb49
--- /dev/null
@@ -0,0 +1,109 @@
+# Copyright (c) 2019, CMCC Technologies Co., Ltd.
+
+# 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.biz.query_ns_lcm_op_occ import QueryNsLcmOpOcc
+from lcm.ns.serializers.response import ProblemDetailsSerializer
+from lcm.ns.serializers.ns_lcm_op_occ import NSLCMOpOccSerializer
+from lcm.ns.serializers.ns_lcm_op_occs import NSLCMOpOccsSerializer
+from lcm.pub.exceptions import NSLCMException
+
+logger = logging.getLogger(__name__)
+EXCLUDE_DEFAULT = ['operationParams', 'error', 'resourceChanges']
+VALID_FILTERS = ["fields", "exclude_fields", "exclude_default",
+                 "id", "operationState", "stateEnteredTime", "startTime",
+                 "nsInstanceId", "operation"]
+
+
+def get_problem_details_serializer(status_code, error_message):
+    problem_details = {
+        "status": status_code,
+        "detail": error_message
+    }
+    problem_details_serializer = ProblemDetailsSerializer(data=problem_details)
+    problem_details_serializer.is_valid()
+    return problem_details_serializer
+
+
+class QueryMultiNsLcmOpOccs(APIView):
+    @swagger_auto_schema(
+        responses={
+            status.HTTP_200_OK: NSLCMOpOccsSerializer(),
+            status.HTTP_400_BAD_REQUEST: ProblemDetailsSerializer(),
+            status.HTTP_500_INTERNAL_SERVER_ERROR: ProblemDetailsSerializer()
+        }
+    )
+    def get(self, request):
+        logger.debug("QueryMultiNsLcmOpOccs--get::> %s" % request.query_params)
+        try:
+            if request.query_params and not set(request.query_params).issubset(set(VALID_FILTERS)):
+                problem_details_serializer = get_problem_details_serializer(status.HTTP_400_BAD_REQUEST, "Not a valid filter")
+                return Response(data=problem_details_serializer.data, status=status.HTTP_400_BAD_REQUEST)
+            resp_data = QueryNsLcmOpOcc(request.query_params).query_multi_ns_lcm_op_occ()
+
+            ns_lcm_op_occs_serializer = NSLCMOpOccsSerializer(data=resp_data)
+            if not ns_lcm_op_occs_serializer.is_valid():
+                raise NSLCMException(ns_lcm_op_occs_serializer.errors)
+
+            logger.debug("QueryMultiNsLcmOpOccs--get::> Remove default fields if exclude_default is specified")
+            if 'exclude_default' in request.query_params.keys():
+                for field in EXCLUDE_DEFAULT:
+                    for lcm_op in ns_lcm_op_occs_serializer.data:
+                        del lcm_op[field]
+            return Response(data=ns_lcm_op_occs_serializer.data, status=status.HTTP_200_OK)
+        except NSLCMException as e:
+            logger.error(e.message)
+            problem_details_serializer = get_problem_details_serializer(status.HTTP_500_INTERNAL_SERVER_ERROR, e.message)
+            return Response(data=problem_details_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+        except Exception as e:
+            logger.error(e.message)
+            logger.error(traceback.format_exc())
+            problem_details_serializer = get_problem_details_serializer(status.HTTP_500_INTERNAL_SERVER_ERROR, e.message)
+            return Response(data=problem_details_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+
+class QuerySingleNsLcmOpOcc(APIView):
+    @swagger_auto_schema(
+        responses={
+            status.HTTP_200_OK: NSLCMOpOccSerializer(),
+            status.HTTP_500_INTERNAL_SERVER_ERROR: ProblemDetailsSerializer()
+        }
+    )
+    def get(self, request, lcmopoccid):
+        logger.debug("QuerySingleNsLcmOpOcc--get::> %s" % request.query_params)
+        try:
+            resp_data = QueryNsLcmOpOcc(request.query_params, lcm_op_occ_id=lcmopoccid).query_single_ns_lcm_op_occ()
+
+            ns_lcm_op_occ_serializer = NSLCMOpOccSerializer(data=resp_data)
+            if not ns_lcm_op_occ_serializer.is_valid():
+                raise NSLCMException(ns_lcm_op_occ_serializer.errors)
+
+            return Response(data=ns_lcm_op_occ_serializer.data, status=status.HTTP_200_OK)
+        except NSLCMException as e:
+            logger.error(e.message)
+            problem_details_serializer = get_problem_details_serializer(status.HTTP_500_INTERNAL_SERVER_ERROR, e.message)
+            return Response(data=problem_details_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+        except Exception as e:
+            logger.error(e.message)
+            logger.error(traceback.format_exc())
+            problem_details_serializer = get_problem_details_serializer(status.HTTP_500_INTERNAL_SERVER_ERROR, e.message)
+            return Response(data=problem_details_serializer.data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
index a6694fa..dc8bfc1 100644 (file)
@@ -345,13 +345,31 @@ class SubscriptionModel(models.Model):
     operation_states = models.TextField(db_column='OPERATIONSTATES', null=True)
     ns_component_types = models.TextField(db_column='NSCOMPONENTTYPES', null=True)
     lcm_opname_impacting_nscomponent = models.TextField(db_column='LCMOPNAMEIMPACTINGNSCOMPONENT', null=True)
-    lcm_opoccstatus_impacting_nscomponent = models.TextField(db_column='LCMOPOCCSTATUSIMPACTINGNSCOMPONENT',
-                                                             null=True)
+    lcm_opoccstatus_impacting_nscomponent = models.TextField(db_column='LCMOPOCCSTATUSIMPACTINGNSCOMPONENT', null=True)
     callback_uri = models.CharField(db_column='CALLBACKURI', max_length=255)
     links = models.TextField(db_column='LINKS', max_length=20000)
     auth_info = models.TextField(db_column='AUTHINFO', max_length=20000, blank=True, null=True)
 
 
+class NSLcmOpOccModel(models.Model):
+    class Meta:
+        db_table = 'NSLCMOPOCCS'
+
+    id = models.CharField(db_column='ID', max_length=255, primary_key=True)
+    operation_state = models.CharField(db_column='OPERATIONSTATE', null=False, max_length=30)
+    state_entered_time = models.CharField(db_column='STATEENTEREDTIME', null=False, max_length=30)
+    start_time = models.CharField(db_column='STARTTIME', null=False, max_length=30)
+    ns_instance_id = models.CharField(db_column='NSINSTANCEID', null=False, max_length=255)
+    operation = models.CharField(db_column='OPERATION', null=False, max_length=30)
+    is_automatic_invocation = models.CharField(db_column='ISAUTOMATICINVOCATION', null=False, max_length=5)
+    operation_params = models.TextField(db_column='OPERATIONPARAMS', null=False)
+    is_cancel_pending = models.CharField(db_column='ISCANCELPENDING', null=False, max_length=5)
+    cancel_mode = models.TextField(db_column='CANCELMODE', null=True)
+    error = models.TextField(db_column='ERROR', null=True)
+    resource_changes = models.TextField(db_column='RESOURCECHANGES', null=True)
+    links = models.TextField(db_column='LINKS', null=False)
+
+
 class PNFInstModel(models.Model):
     class Meta:
         db_table = 'NFVO_PNFINST'