diff --git a/CHANGES.md b/CHANGES.md index e383728..12709a3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,24 @@ +## Version 6.1.0 du 13/02/2017-17:06 + +* `748c2f7` Intégration de la branche update-network + * `367acfe` marquer les fichiers à ignorer pour les projets dépendants + * `ad19121` ipcalc: utiliser ip route au lieu de route + * `feb00bc` support de libvirt sur jessie + * `fa3d3b4` début de réorganisation des fonctions +* `b266663` uproject push: support des options -abt avec des arguments +* `286d1fe` pcrone: support des dépôt en http +* `67f29dd` ulib/sysinfos: implémenter dump_sysinfos, unsupported_system, require_sysinfos +* `a8fa722` ulib/runs: quelques corrections mineures +* `e9e4e6a` correction mineure avec les options de yum +* `e5f0df2` ulib/sysinfos: support de oracle linux; correction d'un bug pour macosx +* `27a2ab0` pyulib: ajouter l'argument nocopy=False à seqof() pour éviter des bugs subtils +* `11b87fd` ajout de netconfig: gestion des interfaces réseaux +* `87edaad` Intégration de la branche better-umountr + * `83d6db3` auto-complétion pour umountr + * `f34f32a` support des options --[no-]recursive et --[no-]poweroff + * `a7ee78f` description branche +* `35a55f0` ajout du script create-user, pour créer un utilisateur sudoer et lui installer une clé publique ssh + ## Version 6.0.1 du 30/12/2016-18:39 * `e79658e` maj de la doc diff --git a/EnsureVM b/EnsureVM index f54042f..ff012dc 100755 --- a/EnsureVM +++ b/EnsureVM @@ -54,19 +54,24 @@ function ensure_kvm() { [ -n "$modified" ] && sleep 1 service= - if check_sysinfos -d redhatlike; then + function __guess_service() { for i in libvirtd libvirtd-bin; do [ -f "/etc/init.d/$i" ] && { service="$i" break } done + } + if check_sysinfos -d redhatlike; then + __guess_service + elif check_sysinfos -d debian -v jessie+; then + __guess_service elif check_sysinfos -d debianlike; then service=libvirt-bin fi if [ -n "$service" ]; then # s'assurer que le service tourne - service libvirt-bin startm + service "$service" startm else return 0 fi diff --git a/VERSION.txt b/VERSION.txt index 5fe6072..dfda3e0 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -6.0.1 +6.1.0 diff --git a/create-user b/create-user new file mode 100755 index 0000000..997f905 --- /dev/null +++ b/create-user @@ -0,0 +1,173 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname "$0")/lib/ulib/ulib" || exit 1 +urequire DEFAULTS + +function display_help() { + uecho "$scriptname: créer un utilisateur sudoer et lui installer une clé publique ssh + +USAGE + $scriptname user [-p pubkey] + +OPTIONS + -p, --pkfile PKFILE + Installer la clé publique ssh contenue dans le fichier spécifié. Par + défaut, prendre le fichier ~/.ssh/id_rsa.pub de l'utilisateur courant. + -s, --pkstring PUBKEY + Installer la clé publique ssh spécifiée. Cette option avancée n'est pas + utilisée en temps normal. Elle a la priorité sur l'option --pkfile + -l, --luser + Ne pas donner à l'utilisateur le droit de sudoer. + -h, --host [USER@]HOST + Créer l'utilisateur sur l'hôte distant spécifié. Si l'utilisateur + distant n'est pas root, il doit être sudoer. + -T, --tmproot TMPROOT + Spécifier le répertoire temporaire sur l'hôte distant, comme par exemple + /var/tmp. Cette option est utile pour certains serveurs, qui ont un /tmp + minuscule. + -S, --ssh SSH + Spécifier le programme à utiliser pour la connection par ssh." +} + +function create_user() { + # Créer le user, si nécessaire + # retourner vrai si le user a été créé, faux si ce n'était pas nécessaire + local user="$1" password="$2" + [ -z "$(getent passwd "$user")" ] || return 1 + estep "Creation de l'utilisateur $user..." + useradd -s /bin/bash -m "$user" + [ -n "$password" ] || return 0 + if ! (echo "$password" | passwd --stdin "$user" 2>/dev/null); then + echo "$user:$password" | chpasswd + fi + return 0 +} + +function init_sudoer() { + local user="$1" + local TAB=$'\t' + if [ -d /etc/sudoers.d ]; then + if [ ! -f "/etc/sudoers.d/$user" ]; then + estep "Ajout de $user comme sudoer dans /etc/sudoers.d/$user" + echo "$user${TAB}ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/$user" + chmod 440 "/etc/sudoers.d/$user" + fi + elif [ -f /etc/sudoers ]; then + if ! grep -q "^$user" /etc/sudoers; then + estep "Ajout de user comme sudoer dans /etc/sudoers..." + echo "$user${TAB}ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers + fi + fi +} + +function install_pubkeys() { + # Installer la clé $1 pour l'utilisateur $2 + # $1 peut contenir autant de clés que nécessaire, une par ligne + local user="$1" pubkeys="$2" + local homedir="$(eval "echo ~$user")" + [ -d "$homedir" ] || return + + local sshdir="$homedir/.ssh" + if [ ! -d "$sshdir" ]; then + mkdir -p "$sshdir" + chmod 700 "$sshdir" + chown -R "$user:" "$sshdir" + fi + local ak="$sshdir/authorized_keys" + if [ ! -f "$ak" ]; then + touch "$ak" + chown "$user:" "$ak" + fi + + local -a pks + local pk + array_from_lines pks "$pubkeys" + for pk in "${pks[@]}"; do + if ! grep -q "$pk" "$ak"; then + estep "Installation de la clé ${pk:0:20}... pour $user" + echo "$pk" >>"$ak" + fi + done +} + +pkfile= +pkstring= +luser= +host= +tmproot= +SSH= +args=( + --help '$exit_with display_help' + -p:,--pkfile: pkfile= + -s:,--pkstring: pkstring= + -l,--luser luser=1 + -h:,-H:,--host: host= + -T:,--tmproot: tmproot= + -S:,--ssh: SSH= +) +parse_args "$@"; set -- "${args[@]}" + +user="$1" +[ -n "$user" ] || die "Vous devez spécifier l'utilisateur à créer" + +if [ -z "$pkstring" ]; then + if [ -z "$pkfile" ]; then + if [ -f ~/.ssh/id_rsa.pub ]; then pkfile=~/.ssh/id_rsa.pub + elif [ -f ~/.ssh/id_dsa.pub ]; then pkfile=~/.ssh/id_dsa.pub + fi + fi + if [ -f "$pkfile" ]; then pkstring="$(<"$pkfile")" + elif [ -n "$pkfile" ]; then die "$pkfile: fichier introuvable" + fi +fi + +if [ -z "$host" ]; then + # déploiement local + run_as_root ${pkstring:+-s "$pkstring"} ${luser:+-l} "$user" + create_user "$user" + [ -z "$luser" ] && init_sudoer "$user" + [ -n "$pkstring" ] && install_pubkeys "$user" "$pkstring" + exit 0 + +else + # déploiement distant + if [ -n "$host" ]; then + splituserhost "$host" remoteuser host + [ -n "$remoteuser" ] || remoteuser=root + fi + if [ -n "$SSH" ]; then + ssh=("$SSH" -o StrictHostKeyChecking=no -o ConnectTimeout=2 -qt) + scp=(scp -S "$SSH" -o StrictHostKeyChecking=no -o ConnectTimeout=2 -q) + else + ssh=(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=2 -qt) + scp=(scp -o StrictHostKeyChecking=no -o ConnectTimeout=2 -q) + fi + + ac_set_tmpdir workdir + mkdir "$workdir/lib" + ulibsync "$workdir/lib" + cp "$script" "$workdir" + echo "#!/bin/bash +$(qvals "./$scriptname" ${pkstring:+-s "$pkstring"} ${luser:+-l} "$user")" >"$workdir/do_remote" + chmod +x "$workdir/do_remote" + + ac_set_tmpfile archive + archivename="$(basename "$archive")" + + "$scriptdir/mkusfx" --tmp-archive --bare -o "$archive" "$workdir" ./do_remote || die + + estep "Copie du script sur $remoteuser@$host" + "${scp[@]}" "$archive" "$remoteuser@$host:" || die + + estep "Exécution du script" + "${ssh[@]}" "$remoteuser@$host" "\ +__estack=$(quoted_arg "$__estack") +__tlevel=$(quoted_arg "$__tlevel") +export __estack __tlevel +${UTOOLS_LANG:+UTOOLS_LANG='$UTOOLS_LANG'; export UTOOLS_LANG +}$(quoted_args "./$archivename" ${tmproot:+--tmproot "$tmproot"})" + r=$? + ac_clean "$workdir" + + exit $r +fi \ No newline at end of file diff --git a/lib/completion.d/nutools b/lib/completion.d/nutools index 79494ac..527d07d 100644 --- a/lib/completion.d/nutools +++ b/lib/completion.d/nutools @@ -13,3 +13,7 @@ if __bash_completion_module_enabled ssh; then shopt -u hostcomplete complete -F _ssh ussh cssh fi + +if __bash_completion_module_enabled umount; then + complete -F _umount -o dirnames umountr +fi diff --git a/lib/pyulib/src/.gitignore b/lib/pyulib/src/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/lib/pyulib/src/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/lib/pyulib/src/ulib/base/base.py b/lib/pyulib/src/ulib/base/base.py index cf9a3e0..22850b5 100644 --- a/lib/pyulib/src/ulib/base/base.py +++ b/lib/pyulib/src/ulib/base/base.py @@ -249,13 +249,17 @@ def isseq(t): """Tester si t est une séquence (list ou tuple) """ return isinstance(t, list) or isinstance(t, tuple) -def seqof(seq, seq_if_None=None): +def seqof(seq, seq_if_None=None, nocopy=False): """Retourner une séquence. - Si seq est une séquence, retourner l'objet lui-même. + Si seq est une séquence, retourner une copie de l'objet si nocopy==False, + sinon l'objet lui-même. Si seq==None et que seq_if_None!=None, retourner seq_if_None. Sinon, retourner une liste ayant un seul élément, seq. + """ - if isseq(seq): return seq + if isseq(seq): + if nocopy: return seq + else: return seq[:] elif seq is None and seq_if_None is not None: if not isseq(seq_if_None): seq_if_None = [seq_if_None] return seq_if_None diff --git a/lib/ulib/.gitignore b/lib/ulib/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/lib/ulib/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/lib/ulib/.ulibver b/lib/ulib/.ulibver index aa19da0..e74570a 100644 --- a/lib/ulib/.ulibver +++ b/lib/ulib/.ulibver @@ -1 +1 @@ -014000000 +014001000 diff --git a/lib/ulib/debian b/lib/ulib/debian index 52e3605..475020d 100644 --- a/lib/ulib/debian +++ b/lib/ulib/debian @@ -79,319 +79,6 @@ function service_enable() { __DEBIAN_NETWORK_DEVEL_SHOW_MODIFS= __DEBIAN_NETWORK_INTERFACES=/etc/network/interfaces -function __network_parse_confbr() { - local br; local -a ifaces - splitpair "$1" br ifaces - array_split ifaces "$ifaces" , - - __npc_destbr="$br" - array_copy __npc_destifaces ifaces -} -function network_parse_confbr() { - # network_parse_confbr "$confbr" br ifaces - local __npc_destbr; local -a __npc_destifaces - __network_parse_confbr "$1" - - set_var "${2:-br}" "$__npc_destbr" - array_copy "${3:-ifaces}" __npc_destifaces -} - -function network_format_confbr() { - # network_format_confbr "$br" ifaces --> "br:ifaces" - echo "$1:$(array_join "${2:-ifaces}" ,)" -} - -function __network_parse_confip() { - local tmpig iface gateway; local -a ipsuffixes - splitfsep2 "$1" : tmpig ipsuffixes - splitfsep "$tmpig" // iface gateway - array_split ipsuffixes "$ipsuffixes" , - - __npc_destiface="$iface" - __npc_destgateway="$gateway" - array_copy __npc_destipsuffixes ipsuffixes -} -function network_parse_confip() { - # network_parse_confip "$confip" iface gateway ipsuffixes - local __npc_destiface __npc_destgateway; local -a __npc_destipsuffixes - __network_parse_confip "$1" - - set_var "${2:-iface}" "$__npc_destiface" - set_var "${3:-gateway}" "$__npc_destgateway" - array_copy "${4:-ipsuffixes}" __npc_destipsuffixes -} - -function network_parse_ipsuffix() { - # network_parse_ipsuffix "$ipsuffix" ip suffix - splitfsep "$1" / "${2:-ip}" "${3:-suffix}" -} - -function network_format_confip() { - # network_format_confip "$iface" "$gateway" ipsuffixes --> "iface//gateway:ipsuffixes" - local tmpig="$1${2:+//$2}" - echo "${tmpig:+$tmpig:}$(array_join "${3:-ipsuffixes}" ,)" -} - -function network_format_ipsuffix() { - # network_format_ipsuffix "$ip" "$suffix" --> "ip/suffix" - local ip="$(strlower "$1")" - if [ "$ip" == "dhcp" ]; then - echo "$ip" - else - echo "$1${2:+/$2}" - fi -} - -function __network_fix_confbrs() { - local -a confbrs ifaces brs ips - local confbr br iface - - # recenser les bridges et créer les tableaux __BR_ifaces - for confbr in "${__nfc_confbrs[@]}"; do - network_parse_confbr "$confbr" br ifaces - array_addu brs "$br" - eval "local -a ${br}_ifaces" - done - # puis constuire la liste des interfaces associées à chaque bridge - for confbr in "${__nfc_confbrs[@]}"; do - network_parse_confbr "$confbr" br ifaces - array_extendu "${br}_ifaces" ifaces - done - # puis construire le tableau final - array_new confbrs - for br in "${brs[@]}"; do - array_add confbrs "$(network_format_confbr "$br" "${br}_ifaces")" - done - - array_copy __nfc_destconfbrs confbrs -} -function network_fix_confbrs() { - # normaliser le tableau $1(=confbrs): fusionner les doublons - local -a __nfc_confbrs __nfc_destconfbrs - array_copy __nfc_confbrs "${1:-confbrs}" - __network_fix_confbrs - - array_copy "${1:-confbrs}" __nfc_destconfbrs -} - -function __network_fix_confips() { - local -a confips ipsuffixes ifaces ips - local confip iface gateway network ip suffix mainip - - local mainiface="$1" - - # recenser les interfaces et créer les tableaux __IFACE_ipspecs - for confip in "${__nfc_confips[@]}"; do - network_parse_confip "$confip" iface gateway ipsuffixes - if [ -n "$iface" ]; then - network="${iface}_network" - if ! array_contains ifaces "$iface"; then - array_add ifaces "$iface" - eval "local ${iface}_gateway $network; local -a ${iface}_ipsuffixes" - fi - if [ -z "${!network}" -a -n "${ipsuffixes[0]}" ]; then - setv "$network" "$(ipcalc_network "${ipsuffixes[0]}")" - fi - fi - done - # puis construire la liste des adresses IP associées à chaque interface - for confip in "${__nfc_confips[@]}"; do - network_parse_confip "$confip" iface gateway ipsuffixes - # si aucune interface n'est spécifiée, sélectionner celle correspondant - # à la même adresse de réseau. sinon prendre $mainiface - if [ -z "$iface" ]; then - network="$(ipcalc_network "${ipsuffixes[0]}")" - local ip_iface ip_network - for ip_iface in "${ifaces[@]}"; do - ip_network="${ip_iface}_network" - if [ "${!ip_network}" == "$network" ]; then - iface="$ip_iface" - break - fi - done - fi - [ -n "$iface" ] || iface="$mainiface" - # si la passerelle a déjà été spécifiée, la récupérer - local tmpgw="${iface}_gateway" - [ -n "${!tmpgw}" ] && gateway="${!tmpgw}" - # calculer l'adresse ip principale, pour pouvoir traiter le cas où - # l'adresse ip principale est l'adresse de la passerelle. - mainip= - for ipsuffix in "${ipsuffixes[@]}"; do - network_parse_ipsuffix "$ipsuffix" ip suffix - if ! array_contains ips "$ip"; then - [ -n "$suffix" ] || suffix=24 - if [ -z "$mainip" ]; then - [ -n "$gateway" ] || gateway="$(ipcalc_gateway "$ip" "$suffix")" - mainip="$ip" - fi - array_add "${iface}_ipsuffixes" "$(network_format_ipsuffix "$ip" "$suffix")" - array_add ips "$ip" - fi - done - [ "$gateway" == "$mainip" ] && gateway= - # si l'adresse ip principale est obtenue par dhcp, il ne faut pas - # spécifier la passerelle: elle sera fournie par le serveur DHCP. - # Utiliser le marqueur "none" pour que la valeur ne soit pas modifiée. - [ "${ipsuffixes[0]}" == "dhcp" ] && gateway=none - set_var "${iface}_gateway" "$gateway" - done - # puis construire le tableau final - array_new confips - for iface in "${ifaces[@]}"; do - gateway="${iface}_gateway"; gateway="${!gateway}" - [ "$gateway" == "none" ] && gateway= - array_add confips "$(network_format_confip "$iface" "$gateway" "${iface}_ipsuffixes")" - done - - array_copy __nfc_destconfips confips -} -function network_fix_confips() { - # normaliser le tableau $1(=confips): fusionner les doublons, spécifier le - # suffixe /24 par défaut, etc. $2 est le cas échéant l'interface associée - # aux adresses ip non qualifiées - local -a __nfc_confips __nfc_destconfips - array_copy __nfc_confips "${1:-confips}" - __network_fix_confips "$2" - - array_copy "${1:-confips}" __nfc_destconfips -} - -function __network_fix_mainiface() { - local -a confips ifaces ipsuffixes - local br iface gateway confip mainconfip - - local mainiface="$1" - - # déterminer mainiface - if [ -z "$mainiface" -a -n "${__nfm_confbrs[0]}" ]; then - network_parse_confbr "${__nfm_confbrs[0]}" br ifaces - mainiface="$br" - fi - if [ -z "$mainiface" -a -n "${__nfm_confips[0]}" ]; then - network_parse_confip "${__nfm_confips[0]}" iface gateway ipsuffixes - mainiface="$iface" - fi - [ -n "$mainiface" ] || mainiface=eth0 - - # ensuite, il faut reécrire confips avec la valeur de mainiface - array_new confips - for confip in "${__nfm_confips[@]}"; do - network_parse_confip "$confip" iface gateway ipsuffixes - [ -n "$iface" ] || iface="$mainiface" - confip="$(network_format_confip "$iface" "$gateway" ipsuffixes)" - if [ "$iface" == "$mainiface" ]; then - mainconfip="$confip" - else - array_add confips "$confip" - fi - done - [ -n "$mainconfip" ] && array_ins confips "$mainconfip" - - array_copy __nfm_destconfips confips -} -function network_fix_mainiface() { - # A partir des valeurs des tableaux $1(=confbrs) et $2(=confips), et de - # l'interface principale $3, déterminer l'interface principale. Si $3 est - # spécifié, c'est la valeur sélectionnée. Sinon, si un bridge existe, c'est - # le premier bridge qui est sélectionné. Sinon, la première interface est - # sélectionnée. Sinon, on prend eth0. - # Ensuite, réorganiser les tableaux de façon que confips[0] devienne la - # configuration ip de l'interface principale. - local -a __nfm_confbrs __nfm_confips __nfm_destconfips - array_copy __nfm_confbrs "${1:-confbrs}" - array_copy __nfm_confips "${2:-confips}" - __network_fix_mainiface "$3" - - array_copy "${2:-confips}" __nfm_destconfips -} - -function network_fix_confs() { - network_fix_confbrs "${1:-confbrs}" - network_fix_confips "${2:-confips}" - network_fix_mainiface "${1:-confbrs}" "${2:-confips}" "$3" -} - -function __network_valid_ifaces() { - ip link | awk '/<.*>/ { - flags = $0; sub(/^.*.*$/, ",", flags) - if (flags ~ /,LOOPBACK,/) next - if (flags !~ /,UP,/) next - sub(/:$/, "", $2); print $2 -}' -} - -function __network_set_confbrs() { - local -a ifaces tmpconfbrs confbrs - local confbr br iface - array_from_lines ifaces "$(__network_valid_ifaces)" - array_from_lines tmpconfbrs "$(brctl show 2>/dev/null | awk ' -BEGIN { confbrs = "" } -NR == 1 { next } -{ - if ($1 != "" && $2 != "") { - if (confbr != "") print confbr - confbr = $1 ":" $4 - } else { - confbr = confbr "," $1 - } -} -END { - if (confbr != "") print confbr -} -')" - for confbr in "${tmpconfbrs[@]}"; do - splitpair "$confbr" br iface - array_contains ifaces "$br" || continue - array_add confbrs "$confbr" - done - - array_copy __nsc_destconfbrs confbrs -} -function network_set_confbrs() { - # initialiser $1(=confbrs) avec l'état des bridges sur le système courant - local -a __nsc_destconfbrs - __network_set_confbrs - - array_copy "${1:-confbrs}" __nsc_destconfbrs -} - -function __network_set_gateway() { - # initialiser la variable gateway avec la passerelle associée à l'interface - # $1 - gateway="$(route -n | awk -v iface="$1" '$1 == "0.0.0.0" && $8 == iface { print $2 }')" -} -function __network_set_confip() { - # initialiser la variable confip avec l'état de l'interface $1, en assumant - # que la passerelle vaut $2. - # retourner 1 si l'interface n'a pas d'adresse ip associée - local -a ipsuffixes - array_from_lines ipsuffixes "$(ip addr show dev "$1" | awk '$1 == "inet" { print $2 }')" - confip="$(network_format_confip "$1" "$2" ipsuffixes)" - [ "${#ipsuffixes[*]}" -gt 0 ] -} -function __network_set_confips() { - local -a confips ifaces - local iface gateway - array_from_lines ifaces "$(__network_valid_ifaces)" - for iface in "${ifaces[@]}"; do - __network_set_gateway "$iface" - [ -n "$gateway" ] || gateway=- - __network_set_confip "$iface" "$gateway" || continue - array_add confips "$confip" - done - - array_copy __nsc_destconfips confips -} -function network_set_confips() { - # initialiser le tableau $1(=confips) avec l'état des interfaces sur le - # système courant - local -a __nsc_destconfips - __network_set_confips - - array_copy "${1:-confips}" __nsc_destconfips -} - function network_interfaces_check_confbr() { # Vérifier que la configuration du bridge $1, dont les membres sont les # interfaces du tableau $2(=ifaces) est faite dans le fichier @@ -783,17 +470,11 @@ iface $iface inet manual" bridge_maxwait 0" } -function __network_backup() { - local file="$1" - local backup="$file.orig$(date +%Y%m%d)" - [ -f "$backup" ] || cat "$file" >"$backup" 2>/dev/null -} - function network_fix_hostname() { local hostname="${1%%.*}" local modified [ -f /etc/hostname ] || touch /etc/hostname - if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" ]; then + if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" -o -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then uecho "Setting /etc/hostname to $hostname" elif [ "$("$tmpfile" " -/^dc_other_hostnames=/c\\ -dc_other_hostnames='$host'" - if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" ]; then - if testdiff "$tmpfile" /etc/exim4/update-exim4.conf.conf; then - uecho "Setting /etc/exim4/update-exim4.conf.conf to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - uecho "/etc/exim4/update-exim4.conf.conf: pas de modifications" - fi - elif testdiff "$tmpfile" /etc/exim4/update-exim4.conf.conf; then - __network_backup /etc/exim4/update-exim4.conf.conf - if show_debug; then - edebug "Setting /etc/exim4/update-exim4.conf.conf to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - estep /etc/exim4/update-exim4.conf.conf - fi - cat "$tmpfile" >/etc/exim4/update-exim4.conf.conf - update-exim4.conf - modified=1 - fi - ac_clean "$tmpfile" - [ -n "$modified" ] -} - -function network_fix_postfix() { - local host="$1" oldhost="$2" - local tmpfile; ac_set_tmpfile tmpfile - local modified - - awkrun "$tmpfile" host="$host" oldhost="$oldhost" ' -/^myhostname *=/ { $0 = "myhostname = " host } -/^mydestination *=/ { - gsub(" *" oldhost " *,? *", "") - if ($0 !~ (" *" host " *,? *")) { - sub(/^mydestination *= */, "mydestination = " host ", ") - } -} -{ print }' - if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" ]; then - if testdiff "$tmpfile" /etc/postfix/main.cf; then - uecho "Setting /etc/postfix/main.cf to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - uecho "/etc/postfix/main.cf: pas de modifications" - fi - elif testdiff "$tmpfile" /etc/postfix/main.cf; then - __network_backup /etc/postfix/main.cf - if show_debug; then - edebug "Setting /etc/postfix/main.cf to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - estep /etc/postfix/main.cf - fi - cat "$tmpfile" >/etc/postfix/main.cf - modified=1 - fi - ac_clean "$tmpfile" - [ -n "$modified" ] -} - -function network_fix_hosts() { - local host="$1" hostname="${1%%.*}"; local shost="${host//./\\.}" - local ip="$2"; local sip="${ip//./\\.}" - local oldhost="$3" oldhostname="${3%%.*}"; soldhost="${host//./\\.}" - local tmpfile; ac_set_tmpfile tmpfile - local modified - - awkrun "$tmpfile" \ - host="$host" hostname="$hostname" \ - ip="$ip" \ - oldhost="$oldhost" oldhostname="$oldhostname" \ - ' -/^[^# \t]/ { - gsub("[ \\t]+" host "[ \\t]*", " ") - gsub("[ \\t]+" hostname "[ \\t]*", " ") - gsub("[ \\t]+" oldhost "[ \\t]*", " ") - gsub("[ \\t]+" oldhostname "[ \\t]*", " ") - if ($0 ~ /^[^ \t]+[ \t]*$/) next - gsub(/[ \t]*$/, "") -} -{ print }' - if quietgrep "^$sip[ $TAB]\\+$shost[ $TAB]\\+$hostname" "$tmpfile"; then - sed -i "\ -s/\$/ / -/^[ $TAB]$oldhost[ $TAB]/d -/^[ $TAB]$oldhostname[ $TAB]/d -s/ \$// -" "$tmpfile" - fi - if ! quietgrep "^$sip[ $TAB]\\+$shost[ $TAB]\\+$hostname" "$tmpfile"; then - sed -i "/^$sip[ $TAB]/d" "$tmpfile" - sed -i "1i\\ -$ip$TAB$host $hostname" "$tmpfile" - fi - - if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" ]; then - if testdiff "$tmpfile" /etc/hosts; then - uecho "Setting /etc/hosts to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - uecho "/etc/hosts: pas de modifications" - fi - elif testdiff "$tmpfile" /etc/hosts; then - __network_backup /etc/hosts - if show_debug; then - edebug "Setting /etc/hosts to:" - cat "$tmpfile" | sed 's/^/ /g' 1>&2 - else - estep /etc/hosts - fi - cat "$tmpfile" >/etc/hosts - modified=1 - fi - ac_clean "$tmpfile" - [ -n "$modified" ] -} - function network_config() { # (Re)configurer le réseau sur l'hôte courant. Des efforts sont faits pour # ne mettre à jour les fichiers que si c'est nécessaire. Si un des arguments @@ -1096,7 +653,7 @@ iface lo inet loopback done # Fin de traitement - if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" ]; then + if [ -n "$__DEBIAN_NETWORK_DEVEL_SHOW_MODIFS" -o -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then if testdiff "$interfaces" "$nifile"; then uecho "Setting $nifile to:" cat "$interfaces" | sed 's/^/ /g' 1>&2 diff --git a/lib/ulib/ipcalc b/lib/ulib/ipcalc index 61ca049..2b29c45 100644 --- a/lib/ulib/ipcalc +++ b/lib/ulib/ipcalc @@ -222,3 +222,471 @@ function ipcalc_fqdn_maybe() { ipcalc_fqdn "$1" fi } + +################################################################################ +# Fonctions génériques pour la gestion du réseau + +__NETWORK_DEVEL_SHOW_MODIFS= + +function __network_parse_confbr() { + local br; local -a ifaces + splitpair "$1" br ifaces + array_split ifaces "$ifaces" , + + __npc_destbr="$br" + array_copy __npc_destifaces ifaces +} +function network_parse_confbr() { + # network_parse_confbr "$confbr" br ifaces + local __npc_destbr; local -a __npc_destifaces + __network_parse_confbr "$1" + + set_var "${2:-br}" "$__npc_destbr" + array_copy "${3:-ifaces}" __npc_destifaces +} + +function network_format_confbr() { + # network_format_confbr "$br" ifaces --> "br:ifaces" + echo "$1:$(array_join "${2:-ifaces}" ,)" +} + +function __network_parse_confip() { + local tmpig iface gateway; local -a ipsuffixes + splitfsep2 "$1" : tmpig ipsuffixes + splitfsep "$tmpig" // iface gateway + array_split ipsuffixes "$ipsuffixes" , + + __npc_destiface="$iface" + __npc_destgateway="$gateway" + array_copy __npc_destipsuffixes ipsuffixes +} +function network_parse_confip() { + # network_parse_confip "$confip" iface gateway ipsuffixes + local __npc_destiface __npc_destgateway; local -a __npc_destipsuffixes + __network_parse_confip "$1" + + set_var "${2:-iface}" "$__npc_destiface" + set_var "${3:-gateway}" "$__npc_destgateway" + array_copy "${4:-ipsuffixes}" __npc_destipsuffixes +} + +function network_parse_ipsuffix() { + # network_parse_ipsuffix "$ipsuffix" ip suffix + splitfsep "$1" / "${2:-ip}" "${3:-suffix}" +} + +function network_format_confip() { + # network_format_confip "$iface" "$gateway" ipsuffixes --> "iface//gateway:ipsuffixes" + local tmpig="$1${2:+//$2}" + echo "${tmpig:+$tmpig:}$(array_join "${3:-ipsuffixes}" ,)" +} + +function network_format_ipsuffix() { + # network_format_ipsuffix "$ip" "$suffix" --> "ip/suffix" + local ip="$(strlower "$1")" + if [ "$ip" == "dhcp" ]; then + echo "$ip" + else + echo "$1${2:+/$2}" + fi +} + +function __network_fix_confbrs() { + local -a confbrs ifaces brs ips + local confbr br iface + + # recenser les bridges et créer les tableaux __BR_ifaces + for confbr in "${__nfc_confbrs[@]}"; do + network_parse_confbr "$confbr" br ifaces + array_addu brs "$br" + eval "local -a ${br}_ifaces" + done + # puis constuire la liste des interfaces associées à chaque bridge + for confbr in "${__nfc_confbrs[@]}"; do + network_parse_confbr "$confbr" br ifaces + array_extendu "${br}_ifaces" ifaces + done + # puis construire le tableau final + array_new confbrs + for br in "${brs[@]}"; do + array_add confbrs "$(network_format_confbr "$br" "${br}_ifaces")" + done + + array_copy __nfc_destconfbrs confbrs +} +function network_fix_confbrs() { + # normaliser le tableau $1(=confbrs): fusionner les doublons + local -a __nfc_confbrs __nfc_destconfbrs + array_copy __nfc_confbrs "${1:-confbrs}" + __network_fix_confbrs + + array_copy "${1:-confbrs}" __nfc_destconfbrs +} + +function __network_fix_confips() { + local -a confips ipsuffixes ifaces ips + local confip iface gateway network ip suffix mainip + + local mainiface="$1" + + # recenser les interfaces et créer les tableaux __IFACE_ipspecs + for confip in "${__nfc_confips[@]}"; do + network_parse_confip "$confip" iface gateway ipsuffixes + if [ -n "$iface" ]; then + network="${iface}_network" + if ! array_contains ifaces "$iface"; then + array_add ifaces "$iface" + eval "local ${iface}_gateway $network; local -a ${iface}_ipsuffixes" + fi + if [ -z "${!network}" -a -n "${ipsuffixes[0]}" ]; then + setv "$network" "$(ipcalc_network "${ipsuffixes[0]}")" + fi + fi + done + if [ -n "$mainiface" ]; then + iface="$mainiface" + if ! array_contains ifaces "$iface"; then + array_add ifaces "$iface" + eval "local ${iface}_gateway $network; local -a ${iface}_ipsuffixes" + fi + fi + # puis construire la liste des adresses IP associées à chaque interface + for confip in "${__nfc_confips[@]}"; do + network_parse_confip "$confip" iface gateway ipsuffixes + # si aucune interface n'est spécifiée, sélectionner celle correspondant + # à la même adresse de réseau. sinon prendre $mainiface + if [ -z "$iface" ]; then + network="$(ipcalc_network "${ipsuffixes[0]}")" + local ip_iface ip_network + for ip_iface in "${ifaces[@]}"; do + ip_network="${ip_iface}_network" + if [ "${!ip_network}" == "$network" ]; then + iface="$ip_iface" + break + fi + done + fi + [ -n "$iface" ] || iface="$mainiface" + # si la passerelle a déjà été spécifiée, la récupérer + local tmpgw="${iface}_gateway" + [ -n "${!tmpgw}" ] && gateway="${!tmpgw}" + # calculer l'adresse ip principale, pour pouvoir traiter le cas où + # l'adresse ip principale est l'adresse de la passerelle. + mainip= + for ipsuffix in "${ipsuffixes[@]}"; do + network_parse_ipsuffix "$ipsuffix" ip suffix + if ! array_contains ips "$ip"; then + [ -n "$suffix" ] || suffix=24 + if [ -z "$mainip" ]; then + [ -n "$gateway" ] || gateway="$(ipcalc_gateway "$ip" "$suffix")" + mainip="$ip" + fi + array_add "${iface}_ipsuffixes" "$(network_format_ipsuffix "$ip" "$suffix")" + array_add ips "$ip" + fi + done + [ "$gateway" == "$mainip" ] && gateway= + # si l'adresse ip principale est obtenue par dhcp, il ne faut pas + # spécifier la passerelle: elle sera fournie par le serveur DHCP. + # Utiliser le marqueur "none" pour que la valeur ne soit pas modifiée. + [ "${ipsuffixes[0]}" == "dhcp" ] && gateway=none + set_var "${iface}_gateway" "$gateway" + done + # puis construire le tableau final + array_new confips + for iface in "${ifaces[@]}"; do + gateway="${iface}_gateway"; gateway="${!gateway}" + [ "$gateway" == "none" ] && gateway= + array_add confips "$(network_format_confip "$iface" "$gateway" "${iface}_ipsuffixes")" + done + + array_copy __nfc_destconfips confips +} +function network_fix_confips() { + # normaliser le tableau $1(=confips): fusionner les doublons, spécifier le + # suffixe /24 par défaut, etc. $2 est le cas échéant l'interface associée + # aux adresses ip non qualifiées + local -a __nfc_confips __nfc_destconfips + array_copy __nfc_confips "${1:-confips}" + __network_fix_confips "$2" + + array_copy "${1:-confips}" __nfc_destconfips +} + +function __network_fix_mainiface() { + local -a confips ifaces ipsuffixes + local br iface gateway confip mainconfip + + local mainiface="$1" + + # déterminer mainiface + if [ -z "$mainiface" -a -n "${__nfm_confbrs[0]}" ]; then + network_parse_confbr "${__nfm_confbrs[0]}" br ifaces + mainiface="$br" + fi + if [ -z "$mainiface" -a -n "${__nfm_confips[0]}" ]; then + network_parse_confip "${__nfm_confips[0]}" iface gateway ipsuffixes + mainiface="$iface" + fi + [ -n "$mainiface" ] || mainiface=eth0 + + # ensuite, il faut reécrire confips avec la valeur de mainiface + array_new confips + for confip in "${__nfm_confips[@]}"; do + network_parse_confip "$confip" iface gateway ipsuffixes + [ -n "$iface" ] || iface="$mainiface" + confip="$(network_format_confip "$iface" "$gateway" ipsuffixes)" + if [ "$iface" == "$mainiface" ]; then + mainconfip="$confip" + else + array_add confips "$confip" + fi + done + [ -n "$mainconfip" ] && array_ins confips "$mainconfip" + + array_copy __nfm_destconfips confips +} +function network_fix_mainiface() { + # A partir des valeurs des tableaux $1(=confbrs) et $2(=confips), et de + # l'interface principale $3, déterminer l'interface principale. Si $3 est + # spécifié, c'est la valeur sélectionnée. Sinon, si un bridge existe, c'est + # le premier bridge qui est sélectionné. Sinon, la première interface est + # sélectionnée. Sinon, on prend eth0. + # Ensuite, réorganiser les tableaux de façon que confips[0] devienne la + # configuration ip de l'interface principale. + local -a __nfm_confbrs __nfm_confips __nfm_destconfips + array_copy __nfm_confbrs "${1:-confbrs}" + array_copy __nfm_confips "${2:-confips}" + __network_fix_mainiface "$3" + + array_copy "${2:-confips}" __nfm_destconfips +} + +function network_fix_confs() { + network_fix_confbrs "${1:-confbrs}" + network_fix_confips "${2:-confips}" + network_fix_mainiface "${1:-confbrs}" "${2:-confips}" "$3" +} + +function __network_valid_ifaces() { + ip link | awk '/<.*>/ { + flags = $0; sub(/^.*.*$/, ",", flags) + if (flags ~ /,LOOPBACK,/) next + if (flags !~ /,UP,/) next + sub(/:$/, "", $2); print $2 +}' +} + +function __network_set_confbrs() { + local -a ifaces tmpconfbrs confbrs + local confbr br iface + array_from_lines ifaces "$(__network_valid_ifaces)" + array_from_lines tmpconfbrs "$(brctl show 2>/dev/null | awk ' +BEGIN { confbrs = "" } +NR == 1 { next } +{ + if ($1 != "" && $2 != "") { + if (confbr != "") print confbr + confbr = $1 ":" $4 + } else { + confbr = confbr "," $1 + } +} +END { + if (confbr != "") print confbr +} +')" + for confbr in "${tmpconfbrs[@]}"; do + splitpair "$confbr" br iface + array_contains ifaces "$br" || continue + array_add confbrs "$confbr" + done + + array_copy __nsc_destconfbrs confbrs +} +function network_set_confbrs() { + # initialiser $1(=confbrs) avec l'état des bridges sur le système courant + local -a __nsc_destconfbrs + __network_set_confbrs + + array_copy "${1:-confbrs}" __nsc_destconfbrs +} + +function __network_set_gateway() { + # initialiser la variable gateway avec la passerelle associée à l'interface + # $1 + gateway="$(ip route | awk -v iface="$1" '$1 == "default" { + via = "" + dev = "" + for (i = 2; i <= NF; i++) { + if ($i == "via") via = $(i+1) + else if ($i == "dev") dev = $(i+1) + if (via != "" && dev != "") break + } + if (dev == iface && via != "") { + print via + } +}')" + # le code précédent utilisait route, mais ce n'est pas toujours disponible + #gateway="$(route -n | awk -v iface="$1" '$1 == "0.0.0.0" && $8 == iface { print $2 }')" +} +function __network_set_confip() { + # initialiser la variable confip avec l'état de l'interface $1, en assumant + # que la passerelle vaut $2. + # retourner 1 si l'interface n'a pas d'adresse ip associée + local -a ipsuffixes + array_from_lines ipsuffixes "$(ip addr show dev "$1" | awk '$1 == "inet" { print $2 }')" + confip="$(network_format_confip "$1" "$2" ipsuffixes)" + [ "${#ipsuffixes[*]}" -gt 0 ] +} +function __network_set_confips() { + local -a confips ifaces + local iface gateway + array_from_lines ifaces "$(__network_valid_ifaces)" + for iface in "${ifaces[@]}"; do + __network_set_gateway "$iface" + [ -n "$gateway" ] || gateway=- + __network_set_confip "$iface" "$gateway" || continue + array_add confips "$confip" + done + + array_copy __nsc_destconfips confips +} +function network_set_confips() { + # initialiser le tableau $1(=confips) avec l'état des interfaces sur le + # système courant + local -a __nsc_destconfips + __network_set_confips + + array_copy "${1:-confips}" __nsc_destconfips +} + +function __network_backup() { + local file="$1" + local backup="$file.orig$(date +%Y%m%d)" + [ -f "$backup" ] || cat "$file" >"$backup" 2>/dev/null +} + +function network_fix_exim4() { + local host="$1" oldhost="$2" + local tmpfile; ac_set_tmpfile tmpfile + local modified + + sed "$tmpfile" " +/^dc_other_hostnames=/c\\ +dc_other_hostnames='$host'" + if [ -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then + if testdiff "$tmpfile" /etc/exim4/update-exim4.conf.conf; then + uecho "Setting /etc/exim4/update-exim4.conf.conf to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + uecho "/etc/exim4/update-exim4.conf.conf: pas de modifications" + fi + elif testdiff "$tmpfile" /etc/exim4/update-exim4.conf.conf; then + __network_backup /etc/exim4/update-exim4.conf.conf + if show_debug; then + edebug "Setting /etc/exim4/update-exim4.conf.conf to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + estep /etc/exim4/update-exim4.conf.conf + fi + cat "$tmpfile" >/etc/exim4/update-exim4.conf.conf + update-exim4.conf + modified=1 + fi + ac_clean "$tmpfile" + [ -n "$modified" ] +} + +function network_fix_postfix() { + local host="$1" oldhost="$2" + local tmpfile; ac_set_tmpfile tmpfile + local modified + + awkrun "$tmpfile" host="$host" oldhost="$oldhost" ' +/^myhostname *=/ { $0 = "myhostname = " host } +/^mydestination *=/ { + gsub(" *" oldhost " *,? *", "") + if ($0 !~ (" *" host " *,? *")) { + sub(/^mydestination *= */, "mydestination = " host ", ") + } +} +{ print }' + if [ -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then + if testdiff "$tmpfile" /etc/postfix/main.cf; then + uecho "Setting /etc/postfix/main.cf to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + uecho "/etc/postfix/main.cf: pas de modifications" + fi + elif testdiff "$tmpfile" /etc/postfix/main.cf; then + __network_backup /etc/postfix/main.cf + if show_debug; then + edebug "Setting /etc/postfix/main.cf to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + estep /etc/postfix/main.cf + fi + cat "$tmpfile" >/etc/postfix/main.cf + modified=1 + fi + ac_clean "$tmpfile" + [ -n "$modified" ] +} + +function network_fix_hosts() { + local host="$1" hostname="${1%%.*}"; local shost="${host//./\\.}" + local ip="$2"; local sip="${ip//./\\.}" + local oldhost="$3" oldhostname="${3%%.*}"; soldhost="${host//./\\.}" + local tmpfile; ac_set_tmpfile tmpfile + local modified + + awkrun "$tmpfile" \ + host="$host" hostname="$hostname" \ + ip="$ip" \ + oldhost="$oldhost" oldhostname="$oldhostname" \ + ' +/^[^# \t]/ { + gsub("[ \\t]+" host "[ \\t]*", " ") + gsub("[ \\t]+" hostname "[ \\t]*", " ") + gsub("[ \\t]+" oldhost "[ \\t]*", " ") + gsub("[ \\t]+" oldhostname "[ \\t]*", " ") + if ($0 ~ /^[^ \t]+[ \t]*$/) next + gsub(/[ \t]*$/, "") +} +{ print }' + if quietgrep "^$sip[ $TAB]\\+$shost[ $TAB]\\+$hostname" "$tmpfile"; then + sed -i "\ +s/\$/ / +/^[ $TAB]$oldhost[ $TAB]/d +/^[ $TAB]$oldhostname[ $TAB]/d +s/ \$// +" "$tmpfile" + fi + if ! quietgrep "^$sip[ $TAB]\\+$shost[ $TAB]\\+$hostname" "$tmpfile"; then + sed -i "/^$sip[ $TAB]/d" "$tmpfile" + sed -i "1i\\ +$ip$TAB$host $hostname" "$tmpfile" + fi + + if [ -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then + if testdiff "$tmpfile" /etc/hosts; then + uecho "Setting /etc/hosts to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + uecho "/etc/hosts: pas de modifications" + fi + elif testdiff "$tmpfile" /etc/hosts; then + __network_backup /etc/hosts + if show_debug; then + edebug "Setting /etc/hosts to:" + cat "$tmpfile" | sed 's/^/ /g' 1>&2 + else + estep /etc/hosts + fi + cat "$tmpfile" >/etc/hosts + modified=1 + fi + ac_clean "$tmpfile" + [ -n "$modified" ] +} diff --git a/lib/ulib/redhat b/lib/ulib/redhat index 69d18cc..a398446 100644 --- a/lib/ulib/redhat +++ b/lib/ulib/redhat @@ -5,7 +5,7 @@ ##@require sysinfos ##@require service uprovide redhat -urequire base sysinfos service +urequire base sysinfos service ipcalc ################################################################################ # Gestion des packages @@ -26,7 +26,7 @@ function pkg_update() { function pkg_upgrade() { # Mettre à jour la liste des packages silencieusement sans confirmation - LANG=C yum update -qy + LANG=C yum update -q -y } function pkg_install() { @@ -36,7 +36,7 @@ function pkg_install() { #elif check_sysinfos -v rhel4 centos4 redhat4 -b 32; then # LANG=C up2date --channel=rhel-i386-es-4 "${pkgs[@]}" else - LANG=C yum install -qy "$@" + LANG=C yum install -q -y "$@" fi } @@ -71,8 +71,23 @@ function service_enable() { ################################################################################ # Gestion des interfaces réseau -function create_bridge() { - # Créer un nouveau pont nommé $1 avec les paramètres $2 - eerror "non implémenté" - return 1 +__REDHAT_NETWORK_DEVEL_SHOW_MODIFS= + +function network_fix_hostname() { + local hostname="${1%%.*}" + local modified + [ -f /etc/hostname ] || touch /etc/hostname + if [ -n "$__REDHAT_NETWORK_DEVEL_SHOW_MODIFS" -o -n "$__NETWORK_DEVEL_SHOW_MODIFS" ]; then + uecho "Setting /etc/hostname to $hostname" + elif [ "$(/etc/hostname + modified=1 + fi + [ -n "$modified" ] } diff --git a/lib/ulib/runs b/lib/ulib/runs index 1f9aa55..6968329 100644 --- a/lib/ulib/runs +++ b/lib/ulib/runs @@ -500,7 +500,7 @@ function runs_find_scriptfile() { "$__runsdir/$__runshost/$__scriptfile" \ "$__runsdir/$__domain/$__hostname/$__scriptfile"; do if [ "${__runsfile%$__runsext}" == "$__runsfile" ]; then - [ ! -f "$__runsfile" -a -f "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext" + [ ! -e "$__runsfile" -a -e "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext" fi if [ -e "$__runsfile" ]; then runs_initvars "$__runsfile" "$__runsdir" "$__runsdirpath" "$__scriptfile" @@ -513,7 +513,7 @@ function runs_find_scriptfile() { for __runsdir in "${!__runsscriptsdirs}" "${!__runsmodulesdirs}"; do __runsfile="$__runsdir/$__scriptfile" if [ "${__runsfile%$__runsext}" == "$__runsfile" ]; then - [ ! -f "$__runsfile" -a -f "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext" + [ ! -e "$__runsfile" -a -e "$__runsfile$__runsext" ] && __runsfile="$__runsfile$__runsext" fi if [ -e "$__runsfile" ]; then runs_initvars "$__runsfile" "$__runsdir" "$__runsdir" "$__scriptfile" @@ -1143,6 +1143,11 @@ function runs_set_lang() { source_ifexists /etc/default/locale set_var_cmd LANG "$LANG" )" + elif check_sysinfos -d redhatlike; then + eval "$(LANG= + source_ifexists /etc/locale.conf + set_var_cmd LANG "$LANG" + )" fi export LANG fi @@ -1909,6 +1914,9 @@ function runs_action_export() { fi if [ ! -e "$RUNSROOTDIR$RUNSSCRIPT" ]; then + # le script est peut être un lien + local -a __CPNOVCS_RSYNC_ARGS; __CPNOVCS_RSYNC_ARGS=(--copy-links) + estep "Copie du script" mkdirof "$RUNSROOTDIR$RUNSSCRIPT" cpnovcs "$RUNSSCRIPT" "$(dirname "$RUNSROOTDIR$RUNSSCRIPT")" diff --git a/lib/ulib/sysinfos b/lib/ulib/sysinfos index 8a08f9c..c19c746 100644 --- a/lib/ulib/sysinfos +++ b/lib/ulib/sysinfos @@ -12,9 +12,9 @@ urequire base # attention: dans SYSNAMES et *_SYSDISTS, les noms doivent être ordonnés du # moins spécifique au plus spécifique SYSNAMES=(linux linux64 linux32 linuxppc64 linuxppc32 linuxarm macosx) -linux_SYSDISTS=(debianlike debian ubuntu redhatlike rhel fedora centos suse gentoo) -linux32_SYSDISTS=(debianlike debian ubuntu redhatlike rhel fedora centos suse gentoo) -linux64_SYSDISTS=(debianlike debian ubuntu redhatlike rhel fedora centos suse gentoo) +linux_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo) +linux32_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo) +linux64_SYSDISTS=(debianlike debian ubuntu redhatlike ol rhel fedora centos suse gentoo) linuxppc32_SYSDISTS=(debianlike debian ubuntu redhatlike fedora) linuxppc64_SYSDISTS=(debianlike debian ubuntu redhatlike fedora) linuxarm_SYSDISTS=(debianlike debian ubuntu) @@ -28,6 +28,7 @@ debianlike_SYSVERS=() debian_SYSVERS=(stretch jessie wheezy squeeze lenny etch) ubuntu_SYSVERS=(oneiric natty maverick lucid karmic jaunty intrepid hardy) redhatlike_SYSVERS=() +ol_SYSVERS=(ol7 ol6 redhat7 redhat6) rhel_SYSVERS=(rhel7 rhel6 rhel5 rhel4 redhat7 redhat6 redhat5 redhat4) fedora_SYSVERS=(fedora14 fedora13 fedora12 fedora11) centos_SYSVERS=(centos7 centos6 centos5 centos4 redhat7 redhat6 redhat5 redhat4) @@ -66,6 +67,7 @@ function __compute_local_sysinfos_data() { "$UNAME_MACHINE" "$([ -f /etc/debian_version ] && cat /etc/debian_version)" "$([ -f /etc/gentoo-release ] && cat /etc/gentoo-release)" + "$([ -f /etc/oracle-release ] && cat /etc/oracle-release)" "$([ -f /etc/redhat-release ] && cat /etc/redhat-release)" "$([ -f /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist)" "$([ -f /System/Library/Frameworks/CoreServices.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Resources/version.plist)" @@ -81,6 +83,8 @@ echo .----------------. echo .----------------. [ -f /etc/gentoo-release ] && cat /etc/gentoo-release echo .----------------. +[ -f /etc/oracle-release ] && cat /etc/oracle-release +echo .----------------. [ -f /etc/redhat-release ] && cat /etc/redhat-release echo .----------------. [ -f /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist ] && cat /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist @@ -120,10 +124,14 @@ function __compute_sysinfos() { local machine="${SYSINFOS_DATA[1]}" local debian_version="${SYSINFOS_DATA[2]}" local gentoo_release="${SYSINFOS_DATA[3]}" - local redhat_release="${SYSINFOS_DATA[4]}" - local macosx_plist1="${SYSINFOS_DATA[5]}" - local macosx_plist2="${SYSINFOS_DATA[6]}" + local oracle_release="${SYSINFOS_DATA[4]}" + local redhat_release="${SYSINFOS_DATA[5]}" + local macosx_plist1="${SYSINFOS_DATA[6]}" + local macosx_plist2="${SYSINFOS_DATA[7]}" + MYSYSNAME=(unknown) + MYSYSDIST=(unknown) + MYSYSVER=(unknown) if [ "$system" == "Linux" ]; then case "$machine" in x86_64) MYSYSNAME=(linux64 linux); MYBITS=64;; @@ -145,6 +153,12 @@ function __compute_sysinfos() { esac elif [ -n "$gentoo_release" ]; then MYSYSDIST=(gentoo) + elif [ -n "$oracle_release" ]; then + MYSYSDIST=(ol rhel redhatlike) + case "$oracle_release" in + Oracle*Linux*release\ 7*) MYSYSVER=(ol7 rhel7 redhat7);; + Oracle*Linux*release\ 6*) MYSYSVER=(ol6 rhel6 redhat6);; + esac elif [ -n "$redhat_release" ]; then case "$redhat_release" in Fedora*) MYSYSDIST=(fedora redhatlike);; @@ -178,13 +192,14 @@ s/<\/string>.*$//g' done } MYSYSNAME=(macosx darwin) - case "$(get_macosx_version)" in + case "$(get_macosx_version "$macosx_plist1" "$macosx_plist2")" in 10.7*) MYSYSDIST=(lion);; 10.6*) MYSYSDIST=(snowleopard);; 10.5*) MYSYSDIST=(leopard);; 10.4*) MYSYSDIST=(tiger);; 10.3*) MYSYSDIST=(panther);; esac + MYSYSVER=() fi } @@ -316,6 +331,19 @@ function ensure_sysinfos() { __fix_sysinfos_downward } +function dump_sysinfos() { + # Afficher les valeurs de SYSNAME, SYSDIST, SYSVER qui décrivent le système + # actuel + local sysname_="${1:-MYSYSNAME}[*]" + local sysdist_="${2:-MYSYSDIST}[*]" + local sysver_="${3:-MYSYSVER}[*]" + echo "\ +sysname=(${!sysname_}) +sysdist=(${!sysdist_}) +sysver=(${!sysver_}) +bits=$MYBITS" +} + function get_sysinfos_desc() { # Afficher une chaine de la forme SYSNAME/SYSDIST/SYSVER qui décrit le # système actuel @@ -480,6 +508,32 @@ function check_sysinfos() { return $r_ } +function unsupported_system() { + # Afficher un message d'erreur indiquant que le système actuel n'est pas + # supporté, et quitter le script + local msg="Ce script n'est pas supporté sur $(get_sysinfos_desc)" + [ -n "$*" ] && msg="$msg +Il faut au moins l'un des systèmes suivants: $*" + die "$msg" +} + +function require_sysinfos() { + # Vérifier le système actuel avec check_sysinfos(), et afficher un message + # d'erreur avec unsupported_system() s'il ne correspond pas à la requête + check_sysinfos "$@" && return 0 + # Construire une description du type de système attendu en fonction des + # arguments. Actuellement, on se contente de copier la ligne de commande, en + # sautant les options. + # XXX améliorer l'algorithme pour décrire précisément le système attendu + local -a infos; local info + for info in "$@"; do + if ! [[ "$info" == -* ]]; then + infos=("${infos[@]}" "$info") + fi + done + unsupported_system "${infos[@]}" +} + # fonctions de support pour tester certaines versions de debian # utilisation: # on_debian diff --git a/lib/ulib/vcs b/lib/ulib/vcs index 7fe12be..155f28b 100644 --- a/lib/ulib/vcs +++ b/lib/ulib/vcs @@ -513,22 +513,26 @@ function git_push() { return 1 } - if [ $# -gt 0 ]; then - # si des arguments sont spécifiés, les passer à git sans modification - git push "$@" - return $? - elif [ -n "$all" ]; then + if [ -n "$all" ]; then # On a demandé à pusher toutes les branches et tous les tags - git push --all - git push --tags - return $? + local r + git push --all "$@"; r=$? + if [ $r -eq 0 ]; then + git push --tags "$@"; r=$? + fi + return $r elif [ -n "$all_branches" ]; then # On a demandé à pusher toutes les branches - git push --all + git push --all "$@" return $? elif [ -n "$all_tags" ]; then # On a demandé à pusher tous les tags - git push --tags + git push --tags "$@" + return $? + elif [ $# -gt 0 ]; then + # Sinon, si des arguments sont spécifiés, les passer à git sans + # modification + git push "$@" return $? elif git_have_annex; then # Si une annexe existe dans le dépôt, demander à git-annex de faire la diff --git a/netconfig b/netconfig new file mode 100755 index 0000000..6c4ee0a --- /dev/null +++ b/netconfig @@ -0,0 +1,171 @@ +#!/bin/bash +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 +source "$(dirname "$0")/lib/ulib/ulib" || exit 1 +urequire DEFAULTS debian + +function display_help() { + uecho "$scriptname: gérer la configuration du réseau + +USAGE + $scriptname -c network.conf + $scriptname [iface:]ip[/suffix]... + +OPTIONS + -P, --partial + Activer le mode de configuration partielle. C'est la valeur par défaut. + Dans ce mode, la configuration courante n'est pas modifiée. Seules de + nouvelles adresses ips sont configurées le cas échéant. + -F, --full + Activer le mode de configuration complète. Dans ce mode, le nom d'hôte + ainsi que toutes les interfaces, pont et adresses sont configurés. + -z, --reset + En mode full, recréer le fichier /etc/network/interfaces au lieu + d'essayer de le mettre à jour. + -l, --inline + Prendre la configuration depuis la ligne de commande. C'est la valeur + par défaut, sauf si un fichier network.conf existe dans le répertoire + courant. + Dans ce mode, chaque argument est une spécification d'adresse IP à + configurer. Les autres paramètres i.e les ponts, le nom d'hôte et le + contenu du fichier /etc/networks sont spécifiés avec les options -b, + -h et -e + -c, --config CONFIG + Spécifier le fichier de configuration à utiliser pour la configuration + du réseau. Cette option est automatiquement activée si le répertoire + courant contient un fichier network.conf + -w, --write + Ecrire la configuration actuelle dans le fichier network.conf + Note: comme ce script demande les droits de root, le fichier sera écrit + avec le propriétaire root. + -b, --bridge BR:IFACES + En mode inline, spécifier une liste de ponts à configurer. + -h, --host HOST + En mode inline, spécifier le nom d'hôte pleinement qualifié + -e, --etc-networks CONTENT + Spécifier un contenu pour remplacer le fichier /etc/networks" +} + +mode=partial +reset= +source=auto +config= +write= +brs=() +host= +etc_networks= +args=( + --help '$exit_with display_help' + -P,--partial mode=partial + -F,--full mode=full + -z,--reset reset=1 + -l,--inline source=inline + -c:,--config: '$set@ config; source=config' + -w,--write write=1 + -b:,--bridge: brs + -h:,--host: host= + -e:,--etc-networks: etc_networks= +) +parse_args "$@"; set -- "${args[@]}" + +# vérification du système +check_sysinfos -d debian || die "Ce script n'est supporté que sur debian linux" + +# relancer en root +args=() + +case "$mode" in +p|partial) mode=partial; array_add args --partial;; +f|full) mode=full; array_add args --full;; +*) die "$mode: mode invalide. ce doit être full ou partial";; +esac +[ "$mode" == full ] || reset= +[ -n "$reset" ] && array_add args --reset + +if [ "$source" == auto ]; then + if [ -f network.conf ]; then + estepi "Chargement automatique de network.conf" + source=config + config=network.conf + else + source=inline + fi +fi +case "$source" in +i|inline) + ips=("$@") + ;; +c|config) + [ -f "$config" ] || die "$config: fichier introuvable" + eval "$( + ips=(); brs=(); host= + source "$config" >&/dev/null + set_array_cmd ips + set_array_cmd brs + echo_setv host "$host" + echo_setv etc_networks "$etc_networks" + )" + ;; +esac +array_add args --inline +for br in "${brs[@]}"; do + array_add args --bridge "$br" +done +[ -n "$host" ] && array_add args --host "$host" +[ -n "$write" ] && array_add args --write +array_add args "${ips[@]}" + +run_as_root "${args[@]}" + +# (re)configurer le réseau +modified= +if [ "$mode" == full ]; then + enote "La configuration COMPLETE suivante va être appliquée + brs: ${brs[*]} + ips: ${ips[*]} + host: $host" + ask_yesno "Voulez-vous continuer?" O || die + if [ ${#ips[*]} -gt 0 -o ${#brs[*]} -gt 0 -o -n "$hosts" ]; then + network_config "$host" ips brs "" "$reset" && modified=1 + fi + [ -n "$etc_networks" ] && network_update_etc_networks "$etc_networks" + [ -n "$modified" ] && eimportant "Vous devriez redémarrer le serveur pour prendre en compte la nouvelle configuration" + +elif [ "$mode" == partial ]; then + enote "La configuration PARTIELLE suivante va être appliquée + ips: ${ips[*]}" + ask_yesno "Voulez-vous continuer?" O || die + if [ ${#ips[*]} -gt 0 ]; then + network_config_partial ips && modified=1 + fi +fi + +# Ecrire le fichier de configuration +if [ -n "$write" ]; then + if [ -f network.conf ]; then + ask_yesno "Le fichier network.conf existe. Voulez-vous l'écraser?" N || die + fi + + network_set_confbrs brs + network_set_confips ips + network_fix_confs brs ips + [ -n "$host" ] || setx host=hostname -f + + estep "network.conf" + echo >network.conf "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +# Liste des ponts à configurer. Chaque élément est de la forme BR:IFACES +# BR est le nom du pont, e.g. br0. IFACES est une liste d'interfaces séparées +# par une virgule. e.g. br0:eth0,eth1 +$(set_array_cmd brs) + +# Liste des adresses IPs à configurer. Chaque élément est de la forme +# [IFACE:]dhcp ou [[IFACE][//GATEWAY]:]IP[/SUFFIX] +$(set_array_cmd ips) + +# Nom d'hôte pleinement qualifié. Si ce paramètre est spécifié, les fichiers +# /etc/hosts, /etc/hostname et /etc/mailname sont mis à jour. +$(echo_setv host "$host") + +# Contenu du fichier /etc/networks +$(echo_setv etc_networks "$etc_networks")" +fi diff --git a/umountr b/umountr index 00c5a1a..2c46d8b 100755 --- a/umountr +++ b/umountr @@ -9,19 +9,36 @@ function display_help() { USAGE $scriptname mountpoint -Démonter tous les systèmes de fichiers qui sont montés en-dessous de mountpoint -puis démonter mountpoint. Démonter aussi tous les systèmes de fichiers -bind-montés à partir d'un sous-répertoire de mountpoint. - OPTION -c, --continuous - Continuer même en cas d'erreur" + Continuer même en cas d'erreur + -r, --recursive + -1, --no-recursive + Spécifier le type de démontage: + Avec -1, un démontage simple est effectué, comme avec umount. Ce type de + démontage est automatiquement sélectionné pour les systèmes de fichier + montés sous le répertoire /media + Avec -r, le démontage est récursif: tous les systèmes de fichiers qui + sont montés en-dessous de mountpoint sont démontés puis mountpoint est + démonté. Tous les systèmes de fichiers bind-montés à partir d'un sous- + répertoire de mountpoint sont démontés aussi. + -o, --poweroff + -k, --no-poweroff + Après avoir démonté le système de fichier mountpoint, éteindre le + périphérique qui y correspond. --poweroff est automatiquement activé + pour les systèmes de fichier montés sous le répertoire /media" } continuous= +recursive=auto +poweroff=auto args=( --help '$exit_with display_help' -c,--continuous continuous=1 + -r,--recursive recursive=1 + -1,--no-recursive recursive= + -o,--poweroff poweroff=1 + -k,--no-poweroff poweroff= ) parse_args "$@"; set -- "${args[@]}" @@ -30,26 +47,89 @@ mountp="$1" [ -d "$mountp" ] || die "$mountp: répertoire introuvable" setx mountp=abspath "$mountp" -run_as_root ${continuous:+-c} "$@" +args=( + $(get_verbosity_option) $(get_interaction_option) + ${continuous:+-c} +) +if [ "$recursive" == 1 ]; then array_add args --recursive +elif [ -z "$recursive" ]; then array_add args --no-recursive +fi +if [ "$poweroff" == 1 ]; then array_add args --poweroff +elif [ -z "$poweroff" ]; then array_add args --no-poweroff +fi +run_as_root "${args[@]}" "$mountp" + +if withinpath /media "$mountp"; then + [ "$recursive" == auto ] && recursive= + [ "$poweroff" == auto ] && poweroff=1 +else + [ "$recursive" == auto ] && recursive=1 + [ "$poweroff" == auto ] && poweroff= +fi + +etitle "Calcul des informations" setx -a mountps=findmnt -nlo TARGET -array_contains mountps "$mountp" || die "Vous devez spécifier un répertoire de montage valide" +array_contains mountps "$mountp" || die "$mountp: répertoire de montage invalide" function show_all() { findmnt -T "$mountp" -Rnlo TARGET findmnt -nlo TARGET | awkrun mountp="$mountp" '{ if (substr($0, 1, length(mountp) + 1) == (mountp "/")) print }' } +if [ -n "$recursive" ]; then + estepi "Type de démontage: récursif" + + setx -a mounts=evalp show_all // sort -u // \ + awk '{print length($0) "," $0}' // \ + sort -nr // \ + awk '{sub(/[0-9]+,/, ""); print}' + + estepi "${#mounts[*]} systèmes de fichier à démonter" + if show_debug; then + edebug "Les systèmes de fichiers suivants seront démontés:" + for mount in "${mounts[@]}"; do + estep "$mount" + done + fi +else + estepi "Type de démontage: simple" +fi + +setx device=findmnt -T "$mountp" -vnlo SOURCE +[ -n "$device" ] || die "Impossible de trouver le périphérique correspondant à $mountp" +if [ -n "$poweroff" ]; then + estepi "Le périphérique $device sera éteint après démontage" +else + edebug "Le périphérique correspondant est $device" +fi + +eend + +ask_yesno -i "Voulez-vous continuer?" O || die + function die_maybe() { [ -n "$continuous" ] && return die "$@" } +etitled "Démontage des systèmes de fichier" +if [ -n "$recursive" ]; then + for mount in "${mounts[@]}"; do + estep "$mount" + umount "$mount" || die_maybe + done +else + estep "$mountp" + umount "$mountp" || die_maybe +fi +eend -setx -a mounts=evalp show_all // sort -u // \ - awk '{print length($0) "," $0}' // \ - sort -nr // \ - awk '{sub(/[0-9]+,/, ""); print}' +if [ -n "$poweroff" ]; then + etitle "Arrêt des périphériques" + estep "$device" + udisksctl power-off -b "$device" || die + eend -for mount in "${mounts[@]}"; do - estep "$mount" - umount "$mount" || die_maybe -done + enote "Vous pouvez maintenant débrancher le périphérique!" +fi + +exit 0 diff --git a/uproject b/uproject index 61f5a53..bb046a8 100755 --- a/uproject +++ b/uproject @@ -57,11 +57,13 @@ COMMANDS -R Afficher les modifications effectuées depuis la dernière release. clone git@host:path/to/repo [destdir] + clone http://host/gituser/path/to/repo [destdir] Cloner un dépôt distant. Basculer sur la branche develop si elle existe. Initialiser git annex si le dépôt contient des fichiers annexés. Récupérer aussi ces fichiers avec 'git annex get' crone git@host:path/to/repo [destdir] + crone http://host/gituser/path/to/repo [destdir] Créer un dépôt distant sur gitolite, puis le cloner develop @@ -290,7 +292,24 @@ elif [ "$CMD" == clone ]; then elif [ "$CMD" == crone ]; then repourl="${1%.git}" [ -n "$repourl" ] || die "Vous devez spécifier l'url du dépôt git" - splitfsep "$repourl" : userhost path + if [ "${repourl#http://}" != "$repourl" -o "${repourl#https://}" != "$repourl" ]; then + # accès par http + mode=http + splitfsep "$repourl" :// scheme hostuserpath + splitfsep "$hostuserpath" / host userpath + splitfsep "$userpath" / user path + [ -n "$host" -a -n "$user" ] || die "Vous devez spécifier l'hôte e.g http://host/git/repo" + hostuser="$scheme://$host/$user" + else + # accès par ssh + mode=ssh + splitfsep "$repourl" : userhost path + splituserhost "$userhost" user host + [ -n "$user" ] || user=git + [ -n "$host" ] || die "Vous devez spécifier l'hôte" + userhost="$user@$host" + fi + [ -n "$path" ] || die "Vous devez spécifier le chemin du dépôt git" destdir="$2" if [ -z "$destdir" ]; then @@ -303,21 +322,31 @@ elif [ "$CMD" == crone ]; then ac_set_tmpdir tmpdestdir fi - splituserhost "$userhost" user host - [ -n "$user" ] || user=git - [ -n "$host" ] || die "Vous devez spécifier l'hôte" - userhost="$user@$host" - [ -n "$path" ] || die "Vous devez spécifier le chemin du dépôt git" - - git_annex_use_ssh_wrapper - ssh "$userhost" create "$path" || die - if [ -n "$tmpdestdir" ]; then - setxx destname=abspath "$destdir" // basename - git clone "$userhost:$path" "$tmpdestdir/$destname" || die - mv "$tmpdestdir/$destname/.git" "$destdir" || die - ac_clean "$tmpdestdir" + if [ "$mode" == http ]; then + setx result=curl -fs "$hostuser/create?$path" || die + echo "$result" + [[ "$result" == FATAL:* ]] && die + if [ -n "$tmpdestdir" ]; then + setxx destname=abspath "$destdir" // basename + git clone "$hostuser/$path" "$tmpdestdir/$destname" || die + mv "$tmpdestdir/$destname/.git" "$destdir" || die + ac_clean "$tmpdestdir" + else + git clone "$hostuser/$path" "$destdir" || die + fi + elif [ "$mode" == ssh ]; then + git_annex_use_ssh_wrapper + ssh "$userhost" create "$path" || die + if [ -n "$tmpdestdir" ]; then + setxx destname=abspath "$destdir" // basename + git clone "$userhost:$path" "$tmpdestdir/$destname" || die + mv "$tmpdestdir/$destname/.git" "$destdir" || die + ac_clean "$tmpdestdir" + else + git clone "$userhost:$path" "$destdir" || die + fi else - git clone "$userhost:$path" "$destdir" || die + die "bug: mode non prévu" fi git_annex_initial "$destdir" || die diff --git a/usysinfos b/usysinfos index 740605a..e9a36cf 100755 --- a/usysinfos +++ b/usysinfos @@ -20,9 +20,5 @@ Sinon, afficher les informations sur le système courant." if [ -n "$*" ]; then check_sysinfos "$@" else - echo "\ -sysname=(${MYSYSNAME[*]}) -sysdist=(${MYSYSDIST[*]}) -sysver=(${MYSYSVER[*]}) -bits=$MYBITS" + dump_sysinfos fi