diff options
author | Michael DeHaan <mdehaan@redhat.com> | 2008-06-23 12:30:56 -0400 |
---|---|---|
committer | Michael DeHaan <mdehaan@redhat.com> | 2008-06-23 12:30:56 -0400 |
commit | 5aeaa5a411c2e5b8f297ba1eed02aa2663ff7225 (patch) | |
tree | 3d93438c48edb9b3fdb27dafb01cd38b3f754321 /func/minion | |
parent | 76996c8ac3016389fdafb47e7791f2c636e2a4ed (diff) | |
parent | 30a2391e1078bca14c83ad3b433a46f6929b29f4 (diff) | |
download | third_party-func-5aeaa5a411c2e5b8f297ba1eed02aa2663ff7225.tar.gz third_party-func-5aeaa5a411c2e5b8f297ba1eed02aa2663ff7225.tar.xz third_party-func-5aeaa5a411c2e5b8f297ba1eed02aa2663ff7225.zip |
Merge branch 'makkalot_extreme'
Diffstat (limited to 'func/minion')
-rw-r--r-- | func/minion/func_arg.py | 225 | ||||
-rw-r--r-- | func/minion/modules/func_module.py | 57 | ||||
-rw-r--r-- | func/minion/modules/iptables/port.py | 85 | ||||
-rw-r--r-- | func/minion/modules/service.py | 29 |
4 files changed, 392 insertions, 4 deletions
diff --git a/func/minion/func_arg.py b/func/minion/func_arg.py new file mode 100644 index 0000000..5025e17 --- /dev/null +++ b/func/minion/func_arg.py @@ -0,0 +1,225 @@ +## +## Copyright 2007, Red Hat, Inc +## see AUTHORS +## +## This software may be freely redistributed under the terms of the GNU +## general public license. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +## + +class ArgCompatibility(object): + """ + That class is going to test if the module that was created by module + writer if he/she obeys to the rules we put here + """ + + #these are the common options can be used with all types + __common_options = ('optional','default','description','order') + __method_options = ('description','args') #making method declarations more generic like method_name:{'args':{...},'description':"bla bla"} + + #basic types has types also + __basic_types={ + 'range':[1,], + 'min':0, + 'max':0, + 'optional':False, + 'description':'', + 'options':[1,], + 'min_length':0, + 'max_length':0, + 'validator':'', + 'type':'', + 'default':None, #its type is unknown, + 'order':0 + } + + def __init__(self,get_args_result): + """ + The constructor initilized by the get_method_args()(the dict to test) + @param : get_args_result : The dict with all method related info + """ + self.__args_to_check = get_args_result + + #what options does each of the basic_types have : + self.__valid_args={ + 'int':('range','min','max',), + 'string':('options','min_length','max_length','validator',), + 'boolean':(), + 'float':('range','min','max'), + 'hash':('validator',), + 'list':('validator',), + } + + + def _is_type_options_compatible(self,argument_dict): + """ + Checks the method's argument_dict's options and looks inside + self.__valid_args to see if the used option is there + + @param : argument_dict : current argument to check + @return : True of raises IncompatibleTypesException + + """ + #did module writer add a key 'type' + if not argument_dict.has_key('type') or not self.__valid_args.has_key(argument_dict['type']): + raise IncompatibleTypesException("%s is not in valid options,possible ones are :%s"%(argument_dict['type'],str(self.__valid_args))) + + #we need some specialization about if user has defined options + #there is no need for using validator,min_lenght,max_length + if argument_dict.has_key('options'): + for arg_option in argument_dict.keys(): + if arg_option!='options' and arg_option in self.__valid_args['string']: + raise IncompatibleTypesException('The options keyword should be used alone in a string cant be used with min_length,max_length,validator together') + + #if range keyword is used into a int argument the others shouldnt be there + if argument_dict.has_key('range'): + if len(argument_dict['range'])!=2: + raise IncompatibleTypesException('The range option should have 2 members [min,max]') + if not argument_dict['range'][0] < argument_dict['range'][1]: + raise IncompatibleTypesException('In the range option first member should be smaller than second [min,max]') + #check if another option was used there ... + for arg_option in argument_dict.keys(): + if arg_option!='range' and arg_option in self.__valid_args['int']: + raise IncompatibleTypesException('The options range should be used alone into a int argument') + + + # we will use it everytime so not make lookups + the_type = argument_dict['type'] + from itertools import chain #may i use chain ? + + for key,value in argument_dict.iteritems(): + + if key == "type": + continue + if key not in chain(self.__valid_args[the_type],self.__common_options): + raise IncompatibleTypesException("There is no option like %s in %s"%(key,the_type)) + + return True + + + def _is_basic_types_compatible(self,type_dict): + """ + Validates that if the types that were submitted with + get_method_args were compatible with our format above + in __basic_types + + @param : type_dict : The type to examine + @return : True or raise IncompatibleTypesException Exception + """ + #print "The structure we got is %s:"%(type_dict) + for key,value in type_dict.iteritems(): + + #do we have that type + if not self.__basic_types.has_key(key): + raise IncompatibleTypesException("%s not in the basic_types"%key) + + #if type matches and dont match default + #print "The key: %s its value %s and type %s"%(key,value,type(value)) + if key!='default' and type(value)!=type(self.__basic_types[key]): + raise IncompatibleTypesException("The %s keyword should be in that type %s"%(key,type(self.__basic_types[key]))) + + return True + + def is_all_arguments_registered(self,cls,method_name,arguments): + """ + Method inspects the method arguments and checks if the user + has registered all the arguments succesfully and also adds a + 'order' keyword to method arguments to + """ + import inspect + from itertools import chain + #get the arguments from real object we have [args],*arg,**kwarg,[defaults] + tmp_arguments=inspect.getargspec(getattr(cls,method_name)) + check_args=[arg for arg in chain(tmp_arguments[0],tmp_arguments[1:3]) if arg and arg!='self'] + #print "The arguments taken from the inspect are :",check_args + #the size may change of the hash so should a copy of it + copy_arguments = arguments.copy() + for compare_arg in copy_arguments.iterkeys(): + if not compare_arg in check_args: + raise ArgumentRegistrationError("The argument %s is not in the %s"%(compare_arg,method_name)) + else: + #should set its ordering thing + arguments[compare_arg]['order']=check_args.index(compare_arg) + + return True + + def validate_all(self): + """ + Validates the output for minion module's + get_method_args method + + The structure that is going to be validated is in that format : + + { + method_name1 : {'args':{...}, + 'description':"wowo"}, + method_name12 : {...} + } + + @return : True or raise IncompatibleTypesException Exception + """ + + for method in self.__args_to_check.iterkeys(): + #here we got args or description part + #check if user did submit something not in the __method_options + for method_option in self.__args_to_check[method].iterkeys(): + if method_option not in self.__method_options: + raise IncompatibleTypesException("There is no option for method_name like %s,possible ones are : %s"%(method_option,str(self.__method_options))) + #check what is inside the args + if method_option == "args": + for argument in self.__args_to_check[method][method_option].itervalues(): + #print argument + #check if user registered all the args and add to them ordering option! + self._is_basic_types_compatible(argument) + self._is_type_options_compatible(argument) + + return True + + +###The Exception classes here they will be raised during the validation part +###If a module passes all the tests it is ready tobe registered + + +class IncompatibleTypesException(Exception): + """ + Raised when we assign some values that breaksour rules + @see ArgCompatibility class for allowed situations + """ + def __init__(self, value=None): + Exception.__init__(self) + self.value = value + def __str__(self): + return "%s" %(self.value,) + +class NonExistingMethodRegistered(IncompatibleTypesException): + """ + That Exception is raised when a non existent module is + tried to be registerd we shouldnt allow that + """ + pass + +class UnregisteredMethodArgument(IncompatibleTypesException): + """ + That exception is to try to remove the errors that user may + do during method registration process. If a argument is missed + to be registerted in the method that exception is Raised! + """ + pass + + +class NonExistingMethodRegistered(IncompatibleTypesException): + """ + Raised when module writer registers a method that doesnt + exist in his/her module class (probably by mistake) + """ + pass + +class ArgumentRegistrationError(IncompatibleTypesException): + """ + When user forgets to register soem of the arguments in the list + or adds some argument that is not there + """ + pass diff --git a/func/minion/modules/func_module.py b/func/minion/modules/func_module.py index 7d476dc..53fd66b 100644 --- a/func/minion/modules/func_module.py +++ b/func/minion/modules/func_module.py @@ -15,7 +15,7 @@ import inspect from func import logger from func.config import read_config from func.commonconfig import FuncdConfig - +from func.minion.func_arg import * #the arg getter stuff class FuncModule(object): @@ -34,7 +34,8 @@ class FuncModule(object): "module_version" : self.__module_version, "module_api_version" : self.__module_api_version, "module_description" : self.__module_description, - "list_methods" : self.__list_methods + "list_methods" : self.__list_methods, + "get_method_args" : self.__get_method_args, } def __init_log(self): @@ -58,8 +59,7 @@ class FuncModule(object): """ handlers = {} for attr in dir(self): - if inspect.ismethod(getattr(self, attr)) and attr[0] != '_' and \ - attr != 'register_rpc': + if self.__is_public_valid_method(attr): handlers[attr] = getattr(self, attr) return handlers @@ -74,3 +74,52 @@ class FuncModule(object): def __module_description(self): return self.description + + def __is_public_valid_method(self,attr): + if inspect.ismethod(getattr(self, attr)) and attr[0] != '_' and\ + attr != 'register_rpc' and attr!='register_method_args': + return True + return False + + def __get_method_args(self): + """ + Gets arguments with their formats according to ArgCompatibility + class' rules. + + @return : dict with args or Raise Exception if something wrong + happens + """ + tmp_arg_dict = self.register_method_args() + + #if it is not implemeted then return empty stuff + if not tmp_arg_dict: + return {} + + #see if user tried to register an not implemented method :) + for method in tmp_arg_dict.iterkeys(): + if not hasattr(self,method): + raise NonExistingMethodRegistered("%s is not in %s "%(method,self.__class__.__name__)) + + #create argument validation instance + self.arg_comp = ArgCompatibility(tmp_arg_dict) + #see if all registered arguments are there + for method in tmp_arg_dict.iterkeys(): + self.arg_comp.is_all_arguments_registered(self,method,tmp_arg_dict[method]['args']) + #see if the options that were used are OK.. + self.arg_comp.validate_all() + + return tmp_arg_dict + + def register_method_args(self): + """ + That is the method where users should override in their + modules according to be able to send their method arguments + to the Overlord. If they dont have it nothing breaks + just that one in the base class is called + + @return : empty {} + """ + + # to know they didnt implement it + return {} + diff --git a/func/minion/modules/iptables/port.py b/func/minion/modules/iptables/port.py index 370123b..3d3902b 100644 --- a/func/minion/modules/iptables/port.py +++ b/func/minion/modules/iptables/port.py @@ -128,6 +128,91 @@ class Port(func_module.FuncModule): clear_all("-D OUTPUT -p %s --%sport %s -d %s -j REJECT" % (prot, dir, port, ip) ) return call_if_policy("OUTPUT", "DROP", "-I OUTPUT -p %s --%sport %s -d %s -j ACCEPT" % (prot, dir, port, ip) ) + def register_method_args(self): + """ + Export the methods and their definitons + """ + #they are all same so just declare here + port={ + 'type':'string', + 'optional':False, + + } + ip={ + 'type':'string', + 'optional':False, + 'default':'0.0.0.0' + } + prot={ + 'type':'string', + 'options':['tcp','udp','icmp','sctp'], + 'default':'tcp', + 'optional':False + } + dir={ + 'type':'string', + 'default':'dst', + 'options':['src','dst'], + 'optional':False + } + + return { + 'drop_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + } + }, + 'reject_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'accept_from':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'drop_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'reject_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + 'accept_to':{'args': + { + 'ip':ip, + 'prot':prot, + 'dir':dir, + 'port':port + + } + }, + + } + def parse_dir(dir): if (dir == "dst"): return "d" diff --git a/func/minion/modules/service.py b/func/minion/modules/service.py index 062aea5..25acea3 100644 --- a/func/minion/modules/service.py +++ b/func/minion/modules/service.py @@ -86,3 +86,32 @@ class Service(func_module.FuncModule): tokens = line.split() results.append((tokens[0], tokens[-1].replace("...",""))) return results + + def register_method_args(self): + """ + Implementing the argument getter + """ + + #service_name options they are same so use only one + service_name = { + 'type':'string', + 'optional':False, + 'description':'The name of the running services', + 'validator':'^[a-z\-\_0-9]+$'} + + return { + 'get_running':{'args':{}}, + 'get_enabled':{'args':{}}, + 'inventory':{'args':{}}, + 'status':{'args':{ + 'service_name':service_name, + }, + 'description':'Getting the status of the service_name' + }, + 'reload':{'args':{'service_name':service_name}}, + 'restart':{'args':{'service_name':service_name}}, + 'stop':{'args':{'service_name':service_name}}, + 'start':{'args':{'service_name':service_name}}, + + + } |