450 lines
13 KiB
Python
450 lines
13 KiB
Python
"""
|
|
Fuzzbunch plugin base class
|
|
|
|
Wraps the truantchild Config class to provide easy access to setting and
|
|
getting parameters.
|
|
|
|
"""
|
|
import truantchild
|
|
import exception
|
|
import util
|
|
import edfmeta
|
|
|
|
|
|
__all__ = ["Plugin"]
|
|
|
|
|
|
"""
|
|
Decorators
|
|
|
|
"""
|
|
def setwrapper(f):
|
|
def wrap(*args, **kwargs):
|
|
try:
|
|
return f(*args, **kwargs)
|
|
except AttributeError:
|
|
raise exception.CmdErr, "Unknown parameter"
|
|
except (ValueError, TypeError, OverflowError):
|
|
raise exception.CmdErr, "Invalid value"
|
|
except (IOError, RuntimeError, ZeroDivisionError,
|
|
IndexError, SyntaxError, MemoryError) as err:
|
|
raise exception.CmdErr("TRCH internal : " + str(err))
|
|
|
|
return wrap
|
|
|
|
def resetwrapper(f):
|
|
def wrap(*args, **kwargs):
|
|
try:
|
|
return f(*args, **kwargs)
|
|
except AttributeError:
|
|
raise exception.CmdErr, "Unknown parameter"
|
|
except (IOError, RuntimeError, ZeroDivisionError,
|
|
IndexError, SyntaxError, MemoryError) as err:
|
|
raise exception.CmdErr("TRCH internal : " + str(err))
|
|
return wrap
|
|
|
|
def getwrapper(f):
|
|
def wrap(*args, **kwargs):
|
|
try:
|
|
return f(*args, **kwargs)
|
|
except AttributeError:
|
|
raise exception.CmdErr, "Unknown parameter"
|
|
return wrap
|
|
|
|
def safesetparameter(f):
|
|
"""save and restore old value if new is invalid"""
|
|
def wrap(self, name, value):
|
|
old = self.get(name)
|
|
f(self, name, value)
|
|
if not self.hasValidValue(name):
|
|
self._trch_set(name, old)
|
|
raise exception.CmdErr, "Invalid value for '%s' (%s)" % (name, value)
|
|
return wrap
|
|
|
|
def safesetchoice(f):
|
|
"""Set a choice (cannot be invalid setting) and update
|
|
[non-hidden] parameters lower in the tree."""
|
|
def wrap(self, name, value):
|
|
paramcache = self.cache_choiceparams(name)
|
|
old = self.get(name)
|
|
f(self, name, value)
|
|
if not self.hasValidValue(name):
|
|
# Restore to the old
|
|
self._trch_set(name, old)
|
|
raise exception.CmdErr, "Invalid value for %s (%s)" % (name, value)
|
|
# We want var matches, not var/val
|
|
for param in paramcache:
|
|
if param.name in util.iDict(self.cache_choiceparams(name)):
|
|
try:
|
|
if not self.getParameter(param.name).isHidden():
|
|
self.set(*param)
|
|
except (exception.CmdErr, AttributeError):
|
|
# XXX Is ignoring errors here a good idea?
|
|
pass
|
|
return wrap
|
|
|
|
"""
|
|
Plugin base class
|
|
|
|
"""
|
|
class Plugin(truantchild.Config):
|
|
def __init__(self, files, io):
|
|
import truantchild
|
|
from pytrch import TrchError as TruantchildError
|
|
try:
|
|
truantchild.Config.__init__(self, files)
|
|
self.param_order = edfmeta.parse_iparamorder(self.xmlInConfig)
|
|
self._curParams = self._inputParams
|
|
self._defaults = self.getParameters()
|
|
|
|
self.io = io
|
|
self.touchlist = []
|
|
self.redirection = {}
|
|
self.consolemode = util.CONSOLE_DEFAULT
|
|
self.lastsession = None
|
|
except AttributeError:
|
|
#print >>sys.stderr, "Plugin.__init__ failed to find an attribute - %s" % (str(e))
|
|
raise
|
|
except TruantchildError:
|
|
#print >>sys.stderr, "Plugin.__init__ failed to initialize Config - %s" % (str(e))
|
|
raise
|
|
|
|
"""
|
|
Parameter value set and get
|
|
|
|
"""
|
|
def set(self, name, value, globalvars={}):
|
|
if self.isParameter(name):
|
|
self.set_parameter(name, util.variable_replace(value, globalvars))
|
|
else:
|
|
self.set_choice(name, util.variable_replace(value, globalvars))
|
|
|
|
def get(self, name):
|
|
"""Get a specific parameter value"""
|
|
return self._trch_get(name)
|
|
|
|
@resetwrapper
|
|
def reset(self, name):
|
|
self._trch_reset(name)
|
|
|
|
@safesetparameter
|
|
def set_parameter(self, name, value):
|
|
"""Set a parameter to value"""
|
|
self._trch_set(name, value)
|
|
|
|
@safesetchoice
|
|
def set_choice(self, name, value):
|
|
"""Set a choice to a value."""
|
|
self._trch_set(name, value)
|
|
|
|
def cache_choiceparams(self, name):
|
|
"""Cache values, Ignore hidden"""
|
|
paramcache = []
|
|
choice = self._trch_findparamchoice(name)
|
|
if choice:
|
|
for param in choice.getParameterList():
|
|
if param.name == name:
|
|
continue
|
|
paramcache.append(param)
|
|
paramcache += self.cache_choiceparams(param.name)
|
|
return paramcache
|
|
|
|
"""
|
|
Individual Parameter Interface
|
|
|
|
"""
|
|
def getDescription(self, name):
|
|
"""Get the description of a parameter"""
|
|
return self._trch_getdescription(name)
|
|
|
|
def getType(self, name):
|
|
"""Get the type of a parameter"""
|
|
return self._trch_gettype(name)
|
|
|
|
def getFormat(self, name):
|
|
"""Get the format of a parameter"""
|
|
return self._trch_getformat(name)
|
|
|
|
def getAttributeList(self, name):
|
|
"""Get the attribute list of a parameter"""
|
|
return self._trch_getattributelist(name)
|
|
|
|
def getParameter(self, name):
|
|
"""Get the parameter struct"""
|
|
return self._trch_findoption(name)
|
|
|
|
def hasParameter(self, name):
|
|
if self.getParameter(name):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def isParamchoice(self, name):
|
|
return self._trch_isparamchoice(name)
|
|
|
|
def isParameter(self, name):
|
|
return self._trch_isparameter(name)
|
|
|
|
# Added to support fixing bug #2133
|
|
def isHiddenParameter(self, name):
|
|
"""Given a parameter name, is that parameter hidden?"""
|
|
param = self.getParameter(name)
|
|
if self.isParameter(name):
|
|
return param.isHidden()
|
|
return False
|
|
|
|
"""
|
|
Multiple parameters
|
|
|
|
"""
|
|
def getParameters(self, hidden=True):
|
|
"""Get the current parameter list"""
|
|
# Members of the plist array are dictionary items
|
|
plist = self._trch_getparameterlist()
|
|
if not hidden:
|
|
plist = [x for x in plist if not self.isHiddenParameter(x.name)]
|
|
|
|
if not self.param_order:
|
|
return plist
|
|
|
|
# Give them same order in which they appear in xml file
|
|
pdict = util.iDict(plist)
|
|
order = [ util.Param(pname, pdict.pop(pname) or "")
|
|
for pname in self.param_order
|
|
if pname in pdict ]
|
|
|
|
return order + list(pdict.items())
|
|
|
|
def iterPromptParameters(self):
|
|
|
|
# Take all the root level parameters first
|
|
rootparams = self._trch_getrootparameterlist()
|
|
for param in self.getParameters():
|
|
if self._trch_isparameter(param.name) and \
|
|
param in rootparams and \
|
|
not self.isHiddenParameter(param.name):
|
|
yield param
|
|
|
|
# Walk all choices. Need to take into account that setting a choice
|
|
# causes changes to everything below it.
|
|
usedchoices = []
|
|
done = False
|
|
while not done:
|
|
for param in self.getParameters():
|
|
if self._trch_isparamchoice(param.name) and \
|
|
param.name not in usedchoices and \
|
|
not self.isHiddenParameter(param.name):
|
|
usedchoices.append(param.name)
|
|
yield param
|
|
break
|
|
else:
|
|
done = True
|
|
usedchoices += util.iDict(rootparams).keys()
|
|
|
|
# Now all the choices are stable, we can walk all params that are under
|
|
# a choice which is anything that we haven't looked at yet
|
|
for param in self.getParameters():
|
|
if self._trch_isparameter(param.name) and \
|
|
param.name not in usedchoices and \
|
|
not self.isHiddenParameter(param.name):
|
|
yield param
|
|
|
|
def getOutputParameters(self):
|
|
"""Get the output parameter list"""
|
|
return self._trch_getoutputparameters()
|
|
|
|
def getDefaultParameters(self):
|
|
"""Return the defaults parameters"""
|
|
return self._defaults
|
|
|
|
def setParameters(self, params):
|
|
for param in self.iterPromptParameters():
|
|
if param in params.items():
|
|
try:
|
|
self.set(param.name, params[param.name])
|
|
except exception.CmdErr:
|
|
self.io.print_warning("Skipping %s - Bad value" % param.name)
|
|
else:
|
|
self.io.print_success("Set %s => %s" % (param.name, params[param.name]))
|
|
|
|
if self.redirection:
|
|
targetip = params.get('targetip', None)
|
|
targetport = params.get('targetport', None)
|
|
callbackip = params.get('callbackip', None)
|
|
|
|
redir = self.getRedirection()
|
|
if callbackip:
|
|
for r in redir['remote']:
|
|
self.set(r.listenaddr, callbackip)
|
|
if targetip:
|
|
for l in redir['local']:
|
|
# Only set this if we want the TargetIp
|
|
if l.listenaddr == 'TargetIp':
|
|
self.set(l.listenaddr, targetip)
|
|
|
|
"""
|
|
Parameter validity
|
|
|
|
"""
|
|
def hasValidValue(self, name):
|
|
"""Check if a parameter of the whole set has a valid value"""
|
|
return self._trch_hasvalidvalue(name)
|
|
|
|
def isValid(self, name=None):
|
|
"""Check if a parameter or the whole set is invalid"""
|
|
return self._trch_isvalid(name)
|
|
|
|
def getInvalid(self):
|
|
"""Get a list of all parameters with invalid values"""
|
|
# XXX - Should be smarter about choices
|
|
return [ (param.name, param.value, self.getDescription(param.name))
|
|
for param in self.getParameters()
|
|
if not self.isValid(param.name) ]
|
|
|
|
"""
|
|
Plugin execution
|
|
|
|
"""
|
|
def execute(self, session, mode):
|
|
"""Execute the plugin"""
|
|
pass
|
|
|
|
def validate(self):
|
|
"""Validate the plugin"""
|
|
return True
|
|
|
|
def getSessionDescription(self):
|
|
"""Extra information about a session"""
|
|
return ""
|
|
|
|
"""
|
|
Rendezvous
|
|
|
|
"""
|
|
def doRendezvous(self, value):
|
|
"""Do required actions to complete EDF Rendezvous"""
|
|
return False
|
|
|
|
def createsRendezvous(self):
|
|
for name,val in self._outputParams.getParameterList():
|
|
if "Socket" == self._outputParams.findOption(name).getType():
|
|
return True
|
|
return False
|
|
|
|
"""
|
|
Run Mode
|
|
|
|
"""
|
|
def initConsoleMode(self):
|
|
self.consolemode = util.CONSOLE_DEFAULT
|
|
|
|
def getConsoleMode(self):
|
|
return self.consolemode
|
|
|
|
"""
|
|
Redirection
|
|
|
|
"""
|
|
def initRedirection(self):
|
|
self.redirection = {}
|
|
|
|
def getRedirection(self):
|
|
return self.redirection
|
|
|
|
def canRedirect(self):
|
|
if not self.redirection:
|
|
return False
|
|
if not self.redirection['remote'] and not self.redirection['local']:
|
|
return False
|
|
return True
|
|
|
|
def canDeploy(self):
|
|
return False
|
|
|
|
"""
|
|
Touches
|
|
|
|
"""
|
|
def initTouches(self):
|
|
self.touchlist = []
|
|
|
|
def getTouchList(self):
|
|
return self.touchlist
|
|
|
|
def get_touch(self, index):
|
|
try:
|
|
return self.getTouchList()[index]
|
|
except IndexError:
|
|
raise exception.CmdErr, "Bad touch"
|
|
|
|
"""
|
|
Truantchild abstractions
|
|
"""
|
|
@setwrapper
|
|
def _trch_set(self, name, value):
|
|
"""Set a parameter to a value"""
|
|
self._curParams.set(name, value)
|
|
|
|
@getwrapper
|
|
def _trch_get(self, name):
|
|
"""Return the value of a parameter"""
|
|
return self._curParams.get(name)
|
|
|
|
def _trch_reset(self, name):
|
|
return self._curParams.reset(name)
|
|
|
|
@getwrapper
|
|
def _trch_getdescription(self, name):
|
|
return self._curParams.getDescription(name)
|
|
|
|
@getwrapper
|
|
def _trch_gettype(self, name):
|
|
return self._curParams.getType(name)
|
|
|
|
@getwrapper
|
|
def _trch_getformat(self, name):
|
|
return self._curParams.getFormat(name)
|
|
|
|
@getwrapper
|
|
def _trch_getattributelist(self, name):
|
|
return self._curParams.getAttributeList(name)
|
|
|
|
def _trch_findoption(self, name):
|
|
return self._curParams.findOption(name)
|
|
|
|
def _trch_isparamchoice(self, name):
|
|
return self._curParams.isParamchoice(name)
|
|
|
|
def _trch_isparameter(self, name):
|
|
return self._curParams.isParameter(name)
|
|
|
|
def _trch_findparamchoice(self, name):
|
|
return self._curParams.findParamchoice(name)
|
|
|
|
def _trch_getparameterlist(self):
|
|
return self._curParams.getParameterList()
|
|
|
|
def _trch_getrootparameterlist(self):
|
|
return self._curParams.getRootParameterList()
|
|
|
|
@getwrapper
|
|
def _trch_hasvalidvalue(self, name):
|
|
return self._curParams.hasValidValue(name)
|
|
|
|
@getwrapper
|
|
def _trch_isvalid(self, name):
|
|
return self._curParams.isValid(name)
|
|
|
|
def _trch_addrendezvousparam(self, value):
|
|
self._curParams.addRendezvousParam(value)
|
|
|
|
def _trch_getoutputparameters(self):
|
|
return self._outputParams.getParameterList()
|
|
|
|
# Added to support fixing Bug #2133
|
|
@getwrapper
|
|
def _trch_findparameter(self, name):
|
|
return self._curParams.findParameter(name)
|
|
|
|
|
|
|