diff options
author | Ross Brattain <ross.b.brattain@intel.com> | 2017-08-07 14:32:45 -0700 |
---|---|---|
committer | Ross Brattain <ross.b.brattain@intel.com> | 2017-08-15 20:36:32 -0700 |
commit | c3d309865bb57e2aba2033d3bbe1c16adca4f0ba (patch) | |
tree | bebe3ecb46b1ac7983d2542867058c5420a06ab1 /yardstick/network_services/vnf_generic | |
parent | 7d5cc542a9bfa35cba6d2b681e0cf5f90bc77d40 (diff) |
YAML fixes
There are multiple issues wiht YAML loading.
1. Jinja2 renders None values as a string 'None'. This is not valid YAML
we need to render None values to '~' or 'null' which is the native YAML
None value.
2. Jinja2 renders dict and lists that contain unicode with
u'foo' values. This is not value YAML syntax.
Because we are serializing dict and lists into YAML, we
need to encode them as valid YAML. We can override Jinja2 finalize to
use yaml.dump to dump inline YAML.
We use yaml.safe_dump(elem, default_flow_style=True).replace('\n', '')
to generate valid single-line YAML dict and list values.
But this problem highlights the general difficulties with templating and
loading files.
We could avoid this Python->Jinja2->YAML->Python issue by directly
injecting the list or dict after the YAML is loaded.
I'm not sure of the real utility of these templates.
3. On Python 2 YAML loader is rendering all strings
as unicode. This does not work for Trex because Trex is broken
and badly coded. Trex does type checking against str() which
is different for Python 2 and Python 3.
The default YAML loader will return native string types, str() or unicode()
for Python 2 and Python 3 respectively.
The bad Trex codes is in convert_val:
https://github.com/cisco-system-traffic-generator/trex-core/blob/master/scripts/automation/trex_control_plane/stl/trex_stl_lib/trex_stl_packet_builder_scapy.py#L674
def convert_val (val):
if is_integer(val):
return val
if type(val) == str:
return ipv4_str_to_num (is_valid_ipv4(val))
raise CTRexPacketBuildException(-11,("init val invalid %s ") % val );
This code is doing type(val) == str. This is bad and broken.
We can't fix Trex, so we have to render all strings as native str() types
The bug here was that the Heat template loader template_format.py
was overriding the global YAML loader to always return unicode.
We don't want this global override.
To fix this we have to use local subclasses of the yaml.SafeLoader
class.
But in order to dynamically subclass from CSafeLoader or SafeLoader
we have to use the type() builtin to define a new class at runtime.
Once we have new classes defined, we can safely isolate different
YAML constructors and return unicode or not depending on the case.
To be consistent we implement a new yaml_loader.py module to centralize
all non-Heat template yaml loading to ensure correct uncode/str
conversion
Change-Id: Iebf9cf78fbda390977c390436b0869e7bbf503eb
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
Signed-off-by: Deepak S <deepak.s@linux.intel.com>
Signed-off-by: Ross Brattain <ross.b.brattain@intel.com>
Diffstat (limited to 'yardstick/network_services/vnf_generic')
-rw-r--r-- | yardstick/network_services/vnf_generic/vnfdgen.py | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/yardstick/network_services/vnf_generic/vnfdgen.py b/yardstick/network_services/vnf_generic/vnfdgen.py index 474403dee..f42635006 100644 --- a/yardstick/network_services/vnf_generic/vnfdgen.py +++ b/yardstick/network_services/vnf_generic/vnfdgen.py @@ -14,26 +14,29 @@ """ Generic file to map and build vnf discriptor """ from __future__ import absolute_import + from functools import reduce import jinja2 import logging -import yaml +from yardstick.common.task_template import finalize_for_yaml from yardstick.common.utils import try_int +from yardstick.common.yaml_loader import yaml_load LOG = logging.getLogger(__name__) def render(vnf_model, **kwargs): """Render jinja2 VNF template + Do not check for missing arguments :param vnf_model: string that contains template :param kwargs: Dict with template arguments :returns:rendered template str """ - return jinja2.Template(vnf_model).render(**kwargs) + return jinja2.Template(vnf_model, finalize=finalize_for_yaml).render(**kwargs) def generate_vnfd(vnf_model, node): @@ -54,7 +57,7 @@ def generate_vnfd(vnf_model, node): rendered_vnfd = render(vnf_model, **node) # This is done to get rid of issues with serializing node del node["get"] - filled_vnfd = yaml.safe_load(rendered_vnfd) + filled_vnfd = yaml_load(rendered_vnfd) return filled_vnfd |