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
.YangData_Vnfd_VnfdCatalog_Vnfd_VnfConfiguration_InitialConfigPrimitive(seq
=seq
, name
=name
)
123 class NsInitialServicePrimitiveReader(InitialConfigPrimitiveReader
):
124 '''Class to read the NS initial config primitives'''
126 def __init__(self
, primitive_input
):
127 super(NsInitialServicePrimitiveReader
, self
).__init
__(primitive_input
)
129 def get_initial_config_primitive(self
, seq
, name
):
130 return NsdYang
.YangData_Nsd_NsdCatalog_Nsd_InitialServicePrimitive(seq
=seq
, name
=name
)
133 class ConfigPrimitiveConvertor(object):
134 PARAMETER
= "parameter"
135 PARAMETER_GROUP
= "parameter_group"
136 SERVICE_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
.SERVICE_PRIMITIVE
] = {}
184 for config_primitive
in config_primitives
:
185 input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
] = {}
186 self
._extract
_parameters
(
187 config_primitive
.parameter
,
188 input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
])
191 self
._extract
_parameter
_group
(
192 config_primitive
.parameter_group
,
193 input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
])
194 except AttributeError:
197 if not input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
]:
198 del input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
]
200 if not input_data
[self
.SERVICE_PRIMITIVE
]:
201 del input_data
[self
.SERVICE_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_service_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
.config_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 service 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
= NsInitialServicePrimitiveReader(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 service_primitive
in nsd
.initial_service_primitive
:
295 for cfg
in input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]:
296 if cfg
['name'] == service_primitive
.name
:
298 service_primitive
.parameter
,
303 except AttributeError as e
:
304 self
._log
.debug("Did not find initial-service-primitive for NSD {}: {}".
307 def merge_nsd_config(self
, nsd
, input_data
):
308 for service_primitive
in nsd
.service_primitive
:
310 cfg
= input_data
[self
.SERVICE_PRIMITIVE
][service_primitive
.name
]
315 service_primitive
.parameter
,
318 for param_group
in service_primitive
.parameter_group
:
320 param_group
.parameter
,
321 cfg
[self
.PARAMETER_GROUP
][param_group
.name
])
323 def add_vnfd_initial_config(self
, vnfd_init_cfg_prim_msg
, input_data
):
324 """ Add initial config primitives from VNF Initial Config Input Data
327 vnfd_init_cfg_prim_msg - manotypes:vnf-configuration/initial_config_primitive pb msg
328 vnf_input_data - VnfInitialConfigPrimitiveReader documented input data
331 InitialConfigReadError: VNF input data was malformed
333 if self
.INITIAL_CONFIG_PRIMITIVE
in input_data
:
334 vnf_input_data
= input_data
[self
.INITIAL_CONFIG_PRIMITIVE
]
336 reader
= VnfInitialConfigPrimitiveReader(vnf_input_data
)
337 for prim
in reader
.primitives
:
338 vnfd_init_cfg_prim_msg
.append(prim
)
340 def merge_vnfd_config(self
, vnfd
, input_data
):
341 for config_primitive
in vnfd
.vnf_configuration
.config_primitive
:
343 cfg
= input_data
[self
.SERVICE_PRIMITIVE
][config_primitive
.name
]
348 config_primitive
.parameter
,
352 class ConfigStore(object):
353 """Convenience class that fetches all the instance related data from the
354 $RIFT_VAR_ROOT/launchpad/libs directory.
357 def __init__(self
, log
):
363 self
.converter
= ConfigPrimitiveConvertor()
365 def merge_vnfd_config(self
,project_name
, nsd_id
, vnfd
, member_vnf_index
):
366 """Merges the vnfd config from the config directory.
369 nsd_id (str): Id of the NSD object
370 vnfd_msg : VNFD pb message containing the VNFD id and
371 the member index ref.
373 nsd_archive
= os
.path
.join(
374 os
.getenv('RIFT_VAR_ROOT'),
375 "launchpad/packages/vnfd/",
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
, project_name
):
408 nsd_archive
= os
.path
.join(
409 os
.getenv('RIFT_VAR_ROOT'),
410 "launchpad/packages/nsd/",
415 self
._log
.info("Looking for config from the archive {}".format(nsd_archive
))
417 if not os
.path
.exists(nsd_archive
):
420 config_file
= os
.path
.join(nsd_archive
,
421 "{}.yaml".format(nsd
.id))
422 if not os
.path
.exists(config_file
):
423 self
._log
.info("Could not find NS config in archive: %s", config_file
)
426 input_data
= self
.read_from_file(config_file
)
427 self
._log
.info("Loaded NS config file {}: {}".format(config_file
, input_data
))
429 self
.converter
.merge_nsd_config(nsd
, input_data
)
431 self
.converter
.merge_nsd_initial_config(nsd
, input_data
)