rougail/creole/reconfigure.py

1007 lines
37 KiB
Python
Raw Normal View History

2019-11-23 08:17:35 +01:00
# -*- coding: utf-8 -*-
"""Apply configuration of EOLE servers.
"""
import os
import argparse
import time
import shutil
from glob import glob
import spwd
import getpass
from itertools import count
from pyeole.log import getLogger
from pyeole.log import init_logging
from pyeole.log import set_formatter
from pyeole.log import set_filters
from pyeole import scriptargs
from pyeole.lock import acquire, release
from pyeole import process
from pyeole.schedule import display_schedules, apply_schedules
from pyeole import ihm
from pyeole.pkg import report, EolePkg, _configure_sources_mirror, _MIRROR_DIST
from pyeole.pkg import PackageNotFoundError, RepositoryError, AptProxyError, AptCacherError
from pyeole.service import manage_service, unmanaged_service, manage_services, \
ServiceError
from pyeole.encode import normalize
from pyeole.diagnose.diagnose import MAJ_SUCCES_LOCK
from .error import FileNotFound, LockError, UnlockError
from .error import UserExit, UserExitError
from .error import VirtError
from .client import CreoleClient, CreoleClientError, NotFoundError
import fonctionseole, template, cert
from .eosfunc import is_instanciate
from .config import configeol, INSTANCE_LOCKFILE, UPGRADE_LOCKFILE, \
container_instance_lockfile, gen_conteneurs_needed, VIRTROOT, charset
from .containers import is_lxc_enabled, is_lxc_running, is_lxc_started, \
generate_lxc_container, create_mount_point, lxc_need_restart
from .error import NetworkConfigError
from pyeole.i18n import i18n
_ = i18n('creole')
try:
from zephir.lib_zephir import lock, unlock
zephir_libs = True
except Exception:
zephir_libs = False
client = CreoleClient()
global PKGMGR
PKGMGR = None
error_msg_documentation = _(u"""For more informations, read section
'Mise en œuvre des modules EOLE' in module documentation or
common documentation.""")
def load_pkgmgr():
global PKGMGR
if PKGMGR is None:
cache()
PKGMGR = EolePkg('apt', container_mode=CACHE['is_lxc_enabled'])
PKGMGR.pkgmgr.groups = CACHE
PKGMGR.pkgmgr._load_apt_cache()
eoles = []
for eole in client.get_creole(u'serveur_maj'):
eoles.append('http://{0}/eole/'.format(eole))
ubuntus = []
for ubuntu in client.get_creole(u'ubuntu_update_mirrors'):
ubuntus.append('http://{0}/ubuntu/'.format(ubuntu))
envoles = []
try:
for envole in client.get_creole(u'envole_update_mirrors'):
envoles.append('http://{0}/envole/'.format(envole))
except NotFoundError:
pass
for cache_ in PKGMGR.pkgmgr.cache._list.list:
if cache_.uri in eoles:
PKGMGR.pkgmgr._test_mirror(cache_.uri, _MIRROR_DIST['EOLE'])
eoles = []
if cache_.uri in ubuntus:
PKGMGR.pkgmgr._test_mirror(cache_.uri, _MIRROR_DIST['Ubuntu'])
ubuntus = []
if cache_.uri in envoles:
PKGMGR.pkgmgr._test_mirror(cache_.uri, _MIRROR_DIST['Envole'])
envoles = []
fonctionseole.PkgManager = PKGMGR
_LOGFILENAME = '/var/log/reconfigure.log'
# Command line options
class Option:
"""Manage commande line options with defaults
"""
def __init__(self):
self.parser = argparse.ArgumentParser(
description=_(u"Applying EOLE configuration."),
parents=[scriptargs.container(),
scriptargs.logging(level='info')])
self.parser.add_argument('-i', '--interactive', action='store_true',
help=_(u"leave process in interactive mode"))
self.parser.add_argument('-f', '--force', action='store_true',
help=_(u"override Zéphir lock"))
self.parser.add_argument('-a', '--auto', action='store_true',
help=_(u"automatic reboot if necessary"))
self.__opts = self.parser.parse_args([])
def update_from_cmdline(self, force_args=None, force_options=None):
"""Parse command line
"""
self.__opts = self.parser.parse_args(force_args)
if self.__opts.verbose:
self.__opts.log_level = 'info'
if self.__opts.debug:
self.__opts.log_level = 'debug'
if force_options is not None:
for key, value in force_options.items():
setattr(self.__opts, key, value)
self.__dict__.update(self.__opts.__dict__)
def __getattr__(self, name):
if name in ['__opts', 'update_from_cmdline']:
return self.__dict__[name]
else:
return getattr(self.__opts, name)
options = Option()
# To use log from every functions
log = getLogger(__name__)
# Same name for instance and reconfigure
LOCK_NAME = u'reconfigure'
# Run scripts in directories
RUNPARTS_PATH = u'/usr/share/eole'
RUNPARTS_CMD = u'/bin/run-parts --exit-on-error -v {directory} --arg {compat} 2>&1'
# Compatibility
COMPAT_NAME = u'reconfigure'
#def parse_cmdline():
# """Parse command line
# """
# descr = u"Application de la configuration EOLE"
# parser = argparse.ArgumentParser(description=descr,
# parents=[scriptargs.container(),
# scriptargs.logging(level='info')])
# parser.add_argument('-i', '--interactive', action='store_true',
# help=u"lancer le processus en mode interactif")
# parser.add_argument('-f', '--force', action='store_true',
# help=u"force l'action même s'il existe des verrous")
# parser.add_argument('-a', '--auto', action='store_true',
# help=u"redémarrage automatique si nécessaire")
#
# opts = parser.parse_args()
# if opts.verbose:
# opts.log_level = 'info'
# if opts.debug:
# opts.log_level = 'debug'
# return opts
def copyDirectoryContent(src, dst):
for fic in os.listdir(src):
# Skip links or we ovewrite existing certificates
if os.path.islink(os.path.join(src, fic)):
continue
try:
shutil.copy2(os.path.join(src, fic), dst)
except shutil.Error, err:
# ignore if files already exists
pass
def user_exit(*args, **kwargs):
"""
sortie utilisateur "propre"
"""
log.warn(_(u'! Abandoning configuration !'))
log.warn(_(u'System may be in an incoherent state.\n\n'))
raise UserExitError()
def unlock_actions(need_lock=True):
if zephir_libs:
#FIXME: lock de Zephir !
unlock('actions')
try:
release(LOCK_NAME, level='system')
except Exception, err:
# FIXME: move lock exception to pyeole.lock #7400
if need_lock:
raise UnlockError(str(err))
def lock_actions():
try:
acquire(LOCK_NAME, level="system")
except Exception, err:
# FIXME: move lock exception to pyeole.lock #7400
raise LockError(str(err))
if zephir_libs:
#FIXME: lock de Zephir !
lock('actions')
def reset_compat_name():
"""
Réinitialise le nom de la procédure en cours
en fonction de l'environnement
"""
global COMPAT_NAME
if options.interactive:
COMPAT_NAME = u'instance'
else:
COMPAT_NAME = u'reconfigure'
def run_parts(directory):
"""Run scripts in a directory
@param directory: name of a directory
@type directory: C{str}
"""
dirpath = os.path.join(RUNPARTS_PATH, directory)
if os.path.isdir(dirpath):
ihm.print_title(_(u'Running scripts {0}').format(directory))
code = os.system(RUNPARTS_CMD.format(directory=dirpath, compat=COMPAT_NAME))
if code != 0:
raise Exception(_(u'Error {0}').format(directory))
def restart_creoled():
"""
Restart creoled service and verify if the client is OK
"""
unmanaged_service(u'restart', u'creoled', u'service', display='console')
try:
client.get_creole(u'eole_version')
except CreoleClientError:
msg = _(u"Please check creoled's log (/var/log/rsyslog/local/creoled/creoled.info.log)\nand restart service with command 'service creoled start'")
raise CreoleClientError(msg)
def prepare(need_lock=True):
"""Sanity checks.
"""
global RUNPARTS_CMD
# Clean exit
if need_lock:
ihm.catch_signal(user_exit)
lock_actions()
if options.container != None:
RUNPARTS_CMD += u" --regex '^[09][09]-{0}$'".format(options.container)
ihm.print_title(_(u"Preparation for {0}").format(COMPAT_NAME))
if not os.path.isfile(configeol):
print _(u"Server is not configured.")
print
print error_msg_documentation
print
raise FileNotFound(_(u'Missing file {0}.').format(configeol))
display_info = False
if not options.interactive and (is_instanciate() == 'non' or os.path.isfile(UPGRADE_LOCKFILE)):
ihm.print_red(_(u"Server must be instantiated before any reconfiguration can occur."))
display_info = True
if options.interactive and is_instanciate() == 'oui' and \
not os.path.isfile(UPGRADE_LOCKFILE) and \
not os.path.isfile(container_instance_lockfile):
ihm.print_red(_(u"Server already instantiated."))
print
print _(u"To modify configuration parameter (e.g. IP address), use:")
print _(u"'gen_config'")
print _(u"then 'reconfigure' to apply changes.")
display_info = True
if os.path.isfile(container_instance_lockfile) and not options.interactive:
raise Exception(_('you have run gen_conteneurs, please use instance instead of reconfigure'))
if os.path.isfile(gen_conteneurs_needed):
raise Exception(_('You have to run gen_conteneurs before instance'))
if display_info:
print
print error_msg_documentation
print
if not options.interactive:
raise Exception(_(u"First instantiate server."))
else:
if ihm.prompt_boolean(_(u"Proceeding with instantiation ?"),
interactive=options.interactive,
default=False) is False:
raise UserExit()
else:
fonctionseole.zephir("MSG", "Instance forcée par l'utilisateur",
COMPAT_NAME.upper())
# redémarrage du service creoled
restart_creoled()
if fonctionseole.init_proc(COMPAT_NAME.upper()) == False and not options.force:
log.warn(_(u"This process is blocked, contact Zéphir administrator."))
if ihm.prompt_boolean(_(u"Force execution?"),
interactive=options.interactive,
default=False) is False:
if not options.interactive:
log.warn(_(u"Use -f option if you want to force execution"))
raise UserExitError()
else:
fonctionseole.zephir("MSG",
"Instance forcée par l'utilisateur",
COMPAT_NAME.upper())
def valid_mandatory(need_lock):
try:
client.valid_mandatory()
except Exception, err:
log.warn(_('Configuration validation problem, please check server configuration.'))
print
print error_msg_documentation
print
unlock_actions(need_lock)
raise ValueError(str(err))
def _start_containers():
""" Try to start containers and make sure they are started
"""
cache()
for group_name in CACHE['groups_container']:
group = CACHE['group_infos'][group_name]
create_mount_point(group)
if os.access('/usr/share/eole/preservice/00-lxc-net', os.X_OK):
log.debug("Override lxc-net systemd script")
process.system_code(['/usr/share/eole/preservice/00-lxc-net'])
unmanaged_service(u'start', u'lxc-net', u'systemd', display='console', ctx=CACHE['group_infos']['root'])
try:
unmanaged_service(u'status', u'lxc', u'systemd')
except ServiceError:
unmanaged_service(u'start', u'lxc', u'systemd', display='console', ctx=CACHE['group_infos']['root'])
#if lxc not started, do not wait for it
#(we already waiting for it in systemd service)
#if started, waiting for ssh access
max_try = 10
for count in range(max_try):
s_code, s_out, s_err = process.system_out(['lxc-ls', '--stopped'])
stopped = s_out.split()
f_code, f_out, f_err = process.system_out(['lxc-ls', '--frozen'])
frozen = f_out.split()
if stopped or frozen:
not_running = stopped + frozen
else:
# Everything is started by LXC
# Are they reachable by SSH?
not_running = []
for group_name in CACHE['groups_container']:
group_infos = CACHE['group_infos'][group_name]
if not is_lxc_running(group_infos):
not_running.append(group_name)
log.debug('Waiting 1 second for SSH access')
time.sleep(1)
if not not_running:
break
if stopped:
for cont in stopped:
log.debug('Manual start of stopped container “{0}'.format(cont))
process.system_out(['lxc-start', '--name', cont, '--daemon',
'-o', '/var/log/lxc-{0}.log'.format(cont)])
if frozen:
for cont in frozen:
log.debug('Manual unfreeze of frozen container “{0}'.format(cont))
process.system_out(['lxc-unfreeze', '--name', cont,
'-o', '/var/log/lxc-{0}.log'.format(cont)])
if not_running:
waiting_for = ', '.join(not_running)
msg = _(u'Unable to start LXC container : {0}',
u'Unable to start LXC containers : {0}', len(not_running))
raise VirtError(msg.format(waiting_for))
def containers(minimal=False, log_=None):
"""Generate containers
"""
if log_ is None:
log_ = log
VAR_LXC='/var/lib/lxc'
OPT_LXC='/opt/lxc'
cache()
if not CACHE['is_lxc_enabled']:
log.debug(_(u'Container mode is disabled.'))
return True
if not options.interactive:
for group in CACHE['groups_container']:
if not os.path.isdir(os.path.join(VIRTROOT, group)):
raise Exception(_(u'container {0} does not already exist, please use gen_conteneurs to create this container').format(group))
else:
# make /var/lib/lxc -> /opt/lxc
if os.path.isdir(VAR_LXC) and not os.path.exists(OPT_LXC):
ihm.print_title(_(u"Setting up {0}").format(OPT_LXC))
unmanaged_service(u'stop', u'lxc', u'systemd', display='console')
unmanaged_service(u'stop', u'lxc-net', u'systemd', display='console')
shutil.move(VAR_LXC, OPT_LXC)
os.symlink(OPT_LXC, VAR_LXC)
#first instance should be in minimal mode
minimal = True
ihm.print_title(_(u'Generating containers'))
engine = template.CreoleTemplateEngine()
rootctx = CACHE['group_infos']['root']
if minimal:
# inject var _minimal_mode in creole's vars that can be used in template
engine.creole_variables_dict['_minimal_mode'] = True
engine.instance_file(u'/etc/ssh/ssh_config', ctx=rootctx)
engine.instance_file(u'/etc/lxc/default.conf', ctx=rootctx)
engine.instance_file(u'/etc/dnsmasq.d/lxc', ctx=rootctx)
engine.instance_file(u'/etc/default/lxc-net', ctx=rootctx)
engine.instance_file(u'/etc/apt/apt.conf.d/02eoleproxy', ctx=rootctx)
if CACHE['module_instancie'] == 'oui':
engine.instance_file(u'/etc/resolv.conf', ctx=rootctx)
load_pkgmgr()
PKGMGR.pkgmgr._prepare_cache()
for group in CACHE['groups_container']:
generate_lxc_container(group)
groupctx = CACHE['group_infos'][group]
if minimal:
engine.instance_file(u'../fstab', container=group, ctx=groupctx)
engine.instance_file(u'../config', container=group, ctx=groupctx)
engine.instance_file(u'../devices.hook', container=group, ctx=groupctx)
engine.instance_file(u'/etc/network/interfaces', container=group, ctx=groupctx)
engine.instance_file(u'/etc/apt/apt.conf.d/02eoleproxy', container=group, ctx=groupctx)
engine.instance_file(u'/etc/ssh/sshd_config', container=group, ctx=groupctx)
if CACHE['module_instancie'] == 'oui':
container_path = os.path.join(groupctx['path'], 'etc/resolv.conf')
if os.path.islink(container_path):
os.remove(container_path)
engine.instance_file(u'/etc/resolv.conf', container=group, ctx=groupctx)
PKGMGR.pkgmgr._umount_cdrom()
ihm.print_title(_(u'Starting containers'))
_start_containers()
def remove_packages():
""" Remove packages listed in /usr/share/eole/remove.d/ files
param: repo: EoleApt Object
"""
torm_conf = glob(u'/usr/share/eole/remove.d/*.conf')
pkg_list = []
for config in torm_conf:
try:
f_h = open(config, 'r')
for line in f_h.readlines():
pkg_list.append(line.strip('\n'))
f_h.close()
except IOError, err:
log.error(_(u'Can not read file {0}: {1}').format(config, err))
try:
load_pkgmgr()
except (RepositoryError, AptProxyError, AptCacherError), err:
pass
kernels = fonctionseole.get_kernel_to_remove()
if kernels:
ihm.print_line(_(u"Removing old linux kernels and associate headers."))
pkg_list.extend(kernels)
if pkg_list != []:
try:
PKGMGR.remove(packages=pkg_list)
except (PackageNotFoundError, SystemError), err:
msg = _(u'Unable to remove some packages: {0}')
log.warn(msg.format(err))
log.warn(_(u"These packages will be removed next 'reconfigure'"))
CACHE = {}
def cache():
global CACHE
if not 'groups' in CACHE:
CACHE['groups'] = client.get_groups()
CACHE['groups_container'] = []
for group in CACHE['groups']:
if group not in ['root', 'all']:
CACHE['groups_container'].append(group)
CACHE['group_infos'] = {}
for group_name in CACHE['groups']:
group_infos = client.get_group_infos(group_name)
CACHE['group_infos'][group_name] = group_infos
CACHE['is_lxc_enabled'] = is_lxc_enabled()
CACHE['module_instancie'] = client.get_creole('module_instancie')
def install_packages(silent=False):
"""Install package for each container group
"""
load_pkgmgr()
cache()
header = _(u'Checking Packages for container')
for group_name, group_infos in CACHE['group_infos'].items():
package_names = [pkg[u'name'] for pkg in group_infos[u'packages']]
if package_names != []:
msg = header + ' {0}: {1}'.format(group_name, ' '.join(package_names))
ihm.print_line(msg)
PKGMGR.install(packages=package_names,
silent=silent,
container=group_infos[u'name'])
def packages():
"""Manage packages
"""
ihm.print_title(_(u'Managing packages'))
log.info(_(u' Removing packages'))
ihm.print_line(_(u'Removing packages'))
remove_packages()
log.info(_(u' Installing packages'))
ihm.print_line(_(u'Installing packages'))
install_packages()
def templates():
"""Run pretemplate scripts and manage templates
"""
ihm.print_title(_(u'Generating configuration files'))
log.info(_(u'Generating configuration files'))
cache()
try:
tmpl = template.CreoleTemplateEngine()
tmpl.instance_files(container=options.container, containers_ctx=CACHE['group_infos'].values())
except Exception, err:
if options.debug:
log.debug(err, exc_info=True)
else:
log.error(err)
raise err
def services(action, display_title=True, try_restart_lxc=True):
"""Manage services
"""
cache()
exclude = None
if action == u'stop':
if display_title:
ihm.print_title(_(u"Stopping services"))
exclude = (('root', 'networking'),)
elif action == u'start':
if display_title:
ihm.print_title(_(u"Starting services"))
# ne pas demarrer le service certbot, c'est un service oneshot
# et pyeole.service n'a pas l'air d'aimer ... #22092
exclude = (('root', 'networking'), ('root', 'certbot'))
ctx = CACHE['group_infos']['root']
manage_services(action, u'networking', display='console', containers_ctx=[ctx])
if try_restart_lxc and CACHE['is_lxc_enabled']:
if lxc_need_restart():
unmanaged_service(u'stop', u'lxc', u'systemd', display='console', ctx=ctx)
unmanaged_service(u'stop', u'lxc-net', u'systemd', display='console', ctx=ctx)
_start_containers()
elif action == u'configure':
if display_title:
ihm.print_title(_(u"Configuring services"))
else:
raise ValueError(_(u"Unknown service action: {0}").format(action))
if options.container is not None:
containers_ctx = [CACHE['group_infos'][options.containers]]
else:
containers_ctx = CACHE['group_infos'].values()
manage_services(action, container=options.container, display='console', exclude=exclude, containers_ctx=containers_ctx)
def _gen_user_list():
"""Generate list of users for password modification
Start with basic one and ask for supplementary users.
"""
yield 'root'
node = client.get_creole(u'activer_onenode', 'non')
master = client.get_creole(u'activer_onesinglenode', 'non')
if node == 'oui' and master == 'non':
yield 'oneadmin'
for number in count(1):
if number == 1:
yield 'eole'
else:
yield 'eole{0}'.format(number)
def users():
"""Manage users
"""
from passlib.context import CryptContext
ihm.print_title(_(u'Managing system user accounts'))
schemes = [u'sha512_crypt', u'sha256_crypt', u'sha1_crypt', u'md5_crypt']
cryptctx = CryptContext(schemes=schemes)
default_pass = {u'root': u'$eole&123456$',
u'eole': u'$fpmf&123456$',
u'oneadmin': u'$eole&123456$'}
if not options.interactive:
log.debug(_(u'No system user account management in non-interactive mode.'))
return
for user in _gen_user_list():
try:
user_infos = spwd.getspnam(user)
except KeyError:
if user == u'root':
msg = _(u"'root' user unknown. This is abnormal.")
raise Exception(msg)
# no new administrator with NFS (#16321)
if user != 'eole' and client.get_creole(u'adresse_serveur_nfs', None) is not None:
log.warn(_(u'No new EOLE account with /home on NFS'))
break
prompt = _('Create new administrator user account {0}?')
if user != 'eole' and ihm.prompt_boolean(prompt.format(user)) is False:
break
msg = _(u"Creating unexistent user {0}")
log.info(msg.format(user))
cmd = ['adduser', '--quiet', '--shell', '/usr/bin/manage-eole',
'--gecos', '{0} user'.format(user.upper()),
'--disabled-password', user]
code = process.system_code(cmd)
if code != 0:
msg = _(u"Unable to create user {0}")
raise Exception(msg.format(user))
cmd = ['usermod', '--append', '--groups', 'adm,mail', user]
code, out, err = process.system_out(cmd)
if code != 0:
msg = _(u"Unable to add '{0}' to group 'adm'.")
raise Exception(msg.format(user))
# Update informations
user_infos = spwd.getspnam(user)
if user not in default_pass and user_infos.sp_pwd not in ['!', '*']:
msg = _(u"No modification of password of administrator user account {0}.")
log.warn(msg.format(user))
continue
# Change password:
# - on first instance
# - if user is not an EOLE default user
# - if user password match default ones
if (not os.path.isfile(INSTANCE_LOCKFILE)
or (user not in default_pass or user_infos.sp_pwd in ['!', '*']
or cryptctx.verify(default_pass[user], user_infos.sp_pwd))):
msg = _(u"# Modificating password for user account {0} #")
msg = msg.format(user)
log.warn(u'#' * len(msg))
log.warn(msg)
log.warn(u'#' * len(msg))
max_try = 5
prompt = u'{0}{1}: '
first_prompt = _(u"New password")
second_prompt = _(u"Confirming new password")
loop_counter = u''
for attempt in range(1, max_try+2):
if attempt == max_try+1:
msg = _(u"Password input errors for {0}. Abandon.")
raise Exception(msg.format(user))
loop_counter = loop_counter.format(attempt, max_try)
passwd = getpass.getpass(prompt.format(first_prompt,
loop_counter))
confirm_pass = getpass.getpass(prompt.format(second_prompt,
loop_counter))
if passwd == confirm_pass:
if user in default_pass and default_pass[user] == passwd:
log.error(_(u"Can not use default password."))
else:
# Now we have the password
stdin = '{0}:{1}'.format(user, passwd)
code, stdout, stderr = process.system_out(['chpasswd'],
stdin=stdin)
if code == 0:
msg = _(u'User {0} password updated.')
log.info(msg.format(user))
# Success
break
msg = _(u"Error changing password for {0}.")
try_again_pos = stdout.find('Try again.')
chpassmsg = stdout[0:try_again_pos]
log.error(msg.format(user))
print chpassmsg
else:
log.error(_(u"Passwords mismatch."))
# Display counter
loop_counter = u' ({0}/{1})'
def certificates():
"""Manage certificates
"""
ihm.print_title(_(u'Managing certificates'))
try:
# regénération des hashes des certificats SSL après avec créé les nouveaux certificats
# porté de 2.3 #8488
cert.rehash_if_needed()
cert.gen_certs()
except Exception, err:
if options.debug:
log.debug(err, exc_info=True)
else:
log.error(err)
raise Exception(_(u"Error while generating certificates: {0}").format(err))
cache()
if CACHE['is_lxc_enabled']:
src = os.path.join(cert.ssl_dir, "certs")
for group_name in CACHE['groups_container']:
group = CACHE['group_infos'][group_name]
ihm.print_line(_("Copying certificates in {0}").format(group['name']))
dst = os.path.join('/', group['path'].lstrip('/').encode(charset), src.lstrip('/'))
copyDirectoryContent(src, dst)
process.system_out(['/usr/bin/c_rehash'], container=group_name)
def param_kernel():
"""Manage kernel parameters
"""
ihm.print_title(_(u'Applying kernel parameters'))
os.system('/sbin/sysctl -p >/dev/null')
def kill_dhclient():
"""Kill dhclient for static IP configuration.
"""
if client.get_creole(u'eth0_method') == u'statique':
os.system('killall dhclient dhclient3 2>/dev/null')
def finalize(need_lock=True):
"""Clean up
"""
ihm.print_title(_(u'Finalizing configuration'))
# enregistrement
try:
process.system_out("/usr/share/creole/diag.py")
except Exception:
pass
fonctionseole.zephir("FIN", "Configuration terminée", COMPAT_NAME.upper())
if not os.path.isfile(INSTANCE_LOCKFILE):
# l'instance est allée à son terme (#7051)
file(INSTANCE_LOCKFILE, 'w').close()
if os.path.isfile(UPGRADE_LOCKFILE):
os.unlink(UPGRADE_LOCKFILE)
if os.path.isfile(container_instance_lockfile):
os.unlink(container_instance_lockfile)
# sauvegarde des 2 dernières versions de la configuration (#8455)
old = '{0}.bak'.format(configeol)
old1 = '{0}.bak.1'.format(configeol)
if not os.path.isfile(old):
log.debug(_(u'Backup {0} in {1}'.format(configeol, old)))
shutil.copy(configeol, old)
elif process.system_out(['diff', '-q', configeol, old])[0] == 0:
log.debug(_(u"{0} was not modified".format(configeol)))
else:
log.debug(_(u'Backup {0} in {1}'.format(old, old1)))
shutil.copy(old, old1)
log.debug(_(u'Backup {0} in {1}'.format(configeol, old)))
shutil.copy(configeol, old)
if need_lock:
unlock_actions()
def update_server():
"""Manage server update
"""
if os.path.isfile(MAJ_SUCCES_LOCK):
os.remove(MAJ_SUCCES_LOCK)
if options.interactive:
log.info(_(u'Managing update'))
ihm.print_title(_(u'Updating server'))
if ihm.prompt_boolean(_(u"""An update is recommended.
Do you want to proceed with network update now ?"""),
default=True, level='warn',
default_uninteractive=False) is True:
report(2)
try:
load_pkgmgr()
_configure_sources_mirror(PKGMGR.pkgmgr)
PKGMGR.update(silent=True)
upgrades = PKGMGR.get_upgradable_list(silent=True)
require_dist_upgrade = False
for container, upgrades in upgrades.items():
if upgrades:
require_dist_upgrade = True
break
if require_dist_upgrade:
# At least one container require upgrade
PKGMGR.dist_upgrade()
# Update lock => OK, will be deleted at next reconfigure
report(0)
# recall reconfigure
main(force_options={'interactive': False})
# back to instance
options.interactive = True
reset_compat_name()
else:
log.warn(_(u"No updates available."))
report(3)
except Exception, err:
report(1, normalize(err))
raise err
def schedule():
"""Manage task scheduling
"""
ihm.print_title(_(u'Task scheduling'))
apply_schedules()
display_schedules()
# 1er lancement de instance
#if not os.path.isfile(schedule.SCHEDULE_FILE):
# schedule.add_post_schedule('majauto', 'weekly')
#schedule.prog_schedule()
def is_valid_ip_eth0():
"""Check if adresse_ip_eth0 is 169.254.0.1
"""
ip_eth0 = client.get_creole(u'adresse_ip_eth0')
if ip_eth0 == "169.254.0.1":
return False
else:
return True
def reboot_server():
"""Reboot the server if required
"""
if fonctionseole.controle_kernel():
if options.interactive:
print
if ihm.prompt_boolean(_(u"""Reboot is necessary.
Do you want to reboot now?"""),
default=True, level='warn') is True:
fonctionseole.zephir("MSG",
"Demande de redémarrage acceptée par l'utilisateur",
COMPAT_NAME.upper())
process.system_code(['reboot'])
else:
fonctionseole.zephir("MSG",
"Demande de redémarrage refusée par l'utilisateur",
COMPAT_NAME.upper())
else:
print
ihm.print_orange(_(u'Reboot necessary'))
time.sleep(1)
print
if options.auto:
fonctionseole.zephir("MSG", "Redémarrage automatique",
COMPAT_NAME.upper())
process.system_code(['reboot'])
else:
fonctionseole.zephir("MSG", "Redémarrage du serveur à planifier",
COMPAT_NAME.upper())
def main(force_options=None, force_args=None, need_lock=True):
"""Entry point
"""
global log
options.update_from_cmdline(force_args=force_args,
force_options=force_options)
try:
# module level logger
log = init_logging(name=u'reconfigure', level=options.log_level,
console=['stderr', 'stddebug'],
filename=_LOGFILENAME)
# Remove module name prefix from Warn/error messages emitted
# from here
set_formatter(log, 'stderr', 'brief')
# Define handlers for additional loggers
# Thoses logger are not for use
# Log pyeole.service
pyeole_service_log = init_logging(name=u'pyeole.service',
level=options.log_level,
filename=_LOGFILENAME,
console=['stderr'])
# Log pyeole.pkg
pyeole_pkg_log = init_logging(name=u'pyeole.pkg',
level=options.log_level,
filename=_LOGFILENAME)
passlib_log = init_logging(name=u'passlib.registry',
level='error',
filename=_LOGFILENAME)
# Disable warnings from pyeole.service
set_filters(pyeole_service_log, 'stderr',
['error', 'critical'])
if options.verbose or options.debug:
# Enable creole logs
creole_log = init_logging(name=u'creole', level=options.log_level,
filename=_LOGFILENAME)
# Define a root logger when verbose or debug is activated
root_log = init_logging(level=options.log_level)
else:
# Enable creole logs
creole_log = init_logging(name=u'creole', level=options.log_level,
filename=_LOGFILENAME,
console=['stderr'])
creolemajauto_log = init_logging(name=u'creole.majauto', level=options.log_level,
filename=_LOGFILENAME, console=['stderr', 'stdout'])
ihm.print_title(_(u'Beginning of configuration'))
# instance or reconfigure ?
reset_compat_name()
fonctionseole.zephir("INIT", "Début de configuration",
COMPAT_NAME.upper())
prepare(need_lock)
valid_mandatory(need_lock)
cache()
containers()
packages()
run_parts(u'preservice')
services(action=u'stop')
run_parts(u'pretemplate')
templates()
if not is_valid_ip_eth0():
log.info(_(u"eth0 network interface does not have a valid IP address."))
log.info(_(u"Restarting networking service"))
manage_service(u'restart', u'networking', display='console')
templates()
if not is_valid_ip_eth0():
log.info(_(u"eth0 network interface does not have a valid IP address."))
msg = _(u"Unable to obtain IP address.")
raise NetworkConfigError(msg)
services(action=u'configure')
# posttemplate/00-annuaire needs the certificates
certificates()
run_parts(u'posttemplate')
#close all connexion before param kernel #17408
client.close()
param_kernel()
kill_dhclient()
services(action=u'start')
users()
run_parts(u'postservice')
schedule()
finalize(need_lock)
ihm.print_title(_(u'Reconfiguration OK'))
update_server()
# IMPORTANT : Ne rien faire après ces lignes
# car le serveur est susceptible d'être redémarré
reboot_server()
except (UserExit, UserExitError), err:
unlock_actions(need_lock)
fonctionseole.zephir("FIN", "Abandon par l'utilisateur",
COMPAT_NAME.upper())
raise err
except Exception, err:
if options.debug:
log.debug(err, exc_info=True)
else:
log.error(err)
fonctionseole.zephir('ERR', str(err),
COMPAT_NAME.upper(),
console=False)
if need_lock:
release(LOCK_NAME, valid=False, level='system')
raise err
if __name__ == '__main__':
main()