def guess_system(self, systype = None): """ guess on system of remote target """ if systype is None: if not self.is_up(): return False try: sysinfos_mod = "callbacks.systems_infos" __import__(sysinfos_mod) except ImportError: sysinfos_mod = "generic_callbacks.systems_infos" __import__(sysinfos_mod) LOG.log_d("guessing system using '%s'" % (sysinfos_mod)) guess = sys.modules[sysinfos_mod].sysguess requisites = sys.modules[sysinfos_mod].check_prerequisites requisites(self.srv_ip) (self.hostname, self.systemtype, self.callbacks_paths) = guess(self.srv_ip) LOG.log_d("system guessed as %s" % (self.systemtype)) else: self.systemtype = systype self.callbacks_paths.append(systype) return True
def __init__(self, parent, module): LOG.log_d("initialising Callbacks class %s" % (module)) self.__parent = parent modlist = list() # replace OS type by generic prefix in module name # "debian.system" become "generic_callbacks.system" clean_mod = ".".join(module.split('.')[1:]) generic_module = "generic_callbacks.%s" % (clean_mod) LOG.log_d("generic module is %s" % (generic_module)) # add users' callbacks prefix target_module = "callbacks.%s" % (module) generic_imported = self.try_import(generic_module) if generic_imported is not None: LOG.log_d("generic module successfully imported") modlist.extend([generic_imported]) specific_imported = self.try_import(target_module) if specific_imported is not None: LOG.log_d("user's module successfully imported") modlist.extend([specific_imported]) if not len(modlist): raise ImportError("unable to import required callbacks: %s" % ( module)) LOG.log_d("importing methods and attributes from each module") self.retriev_attrs_and_methods(modlist)
def __init__(self, trunk, parent, module, search_paths): LOG.log_d("initialising Callbacks class %s" % (module)) self.trk = trunk self.mom = parent modlist = list() generic_module = "generic_callbacks.%s" % (module) LOG.log_d("generic module is %s" % (generic_module)) generic_imported = self.try_import(generic_module) if generic_imported is not None: LOG.log_d("generic module successfully imported") modlist.extend([generic_imported]) # add users' callbacks_path prefix for path in search_paths: path = '.'.join(path.split('/')) target_module = "callbacks.%s.%s" % (path, module) specific_imported = self.try_import(target_module) if specific_imported is not None: LOG.log_d("%s successfully imported" % (target_module)) modlist.extend([specific_imported]) if not len(modlist): raise ImportError("unable to import required callbacks: %s" % ( module)) LOG.log_d("importing methods and attributes from each module") self.retriev_attrs_and_methods(modlist)
def load_all_domus(self, domus): """ create and load all found domus """ log.log_d("%s: loading all hosted domUs infos" % (self.srv_ip)) for domu in domus: self.new_domu(domu, load=True) return True
def load_domain0(self): """ load domain-0 running state """ log.log_d("%s: loading domain0 infos" % (self.srv_ip)) domustate_list = self.xenapi.xmlist_bydomu_raw('Domain-0') domustate_dict = scc.list2dict(eval(domustate_list))['domain'] scc.dict2struct(self.infos.domain0, domustate_dict) return True
def try_import(module): """ try to import module """ # add generic_callbacks methods and attributes if found try: __import__(module) return sys.modules[module] except ImportError: LOG.log_d("module '%s' not found" % (module)) return None
def __init__(self, srv_ip, load=True, systemtype=None): LOG.log_d("initialising Server(%s, %s, %s)" % (srv_ip, load, systemtype)) self.srv_ip = srv_ip self.hostname = None self.systemtype = systemtype if load: LOG.log_d("guessing server's system type") self.guess_system(systemtype)
def sysgroup_del(self, groupname): """ delete system group """ __LOG.log_d("deleting group %s" % (groupname)) config = retrieve_config_infos(self)[1] context = {'groupname': groupname} ret = user_group_ctl(self, config, context) __LOG.log_d("group added: %s" % (repr(ret))) return ret
def gen_pwhash(self, password): """ generate password hash on remote host """ __LOG.log_d("generating password hash") config = self.users.retrieve_config_infos()[1] context = {'password': password} ret = user_group_ctl(self, config, context) __LOG.log_d("password hash generated: %s" % (ret[0])) return ret
def sysuser_exists(self, username): """ check if sysuser exists """ __LOG.log_d("checking user %s" % (username)) config = retrieve_config_infos(self)[1] context = {'username': username} ret = user_group_ctl(self, config, context) __LOG.log_d("user %s exists: %s" % (username, ret)) return ret
def sysuser_get_uid(self, username): """ get sysuser numeric uid """ __LOG.log_d("getting user %s id" % (username)) config = retrieve_config_infos(self)[1] context = {'username': username} ret = user_group_ctl(self, config, context) __LOG.log_d("got user uid: %s" % (repr(ret))) return ret
def load_state(self): """ import domU running state """ log.log_d("%s: loading domU running state" % (self.srv_ip)) domustate_list = self.dom0.xenapi.xmlist_bydomu_raw(self.name) e_domustate_list = eval(domustate_list) if len(e_domustate_list): domustate_dict = scc.list2dict(e_domustate_list)['domain'] self.state = scc.dict2struct(scc.AttStr("state structure"), domustate_dict) return True
def list_domus_configs(self): """ domU configuration listing """ log.log_d("%s: listing domUs configuration" % (self.srv_ip)) # list filename *.cfg in xen config path configs = fapi.list_files(self.srv_ip, "%s/*.cfg" % (self.xen.confpath_xen), full=False) # return files list without extensions return [ ".".join(config.split('.')[0:-1]) for config in configs ]
def get_config(configfile, search_paths = list()): """ get Config classes by filename and prefix """ try: if search_paths != CONFIG_LIST[configfile].search_paths: CONFIG_LIST[configfile].empty_config() CONFIG_LIST[configfile].search_paths = search_paths CONFIG_LIST[configfile].load() return CONFIG_LIST[configfile] except (KeyError, AttributeError): __LOG.log_d("reading configfile: %s (%s)" % (configfile, search_paths)) return Config(configfile, search_paths = search_paths)
def sysuser_add(self, userinfos, mkgrp=False, mkhome=False): """ add a sysuser """ __LOG.log_d("adding user %s" % (userinfos['username'])) config = retrieve_config_infos(self)[1] userinfos = __check_userinfos(userinfos) bl_fields = ['ref_user', 'password', 'username'] common_fields = [ field for field in userinfos if field not in bl_fields ] if userinfos['ref_user'] != None: ret = sysuser_get_infos(self, userinfos['ref_user']) if not ret[0]: return False, "unable to retrieve ref_user informations" ref_infos = ret[1] # retrieve ref_user's groups ref_groups = sysuser_get_groups(self, userinfos['ref_user'])[1] ref_groups.pop(0) ref_infos['groups'] = ref_groups for field in common_fields: if userinfos[field] == None: userinfos[field] = ref_infos[field] if userinfos['groups'] != None: if mkgrp: for group in userinfos['groups']: sysgroup_exists(self, group)[0] or sysgroup_add(self, group) userinfos['groups'] = ",".join(userinfos['groups']) context = {'username': userinfos['username']} for field in common_fields: context['%s_opt' % field] = "" if userinfos[field] != None: context['%s_opt' % field] = config['%s_opt' % field] % ( {field: userinfos[field]}) if userinfos['uid'] != None: context['force_uid_opt'] = config['force_uid_opt'] else: context['force_uid_opt'] = "" if mkhome: context['mkhome_opt'] = config['mkhome_opt'] else: context['mkhome_opt'] = "" ret = user_group_ctl(self, config, context) __LOG.log_d("user added: %s" % (repr(ret))) if userinfos['password'] != None: sysuser_set_passwd(self, userinfos['username'], userinfos['password']) #return ret return ret
def sysgroup_exists(self, groupname): """ check if groupname exists """ __LOG.log_d("checking group %s" % (groupname)) config = retrieve_config_infos(self)[1] out = __fapi.file_contains(self.srv_ip, "^" + groupname + ":", config['groupfile']) __LOG.log_d("group %s exists: %s" % (groupname, not out.failed)) return (not out.failed, out)
def sysuser_change_home(self, username, home): """ change user's home """ __LOG.log_d("changing user %s home to %s" % (username, home)) config = retrieve_config_infos(self)[1] context = { 'username': username, 'home': home, } ret = user_group_ctl(self, config, context) __LOG.log_d('home changed: %s' % (repr(ret))) return ret
def sysuser_rename(self, username_src, username_dst): """ rename a sysuser """ __LOG.log_d("renamming user %s to %s" % (username_src, username_dst)) config = retrieve_config_infos(self)[1] context = { 'username_src': username_src, 'username_dst': username_dst, } ret = user_group_ctl(self, config, context) __LOG.log_d("user renamed: %s" % (repr(ret))) return ret
def sysuser_set_passwd(self, username, password): """ set sysuser password """ __LOG.log_d("setting user %s password" % (username)) config = retrieve_config_infos(self)[1] context = { 'username': username, 'password_hash': gen_pwhash(self, password)[1] } ret = user_group_ctl(self, config, context) __LOG.log_d('password setted: %s' % (repr(ret))) return ret
def sysgroup_rename(self, groupname_src, groupname_dst): """ rename a sysuser """ __LOG.log_d("renamming group %s to %s" % (groupname_src, groupname_dst)) config = retrieve_config_infos(self)[1] context = { 'groupname_src': groupname_src, 'groupname_dst': groupname_dst } ret = user_group_ctl(self, config, context) __LOG.log_d("group renammed: %s" % (repr(ret))) return ret
def __init__(self, srv_ip, load=True, systemtype=None): LOG.log_d("initialising Server(%s, %s, %s)" % (srv_ip, load, systemtype)) self.srv_ip = srv_ip self.hostname = None self.systemtype = systemtype self.callbacks_paths = list() self.fapi = scc.AttStr('fapi calls wrapper') self.load_fapi() if load: LOG.log_d("guessing server's system type") self.guess_system(systemtype)
def load_config(self, config_content=list(), reinit=False): """ import domU configuration to config struct """ log.log_d("%s: loading domU configuration" % (self.srv_ip)) configfile = "%s/%s.cfg" % (self.dom0.xen.confpath_xen, self.name) if not len(config_content): config = fapi.get_file_content(self.dom0.srv_ip, configfile) if config == None: return False config = config.lines else: config = config_content clean_config = list() # cleaning config but formating is kept for line in config: clean_line = re.sub(r"#.*", r"", line) clean_line = re.sub(r"^\s+$", r"", clean_line) if len(clean_line): clean_config.extend([clean_line]) # exec python domU configfile in a dict context plaintext_config = "\n".join(clean_config) config_dict = dict() unused = dict() exec plaintext_config in unused, config_dict # convert config dict in config structure self.config = scc.dict2struct(scc.AttStr("config structure"), config_dict) # check if domu is auto started configfile_auto = "%s/auto/%s.cfg" % (self.dom0.xen.confpath_xen, self.name) if fapi.file_exists(self.dom0.srv_ip, configfile_auto): self.config.auto = True else: self.config.auto = False # store domu configuration filename self.config.configfile = configfile # reinit parent with IP and reload callbacks if asked domu_ip = self.dom0.xen.get_ip_domuconfig(config_dict) self.srv_ip = domu_ip if reinit: self.init_domu() return True
def is_host_up(host, port=22): """ check host connection on ip/port """ original_timeout = socket.getdefaulttimeout() new_timeout = 3 socket.setdefaulttimeout(new_timeout) host_status = False try: paramiko.Transport((host, port)) host_status = True except: pass socket.setdefaulttimeout(original_timeout) __LOG.log_d("connection on %s port %s: %s" % (host, port, host_status)) return host_status
def sysuser_del(self, username, purge=False): """ delete a system user """ __LOG.log_d("removing user %s" % (username)) config = retrieve_config_infos(self)[1] # if purge is True, use purge_opt from config purge_opt = purge and config['purge_opt'] or "" context = { 'username': username, 'purge_opt': purge_opt } ret = user_group_ctl(self, config, context) __LOG.log_d("user removed: %s" % (repr(ret))) return ret
def check_prerequisites(srv_ip): """ check prerequisites on remote host """ ret = True __LOG.log_d("trying to run command") out = __fapi.run(srv_ip, 'whoami', nocheck=True) if out.failed: __LOG.log_c("unable to execute commands on remote host") ret = False __LOG.log_d("trying to run sudo command") out = __fapi.sudo(srv_ip, 'whoami', nocheck=True) if out.failed: __LOG.log_c("unable to execute commands with sudo on remote host") ret = False return ret
def sysuser_get_groups(self, username, numeric=False): """ get sysuser groups list (primay first) """ __LOG.log_d("getting groups of user %s" % (username)) config = retrieve_config_infos(self)[1] # if numeric is True, use numeric_opt from config numeric_opt = numeric and config['numeric_opt'] or "" context = { 'username': username, 'numeric_opt': numeric_opt } ret = user_group_ctl(self, config, context) __LOG.log_d("got user groups: %s" % (repr(ret))) # if succeed, split groups by space groups = ret[0] and ret[1].split() or [] return ret[0], groups
def retriev_attrs_and_methods(self, modules_list): """ retrieve attributes and methods from each module """ for mod in modules_list: LOG.log_d("importing from %s" % (mod.__name__)) for attr in dir(mod): # import everything but builtins and privates if attr[0:2] == "__": continue module_attr = getattr(mod, attr) ## store callback, if callable self refer to the callback if isinstance(module_attr, collections.Callable): setattr(self, attr, types.MethodType(module_attr, self)) else: setattr(self, attr, module_attr) return True
def load_xminfo(self): """ xm info output to python struct """ log.log_d("%s: loading xminfos" % (self.srv_ip)) err = self.xenapi.xminfo_raw() raw_lines = err.lines xminfo_entries = [] for line in raw_lines: s_line = re.split("\s+:\s+", line.strip(), maxsplit=1) if len(s_line) >= 2: xminfo_entries.append(s_line) else: xminfo_entries[-1].extend(s_line) #log.log_d('xminfo_entries: %s' % (xminfo_entries)) scc.list2struct(self.infos, xminfo_entries) return self.infos
def sysuser_get_infos(self, username): """ get passwd entry for username """ __LOG.log_d("getting infos for user %s" % (username)) config = retrieve_config_infos(self)[1] fields_desc = ['username', 'password', 'uid', 'gid', 'infos', 'homedir', 'shell'] passwd_content = __fapi.get_file_content(self.srv_ip, config['passwdfile']) for line in passwd_content.lines: fields = line.split(':') if not len(fields) == 7: continue if fields[0] == username: return True, dict(zip(fields_desc, fields)) return False, None
def list_running_domus(self): """ running domus listing """ log.log_d("%s: listing running domUs" % (self.srv_ip)) running_domus = [] self.infos.used_cpus = 0 # retrieve xm list output and convert each domU in dict out = self.xenapi.xmlist_bytype_raw() for domu in eval(out): domu_dict = scc.list2dict(domu)['domain'] if domu_dict['name'] != "Domain-0": running_domus.append(domu_dict['name']) self.infos.used_cpus += int(domu_dict['vcpus']) # return list of domU dicts if hasattr(self.infos, 'nr_cpus'): self.infos.free_cpus = ( int(self.infos.nr_cpus) - self.infos.used_cpus ) return running_domus