blob: dbfd2113e1cb0d9dad35b4f19dcf2fec8f498f92 [file] [log] [blame]
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +03001#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
Dennis Dmitriev6bd44252017-06-22 17:33:40 +03004import copy
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +03005import hashlib
6import os
7import re
8import tarfile
9
10import urllib2
11import yaml
12
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030013
Dennis Dmitriev6bd44252017-06-22 17:33:40 +030014def walkfiles(topdir, verbose=False):
15 walker = os.walk(topdir)
16 opener = open
17 prefix = ''
18 isdir = os.path.isdir(topdir)
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030019
20 if isdir:
21 for dirName, subdirList, fileList in walker:
22 for filename in fileList:
23 filepath = os.path.join(dirName,filename)
24 if verbose:
25 print (prefix + filepath)
26 with OpenFile(filepath, opener) as log:
27 yield (log)
28 else:
29 if verbose:
30 print (topdir)
31 with OpenFile(topdir, opener) as log:
32 yield (log)
33
34
35def yaml_read(yaml_file):
36 if os.path.isfile(yaml_file):
37 with open(yaml_file, 'r') as f:
38 return yaml.load(f)
39 else:
40 print("\'{}\' is not a file!".format(yaml_file))
41
42
43class OpenFile(object):
44
45 fname = None
46 opener = None
47 readlines = None
48 fobj = None
49
50 def __init__(self, fname, opener):
51 self.fname = fname
52 self.opener = opener
53
54 def get_parser(self):
55 parsers = {'/lastlog': self.fake_parser,
56 '/wtmp': self.fake_parser,
57 '/btmp': self.fake_parser,
58 '/atop.log': self.fake_parser,
59 '/atop_': self.fake_parser,
60 '/atop_current': self.fake_parser,
61 '/supervisord.log': self.docker_parser,
62 '.gz': self.gz_parser,
63 '.bz2': self.gz_parser,
64 }
65 for w in parsers.keys():
66 if w in self.fname:
67 self.readlines = parsers[w]
68 return
69 try:
70 self.fobj = self.opener(self.fname, 'r')
71 self.readlines = self.plaintext_parser
72 except IOError as e:
73 print("Error opening file {0}: {1}".format(self.fname, e))
74 if self.fobj:
75 self.fobj.close()
76 self.fobj = None
77 self.readlines = self.fake_parser
78
79 def plaintext_parser(self):
80 try:
81 for s in self.fobj.readlines():
82 yield s
83 except IOError as e:
84 print("Error reading file {0}: {1}".format(self.fname, e))
85
86 def fake_parser(self):
87 yield ''
88
89 def docker_parser(self):
90 yield ''
91
92 def gz_parser(self):
93 yield ''
94
95 def bz2_parser(self):
96 yield ''
97
98 def __enter__(self):
99 self.get_parser()
100 return self
101
102 def __exit__(self, x, y, z):
103 if self.fobj:
104 self.fobj.close()
105
106
107def get_nested_key(data, path=None):
108 if type(path) is not list:
109 raise("Use 'list' object with key names for 'path'")
110 for key in path:
111 value = data.get(key, None)
112 if value:
113 data = value
114 else:
115 return None
116 return data
117
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300118
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300119def remove_nested_key(data, path=None):
120 if type(path) is not list:
121 raise("Use 'list' object with key names for 'path'")
122
123 # Remove the value from the specified key
124 val = get_nested_key(data, path[:-1])
125 val[path[-1]] = None
126
127 # Clear parent keys if empty
128 while path:
129 val = get_nested_key(data, path)
130 if val:
131 # Non-empty value, nothing to do
132 return
133 else:
134 get_nested_key(data, path[:-1]).pop(path[-1])
135 path = path[:-1]
136
137
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300138def get_all_reclass_params(paths, verbose=False):
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300139 """Return dict with all used values for each param"""
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300140 _params = dict()
141 for path in paths:
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300142 for log in walkfiles(path, verbose):
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300143 if log.fname.endswith('.yml'):
144 model = yaml_read(log.fname)
145 if model is not None:
146 # Collect all params from the models
147 _param = get_nested_key(model, ['parameters', '_param'])
148 if _param:
149 for key, val in _param.items():
150 if key in _params:
Dennis Dmitrievefaa1352017-06-19 12:56:11 +0300151 # Keep list values sorted
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300152 _params[key].append(val)
Dennis Dmitrievefaa1352017-06-19 12:56:11 +0300153 _params[key] = sorted(_params[key])
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300154 else:
155 _params[key] = [val]
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300156 return _params
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300157
158
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300159def remove_reclass_parameter(paths, key,
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300160 verbose=False,
161 pretend=False):
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300162 """Removes specified key from parameters from all reclass models
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300163
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300164 :param key: string with point-separated nested objects, for
165 example: parameters.linux.network.interface
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300166 :rtype dict: { 'file path': {nested_key}, ...}
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300167 """
168 remove_key = key.split('.')
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300169 found_keys = {}
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300170
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300171 for path in paths:
172 for fyml in walkfiles(path, verbose=verbose):
173 if fyml.fname.endswith('.yml'):
174 model = yaml_read(fyml.fname)
175 if model is not None:
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300176
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300177 # Clear linux.network.interfaces
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300178 nested_key = get_nested_key(model, remove_key)
179 if nested_key:
180 found_keys[fyml.fname] = copy.deepcopy(nested_key)
181 if pretend:
182 print("\nFound {0} in {1}".format('.'.join(remove_key),
183 fyml.fname))
184 print(yaml.dump(nested_key, default_flow_style=False))
185 else:
186 print("\nRemoving {0} from {1}".format('.'.join(remove_key),
187 fyml.fname))
188 print(yaml.dump(nested_key, default_flow_style=False))
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300189
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300190 remove_nested_key(model, remove_key)
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300191
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300192 with open(fyml.fname, 'w') as f:
193 f.write(
194 yaml.dump(
195 model, default_flow_style=False
196 )
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300197 )
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300198 return found_keys