NFVBENCH-11 Cannot override extra_specs in flavor using -c
[nfvbench.git] / nfvbench / config.py
1 # Copyright 2016 Cisco Systems, Inc.  All rights reserved.
2 #
3 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
4 #    not use this file except in compliance with the License. You may obtain
5 #    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, WITHOUT
11 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 #    License for the specific language governing permissions and limitations
13 #    under the License.
14 #
15
16 from attrdict import AttrDict
17 from log import LOG
18 import yaml
19
20
21 def config_load(file_name, from_cfg=None, whitelist_keys=[]):
22     """Load a yaml file into a config dict, merge with from_cfg if not None
23     The config file content taking precedence in case of duplicate
24     """
25     try:
26         with open(file_name) as fileobj:
27             cfg = AttrDict(yaml.safe_load(fileobj))
28     except IOError:
29         raise Exception("Configuration file at '{}' was not found. Please use correct path "
30                         "and verify it is visible to container if you run nfvbench in container."
31                         .format(file_name))
32
33     if from_cfg:
34         _validate_config(cfg, from_cfg, whitelist_keys)
35         cfg = from_cfg + cfg
36
37     return cfg
38
39
40 def config_loads(cfg_text, from_cfg=None, whitelist_keys=[]):
41     """Same as config_load but load from a string
42     """
43     try:
44         cfg = AttrDict(yaml.load(cfg_text))
45     except TypeError:
46         # empty string
47         cfg = AttrDict()
48     if from_cfg:
49         _validate_config(cfg, from_cfg, whitelist_keys)
50         return from_cfg + cfg
51     return cfg
52
53 def _validate_config(subset, superset, whitelist_keys):
54     def get_err_config(subset, superset):
55         result = {}
56         for k, v in subset.items():
57             if k not in whitelist_keys:
58                 if k not in superset:
59                     result.update({k: v})
60                 elif v is not None and superset[k] is not None:
61                     if not isinstance(v, type(superset[k])):
62                         result.update({k: v})
63                         continue
64                 if isinstance(v, dict):
65                     res = get_err_config(v, superset[k])
66                     if res:
67                         result.update({k: res})
68         if not result:
69             return None
70         return result
71
72     err_cfg = get_err_config(subset, superset)
73     if err_cfg:
74         err_msg = 'The provided configuration has unknown options or values with invalid type: '\
75                   + str(err_cfg)
76         LOG.error(err_msg)
77         raise Exception(err_msg)