NFVBENCH-11 Cannot override extra_specs in flavor using -c 23/40423/1 1.0.3
authorahothan <ahothan@cisco.com>
Mon, 28 Aug 2017 15:04:52 +0000 (08:04 -0700)
committerahothan <ahothan@cisco.com>
Mon, 28 Aug 2017 15:04:52 +0000 (08:04 -0700)
Add a whitelist for keys that can't be verified

Change-Id: I8d56cb850fb133eec0097ae80f6ee5f827e651c6
Signed-off-by: ahothan <ahothan@cisco.com>
nfvbench/config.py
nfvbench/nfvbench.py
test/test_nfvbench.py

index 915b42c..2ed726d 100644 (file)
@@ -18,7 +18,7 @@ from log import LOG
 import yaml
 
 
-def config_load(file_name, from_cfg=None):
+def config_load(file_name, from_cfg=None, whitelist_keys=[]):
     """Load a yaml file into a config dict, merge with from_cfg if not None
     The config file content taking precedence in case of duplicate
     """
@@ -31,13 +31,13 @@ def config_load(file_name, from_cfg=None):
                         .format(file_name))
 
     if from_cfg:
-        _validate_config(cfg, from_cfg)
+        _validate_config(cfg, from_cfg, whitelist_keys)
         cfg = from_cfg + cfg
 
     return cfg
 
 
-def config_loads(cfg_text, from_cfg=None):
+def config_loads(cfg_text, from_cfg=None, whitelist_keys=[]):
     """Same as config_load but load from a string
     """
     try:
@@ -46,30 +46,30 @@ def config_loads(cfg_text, from_cfg=None):
         # empty string
         cfg = AttrDict()
     if from_cfg:
-        _validate_config(cfg, from_cfg)
+        _validate_config(cfg, from_cfg, whitelist_keys)
         return from_cfg + cfg
     return cfg
 
+def _validate_config(subset, superset, whitelist_keys):
+    def get_err_config(subset, superset):
+        result = {}
+        for k, v in subset.items():
+            if k not in whitelist_keys:
+                if k not in superset:
+                    result.update({k: v})
+                elif v is not None and superset[k] is not None:
+                    if not isinstance(v, type(superset[k])):
+                        result.update({k: v})
+                        continue
+                if isinstance(v, dict):
+                    res = get_err_config(v, superset[k])
+                    if res:
+                        result.update({k: res})
+        if not result:
+            return None
+        return result
 
-def _get_err_config(subset, superset):
-    result = {}
-    for k, v in subset.items():
-        if k not in superset:
-            result.update({k: v})
-        elif v is not None and superset[k] is not None:
-            if not isinstance(v, type(superset[k])):
-                result.update({k: v})
-                continue
-        if isinstance(v, dict):
-            res = _get_err_config(v, superset[k])
-            if res:
-                result.update({k: res})
-    if not result:
-        return None
-    return result
-
-def _validate_config(subset, superset):
-    err_cfg = _get_err_config(subset, superset)
+    err_cfg = get_err_config(subset, superset)
     if err_cfg:
         err_msg = 'The provided configuration has unknown options or values with invalid type: '\
                   + str(err_cfg)
index e9594d5..b36d328 100644 (file)
@@ -461,15 +461,17 @@ def main():
 
         config.name = ''
         if opts.config:
+            # do not check extra_specs in flavor as it can contain any key/value pairs
+            whitelist_keys = ['extra_specs']
             # override default config options with start config at path parsed from CLI
             # check if it is an inline yaml/json config or a file name
             if os.path.isfile(opts.config):
                 LOG.info('Loading configuration file: ' + opts.config)
-                config = config_load(opts.config, config)
+                config = config_load(opts.config, config, whitelist_keys)
                 config.name = os.path.basename(opts.config)
             else:
                 LOG.info('Loading configuration string: ' + opts.config)
-                config = config_loads(opts.config, config)
+                config = config_loads(opts.config, config, whitelist_keys)
 
         # traffic profile override options
         override_custom_traffic(config, opts.frame_sizes, opts.unidir)
index 1d985b8..ff4625b 100644 (file)
@@ -673,7 +673,13 @@ def test_config():
             expected = fail_pair[0]
         assert expected in e_info.value.message
 
-
+    # whitelist keys
+    flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
+              'extra_specs': {'hw:cpu_policy': 'dedicated'}}}
+    new_flavor = {'flavor': {'vcpus': 2, 'ram': 8192, 'disk': 0,
+                  'extra_specs': {'hw:cpu_policy': 'dedicated', 'hw:numa_nodes': 2}}}
+    assert(config_loads("{'flavor': {'extra_specs': {'hw:numa_nodes': 2}}}", flavor,
+                        whitelist_keys=['alpha', 'extra_specs']) == new_flavor)
 
 def test_fluentd():
     logger = logging.getLogger('fluent-logger')