NSB update
[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 from functools import reduce
18
19 import jinja2
20 import logging
21 import yaml
22
23 from yardstick.common.utils import try_int
24
25 LOG = logging.getLogger(__name__)
26
27
28 def render(vnf_model, **kwargs):
29     """Render jinja2 VNF template
30
31     :param vnf_model: string that contains template
32     :param kwargs: Dict with template arguments
33     :returns:rendered template str
34     """
35
36     return jinja2.Template(vnf_model).render(**kwargs)
37
38
39 def generate_vnfd(vnf_model, node):
40     """
41
42     :param vnf_model: VNF definition template, e.g. tg_ping_tpl.yaml
43     :param node: node configuration taken from pod.yaml
44     :return: Complete VNF Descriptor that will be taken
45              as input for GenericVNF.__init__
46     """
47     # get is unused as global method inside template
48     # node["get"] = key_flatten_get
49     node["get"] = deepgetitem
50     # Set Node details to default if not defined in pod file
51     # we CANNOT use TaskTemplate.render because it does not allow
52     # for missing variables, we need to allow password for key_filename
53     # to be undefined
54     rendered_vnfd = render(vnf_model, **node)
55     # This is done to get rid of issues with serializing node
56     del node["get"]
57     filled_vnfd = yaml.safe_load(rendered_vnfd)
58     return filled_vnfd
59
60
61 # dict_flatten was causing recursion errors with Jinja2 so we removed and replaced
62 # which this function from stackoverflow that doesn't require generating entire dictionaries
63 # each time we query a key
64 def deepgetitem(obj, item, default=None):
65     """Steps through an item chain to get the ultimate value.
66
67     If ultimate value or path to value does not exist, does not raise
68     an exception and instead returns `fallback`.
69
70     Based on
71     https://stackoverflow.com/a/38623359
72     https://stackoverflow.com/users/1820042/donny-winston
73
74     add try_int to work with sequences
75
76     >>> d = {'snl_final': {'about': {'_icsd': {'icsd_id': 1, 'fr': [2, 3]}}}}
77     >>> deepgetitem(d, 'snl_final.about._icsd.icsd_id')
78     1
79     >>> deepgetitem(d, 'snl_final.about._sandbox.sbx_id')
80     >>>
81     >>> deepgetitem(d, 'snl_final.about._icsd.fr.1')
82     3
83     """
84     def getitem(obj, name):
85         # if integer then list index
86         name = try_int(name)
87         try:
88             return obj[name]
89         except (KeyError, TypeError, IndexError):
90             return default
91     return reduce(getitem, item.split('.'), obj)