blob: 7eff67e159fbff41d2a59a0540a0e7b8d16f371e [file] [log] [blame]
garciadeblas361145b2019-10-28 11:11:48 +01001# -*- coding: utf-8 -*-
2
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import yaml
garciaale76f6a622020-11-19 17:57:42 -030017import importlib
garciadeblas361145b2019-10-28 11:11:48 +010018from osm_im.vnfd import vnfd as vnfd_im
19from osm_im.nsd import nsd as nsd_im
20from osm_im.nst import nst as nst_im
sousaedu048e5e02021-07-29 14:55:35 +020021from osm_im import etsi_nfv_vnfd, etsi_nfv_nsd
garciadeblas361145b2019-10-28 11:11:48 +010022from pyangbind.lib.serialise import pybindJSONDecoder
23import pyangbind.lib.pybindJSON as pybindJSON
24
25class ValidationException(Exception):
26 pass
27
garciadeblasc214d9e2019-11-08 14:23:04 +010028class Validation:
garciadeblas361145b2019-10-28 11:11:48 +010029
30 def pyangbind_validation(self, item, data, force=False):
31 '''
32 item: vnfd, nst, nsd
33 data: dict object loaded from the descriptor file
34 force: True to skip unknown fields in the descriptor
35 '''
36 if item == "vnfd":
37 myobj = vnfd_im()
38 elif item == "nsd":
39 myobj = nsd_im()
40 elif item == "nst":
41 myobj = nst_im()
garciaale76f6a622020-11-19 17:57:42 -030042 elif item == "etsi_nfv_vnfd":
43 myobj = etsi_nfv_vnfd.etsi_nfv_vnfd()
44 elif item == "etsi_nfv_nsd":
45 myobj = etsi_nfv_nsd.etsi_nfv_nsd()
garciadeblas361145b2019-10-28 11:11:48 +010046 else:
47 raise ValidationException("Not possible to validate '{}' item".format(item))
48
49 try:
50 pybindJSONDecoder.load_ietf_json(data, None, None, obj=myobj,
51 path_helper=True, skip_unknown=force)
52 out = pybindJSON.dumps(myobj, mode="ietf")
53 desc_out = yaml.safe_load(out)
54 return desc_out
55 except Exception as e:
56 raise ValidationException("Error in pyangbind validation: {}".format(str(e)))
57
58 def yaml_validation(self, descriptor):
59 try:
60 data = yaml.safe_load(descriptor)
61 except Exception as e:
garciadeblasc214d9e2019-11-08 14:23:04 +010062 raise ValidationException("Error in YAML validation. Not a proper YAML file: {}".format(e))
63 if 'vnfd:vnfd-catalog' in data or 'vnfd-catalog' in data:
garciadeblas361145b2019-10-28 11:11:48 +010064 item = "vnfd"
garciadeblasc214d9e2019-11-08 14:23:04 +010065 elif 'nsd:nsd-catalog' in data or 'nsd-catalog' in data:
garciadeblas361145b2019-10-28 11:11:48 +010066 item = "nsd"
67 elif 'nst' in data:
68 item = "nst"
garciaale76f6a622020-11-19 17:57:42 -030069 elif 'vnfd' in data:
70 item = "etsi_nfv_vnfd"
71 elif 'nsd' in data:
72 item = "etsi_nfv_nsd"
garciadeblas361145b2019-10-28 11:11:48 +010073 else:
garciadeblasc214d9e2019-11-08 14:23:04 +010074 raise ValidationException("Error in YAML validation. Not possible to determine the type of descriptor in the first line. Expected values: vnfd:vnfd-catalog, vnfd-catalog, nsd:nsd-catalog, nsd-catalog, nst")
garciadeblas361145b2019-10-28 11:11:48 +010075
76 return item, data
77
78 def descriptor_validation(self, descriptor):
79 item, data = self.yaml_validation(descriptor)
80 self.pyangbind_validation(item, data)
81
adurti607a9de2025-07-22 13:48:52 +053082 def validate_instantiation_level_descriptor(self, indata):
83 all_vdu_ids = set()
84 for vdu in indata.get("vdu", ()):
85 all_vdu_ids.add(vdu.get("id"))
86
87 for df in indata.get("df", ()):
88 for il in df.get("instantiation-level", ()):
89 for vl in il.get("vdu-level", ()):
90 vl_vdu_id = vl.get("vdu-id")
91 if vl_vdu_id and vl_vdu_id not in all_vdu_ids:
92 raise ValidationException(
93 "df[id='{}']:instantiation-level[id='{}']:vdu-level"
94 "vdu-id='{}' not defined in vdu".format(
95 df["id"],
96 il["id"],
97 vl_vdu_id,
98 )
99 )
100
101 def validate_vdu_profile_in_descriptor(self, indata):
102 all_vdu_ids = set()
103 for df in indata.get("df", ()):
104 if "vdu-profile" in df:
105 if not df.get("vdu-profile"):
106 if indata.get("vdu"):
107 raise ValidationException(
108 "no profiles are defined under vdu-profile section"
109 )
110 for vp in df["vdu-profile"]:
111 missing = None
112 if not vp.get("id"):
113 missing = "id"
114 if df.get("scaling-aspect"):
115 if not vp.get("min-number-of-instances"):
116 missing = "min-number-of-instances"
117 if "min-number-of-instances" in vp:
118 if not vp.get("min-number-of-instances"):
119 missing = "min-number-of-instances"
120 if "max-number-of-instances" in vp:
121 if not vp.get("max-number-of-instances"):
122 missing = "max-number-of-instances"
123 if missing:
124 raise ValidationException(
125 "{} key-value pair is missing in vdu-profile".format(
126 missing
127 )
128 )
129
130 for df in indata.get("df", ()):
131 for il in df.get("instantiation-level", ()):
132 for vl in il.get("vdu-level", ()):
133 all_vdu_ids.add(vl.get("vdu-id"))
134
135 for df in indata.get("df", ()):
136 for vp in df.get("vdu-profile", ()):
137 vp_vdu_id = vp.get("id")
138 if vp_vdu_id and vp_vdu_id not in all_vdu_ids:
139 raise ValidationException(
140 "df[id='{}']:vdu-profile:vdu-id='{}' not defined in vdu".format(
141 df["id"],
142 vp_vdu_id,
143 )
144 )