from __future__ import print_function
try:
from configparser import ConfigParser, NoOptionError, NoSectionError
except ImportError:
from ConfigParser import ConfigParser, NoOptionError, NoSectionError
import os
import sys
CFG_SECTION_TASK_DEFAULT = 'task.default'
CFG_SECTION_TASK_INFO = 'task.info'
CFG_SECTION_NODESET = 'nodeset'
CFG_SECTION_ENGINE = 'engine'
def _task_print_debug(task, line):
print(line)
def _load_workerclass(workername):
try:
modname = "ClusterShell.Worker.%s" % workername.capitalize()
_import_module(modname)
except ImportError:
modname = workername
_import_module(modname)
return sys.modules[modname].WORKER_CLASS
def _import_module(modname):
if modname.lower() not in [mod.lower() for mod in list(sys.modules)]:
__import__(modname)
def _local_workerclass(defaults):
return _load_workerclass(defaults.local_workername)
def _distant_workerclass(defaults):
return _load_workerclass(defaults.distant_workername)
def config_paths(config_name):
paths = [os.path.join('/etc/clustershell', config_name), os.path.expanduser('~/.local/etc/clustershell/%s' % config_name),
os.path.join(sys.prefix, 'etc/clustershell', config_name),
os.path.join(os.environ.get('XDG_CONFIG_HOME',
os.path.expanduser('~/.config')),
'clustershell', config_name)]
if 'CLUSTERSHELL_CFGDIR' in os.environ:
paths.append(os.path.join(os.environ['CLUSTERSHELL_CFGDIR'],
config_name))
return paths
def _converter_integer_tuple(value):
return tuple(int(x) for x in value.split(',') if x.strip())
def _parser_get_integer_tuple(parser, section, option, **kwargs):
return _converter_integer_tuple(
ConfigParser.get(parser, section, option, **kwargs))
class Defaults(object):
_TASK_DEFAULT = {"stderr" : False,
"stdin" : True,
"stdout_msgtree" : True,
"stderr_msgtree" : True,
"engine" : 'auto',
"port_qlimit" : 100, "auto_tree" : True,
"local_workername" : 'exec',
"distant_workername" : 'ssh'}
_TASK_DEFAULT_CONVERTERS = {"stderr" : ConfigParser.getboolean,
"stdin" : ConfigParser.getboolean,
"stdout_msgtree" : ConfigParser.getboolean,
"stderr_msgtree" : ConfigParser.getboolean,
"engine" : ConfigParser.get,
"port_qlimit" : ConfigParser.getint, "auto_tree" : ConfigParser.getboolean,
"local_workername" : ConfigParser.get,
"distant_workername" : ConfigParser.get}
_TASK_INFO = {"debug" : False,
"print_debug" : _task_print_debug,
"fanout" : 64,
"grooming_delay" : 0.25,
"connect_timeout" : 10,
"command_timeout" : 0}
_TASK_INFO_CONVERTERS = {"debug" : ConfigParser.getboolean,
"fanout" : ConfigParser.getint,
"grooming_delay" : ConfigParser.getfloat,
"connect_timeout" : ConfigParser.getfloat,
"command_timeout" : ConfigParser.getfloat}
_TASK_INFO_PKEYS_BL = ['engine', 'print_debug']
_NODESET = {"fold_axis" : ()}
_NODESET_CONVERTERS = {"fold_axis" : _parser_get_integer_tuple}
_ENGINE = {"port_qlimit" : 100}
_ENGINE_CONVERTERS = {"port_qlimit" : ConfigParser.getint}
def __init__(self, filenames):
self._task_default = self._TASK_DEFAULT.copy()
self._task_info = self._TASK_INFO.copy()
self._task_info_pkeys_bl = list(self._TASK_INFO_PKEYS_BL)
self._nodeset = self._NODESET.copy()
self._engine = self._ENGINE.copy()
config = ConfigParser()
parsed = config.read(filenames)
if parsed:
self._parse_config(config)
def _parse_config(self, config):
for key, conv in self._TASK_DEFAULT_CONVERTERS.items():
try:
self._task_default[key] = conv(config, CFG_SECTION_TASK_DEFAULT,
key)
except (NoSectionError, NoOptionError):
pass
for key, conv in self._TASK_INFO_CONVERTERS.items():
try:
self._task_info[key] = conv(config, CFG_SECTION_TASK_INFO, key)
except (NoSectionError, NoOptionError):
pass
for key, conv in self._NODESET_CONVERTERS.items():
try:
self._nodeset[key] = conv(config, CFG_SECTION_NODESET, key)
except (NoSectionError, NoOptionError):
pass
for key, conv in self._ENGINE_CONVERTERS.items():
try:
self._engine[key] = conv(config, CFG_SECTION_ENGINE, key)
except (NoSectionError, NoOptionError):
pass
def __getattr__(self, name):
if name == 'port_qlimit':
if self._engine[name] == self._ENGINE[name]:
return self._task_default[name]
if name in self._engine:
return self._engine[name]
elif name in self._task_default:
return self._task_default[name]
elif name in self._task_info:
return self._task_info[name]
elif name in self._nodeset:
return self._nodeset[name]
raise AttributeError(name)
def __setattr__(self, name, value):
if name in ('_task_default', '_task_info', '_task_info_pkeys_bl',
'_nodeset', '_engine'):
object.__setattr__(self, name, value)
elif name in self._engine:
self._engine[name] = value
elif name in self._task_default:
self._task_default[name] = value
elif name in self._task_info:
self._task_info[name] = value
elif name in self._nodeset:
self._nodeset[name] = value
else:
raise AttributeError(name)
DEFAULTS = Defaults(config_paths('defaults.conf'))