source: installer/opengnsys_import.sh

qndtest
Last change on this file was 73c5e1c, checked in by Irina Gómez <irinagomez@…>, 23 months ago

#1066 Changes devel branch name.

  • Property mode set to 100755
File size: 17.9 KB
Line 
1#!/bin/bash
2#         importclient str_backupfile
3#@file    importclient
4#@brief   Importa los datos de OpenGnsys de un archivo de backup: dhcp, pxe, páginas de inicio y configuración de la consola.
5#@param 1 str_backupfile fichero de backup (creado con exportclient)
6#@exception 1 Error de formato
7#@exception 2 Sólo ejecutable por usuario root
8#@exception 3 Sin acceso al fichero de backup
9#@exception 4 Sin acceso a la configuración de OpenGnsys
10#@exception 5 Errores al importar o exportar de la bd auxiliar
11#@exception 6 Errores al importar los archivos de actualización de la BD desde opengnsys.es
12#@exception 7 El archivo de backup ha sido crearo con una versión incompatible de opengnsys_export. Usar 1.1.0-5594 o posterior.
13#@note En las versiones de desarrollo (pre) no se modifica la estructura de la base de datos.
14#@version 1.1.0 - Versión inicial.
15#@author  Irina Gómez - ETSII Univ. Sevilla
16#@date    2016-10-18
17#@version 1.1.0 - Permite importar de versiones de OpenGnsys anteriores. Cambia la importación de la base de datos.
18#@note    Incompatible con versiones de opengnsys_export.sh anteriores a esta fecha.
19#@date    2018-02-14
20#@version 1.1.1 - Importamos scripts Custom, PXE para UEFI y /etc/default/opengnsys.
21#@date    2019-07-18
22#*/ ##
23
24# Variables globales.
25PROG="$(basename $0)"
26
27DATE=$(date +%Y%m%d)
28PREFIX="opengnsys_export"
29TMPDIR="/tmp/$PREFIX"
30OPENGNSYS="/opt/opengnsys"
31MYCNF=$(mktemp /tmp/.my.cnf.XXXXX)
32CATALOG="ogAdmBD"
33AUXCATALOG="og_import"
34MYSQLFILE="$TMPDIR/$CATALOG.sql"
35MYSQLBCK="$OPENGNSYS/doc/$CATALOG.sql-$DATE"
36
37LOG_FILE=$OPENGNSYS/log/${PROG%.sh}.log
38BRANCH="branches/main"
39SVN_URL="https://github.com/opengnsys/OpenGnsys/$BRANCH/admin/Database"
40DEFAULT_MYSQL_ROOT_PASSWORD="passwordroot"      # Clave por defecto root de MySQL
41
42# Si se solicita, mostrar ayuda.
43if [ "$*" == "help" ]; then
44    cat << EOT
45$PROG: Importa los datos de OpenGnsys desde un archivo de backup:
46  dhcp, pxe, páginas de inicio y configuración de la consola.
47    Formato: $PROG [--check] | [--exclude-logs] [--exclude-repos] [--exclude-users] Backup_File
48    Opciones:
49      --check: comprueba los datos incluidos en el fichero de backup (opcional)
50      --exclude-logs: no restaura los ficheros de log (opcional)
51      --exclude-repos: no recupera los repositorios definidos (opcional)
52      --exclude-users: no recupera los usuarios definidos (opcional)
53      Backup_File: camino del fichero de backup a restaurar
54    Ejemplo: $PROG backup.tgz
55EOT
56    exit
57fi
58
59
60####### Funciones ##############################################
61
62# Procesar parámetros de entrada.
63function process_params() {
64    local options error
65    # Retrieve options.
66    options=$(getopt -n "$PROG" -l check,exclude-logs,exclude-repos,exclude-users -o '' -- "$@") || error=1
67    set -- $options
68    # Process options and set flags.
69    while [ "$1" ]; do
70        case "$1" in
71            --check)
72                CHECK=1; shift ;;
73            --exclude-logs)
74                NOLOGS=1; shift ;;
75            --exclude-repos)
76                NOREPOS=1; shift ;;
77            --exclude-users)
78                NOUSERS=1; shift ;;
79            --)
80                shift; break ;;
81            *)
82                error=1; break ;;
83        esac
84    done
85    [ $# -ne 1 ] && error=1
86    if [ "$error" ]; then
87        echo "$PROG: ERROR: Usage error: Type \"$PROG help\"" >&2
88        exit 1
89    fi
90    # Backup file.
91    eval BACKUPFILE="$1"
92}
93
94# Al salir elimina archivos y base de datos temporal
95function clean()
96{
97        mysql --defaults-extra-file=$MYCNF  -e "DROP DATABASE IF EXISTS $AUXCATALOG"
98        rm -f $MYCNF
99}
100
101function getDateTime()
102{
103        date "+%Y%m%d-%H%M%S"
104}
105
106# Escribe a fichero y muestra por pantalla
107function echoAndLog()
108{
109        echo "      $1"
110        DATETIME=`getDateTime`
111        echo "$DATETIME;$SSH_CLIENT;$1" >> $LOG_FILE
112}
113
114function errorAndLog()
115{
116        echo "      ERROR: $1"
117        DATETIME=`getDateTime`
118        echo "$DATETIME;$SSH_CLIENT;ERROR: $1" >> $LOG_FILE
119}
120
121function mysqlPassword()
122{
123    # Clave root de MySQL
124    while : ; do
125        echo -n -e "\\nEnter root password for MySQL (${DEFAULT_MYSQL_ROOT_PASSWORD}): ";
126        read -r MYSQL_ROOT_PASSWORD
127        if [ -n "${MYSQL_ROOT_PASSWORD//[a-zA-Z0-9]/}" ]; then # Comprobamos que sea un valor alfanumerico
128                echo -e "\\aERROR: Must be alphanumeric, try again..."
129        else
130                # Si esta vacio ponemos el valor por defecto
131                MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-$DEFAULT_MYSQL_ROOT_PASSWORD}"
132                break
133        fi
134    done
135    cat << EOT > $MYCNF
136[client]
137user=root
138password=$MYSQL_ROOT_PASSWORD
139EOT
140}
141
142# Actualización incremental de la BD (versión actual a actual+1, hasta final-1 a final).
143function updateSqlFile()
144{
145        local DBDIR="$TMPDIR/Database"
146        local file FILES=""
147
148        echoAndLog "${FUNCNAME}(): looking for database updates"
149        pushd $DBDIR >/dev/null
150        # Bucle de actualización incremental desde versión actual a la final.
151        for file in $CATALOG-*-*.sql; do
152                case "$file" in
153                        $CATALOG-$OLDVERSION-$NEWVERSION.sql)
154                                # Actualización única de versión inicial y final.
155                                FILES="$FILES $file"
156                                break
157                                ;;
158                        $CATALOG-*-postinst.sql)
159                                # Ignorar fichero específico de post-instalación.
160                                ;;
161                        $CATALOG-$OLDVERSION-*.sql)
162                                # Actualización de versión n a n+1.
163                                FILES="$FILES $file"
164                                OLDVERSION="$(echo ${file%.*} | cut -f3 -d-)"
165                                ;;
166                        $CATALOG-*-$NEWVERSION.sql)
167                                # Última actualización de versión final-1 a final.
168                                if [ -n "$FILES" ]; then
169                                        FILES="$FILES $file"
170                                        break
171                                fi
172                                ;;
173                esac
174        done
175        # Aplicar posible actualización propia para la versión final.
176        file=$CATALOG-$NEWVERSION.sql
177        if [ -n "$FILES" -o "$OLDVERSION" = "$NEWVERSION" ] && [ -r $file ]; then
178                FILES="$FILES $file"
179        fi
180
181        popd >/dev/null
182        if [ -n "$FILES" ]; then
183                mysql --defaults-extra-file=$MYCNF  -e "CREATE DATABASE $AUXCATALOG" 
184                [ $? != 0 ] && errorAndLog "${FUNCNAME}: Can't create database $AUXCATALOG" && exit 5
185                mysql --defaults-extra-file=$MYCNF -D "$AUXCATALOG" < $MYSQLFILE &>/dev/null
186                [ $? != 0 ] && errorAndLog "${FUNCNAME}: Can't import $MYSQLFILE in  $AUXCATALOG" && exit 5
187
188                for file in $FILES; do
189                        importSqlFile $DBDIR/$file
190                done
191
192                cp $MYSQLFILE $MYSQLFILE.backup
193                mysqldump --defaults-extra-file=$MYCNF --opt $AUXCATALOG > $MYSQLFILE
194                [ $? != 0 ] && errorAndLog "${FUNCNAME}: Can't export  $AUXCATALOG in  $MYSQLFILE" && exit 5
195
196                mysql --defaults-extra-file=$MYCNF  -e "DROP DATABASE $AUXCATALOG" 
197                echoAndLog "${FUNCNAME}(): sqlfile update"
198        else
199                echoAndLog "${FUNCNAME}(): sqlfile unchanged"
200        fi
201}
202
203
204# Actualizar la base datos
205function importSqlFile()
206{
207        local sqlfile="$1"
208
209        if [ ! -r $sqlfile ]; then
210                errorAndLog "${FUNCNAME}(): Unable to read $sqlfile!!"
211                exit 5
212        fi
213
214        echoAndLog "${FUNCNAME}(): importing SQL file..."
215        # Ejecutar actualización y borrar fichero de credenciales.
216        mysql --defaults-extra-file=$MYCNF --default-character-set=utf8 -D "$AUXCATALOG" < $sqlfile
217        if [ $? -ne 0 ]; then
218                errorAndLog "${FUNCNAME}(): error importing ${sqlfile##*/} in temporal database"
219                exit 5
220        fi
221        echoAndLog "${FUNCNAME}(): file ${sqlfile##*/} imported to temporal database"
222        return 0
223}
224
225# Comprobar los datos incluidos en el archivo de backup.
226function checkArchive()
227{
228    local CONFIG FILES f
229    local BACKUPFILE="$1"
230    if [ -z "$(command -v jq)" ]; then
231        echo "$PROG: Error: command not found, please install \"jq\"" >&2
232        exit 2
233    fi
234    # Define content items.
235    CONFIG=$(cat << EOT | jq '.[].detected=false'
236[
237  { "path": "/ogAdmBD.sql", "comment": "Database file" },
238  { "path": "/VERSION.json", "comment": "Version file" },
239  { "path": "/VERSION.txt", "comment": "Old version file" },
240  { "path": "/ogliveinfo.json", "comment": "Installed ogLive info" },
241  { "path": "/engine.json", "comment": "Engine config file" },
242  { "path": "/engine.cfg", "comment": "Old engine config file" },
243  { "path": "/default/opengnsys", "comment": "Default config file" },
244  { "path": "/dhcpd.conf", "comment": "DHCP file" },
245  { "path": "Custom", "comment": "Customization scripts" },
246  { "path": "/menu.lst/", "comment": "PXE directory" },
247  { "path": "/menus/", "comment": "Menu directory" },
248  { "path": "/log/", "comment": "Log directory" }
249]
250EOT
251    )
252    # Turn on the detected flag if the item is in the archive.
253    echo "Checking archive content..."
254    FILES=$(tar tzf "$BACKUPFILE") || exit 1
255    for f in $FILES; do
256        CONFIG=$(jq '[ .[] as $p | if "'"${f#$PREFIX}"'" | endswith($p.path) then $p | .detected |= true else $p end ]' <<<"$CONFIG")
257    done
258    # Show comment and detected flag for each defined item.
259    echo $CONFIG | jq -r '.[] as $f | $f.comment + ": " + (if $f.detected then "OK" else "FAIL" end)' | column -ts:
260}
261
262
263##################################################################
264
265# Comprobamos parámetros de entrada.
266process_params "$@"
267
268# Comprobar parámetros.
269if [ "$USER" != "root" ]; then
270    echo "$PROG: Error: solo ejecutable por root." >&2
271    exit 3
272fi
273
274# Comprobamos acceso al fichero de backup
275if ! [ -r $BACKUPFILE ]; then
276    echo "$PROG: ERROR: Sin acceso al fichero de backup." | tee -a $FILESAL
277    exit 3
278fi
279
280# Comprobamos  acceso a ficheros de configuración
281if ! [ -r $OPENGNSYS/etc/ogAdmServer.cfg ]; then
282    echo "$PROG: ERROR: Sin acceso a la configuración de OpenGnsys." | tee -a $FILESAL
283    exit 3
284fi
285
286# Si existe el directorio auxiliar lo borramos
287[ -d $TMPDIR ] && rm -rf $TMPDIR
288
289# Al salir borramos MYCNF y la db tamporal
290trap "clean" 1 2 3 6 9 14 15 EXIT
291
292# Comprobar contenido del archivo.
293if [ "$CHECK" ]; then
294    checkArchive $BACKUPFILE
295    exit
296fi
297
298# Parámetros especiales de restauración.
299[ "$NOLOGS" ] && TARPARAMS="--exclude=$PREFIX/log"
300
301# Descomprimimos backup
302tar -xvzf $BACKUPFILE --directory /tmp $TARPARAMS &>/dev/null
303
304# Comprueba que opengnsys_export sea compatible
305grep "CREATE TABLE.*usuarios" $MYSQLFILE &>/dev/null
306if [ $? -ne 0 ]; then
307    errorAndLog "Backup file created with old version opengnsys_export. Use version 1.1.0-5594 or later."
308    exit 7
309fi
310
311# Comprobamos si es la misma versión
312[ -f $TMPDIR/VERSION.txt ] && OLDVERSION=$(awk '{print $2}' $TMPDIR/VERSION.txt)
313[ -f $TMPDIR/VERSION.json ] && OLDVERSION=$(jq -r '.version' $TMPDIR/VERSION.json)
314NEWVERSION=$(jq -r '.version' $OPENGNSYS/doc/VERSION.json)
315# FALTA: Comprobar que la versión OLD es menor que la NEW
316if [ $OLDVERSION != $NEWVERSION ] ; then
317    echo "La versión del servidor no coincide con la del backup."
318    jq -r '[.project, .version, .codename] | join(" ")' $OPENGNSYS/doc/VERSION.json $TMPDIR/VERSION.json 2>/dev/null \
319            || cat $TMPDIR/VERSION.txt
320    read -p "¿Quiere continuar? (y/n): " ANSWER
321    if [ "${ANSWER^^}" != "Y" ]; then
322        echo "Operación cancelada."
323        exit 0
324    fi
325    # Nos bajamos los archivos de actualización de la base de datos
326    svn export "$SVN_URL" $TMPDIR/Database
327    [ $? -ne 0 ] && errorAndLog "$PROG: Error getting code from $SVN_URL" && exit 6
328   
329    # Solicitamos la clave de mysql.
330    mysqlPassword
331    DIFFVERSION=TRUE
332fi
333
334# MYSQL
335echo "   * Importamos informacion mysql."
336source $OPENGNSYS/etc/ogAdmServer.cfg
337# Crear fichero temporal de acceso a la BD
338if [ ! -r $MYCNF ]; then
339    chmod 600 $MYCNF
340    trap "rm -f $MYCNF" 1 2 3 6 9 15
341    cat << EOT > $MYCNF
342[client]
343user=$USUARIO
344password=$PASSWORD
345EOT
346fi
347
348# Si la versión es diferente usamos una tabla auxiliar para actualizar el .sql
349[ "$DIFFVERSION" == TRUE ] &&  updateSqlFile
350
351# Eliminamos las tablas que no importamos: repositorios, entorno
352#     definimos usuario creador de los "triggers,
353#     añadimos los usuarios, sólo si no existen, y
354#     definimos valores adecuados por defecto.
355# Excluding repository table import, if needed.
356[ "$NOREPOS" ] && sed -i -e '/Table structure.* `repositorios`/,/Table structure/d' $MYSQLFILE
357[ "$NOUSERS" ] && sed -i -e '/INSERT INTO `usuarios`/s/^/\/*/' \
358                         -e '/INSERT INTO `usuarios`/s/$/*\//' \
359                         $MYSQLFILE
360sed -i -e '/Table structure.* `entornos`/,/Table structure/d' \
361       -e '/Table structure.*`usuarios`/,/CHARSET/d' \
362       -e '/usuarios/s/IGNORE//g' \
363       -e '/usuarios/s/^INSERT INTO .usuarios. /\nALTER TABLE usuarios ADD UNIQUE (usuario);\n\nINSERT IGNORE INTO `usuarios` /g' \
364       -e "s/\(DEFINER=\`\)[^\`]*\(\`.* TRIGGER\)/\1$USUARIO\2/" \
365       -e "s/\(\` [a-z]*int([0-9]*) NOT NULL\),/\1 DEFAULT 0,/" \
366       -e "s/\(\` [a-z]*char([0-9]*) NOT NULL\),/\1 DEFAULT '',/" \
367       -e "s/\(\` datetime NOT NULL DEFAULT \)'0000-00-00 00:00:00',/\1'1970-01-01 00:00:00',/" \
368       -e "s/\` text NOT NULL,/\` text,/" \
369       $MYSQLFILE
370
371# Copia de seguridad del estado de la base de datos
372mysqldump --defaults-extra-file=$MYCNF --opt $CATALOG > $MYSQLBCK
373chmod 400 $MYSQLBCK
374# Importamos los datos nuevos
375mysql --defaults-extra-file=$MYCNF -D "$CATALOG" < $MYSQLFILE &>/dev/null
376[ $? -ne 0 ] && echo "ERROR: Error al importar la información de la base de datos."
377
378# Copiamos los archivos a su sitio correcto
379# default/opengnsys
380echo "   * Guardamos la configuración de /etc/default."
381mv /etc/default/opengnsys /etc/default/opengnsys-$DATE
382cp $TMPDIR/default/opengnsys /etc/default/opengnsys
383
384# DHCP
385echo "   * Componemos la configuración del dhcp."
386for DHCPCFGDIR in /etc/dhcp /etc/dhcp3; do
387    if [ -r $DHCPCFGDIR/dhcpd.conf ]; then
388        # Tomamos las variables globales de la configuración actual y las declaraciones host del backup
389        # Inicio declaraciones host
390        OLDHOSTINI=$(grep -n -m1 -e "^[[:blank:]]*host" -e "^#[[:blank:]]*host" $TMPDIR/dhcpd.conf|cut -d: -f1)
391        let BEFOREHOST=$(grep -n -m1 -e "^[[:blank:]]*host" -e "^#[[:blank:]]*host" $DHCPCFGDIR/dhcpd.conf| cut -d: -f1)-1
392        # Copia de seguridad de la configuración anterior
393        cp $DHCPCFGDIR/dhcpd.conf $DHCPCFGDIR/dhcpd.conf-LAST
394        mv $DHCPCFGDIR/dhcpd.conf $DHCPCFGDIR/dhcpd.conf-$DATE
395        # Nuevo fichero
396        sed ${BEFOREHOST}q $DHCPCFGDIR/dhcpd.conf-LAST > $DHCPCFGDIR/dhcpd.conf
397        sed -n -e "$OLDHOSTINI,\$p" $TMPDIR/dhcpd.conf >> $DHCPCFGDIR/dhcpd.conf
398        break
399    fi
400done
401
402# TFTP
403echo "   * Guardamos los ficheros PXE de los clientes."
404for BOOTLOADER in menu.lst grub; do
405    if [ -d $TMPDIR/$BOOTLOADER ]; then
406        mkdir -p $OPENGNSYS/tftpboot/$BOOTLOADER-$DATE
407        mv $OPENGNSYS/tftpboot/$BOOTLOADER/{01-*,templates,examples} $OPENGNSYS/tftpboot/$BOOTLOADER-$DATE 2>/dev/null
408        cp -r $TMPDIR/$BOOTLOADER/{01-*,templates,examples}  $OPENGNSYS/tftpboot/$BOOTLOADER 2>/dev/null
409        chown -R www-data:www-data $OPENGNSYS/tftpboot/$BOOTLOADER
410    fi
411done
412
413if [ -f $OPENGNSYS/tftpboot/menu.lst/templates/01 ]; then
414    echo "   * Cambio del nombre de las plantillas PXE para compatibilidad con UEFI."
415    BIOSPXEDIR="$OPENGNSYS/tftpboot/menu.lst/templates"
416    mv $BIOSPXEDIR/01 $BIOSPXEDIR/10
417    sed -i "s/\bMBR\b/1hd/" $BIOSPXEDIR/10
418
419    # Cambiamos el valor en la base de datos. Si no lo hacemos desaparecen de las columnas del NetBootAvanzado.
420    mysql --defaults-extra-file=$MYCNF -D "$CATALOG" -e "update ordenadores set arranque='10' where arranque='01';" &>/dev/null
421    [ $? -ne 0 ] && echo "ERROR: Error al modificar nombre de las plantilla '10' en la base de datos."
422fi
423
424# Configuración de los clientes
425echo "   * Guardamos la configuración de los clientes."
426mv $OPENGNSYS/client/etc/engine.cfg $OPENGNSYS/client/etc/engine.cfg-$DATE
427cp $TMPDIR/engine.cfg $OPENGNSYS/client/etc/engine.cfg
428
429# Páginas de inicio
430echo "   * Guardamos las páginas de inicio."
431mv $OPENGNSYS/www/menus $OPENGNSYS/www/menus-$DATE
432cp -r $TMPDIR/menus $OPENGNSYS/www
433
434# Script personalizados
435echo "   * Guardamos los scripts personalizados."
436if ls $OPENGNSYS/client/scripts/*Custom &>/dev/null; then
437    mkdir -p $OPENGNSYS/client/scripts/Custom-$DATE
438    mv $OPENGNSYS/client/scripts/*Custom $OPENGNSYS/client/scripts/Custom-$DATE
439fi
440cp -r $TMPDIR/*Custom $OPENGNSYS/client/scripts &>/dev/null
441
442# Log files.
443if [ -d $TMPDIR/log ]; then
444    echo "   * Guardamos los ficheros de log."
445    cp -a $TMPDIR/log/* $OPENGNSYS/log
446fi
447
448if [ -f $TMPDIR/ogliveinfo.json ]; then
449    mv $OPENGNSYS/etc/ogliveinfo.json $OPENGNSYS/etc/ogliveinfo.json-$DATE
450    cp $TMPDIR/ogliveinfo.json $OPENGNSYS/etc
451fi
452
453echo -e "Se ha terminado de importar los datos del backup. \n\nSe han realizado copias de seguridad de los archivos antiguos:" 
454echo    "  - /etc/default/opengnsys-$DATE"
455echo    "  - $DHCPCFGDIR/dhcpd.conf-$DATE"
456echo    "  - $OPENGNSYS/etc/ogliveinfo.json-$DATE"
457echo    "  - $OPENGNSYS/tftpboot/menu.lst-$DATE"
458echo    "  - $OPENGNSYS/tftpboot/grub-$DATE"
459echo    "  - $OPENGNSYS/client/etc/engine.cfg-$DATE"
460echo    "  - $OPENGNSYS/client/scripts/Custom-$DATE"
461echo    "  - $OPENGNSYS/www/menus-$DATE"
462echo -e "  - $MYSQLBCK \n"
463
464echo "Hay que revisar la configuración del dhcp. En la consola es necesario configurar los valores de las ips de repositorios, servidores ntp, etc y lanzar el \"netBoot Avanzado\" a todas las aulas"
465
466echo "Es necesario probar todos los procedimientos y en caso de error borrarlos y generarlos de nuevo."
467
468oglivecli check &>/dev/null || \
469    echo "AVISO: Ejecutar como root \"oglivecli check\" para comprobar si hay que instalar algún cliente ogLive."
Note: See TracBrowser for help on using the repository browser.