summaryrefslogtreecommitdiffstats
path: root/func
diff options
context:
space:
mode:
Diffstat (limited to 'func')
-rw-r--r--func/minion/func_arg.py225
-rw-r--r--func/minion/modules/func_module.py57
-rw-r--r--func/minion/modules/iptables/port.py85
-rw-r--r--func/minion/modules/service.py29
-rw-r--r--func/minion/modules/virt.py29
5 files changed, 418 insertions, 7 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}},
+
+
+ }
diff --git a/func/minion/modules/virt.py b/func/minion/modules/virt.py
index 0828484..40ae274 100644
--- a/func/minion/modules/virt.py
+++ b/func/minion/modules/virt.py
@@ -184,7 +184,25 @@ class Virt(func_module.FuncModule):
pass
return results
- def install(self, server_name, target_name, system=False):
+ def freemem(self):
+ self.conn = self.__get_conn()
+ # Start with the physical memory and subtract
+ memory = self.conn.nodeinfo()[1]
+
+ # Take 256M off which is reserved for Domain-0
+ memory = memory - 256
+
+ vms = self.conn.find_vm(-1)
+ for vm in vms:
+ # Exclude stopped vms and Domain-0 by using
+ # ids greater than 0
+ if vm.ID() > 0:
+ # This node is active - remove its memory (in bytes)
+ memory = memory - int(vm.info()[2])/1024
+
+ return memory
+
+ def install(self, server_name, target_name, system=False, virt_name=None, virt_path=None):
"""
Install a new virt system by way of a named cobbler profile.
@@ -192,6 +210,7 @@ class Virt(func_module.FuncModule):
# Example:
# install("bootserver.example.org", "fc7webserver", True)
+ # install("bootserver.example.org", "client.example.org", True, "client-disk0", "HostVolGroup00")
conn = self.__get_conn()
@@ -204,15 +223,19 @@ class Virt(func_module.FuncModule):
if system:
target = "system"
- # TODO: FUTURE: set --virt-path in cobbler or here
koan_args = [
"/usr/bin/koan",
"--virt",
- "--virt-graphics", # enable VNC
"--%s=%s" % (target, target_name),
"--server=%s" % server_name
]
+ if virt_name:
+ koan_args.append("--virt-name=%s" % virt_name)
+
+ if virt_path:
+ koan_args.append("--virt-path=%s" % virt_path)
+
rc = sub_process.call(koan_args,shell=False)
if rc == 0:
return 0