1 ############################################################################
2 # Copyright 2016 RIFT.io Inc #
4 # Licensed under the Apache License, Version 2.0 (the "License"); #
5 # you may not use this file except in compliance with the License. #
6 # You may obtain a copy of the License at #
8 # http://www.apache.org/licenses/LICENSE-2.0 #
10 # Unless required by applicable law or agreed to in writing, software #
11 # distributed under the License is distributed on an "AS IS" BASIS, #
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
13 # See the License for the specific language governing permissions and #
14 # limitations under the License. #
15 ############################################################################
23 from gi
.repository
import ProjectNsdYang
as NsdYang
24 from gi
.repository
import ProjectVnfdYang
as VnfdYang
27 class InitialConfigReadError(Exception):
31 class InitialConfigMethodError(Exception):
35 class InitialConfigPrimitiveReader(object):
36 """ Reader for the VNF Initial Config Input Data
38 This class interprets the Initial Config Primitive
39 Input data and constructs inital config primitive
42 The reason for creating a new format is to keep the structure
43 as dead-simple as possible for readability.
45 The structure (not serialization format) is defined as the
50 "name": <primitive_name>,
61 def __init__(self
, primitive_input
):
64 self
._parse
_input
_data
(primitive_input
)
66 def _parse_input_data(self
, input_dict
):
67 for seq
, cfg
in enumerate(input_dict
):
69 raise InitialConfigReadError("Initial config primitive must have a name")
73 new_primitive
= self
. get_initial_config_primitive(seq
=seq
, name
=name
)
74 self
._primitives
.append(new_primitive
)
75 if "parameter" in cfg
:
76 for key
, val
in cfg
["parameter"].items():
77 new_primitive
.parameter
.add(name
=key
, value
=val
)
80 def get_initial_config_primitive(self
, seq
, name
):
81 '''Override in sub class to provide the correct yang model'''
82 raise InitialConfigMethodError(
83 "InitialConfigPrimitiveReader Calling abstract class method")
87 """ Returns a copy of the read inital config primitives"""
88 return [prim
.deep_copy() for prim
in self
._primitives
]
91 def from_yaml_file_hdl(cls
, file_hdl
):
92 """ Create a instance of InitialConfigPrimitiveFileData
93 by reading a YAML file handle.
96 file_hdl - A file handle which contains serialized YAML which
97 follows the documented structure.
100 A new InitialConfigPrimitiveFileData() instance
103 InitialConfigReadError: Input Data was malformed or could not be read
106 input_dict
= yaml
.safe_load(file_hdl
)
107 except yaml
.YAMLError
as e
:
108 raise InitialConfigReadError(e
)
110 return cls(input_dict
)
113 class VnfInitialConfigPrimitiveReader(InitialConfigPrimitiveReader
):
114 '''Class to read the VNF initial config primitives'''
116 def __init__(self
, primitive_input
):
117 super(VnfInitialConfigPrimitiveReader
, self
).__init
__(primitive_input
)
119 def get_initial_config_primitive(self
, seq
, name
):
120 return VnfdYang
.InitialConfigPrimitive(seq
=seq
, name
=name
)
123 class NsInitialConfigPrimitiveReader(InitialConfigPrimitiveReader
):
124 '''Class to read the NS initial config primitives'''
126 def __init__(self
, primitive_input
):
127 super(NsInitialConfigPrimitiveReader
, self
).__init
__(primitive_input
)
129 def get_initial_config_primitive(self
, seq
, name
):
130 return NsdYang
.NsdInitialConfigPrimitive(seq
=seq
, name
=name
)
133 class ConfigPrimitiveConvertor(object):
134 PARAMETER
= "parameter"
135 PARAMETER_GROUP
= "parameter_group"
136 CONFIG_PRIMITIVE
= "service_primitive"
137 INITIAL_CONFIG_PRIMITIVE
= "initial_config_primitive"
139 def _extract_param(self
, param
, field
="default_value"):
141 value
= getattr(param
, field
, None)
143 if value
is not None:
144 setattr(param
, field
, None)
148 def _extract_parameters(self
, parameters
, input_data
, field
="default_value"):
149 input_data
[self
.PARAMETER
] = {}
150 for param
in parameters
:
151 key
, value
= self
._extract
_param
(param
, field
)
156 input_data
[self
.PARAMETER
][key
] = value
158 if not input_data
[self
.PARAMETER
]:
159 del input_data
[self
.PARAMETER
]
161 def _extract_parameter_group(self
, param_groups
, input_data
):
162 input_data
[self
.PARAMETER_GROUP
] = {}
163 for param_group
in param_groups
:
164 input_data
[self
.PARAMETER_GROUP
][param_group
.name
] = {}
165 for param
in param_group
.parameter
:
166 key
, value
= self
._extract
_param
(param
)
171 input_data
[self
.PARAMETER_GROUP
][param_group
.name
][key
] = value
173 if not input_data
[self
.PARAMETER_GROUP
]:
174 del input_data
[self
.PARAMETER_GROUP
]
176 def extract_config(self
,
177 config_primitives
=None,
178 initial_configs
=None,
182 if config_primitives
:
183 input_data
[self
.CONFIG_PRIMITIVE
] = {}
184 for config_primitive
in config_primitives
:
185 input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
] = {}
186 self
._extract
_parameters
(
187 config_primitive
.parameter
,
188 input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
])
191 self
._extract
_parameter
_group
(
192 config_primitive
.parameter_group
,
193 input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
])
194 except AttributeError:
197 if not input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
]:
198 del input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
]
200 if not input_data
[self
.CONFIG_PRIMITIVE
]:
201 del input_data
[self
.CONFIG_PRIMITIVE
]
205 input_data
[self
.INITIAL_CONFIG_PRIMITIVE
] = []
206 for in_config_primitive
in initial_configs
:
208 self
._extract
_parameters
(
209 in_config_primitive
.parameter
,
214 input_data
[self
.INITIAL_CONFIG_PRIMITIVE
].append(
216 "name": in_config_primitive
.name
,
217 self
.PARAMETER
: primitive
[self
.PARAMETER
],
221 if not input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]:
222 del input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]
226 return json
.dumps(input_data
)
227 elif format
== "yaml":
228 return yaml
.dump(input_data
, default_flow_style
=False)
232 def extract_nsd_config(self
, nsd
, format
="yaml"):
235 config_prim
= nsd
.service_primitive
236 except AttributeError:
241 initial_conf
= nsd
.initial_config_primitive
242 except AttributeError:
245 return self
.extract_config(
246 config_primitives
=config_prim
,
247 initial_configs
=initial_conf
,
250 def extract_vnfd_config(self
, vnfd
, format
="yaml"):
253 config_prim
= vnfd
.vnf_configuration
.service_primitive
254 except AttributeError:
259 initial_conf
= vnfd
.vnf_configuration
.initial_config_primitive
260 except AttributeError:
263 return self
.extract_config(
264 config_primitives
=config_prim
,
265 initial_configs
=initial_conf
,
268 def merge_params(self
, parameters
, input_config
, field
="default_value"):
269 for param
in parameters
:
271 setattr(param
, field
, input_config
[param
.name
])
275 def add_nsd_initial_config(self
, nsd_init_cfg_prim_msg
, input_data
):
276 """ Add initial config primitives from NS Initial Config Input Data
279 nsd_init_cfg_prim_msg - manotypes:nsd/initial_config_primitive pb msg
280 ns_input_data - NsInitialConfigPrimitiveReader documented input data
283 InitialConfigReadError: VNF input data was malformed
285 if self
.INITIAL_CONFIG_PRIMITIVE
in input_data
:
286 ns_input_data
= input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]
288 reader
= NsInitialConfigPrimitiveReader(ns_input_data
)
289 for prim
in reader
.primitives
:
290 nsd_init_cfg_prim_msg
.append(prim
)
292 def merge_nsd_initial_config(self
, nsd
, input_data
):
294 for config_primitive
in nsd
.initial_config_primitive
:
295 for cfg
in input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]:
296 if cfg
['name'] == config_primitive
.name
:
298 config_primitive
.parameter
,
303 except AttributeError as e
:
304 self
._log
.debug("Did not find initial-config-primitive for NSD {}: {}".
308 def merge_nsd_config(self
, nsd
, input_data
):
309 for config_primitive
in nsd
.service_primitive
:
311 cfg
= input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
]
316 config_primitive
.parameter
,
319 for param_group
in config_primitive
.parameter_group
:
321 param_group
.parameter
,
322 cfg
[self
.PARAMETER_GROUP
][param_group
.name
])
324 def add_vnfd_initial_config(self
, vnfd_init_cfg_prim_msg
, input_data
):
325 """ Add initial config primitives from VNF Initial Config Input Data
328 vnfd_init_cfg_prim_msg - manotypes:vnf-configuration/initial_config_primitive pb msg
329 vnf_input_data - VnfInitialConfigPrimitiveReader documented input data
332 InitialConfigReadError: VNF input data was malformed
334 if self
.INITIAL_CONFIG_PRIMITIVE
in input_data
:
335 vnf_input_data
= input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]
337 reader
= VnfInitialConfigPrimitiveReader(vnf_input_data
)
338 for prim
in reader
.primitives
:
339 vnfd_init_cfg_prim_msg
.append(prim
)
341 def merge_vnfd_config(self
, vnfd
, input_data
):
342 for config_primitive
in vnfd
.vnf_configuration
.service_primitive
:
344 cfg
= input_data
[self
.CONFIG_PRIMITIVE
][config_primitive
.name
]
349 config_primitive
.parameter
,
353 class ConfigStore(object):
354 """Convenience class that fetches all the instance related data from the
355 $RIFT_ARTIFACTS/launchpad/libs directory.
358 def __init__(self
, log
):
364 self
.converter
= ConfigPrimitiveConvertor()
366 def merge_vnfd_config(self
, nsd_id
, vnfd
, member_vnf_index
):
367 """Merges the vnfd config from the config directory.
370 nsd_id (str): Id of the NSD object
371 vnfd_msg : VNFD pb message containing the VNFD id and
372 the member index ref.
374 nsd_archive
= os
.path
.join(
375 os
.getenv('RIFT_ARTIFACTS'),
380 self
._log
.info("Looking for config from the archive {}".format(nsd_archive
))
382 if not os
.path
.exists(nsd_archive
):
385 config_file
= os
.path
.join(nsd_archive
,
386 "{}__{}.yaml".format(vnfd
.id, member_vnf_index
))
388 if not os
.path
.exists(config_file
):
389 self
._log
.info("Could not find VNF initial config in archive: %s", config_file
)
392 input_data
= self
.read_from_file(config_file
)
393 self
._log
.info("Loaded VNF config file {}: {}".format(config_file
, input_data
))
395 self
.converter
.merge_vnfd_config(vnfd
, input_data
)
397 self
.converter
.add_vnfd_initial_config(
398 vnfd
.vnf_configuration
.initial_config_primitive
,
402 def read_from_file(self
, filename
):
403 with
open(filename
) as fh
:
404 input_data
= yaml
.load(fh
)
407 def merge_nsd_config(self
, nsd
):
408 nsd_archive
= os
.path
.join(
409 os
.getenv('RIFT_ARTIFACTS'),
414 self
._log
.info("Looking for config from the archive {}".format(nsd_archive
))
416 if not os
.path
.exists(nsd_archive
):
419 config_file
= os
.path
.join(nsd_archive
,
420 "{}.yaml".format(nsd
.id))
421 if not os
.path
.exists(config_file
):
422 self
._log
.info("Could not find NS config in archive: %s", config_file
)
425 input_data
= self
.read_from_file(config_file
)
426 self
._log
.info("Loaded NS config file {}: {}".format(config_file
, input_data
))
428 self
.converter
.merge_nsd_config(nsd
, input_data
)
430 self
.converter
.merge_nsd_initial_config(nsd
, input_data
)