# -*- coding: utf-8 -*- """ fonctions communes Creole """ import os, time, re from os.path import join, isfile from pyeole.process import system_out, system_code from pyeole.ansiprint import print_orange from pyeole.log import init_logging from pyeole.pkg import EolePkg from pyeole.encode import normalize from .config import LOCALKERNEL_FILE, REBOOT_FILE from .i18n import _ #si creole client n'est pas démarré global PkgManager PkgManager = None ###################### # Gestion des noyaux # ###################### def split_version(version): """ return version as list splitting subnumbers :param version: version number string :type version: string """ version_splitted = re.split('[-\.]', version) version_splitted = map(int, version_splitted) return version_splitted def get_version_filtered_pkgs(prefix='linux-image'): """ return installed packages list ordered by version number """ vers_pkg_re = r"{0}-(?P[0-9]+(?P\.[0-9]+)*(-(?P[0-9]+))?)".format(prefix) vers_pkg_re = re.compile(vers_pkg_re) installed_pkgs = get_installed_kernel(prefix) vers_pkgs = [(pkg, split_version(vers_pkg_re.search(pkg).group('vers'))) for pkg in installed_pkgs if vers_pkg_re.search(pkg)] vers_pkgs = [pkg[0] for pkg in sorted(vers_pkgs, key=lambda p: p[1])] return vers_pkgs def get_custom_kernel(): """ renvoie le nom du noyau personnalisé ou None """ if isfile(LOCALKERNEL_FILE): # noyau personnalisé détecté kernel_file = LOCALKERNEL_FILE return file(kernel_file).read().strip() def get_wanted_kernel(): """ renvoie le nom du noyau sur lequel on veut tourner """ custom_kernel = get_custom_kernel() if custom_kernel: ret = custom_kernel else: kernel_images = get_version_filtered_pkgs() # Get last kernel version last_ver = kernel_images[-1].split('-') if len(last_ver) >= 4: last_ver = "{0}-{1}-{2}".format(*last_ver[2:5]) elif len(last_ver) == 3: last_ver = "{0}".format(last_ver[-1]) ret = last_ver return ret def get_current_kernel(): """ renvoie le nom du noyau sur lequel on tourne """ version = system_out(['uname', '-r'])[1].strip() return version def get_installed_kernel(kernel): """ renvoie la liste des noyaux installés correspondant à celui demandé """ cmd = """COLUMNS=180 dpkg -l 2>/dev/null | awk -F " " '/^(i|h)i.*%s/ {print $2}'""" % kernel return os.popen(cmd).read().splitlines() def get_package_depends(pkg): """ Renvois les dépendances d'un paquet """ try: global PkgManager if PkgManager is None: PkgManager = EolePkg('apt') res = PkgManager.get_depends(pkg) return res except: return [] def controle_kernel(force_grub=True): """ Vérifie si on est sur le noyau désiré Renvoie True si un reboot est nécessaire """ need_boot = False if isfile(REBOOT_FILE): # i.e. /var/run/reboot-required need_boot = True wanted_kernel = get_wanted_kernel() # on utilise le noyau spécifié if wanted_kernel != get_current_kernel(): need_boot = True if force_grub: # Update grub does the job since eole-kernel-version 2.3-eole37~2 print _(u"Updating Grub configuration") # ajout de LVM_SUPPRESS_FD_WARNINGS pour #10761 system_code("/usr/sbin/update-grub2", env={'LVM_SUPPRESS_FD_WARNINGS': '1', "LC_ALL": 'fr_FR.UTF-8'}) # reboot nécessaire ? return need_boot def regen_initrd(): """ vérifie la présence de l'initrd """ noyau = get_wanted_kernel() if not isfile("/boot/initrd.img-%s" % noyau): print _(u"Initramfs missing, generating :") cmd = ["/usr/sbin/update-initramfs", '-c', '-k', noyau] system_code(cmd) def get_kernel_to_remove(): """ Obtenir la liste des noyaux a supprimer. Tous les noyaux sauf : - le noyau courant - les deux noyaux les plus récents - l'éventuel noyau personnalisé """ # tous les noyaux installés installed_kernels = get_version_filtered_pkgs() # les deux noyaux les plus récents to_keep = installed_kernels[-2:] # tous les headers installés installed_kernels.extend(get_version_filtered_pkgs(prefix='linux-headers')) # le noyau courant to_keep.append('linux-image-{0}'.format(get_current_kernel())) # l'éventuel noyau personnalisé custom_kernel = get_custom_kernel() if custom_kernel: to_keep.append('linux-image-{0}'.format(custom_kernel)) # les headers correspondants aux noyaux à conserver headers_to_keep = [k.replace('image', 'headers') for k in to_keep] headers_to_keep.extend([h.replace('-generic', '') for h in headers_to_keep]) to_keep.extend(headers_to_keep) # on fait la différence to_remove = list(set(installed_kernels) - set(to_keep)) return to_remove def purge_rc(): """ Purge des paquets "rc" """ cmd = """COLUMNS=180 dpkg -l|grep "^rc"|awk -F " " '{print $2}'""" rcs = os.popen(cmd).read().splitlines() for pak in rcs: os.system("dpkg -P %s >/dev/null" % pak) def log(etat, msg, type_proc, console=True): """ effectue un log local et éventuellement sur zephir """ msg = normalize(msg) type_proc = normalize(type_proc) display = False log_func = 'info' if etat == "ERR": if console: # affichage sur la console display = True log_func = 'error' try: z_logger = init_logging(name=u'zephir', syslog=True, level=u'info', console=display) except ValueError, err: z_logger = init_logging(name=u'zephir', level=u'info', console=True) z_logger.warn(_(u"Syslog logging is not working properly: {0}".format(err))) z_logger.warn(_(u"You may need to start/restart systemd-journald")) getattr(z_logger, log_func)("%s => %s : %s " % (type_proc, etat, msg)) def zephir(etat, msg, type_proc, console=True): """ gestion des messages Zephir """ etat_zeph = None if etat.upper().startswith("INIT"): etat_zeph = -1 elif etat.upper().startswith("FIN"): etat_zeph = 0 elif etat.upper().startswith('ERR'): etat_zeph = 1 elif etat.upper().startswith('MSG'): etat_zeph = -2 # log local si msg ou erreur if (len(msg) > 0) or (etat.upper() == "ERR"): log(etat, msg, type_proc, console) # log sur zephir si disponible if etat_zeph is not None: try: # si serveur enregistré, on envoie un log à Zéphir from zephir.zephir_conf.zephir_conf import id_serveur except: pass else: from zephir.lib_zephir import log as zlog zlog(type_proc, etat_zeph, msg, str(time.ctime())) def init_proc(type_proc): """ initialisation d'une procédure (log démarrage + bcage éventuel) """ if verify_lock(type_proc): return True else: return False #def end_proc(etat,msg,type_proc): # """ # loggue la fin d'une procédure # """ # log(etat,msg,type_proc ) def verify_lock(name): """ vérifie le bloquage ou non d'une procédure """ LOCK_FILE = "/usr/share/zephir/zephir_locks" if name == "": return True from zephir.lib_zephir import zephir_path try: from zephir.lib_zephir import config, zephir, convert locks = convert(zephir.serveurs.get_locks(config.id_serveur)) if locks[0] == 0: # erreur sur zephir, on ignore cette phase raise Exception locks = [lock[0] for lock in locks[1]] except Exception, mess: # pas de message d'erreur si le serveur n'est pas enregistré zephir_error = False if isfile(join(zephir_path, "zephir_conf", "zephir_conf.py")): # on ne bloque pas si l'appel à zephir échoue print "" print_orange(_(u"Checking permissions on Zéphir for {0} impossible.").format(name)) print_orange(_(u"Error message: {0}").format(mess)) zephir_error = True # on regarde le denier état if os.path.exists(LOCK_FILE): if zephir_error: print_orange(_(u"Using stored parameters")) file_lock = file(LOCK_FILE) locks = file_lock.read().split('\n') file_lock.close() # on bloque si interdit if name in locks: return False else: # mise en place du fichier de droits content = "\n".join(locks) try: file_lock = file(LOCK_FILE, "w") file_lock.write(content) file_lock.close() except: print _(u"Updating {0} impossible (insufficient rights).").format(LOCK_FILE) # retour du code if name in locks: return False return True