Merge "Acquire NSB specific data from Heat."
[yardstick.git] / yardstick / network_services / vnf_generic / vnfdgen.py
1 # Copyright (c) 2016-2017 Intel Corporation
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 implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """ Generic file to map and build vnf discriptor """
15
16 from __future__ import absolute_import
17 import collections
18
19 import jinja2
20 import yaml
21
22
23 def render(vnf_model, **kwargs):
24     """Render jinja2 VNF template
25
26     :param vnf_model: string that contains template
27     :param kwargs: Dict with template arguments
28     :returns:rendered template str
29     """
30
31     return jinja2.Template(vnf_model).render(**kwargs)
32
33
34 def generate_vnfd(vnf_model, node):
35     """
36
37     :param vnf_model: VNF definition template, e.g. tg_ping_tpl.yaml
38     :param node: node configuration taken from pod.yaml
39     :return: Complete VNF Descriptor that will be taken
40              as input for GenericVNF.__init__
41     """
42     # get is unused as global method inside template
43     node["get"] = get
44     # Set Node details to default if not defined in pod file
45     # we CANNOT use TaskTemplate.render because it does not allow
46     # for missing variables, we need to allow password for key_filename
47     # to be undefined
48     rendered_vnfd = render(vnf_model, **node)
49     # This is done to get rid of issues with serializing node
50     del node["get"]
51     filled_vnfd = yaml.load(rendered_vnfd)
52     return filled_vnfd
53
54
55 def dict_key_flatten(data):
56     """ Convert nested dict structure to dotted key
57         (e.g. {"a":{"b":1}} -> {"a.b":1}
58
59     :param data: nested dictionary
60     :return: flat dicrionary
61     """
62     next_data = {}
63
64     # check for non-string iterables
65     if not any((isinstance(v, collections.Iterable) and not isinstance(v, str))
66                for v in data.values()):
67         return data
68
69     for key, val in data.items():
70         if isinstance(val, collections.Mapping):
71             for n_k, n_v in val.items():
72                 next_data["%s.%s" % (key, n_k)] = n_v
73         elif isinstance(val, collections.Iterable) and not isinstance(val,
74                                                                       str):
75             for index, item in enumerate(val):
76                 next_data["%s%d" % (key, index)] = item
77         else:
78             next_data[key] = val
79
80     return dict_key_flatten(next_data)
81
82
83 def get(obj, key, *args):
84     """ Get template key from dictionary, get default value or raise an exception
85     """
86     data = dict_key_flatten(obj)
87     return data.get(key, *args)