2 # -*- coding: utf-8 -*-
7 # Licensed under the Apache License, Version 2.0 (the "License"); you may
8 # not use this file except in compliance with the License. You may obtain
9 # a copy of the License at
11 # http://www.apache.org/licenses/LICENSE-2.0
13 # Unless required by applicable law or agreed to in writing, software
14 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 # License for the specific language governing permissions and limitations
20 from __future__
import print_function
28 Tests the format of OSM VNFD and NSD descriptors
30 __author__
= "Alfonso Tierno, Guillermo Calvino"
31 __date__
= "2018-04-16"
33 version_date
= "Apr 2018"
36 class ArgumentParserError(Exception):
39 class DescriptorValidationError(Exception):
43 print("Usage: {} [options] FILE".format(sys
.argv
[0]))
44 print(" Validates vnfd, nsd and nst descriptors format")
45 print(" FILE: a yaml or json vnfd-catalog, nsd-catalog or nst descriptor")
47 print(" -v|--version: prints current version")
48 print(" -h|--help: shows this help")
49 print(" -i|--input FILE: (same as param FILE) descriptor file to be upgraded")
50 print(" -c|--charms: looks for the charms folder and validates its coherency with the descriptor")
54 def remove_prefix(desc
, prefix
):
56 Recursively removes prefix from keys
57 :param desc: dictionary or list to change
58 :param prefix: prefix to remove. Must
59 :return: None, param desc is changed
61 prefix_len
= len(prefix
)
62 if isinstance(desc
, dict):
64 for k
,v
in desc
.items():
65 if isinstance(v
, (list, tuple, dict)):
66 remove_prefix(v
, prefix
)
67 if isinstance(k
, str) and k
.startswith(prefix
) and k
!= prefix
:
68 prefixed_list
.append(k
)
69 for k
in prefixed_list
:
70 desc
[k
[prefix_len
:]] = desc
.pop(k
)
71 elif isinstance(desc
, (list, tuple)):
73 if isinstance(desc
, (list, tuple, dict)):
74 remove_prefix(i
, prefix
)
77 # Mrityunjay Yadav: Function to verify charm included in VNF Package
78 def validate_charm(charm
, desc_file
):
80 Verify charm included in VNF Package and raised error if invalid
81 :param charm: vnf-configuration/vdu-configuration
82 :param desc_file: descriptor file
85 check_list
= ['layer.yaml', 'metadata.yaml', 'actions.yaml', 'actions', 'hooks']
86 charm_name
= charm
['juju']['charm']
87 charm_dir
= os
.path
.join(os
.path
.abspath(os
.path
.dirname(desc_file
)), 'charms', charm_name
)
89 config_primitive
= charm
.get('config-primitive', [])
90 initial_config_primitive
= charm
.get('initial-config-primitive', [])
92 if charm
.get('metrics'):
93 check_list
.append('metrics.yaml')
95 if os
.path
.exists(charm_dir
):
96 if not all(item
in os
.listdir(charm_dir
) for item
in check_list
):
97 raise KeyError("Invalid charm {}".format(charm_name
))
99 raise KeyError("Provided charm:{} does not exist in descriptor.".format(charm_name
))
102 if __name__
== "__main__":
104 format_output_yaml
= True
105 input_file_name
= None
108 validate_charms
= False
110 # load parameters and configuration
111 opts
, args
= getopt
.getopt(sys
.argv
[1:], "hvi:o:", ["input=", "help", "version",])
114 if o
in ("-v", "--version"):
115 print("test descriptor version THREE " + __version__
+ ' ' + version_date
)
117 elif o
in ("-h", "--help"):
120 elif o
in ("-i", "--input"):
122 elif o
in ("-c", "--charms"):
123 validate_charms
= True
125 assert False, "Unhandled option"
126 if not input_file_name
:
128 raise ArgumentParserError("missing DESCRIPTOR_FILE parameter. Type --help for more info")
129 input_file_name
= args
[0]
132 file_name
= input_file_name
133 with
open(file_name
, 'r') as f
:
134 descriptor_str
= f
.read()
137 if input_file_name
.endswith('.yaml') or input_file_name
.endswith('.yml') or not \
138 (input_file_name
.endswith('.json') or '\t' in descriptor_str
):
139 data
= yaml
.load(descriptor_str
)
141 data
= json
.loads(descriptor_str
)
142 format_output_yaml
= False
144 import osm_im
.vnfd
as vnfd_catalog
145 import osm_im
.nsd
as nsd_catalog
146 import osm_im
.nst
as nst_catalog
147 from pyangbind
.lib
.serialise
import pybindJSONDecoder
149 if "vnfd:vnfd-catalog" in data
or "vnfd-catalog" in data
:
151 # Check if mgmt-interface is defined:
152 remove_prefix(data
, "vnfd:")
153 vnfd_descriptor
= data
["vnfd-catalog"]
154 vnfd_list
= vnfd_descriptor
["vnfd"]
156 for vnfd
in vnfd_list
:
157 if "vdu" not in vnfd
and "kdu" not in vnfd
:
158 raise DescriptorValidationError("vdu or kdu not present in the descriptor")
159 vdu_list
= vnfd
.get("vdu",[])
162 external_interface_list
= vdu
.pop("external-interface", ())
163 for external_interface
in external_interface_list
:
164 if external_interface
.get("virtual-interface", {}).get("type") == "OM-MGMT":
166 "Wrong 'Virtual-interface type': Deprecated 'OM-MGMT' value. Please, use 'PARAVIRT' instead")
167 interface_list
= vdu
.get("interface", ())
168 for interface
in interface_list
:
169 if interface
.get("virtual-interface", {}).get("type") == "OM-MGMT":
171 "Wrong 'Virtual-interface type': Deprecated 'OM-MGMT' value. Please, use 'PARAVIRT' instead")
172 # Mrityunjay yadav: Verify charm if included in vdu
173 if vdu
.get("vdu-configuration", False) and validate_charms
:
174 validate_charm(vdu
["vdu-configuration"], input_file_name
)
175 if vnfd
.get("mgmt-interface"):
177 if vnfd
["mgmt-interface"].get("vdu-id"):
178 raise KeyError("'mgmt-iface': Deprecated 'vdu-id' field. Please, use 'cp' field instead")
179 # Mrityunjay yadav: Verify charm if included in vnf
180 if vnfd
.get("vnf-configuration", False) and validate_charms
:
181 validate_charm(vnfd
["vnf-configuration"], input_file_name
)
182 kdu_list
= vnfd
.get("kdu",[])
185 raise KeyError("'mgmt-interface' is a mandatory field and it is not defined")
186 myvnfd
= vnfd_catalog
.vnfd()
187 pybindJSONDecoder
.load_ietf_json(data
, None, None, obj
=myvnfd
)
188 elif "nsd:nsd-catalog" in data
or "nsd-catalog" in data
:
190 mynsd
= nsd_catalog
.nsd()
191 pybindJSONDecoder
.load_ietf_json(data
, None, None, obj
=mynsd
)
192 elif "nst:nst" in data
or "nst" in data
:
194 mynst
= nst_catalog
.nst()
195 pybindJSONDecoder
.load_ietf_json(data
, None, None, obj
=mynst
)
198 raise KeyError("This is not neither nsd-catalog nor vnfd-catalog descriptor")
201 except yaml
.YAMLError
as exc
:
203 if hasattr(exc
, 'problem_mark'):
204 mark
= exc
.problem_mark
205 error_pos
= "at line:%s column:%s" % (mark
.line
+ 1, mark
.column
+ 1)
206 print("Error loading file '{}'. yaml format error {}".format(input_file_name
, error_pos
), file=sys
.stderr
)
207 except DescriptorValidationError
as e
:
208 print(str(e
), file=sys
.stderr
)
209 except ArgumentParserError
as e
:
210 print(str(e
), file=sys
.stderr
)
212 print("Error loading file '{}': {}".format(file_name
, e
), file=sys
.stderr
)
213 except ImportError as e
:
214 print ("Package python-osm-im not installed: {}".format(e
), file=sys
.stderr
)
215 except Exception as e
:
217 print("Error loading file '{}': {}".format(file_name
, str(e
)), file=sys
.stderr
)
220 print("Error. Invalid {} descriptor format in '{}': {}".format(descriptor
, input_file_name
, str(e
)), file=sys
.stderr
)
222 print("Error. Invalid descriptor format in '{}': {}".format(input_file_name
, str(e
)), file=sys
.stderr
)