Fix Bug 2307 - Invalid references of vdu-id, monitoring-param, storage and compute... 90/13990/3
authorAdurti <adurti.v@tataelxsi.co.in>
Wed, 8 Nov 2023 06:26:04 +0000 (06:26 +0000)
committerAdurti <adurti.v@tataelxsi.co.in>
Tue, 18 Jun 2024 11:27:53 +0000 (11:27 +0000)
Change-Id: I6a8db47f354c94341baede67515640598ee32b8b
Signed-off-by: Adurti <adurti.v@tataelxsi.co.in>
osm_nbi/descriptor_topics.py
osm_nbi/tests/test_descriptor_topics.py
osm_nbi/tests/test_pkg_descriptors.py

index 9695866..7f05efb 100644 (file)
@@ -852,6 +852,9 @@ class VnfdTopic(DescriptorTopic):
         self.validate_internal_virtual_links(indata)
         self.validate_monitoring_params(indata)
         self.validate_scaling_group_descriptor(indata)
+        self.validate_healing_group_descriptor(indata)
+        self.validate_alarm_group_descriptor(indata)
+        self.validate_storage_compute_descriptor(indata)
         self.validate_helm_chart(indata)
 
         return indata
@@ -1112,6 +1115,12 @@ class VnfdTopic(DescriptorTopic):
     @staticmethod
     def validate_scaling_group_descriptor(indata):
         all_monitoring_params = set()
+        all_vdu_ids = set()
+        for df in get_iterable(indata.get("df")):
+            for il in get_iterable(df.get("instantiation-level")):
+                for vl in get_iterable(il.get("vdu-level")):
+                    all_vdu_ids.add(vl.get("vdu-id"))
+
         for ivld in get_iterable(indata.get("int-virtual-link-desc")):
             for mp in get_iterable(ivld.get("monitoring-parameters")):
                 all_monitoring_params.add(mp.get("id"))
@@ -1124,6 +1133,26 @@ class VnfdTopic(DescriptorTopic):
             for mp in get_iterable(df.get("monitoring-parameter")):
                 all_monitoring_params.add(mp.get("id"))
 
+        for df in get_iterable(indata.get("df")):
+            for sa in get_iterable(df.get("scaling-aspect")):
+                for deltas in get_iterable(
+                    sa.get("aspect-delta-details").get("deltas")
+                ):
+                    for vds in get_iterable(deltas.get("vdu-delta")):
+                        sa_vdu_id = vds.get("id")
+                        if sa_vdu_id and sa_vdu_id not in all_vdu_ids:
+                            raise EngineException(
+                                "df[id='{}']:scaling-aspect[id='{}']:aspect-delta-details"
+                                "[delta='{}']: "
+                                "vdu-id='{}' not defined in vdu".format(
+                                    df["id"],
+                                    sa["id"],
+                                    deltas["id"],
+                                    sa_vdu_id,
+                                ),
+                                http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+                            )
+
         for df in get_iterable(indata.get("df")):
             for sa in get_iterable(df.get("scaling-aspect")):
                 for sp in get_iterable(sa.get("scaling-policy")):
@@ -1190,6 +1219,95 @@ class VnfdTopic(DescriptorTopic):
                                 http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
                             )
 
+    @staticmethod
+    def validate_healing_group_descriptor(indata):
+        all_vdu_ids = set()
+        for df in get_iterable(indata.get("df")):
+            for il in get_iterable(df.get("instantiation-level")):
+                for vl in get_iterable(il.get("vdu-level")):
+                    all_vdu_ids.add(vl.get("vdu-id"))
+
+        for df in get_iterable(indata.get("df")):
+            for ha in get_iterable(df.get("healing-aspect")):
+                for hp in get_iterable(ha.get("healing-policy")):
+                    hp_monitoring_param = hp.get("vdu-id")
+                    if hp_monitoring_param and hp_monitoring_param not in all_vdu_ids:
+                        raise EngineException(
+                            "df[id='{}']:healing-aspect[id='{}']:healing-policy"
+                            "[name='{}']: "
+                            "vdu-id='{}' not defined in vdu".format(
+                                df["id"],
+                                ha["id"],
+                                hp["event-name"],
+                                hp_monitoring_param,
+                            ),
+                            http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+                        )
+
+    @staticmethod
+    def validate_alarm_group_descriptor(indata):
+        all_monitoring_params = set()
+        for ivld in get_iterable(indata.get("int-virtual-link-desc")):
+            for mp in get_iterable(ivld.get("monitoring-parameters")):
+                all_monitoring_params.add(mp.get("id"))
+
+        for vdu in get_iterable(indata.get("vdu")):
+            for mp in get_iterable(vdu.get("monitoring-parameter")):
+                all_monitoring_params.add(mp.get("id"))
+
+        for df in get_iterable(indata.get("df")):
+            for mp in get_iterable(df.get("monitoring-parameter")):
+                all_monitoring_params.add(mp.get("id"))
+
+        for vdus in get_iterable(indata.get("vdu")):
+            for alarms in get_iterable(vdus.get("alarm")):
+                alarm_monitoring_param = alarms.get("vnf-monitoring-param-ref")
+                if (
+                    alarm_monitoring_param
+                    and alarm_monitoring_param not in all_monitoring_params
+                ):
+                    raise EngineException(
+                        "vdu[id='{}']:alarm[id='{}']:"
+                        "vnf-monitoring-param-ref='{}' not defined in any monitoring-param".format(
+                            vdus["id"],
+                            alarms["alarm-id"],
+                            alarm_monitoring_param,
+                        ),
+                        http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+                    )
+
+    @staticmethod
+    def validate_storage_compute_descriptor(indata):
+        all_vsd_ids = set()
+        for vsd in get_iterable(indata.get("virtual-storage-desc")):
+            all_vsd_ids.add(vsd.get("id"))
+
+        all_vcd_ids = set()
+        for vcd in get_iterable(indata.get("virtual-compute-desc")):
+            all_vcd_ids.add(vcd.get("id"))
+
+        for vdus in get_iterable(indata.get("vdu")):
+            for vsd_ref in vdus.get("virtual-storage-desc"):
+                if vsd_ref and vsd_ref not in all_vsd_ids:
+                    raise EngineException(
+                        "vdu[virtual-storage-desc='{}']"
+                        "not defined in vnfd".format(
+                            vsd_ref,
+                        ),
+                        http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+                    )
+
+        for vdus in get_iterable(indata.get("vdu")):
+            vcd_ref = vdus.get("virtual-compute-desc")
+            if vcd_ref and vcd_ref not in all_vcd_ids:
+                raise EngineException(
+                    "vdu[virtual-compute-desc='{}']"
+                    "not defined in vnfd".format(
+                        vdus["virtual-compute-desc"],
+                    ),
+                    http_code=HTTPStatus.UNPROCESSABLE_ENTITY,
+                )
+
     def delete_extra(self, session, _id, db_content, not_send_msg=None):
         """
         Deletes associate file system storage (via super)
index dcde0a5..08becec 100755 (executable)
@@ -578,6 +578,49 @@ class Test_VnfdTopic(TestCase):
             "Wrong exception text",
         )
 
+    @patch("osm_nbi.descriptor_topics.shutil")
+    @patch("osm_nbi.descriptor_topics.os.rename")
+    def test_new_vnfd_check_input_validation_scaling_criteria_vdu_id(
+        self, mock_rename, mock_shutil
+    ):
+        """Testing input validation during new vnfd creation
+        for scaling criteria with invalid vdu-id"""
+        did, test_vnfd = self.prepare_vnfd_creation()
+        test_vnfd = self.prepare_test_vnfd(test_vnfd)
+        test_vnfd["df"][0]["scaling-aspect"][0]["aspect-delta-details"]["deltas"][0][
+            "vdu-delta"
+        ][0]["id"] = "vdudelta1"
+        affected_df = test_vnfd["df"][0]
+        sa = affected_df["scaling-aspect"][0]
+        delta = sa["aspect-delta-details"]["deltas"][0]
+        vdu_delta = delta["vdu-delta"][0]
+
+        with self.assertRaises(
+            EngineException, msg="Accepted invalid Scaling Group Policy Criteria"
+        ) as e:
+            self.topic.upload_content(
+                fake_session, did, test_vnfd, {}, {"Content-Type": []}
+            )
+        self.assertEqual(
+            e.exception.http_code,
+            HTTPStatus.UNPROCESSABLE_ENTITY,
+            "Wrong HTTP status code",
+        )
+        self.assertIn(
+            norm(
+                "df[id='{}']:scaling-aspect[id='{}']:aspect-delta-details"
+                "[delta='{}']: "
+                "vdu-id='{}' not defined in vdu".format(
+                    affected_df["id"],
+                    sa["id"],
+                    delta["id"],
+                    vdu_delta["id"],
+                )
+            ),
+            norm(str(e.exception)),
+            "Wrong exception text",
+        )
+
     @patch("osm_nbi.descriptor_topics.shutil")
     @patch("osm_nbi.descriptor_topics.os.rename")
     def test_new_vnfd_check_input_validation_scaling_criteria_monitoring_param_ref(
@@ -698,6 +741,157 @@ class Test_VnfdTopic(TestCase):
             "Wrong exception text",
         )
 
+    @patch("osm_nbi.descriptor_topics.shutil")
+    @patch("osm_nbi.descriptor_topics.os.rename")
+    def test_new_vnfd_check_input_validation_healing_criteria_vdu_id(
+        self, mock_rename, mock_shutil
+    ):
+        """Testing input validation during new vnfd creation
+        for healing criteria with invalid vdu-id"""
+        did, test_vnfd = self.prepare_vnfd_creation()
+        test_vnfd = self.prepare_test_vnfd(test_vnfd)
+        test_vnfd["df"][0]["healing-aspect"][0]["healing-policy"][0][
+            "vdu-id"
+        ] = "vduid1"
+        affected_df = test_vnfd["df"][0]
+        ha = affected_df["healing-aspect"][0]
+        hp = ha["healing-policy"][0]
+        hp_vdu_id = hp["vdu-id"]
+
+        with self.assertRaises(
+            EngineException, msg="Accepted invalid Healing Group Policy Criteria"
+        ) as e:
+            self.topic.upload_content(
+                fake_session, did, test_vnfd, {}, {"Content-Type": []}
+            )
+        self.assertEqual(
+            e.exception.http_code,
+            HTTPStatus.UNPROCESSABLE_ENTITY,
+            "Wrong HTTP status code",
+        )
+        self.assertIn(
+            norm(
+                "df[id='{}']:healing-aspect[id='{}']:healing-policy"
+                "[name='{}']: "
+                "vdu-id='{}' not defined in vdu".format(
+                    affected_df["id"],
+                    ha["id"],
+                    hp["event-name"],
+                    hp_vdu_id,
+                )
+            ),
+            norm(str(e.exception)),
+            "Wrong exception text",
+        )
+
+    @patch("osm_nbi.descriptor_topics.shutil")
+    @patch("osm_nbi.descriptor_topics.os.rename")
+    def test_new_vnfd_check_input_validation_alarm_criteria_monitoring_param_ref(
+        self, mock_rename, mock_shutil
+    ):
+        """Testing input validation during new vnfd creation
+        for alarm with invalid monitoring parameter reference"""
+        did, test_vnfd = self.prepare_vnfd_creation()
+        test_vnfd = self.prepare_test_vnfd(test_vnfd)
+        test_vnfd["vdu"][1]["alarm"][0]["vnf-monitoring-param-ref"] = "unit_test_alarm"
+        vdu = test_vnfd["vdu"][1]
+        alarm = vdu["alarm"][0]
+        alarm_monitoring_param = alarm["vnf-monitoring-param-ref"]
+
+        with self.assertRaises(
+            EngineException, msg="Accepted invalid Alarm Criteria"
+        ) as e:
+            self.topic.upload_content(
+                fake_session, did, test_vnfd, {}, {"Content-Type": []}
+            )
+        self.assertEqual(
+            e.exception.http_code,
+            HTTPStatus.UNPROCESSABLE_ENTITY,
+            "Wrong HTTP status code",
+        )
+        self.assertIn(
+            norm(
+                "vdu[id='{}']:alarm[id='{}']:"
+                "vnf-monitoring-param-ref='{}' not defined in any monitoring-param".format(
+                    vdu["id"],
+                    alarm["alarm-id"],
+                    alarm_monitoring_param,
+                )
+            ),
+            norm(str(e.exception)),
+            "Wrong exception text",
+        )
+
+    @patch("osm_nbi.descriptor_topics.shutil")
+    @patch("osm_nbi.descriptor_topics.os.rename")
+    def test_new_vnfd_check_input_validation_storage_reference_criteria(
+        self, mock_rename, mock_shutil
+    ):
+        """Testing input validation during new vnfd creation
+        for invalid virtual-storge-desc reference"""
+        did, test_vnfd = self.prepare_vnfd_creation()
+        test_vnfd = self.prepare_test_vnfd(test_vnfd)
+        test_vnfd["vdu"][1]["virtual-storage-desc"] = "unit_test_storage"
+        vdu = test_vnfd["vdu"][1]
+        vsd_ref = vdu["virtual-storage-desc"]
+
+        with self.assertRaises(
+            EngineException, msg="Accepted invalid virtual-storage-desc"
+        ) as e:
+            self.topic.upload_content(
+                fake_session, did, test_vnfd, {}, {"Content-Type": []}
+            )
+        self.assertEqual(
+            e.exception.http_code,
+            HTTPStatus.UNPROCESSABLE_ENTITY,
+            "Wrong HTTP status code",
+        )
+        self.assertIn(
+            norm(
+                "vdu[virtual-storage-desc='{}']"
+                "not defined in vnfd".format(
+                    vsd_ref,
+                )
+            ),
+            norm(str(e.exception)),
+            "Wrong exception text",
+        )
+
+    @patch("osm_nbi.descriptor_topics.shutil")
+    @patch("osm_nbi.descriptor_topics.os.rename")
+    def test_new_vnfd_check_input_validation_compute_reference_criteria(
+        self, mock_rename, mock_shutil
+    ):
+        """Testing input validation during new vnfd creation
+        for invalid virtual-compute-desc reference"""
+        did, test_vnfd = self.prepare_vnfd_creation()
+        test_vnfd = self.prepare_test_vnfd(test_vnfd)
+        test_vnfd["vdu"][1]["virtual-compute-desc"] = "unit_test_compute"
+        vdu = test_vnfd["vdu"][1]
+        vcd_ref = vdu["virtual-compute-desc"]
+
+        with self.assertRaises(
+            EngineException, msg="Accepted invalid virtual-compute-desc"
+        ) as e:
+            self.topic.upload_content(
+                fake_session, did, test_vnfd, {}, {"Content-Type": []}
+            )
+        self.assertEqual(
+            e.exception.http_code,
+            HTTPStatus.UNPROCESSABLE_ENTITY,
+            "Wrong HTTP status code",
+        )
+        self.assertIn(
+            norm(
+                "vdu[virtual-compute-desc='{}']"
+                "not defined in vnfd".format(
+                    vcd_ref,
+                )
+            ),
+            norm(str(e.exception)),
+            "Wrong exception text",
+        )
+
     @patch("osm_nbi.descriptor_topics.shutil")
     @patch("osm_nbi.descriptor_topics.os.rename")
     def test_new_vnfd_check_input_validation_everything_right(
index 39c28fe..97549bc 100644 (file)
@@ -118,7 +118,17 @@ db_vnfds_text = """
                 position: 2
                 virtual-interface:
                   type: VIRTIO
-      - id: dataVM
+      - alarm:
+        - actions:
+            alarm:
+            - url: https://webhook.site
+            insufficient-data:
+            - url: https://webhook.site
+            ok:
+            - url: https://webhook.site
+          alarm-id: alarm-1
+          vnf-monitoring-param-ref: dataVM_cpu_util
+        id: dataVM
         name: dataVM
         sw-image-desc: hackfest3-mgmt
         virtual-compute-desc: data-compute
@@ -179,7 +189,7 @@ db_vnfds_text = """
               deltas:
                 - id: delta1
                   vdu-delta:
-                    - id: vdudelta1
+                    - id: dataVM
                       number-of-instances: 1
             scaling-policy:
               - name: auto_cpu_util_above_threshold
@@ -199,6 +209,15 @@ db_vnfds_text = """
                 vnf-config-primitive-name-ref: touch
               - trigger: pre-scale-in
                 vnf-config-primitive-name-ref: touch
+        healing-aspect:
+          - id: heal_dataVM
+            healing-policy:
+            - vdu-id: dataVM
+              event-name: heal-alarm
+              recovery-type: automatic
+              action-on-recovery: REDEPLOY_ONLY
+              cooldown-time: 180
+              day1: false
         lcm-operations-configuration:
           operate-vnf-op-config:
             day1-2: