blob: 024b3cf065dae2313bbffeb0f77391502951da52 [file] [log] [blame]
#!/usr/bin/python
# -*- coding: utf-8 -*-
import hashlib
import os
import re
import tarfile
import urllib2
import yaml
from reclass_tools.helpers import ssh_client
def walkfiles(topdir, identity_files=None, verbose=False):
if ":" in topdir:
host, path = topdir.split(":")
private_keys = ssh_client.get_private_keys(os.environ.get("HOME"), identity_files)
if "@" in host:
username, host = host.split("@")
else:
username = os.environ.get("USER")
remote = ssh_client.SSHClient(
host, username=username, private_keys=private_keys)
walker = remote.walk(path)
opener = remote.open
prefix = remote.host + ":"
isdir = remote.isdir(path, follow_symlink=True)
else:
walker = os.walk(topdir)
opener = open
prefix = ''
isdir = os.path.isdir(topdir)
if isdir:
for dirName, subdirList, fileList in walker:
for filename in fileList:
filepath = os.path.join(dirName,filename)
if verbose:
print (prefix + filepath)
with OpenFile(filepath, opener) as log:
yield (log)
else:
if verbose:
print (topdir)
with OpenFile(topdir, opener) as log:
yield (log)
def yaml_read(yaml_file):
if os.path.isfile(yaml_file):
with open(yaml_file, 'r') as f:
return yaml.load(f)
else:
print("\'{}\' is not a file!".format(yaml_file))
class OpenFile(object):
fname = None
opener = None
readlines = None
fobj = None
def __init__(self, fname, opener):
self.fname = fname
self.opener = opener
def get_parser(self):
parsers = {'/lastlog': self.fake_parser,
'/wtmp': self.fake_parser,
'/btmp': self.fake_parser,
'/atop.log': self.fake_parser,
'/atop_': self.fake_parser,
'/atop_current': self.fake_parser,
'/supervisord.log': self.docker_parser,
'.gz': self.gz_parser,
'.bz2': self.gz_parser,
}
for w in parsers.keys():
if w in self.fname:
self.readlines = parsers[w]
return
try:
self.fobj = self.opener(self.fname, 'r')
self.readlines = self.plaintext_parser
except IOError as e:
print("Error opening file {0}: {1}".format(self.fname, e))
if self.fobj:
self.fobj.close()
self.fobj = None
self.readlines = self.fake_parser
def plaintext_parser(self):
try:
for s in self.fobj.readlines():
yield s
except IOError as e:
print("Error reading file {0}: {1}".format(self.fname, e))
def fake_parser(self):
yield ''
def docker_parser(self):
yield ''
def gz_parser(self):
yield ''
def bz2_parser(self):
yield ''
def __enter__(self):
self.get_parser()
return self
def __exit__(self, x, y, z):
if self.fobj:
self.fobj.close()
def get_nested_key(data, path=None):
if type(path) is not list:
raise("Use 'list' object with key names for 'path'")
for key in path:
value = data.get(key, None)
if value:
data = value
else:
return None
return data
def remove_nested_key(data, path=None):
if type(path) is not list:
raise("Use 'list' object with key names for 'path'")
# Remove the value from the specified key
val = get_nested_key(data, path[:-1])
val[path[-1]] = None
# Clear parent keys if empty
while path:
val = get_nested_key(data, path)
if val:
# Non-empty value, nothing to do
return
else:
get_nested_key(data, path[:-1]).pop(path[-1])
path = path[:-1]
def get_all_reclass_params(paths, identity_files=None, verbose=False):
"""Return dict with all used values for each param"""
_params = dict()
for path in paths:
for log in walkfiles(path, identity_files, verbose):
if log.fname.endswith('.yml'):
model = yaml_read(log.fname)
if model is not None:
# Collect all params from the models
_param = get_nested_key(model, ['parameters', '_param'])
if _param:
for key, val in _param.items():
if key in _params:
_params[key].append(val)
else:
_params[key] = [val]
return _params
def remove_reclass_parameter(paths, key,
identity_files=None, verbose=False):
"""Removes specified key from parameters from all reclass models
:param key: string with point-separated nested objects, for
example: parameters.linux.network.interface
"""
remove_key = key.split('.')
for path in paths:
for fyml in walkfiles(path, verbose=verbose):
if fyml.fname.endswith('.yml'):
model = yaml_read(fyml.fname)
if model is not None:
# Clear linux.network.interfaces
interfaces = get_nested_key(model, remove_key)
if interfaces:
print(fyml.fname)
print(interfaces.keys())
remove_nested_key(model, remove_key)
print(model)
with open(fyml.fname, 'w') as f:
f.write(
yaml.dump(
model, default_flow_style=False
)
)