281 lines
8.9 KiB
Python
281 lines
8.9 KiB
Python
# -*- 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<vers>[0-9]+(?P<upstr_vers>\.[0-9]+)*(-(?P<pkg_vers>[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
|