Fix for KDT node disappearance
One node went for a walk and disappeared. This change
brings it back.
PROD-26064
Change-Id: I67845af1f23f566acf86f9db0a18b2f971d2fc73
diff --git a/reclass/nodegenerator.py b/reclass/nodegenerator.py
index bb21c48..43c451d 100644
--- a/reclass/nodegenerator.py
+++ b/reclass/nodegenerator.py
@@ -31,6 +31,10 @@
_param_reference = re.compile('\$\{_param\:.*?\}')
_refernce_name = re.compile('\$\{_param\:(.*?)\}')
_iprange = re.compile('<<(.*?)>>')
+NODEF = 'NOTADEFINITION'
+CTRAIT = ['storage.system', 'cluster.']
+STRAIT = 'system/reclass/storage'
+ITRAIT = 'infra/init.yml'
def get_references(string):
@@ -43,6 +47,27 @@
return re.findall(_refernce_name, string)
+def contains(x, *sub):
+ return any(x.find(s) != -1 for s in sub)
+
+
+def get_params(data):
+ return data.get('parameters', {}).get('_param', {})
+
+
+def get_nodes(data):
+ return data.get('parameters', {}).get('reclass', {}).get(
+ 'storage', {}).get('node', {})
+
+
+def get_cls(data):
+ return data.get('classes', [])
+
+
+def get_system(data):
+ return data.get("parameters", {}).get("linux", {}).get("system", {})
+
+
def has_subst(value):
"""Checks if an element has slot for substitution."""
# NOTE: the code does not address possible nested references so far since
@@ -105,9 +130,7 @@
# will be used till more statistics is collected and a generic
# solution is created.
if key == 'classes':
- for el in value:
- if 'gateway' in el:
- x[key].extend(value)
+ [x[key].extend(value) for el in value if 'gateway' in el]
continue
if isinstance(x[key], dict) and isinstance(value, dict):
update_dict(x[key], value)
@@ -116,10 +139,8 @@
def get_substitution_parameters(source):
- result = {}
- exps = [x.get('parameters', {}).get('_param', {}) for x in source]
- for expansion in exps:
- update_dict(result, expansion)
+ exps, result = [get_params(x) for x in source], {}
+ [update_dict(result, e) for e in exps]
return result
external = {}
@@ -130,12 +151,9 @@
for fname in [x for x in files if x.endswith('yml')]:
config = os.path.join(rootdir, fname)
if fname == 'init.yml':
- if config.find("infra/init.yml") != -1:
+ if contains(config, ITRAIT):
with open(config, 'r') as f:
- ddd = yaml.load(f)
- external.update(ddd.get("parameters", {}).
- get("linux", {}).
- get("system", {}))
+ external.update(get_system(yaml.load(f)))
configs_to_process.append(config)
# NOTE: this is a special case left here for the time being.
elif fname == 'nodes.yml': # TODO: refactor it.
@@ -145,7 +163,7 @@
data = yaml.load(f)
if data is None:
continue
- if data.get('parameters', {}).get('_param') is not None:
+ if get_params(data):
configs_to_process.append(config)
for config in configs_to_process:
with open(config, 'r') as f:
@@ -160,22 +178,27 @@
fn = os.path.join(basename, x.replace('.', '/') + '.yml')
return fn if os.path.isfile(fn) else os.path.join(fn[:-4], 'init.yml')
- out, storage_classnames, cluster_cn = collections.defaultdict(dict), [], []
- for cfg in cfgs:
- storage_classnames.extend(x for x in cfg.get('classes', [])
- if ((x.find('storage.system') != -1)
- or x.find('cluster.') != -1))
- for x in map(fixname, storage_classnames):
+ def innerread(x, params, content):
with open(x, 'r') as f:
data = yaml.load(f)
- if params is None:
- params = {}
- if data is None:
- data = {}
- update_dict(params, data.get('parameters', {}).get('_param', {}), True)
- node_content = (data.get('parameters', {}).get('reclass', {})
- .get('storage', {}).get('node', {}))
+ params = {} if params is None else params
+ data = {} if data is None else data
+ update_dict(params, get_params(data), True)
+ update_dict(content, get_nodes(data), True)
+ depends_on = get_cls(data)
+ # TODO: this works around single (so far) issue with structured
+ # reference in system/reclass/storage.
+ if depends_on and contains(x, STRAIT):
+ for klass in depends_on:
+ innerread(fixname(klass), params, content)
+ return data
+ out, storage_cnames, cluster_cn = collections.defaultdict(dict), [], []
+ for cfg in cfgs:
+ storage_cnames.extend(x for x in get_cls(cfg) if contains(x, *CTRAIT))
+ for x in map(fixname, storage_cnames):
+ node_content = {}
+ data = innerread(x, params, node_content)
for nodename, nodecontent in node_content.iteritems():
if out[nodename].get('src') is not None:
out[nodename]['src'].append(x)
@@ -192,13 +215,12 @@
def dump_to_files(content, dest):
for res in content:
- tt = ".".join([res.get('name', 'NOTADEFINITION'),
- res.get('domain','NOTADEFINITION'), 'yml'])
- if tt.find('NOTADEFINITION') !=-1:
+ tt = ".".join([res.get('name', NODEF), res.get('domain',NODEF), 'yml'])
+ if contains(tt, NODEF):
continue
systemdesc = UnsortableDict()
- systemdesc['name'] = res.get('name', 'FOO')
- systemdesc['domain'] = res.get('domain', 'BAR')
+ systemdesc['name'] = res.get('name')
+ systemdesc['domain'] = res.get('domain')
# NOTE: this should stay here until cfg01 definition stabilizes.
if systemdesc['name'] != 'cfg01':
systemdesc['cluster'] = res.get('cluster', 'default')