From 6228f88c22e8975e35ca32b2386fe2148c5f92f8 Mon Sep 17 00:00:00 2001 From: ggil Date: Tue, 27 Aug 2024 12:45:04 +0200 Subject: [PATCH] refs #631 - Add getRepoInfo.py --- README.md | 129 ++++++---- admin/Sources/Services/ogAdmRepoAux | 285 +++++++++++++++++++++++ admin/Sources/Services/opengnsys.default | 15 ++ admin/Sources/Services/opengnsys.init | 224 ++++++++++++++++++ py_scripts/deleteImage.py | 5 + py_scripts/getRepoInfo.py | 191 +++++++++++++++ 6 files changed, 809 insertions(+), 40 deletions(-) create mode 100644 admin/Sources/Services/ogAdmRepoAux create mode 100644 admin/Sources/Services/opengnsys.default create mode 100644 admin/Sources/Services/opengnsys.init create mode 100644 py_scripts/getRepoInfo.py diff --git a/README.md b/README.md index 71116bb..53d40ab 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ ogRepository - OpenGnsys Repository Manager Este repositorio GIT contiene la estructura de datos del repositorio de imágenes de OpenGnsys. -- **bin** ----------- Binarios y scripts de gestión del repositorio. -- **etc** ----------- Ficheros y plantillas de configuración del repositorio. -- **py_scripts** --- Scripts en Python 3, algunos de los cuales son traducciones de los scripts bash situados en "bin". +- **admin** --------- Archivos de configuración del repositorio. +- **bin** ----------- Binarios y scripts de gestión del repositorio. +- **etc** ----------- Ficheros y plantillas de configuración del repositorio. +- **py_scripts** --- Scripts en Python 3, algunos de los cuales son traducciones de los scripts bash situados en "bin". --- @@ -19,8 +20,8 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará --- ### Tabla de Contenido: -1. [Obtener Información de todas las Imágenes](#obtener-información-de-todas-las-imágenes) - `GET /ogrepository/v1/images` -2. [Obtener Información de una Imagen concreta](#obtener-información-de-una-imagen-concreta) - `GET /ogrepository/v1/images/get-info` +1. [Obtener Información de todas las Imágenes](#obtener-información-de-todas-las-imágenes) - `GET /ogrepository/v1/images/get-info` +2. [Obtener Información de una Imagen concreta](#obtener-información-de-una-imagen-concreta) - `GET /ogrepository/v1/images/get-info` 3. [Actualizar Información del Repositorio](#actualizar-información-del-repositorio) - `PUT /ogrepository/v1/images` 4. [Eliminar una Imagen](#eliminar-una-imagen) - `DELETE /ogrepository/v1/images/delete-image` 5. [Recuperar una Imagen](#recuperar-una-imagen) - `POST /ogrepository/v1/images/recover-image` @@ -36,16 +37,20 @@ El presente documento detalla los endpoints de la API, con sus respectivos pará --- ### Obtener Información de todas las Imágenes -Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (que corresponde a todas las imágenes monolíticas almacenadas en el repositorio). -Se debe crear un script que devuelva dicha información, porque actualmente no hay ninguno. +Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (que corresponde a todas las imágenes almacenadas en el repositorio), y en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (que corresponde a las imágenes que fueron eliminadas, que estarán en la papelera). +Se puede utilizar el script "**getRepoInfo.py**, que hemos programado recientemente. -**URL:** `/ogrepository/v1/images` +**URL:** `/ogrepository/v1/images/get-info` **Método HTTP:** GET +**Cuerpo de la Solicitud (JSON):** +- **image**: Nombre de la imagen (con extensión), pero en este caso "all". +- **ou_subdir**: Subdirectorio correspondiente a la OU, pero en este caso "none". + **Ejemplo de Solicitud:** ```bash -curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/images +curl -X GET -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d '{"image":"all","ou_subdir":"none"}' http://example.com/ogrepository/v1/images/get-info ``` **Respuestas:** @@ -53,30 +58,68 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag - **Código 200 OK:** La información de las imágenes se obtuvo exitosamente. - **Contenido:** Información de imágenes en formato JSON. ```json + { - "directory": "/opt/opengnsys/images", - "images": [ - { - "name": "UbuntuSATA", - "type": "img", - "clientname": "Ubuntu_SATA", - "clonator": "partclone", - "compressor": "lzop", - "filesystem": "EXTFS", - "datasize": 8704000000 - }, - { - "name": "Windows10", - "type": "img", - "clientname": "Windows_10", - "clonator": "partclone", - "compressor": "lzop", - "filesystem": "NTFS", - "datasize": 23654400000 + "REPOSITORY": { + "directory": "/opt/opengnsys/images", + "images": [ + { + "name": "Ubuntu24", + "type": "img", + "clientname": "Ubuntu_24", + "clonator": "partclone", + "compressor": "lzop", + "filesystem": "EXTFS", + "datasize": 9859634200 + }, + { + "name": "Windows10", + "type": "img", + "clientname": "Windows_10", + "clonator": "partclone", + "compressor": "lzop", + "filesystem": "NTFS", + "datasize": 23654400000 + } + ], + "ous": [ + { + "subdir": "OU_subdir", + "images": [ + { + "name": "Ubuntu20", + "type": "img", + "clientname": "Ubuntu_20", + "clonator": "partclone", + "compressor": "lzop", + "filesystem": "EXTFS", + "datasize": 8704000000 + } + ] + } + ] + } + }, + "TRASH": { + "directory": "/opt/opengnsys/images_trash", + "images": [], + "ous": [ + { + "subdir": "CentroVirtual", + "images": [ + { + "name": "Ubuntu20OLD", + "type": "img", + "clientname": "Ubuntu_20", + "clonator": "partclone", + "compressor": "lzop", + "filesystem": "EXTFS", + "datasize": 8704000000 + } + ] + } + ] } - ], - "ous": [] - } ``` - **name**: Nombre de la imagen, sin extensión. - **type**: Extensión de la imagen. @@ -89,8 +132,8 @@ curl -X GET -H "Authorization: $API_KEY" http://example.com/ogrepository/v1/imag --- ### Obtener Información de una Imagen concreta -Se devolverá la informacion contenida en el archivo "**/opt/opengnsys/etc/repoinfo.json**" (correspondiente a la imagen especificada). -Se debe crear un script que devuelva dicha información, porque actualmente no hay ninguno. +Se devolverá la informacion de la imagen especificada, que puede estar en el archivo "**/opt/opengnsys/etc/repoinfo.json**" o en el archivo "**/opt/opengnsys/etc/trashinfo.json**" (en este último caso, si la imagen está en la papelera). +Se puede utilizar el script "**getRepoInfo.py**, que hemos programado recientemente. **URL:** `/ogrepository/v1/images/get-info` **Método HTTP:** GET @@ -111,14 +154,20 @@ curl -X GET -H "Authorization: $API_KEY" -H "Content-Type: application/json" -d - **Código 200 OK:** La información de la imagen se obtuvo exitosamente. - **Contenido:** Información de la imagen en formato JSON. ```json + { - "name": "Windows10", - "type": "img", - "clientname": "Windows_10", - "clonator": "partclone", - "compressor": "lzop", - "filesystem": "NTFS", - "datasize": 23654400000 + "directory": "/opt/opengnsys/images", + "images": [ + { + "name": "Windows10", + "type": "img", + "clientname": "Windows_10", + "clonator": "partclone", + "compressor": "lzop", + "filesystem": "NTFS", + "datasize": 23654400000 + } + ] } ``` - **name**: Nombre de la imagen, sin extensión. diff --git a/admin/Sources/Services/ogAdmRepoAux b/admin/Sources/Services/ogAdmRepoAux new file mode 100644 index 0000000..ede2bea --- /dev/null +++ b/admin/Sources/Services/ogAdmRepoAux @@ -0,0 +1,285 @@ +#!/bin/bash +PARM=`cat` +#PARM=$@ + + +#TODO: ticket 379 +#buscar parametro de identificador de operacion. +#usar parametro de identificacion para anexarlo al nombre de log +#Comprobar si la variable está seteas. +#Si no lo está setearla. +#Si esta seteada (en progreso) salir. + + +TIME=$SECONDS + +BASEDIR=/opt/opengnsys +PATH=$PATH:$BASEDIR/bin +REPONAME=ogAdmRepo +REPODIR="$BASEDIR/images/" + +# Para las sincronizadas +# BACKUP: Define si se realiza copia de seguridad al crear una imagen (true|false). +# IMGFS: Sistema de ficheros al crear las sincronizadas tipo archivo (EXT4|BTRFS). +[ -z $OGENGINECONFIGURATE ] && source $BASEDIR/client/etc/engine.cfg +# FS segun la configuracion y la version del kernel. ext4 para < 3.7, para >= BTRFS +KERNEL=$(file -bkr /opt/opengnsys/tftpboot/ogclient/ogvmlinuz |awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);printf("%d",v);sub(/[0-9]*\./,"",v);printf(".%02d",v)}}') +[ $KERNEL \< 3.07 ] && IMGFS="EXT4" || IMGFS=${IMGFS:-"BTRFS"} + +# Añade registro de incidencias. +function echolog () { + logger --tag $0 --priority local0.info "$*" + echo "$*" +} + +function mountImage () { + #@param 1 image_file + #@param 2 mount_dir + #@param 3 openciones mount + [ "$3" != "" ] && OPTMOUNT=" -o $3 " + # Si está montado nada que hacer + df |grep "$2$" 2>&1 >/dev/null && return 0 + # FS de la imagen segun el contenido del archivo .img + if file "$1" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then + echolog "mount $OPTMOUNT -t ext4 $1 $2" + mount $OPTMOUNT -t ext4 $1 $2 + else + echolog "mount $OPTMOUNT -o compress=lzo $1 $2" + mount $OPTMOUNT -o compress=lzo "$1" "$2" + fi + # Si esta montado da error 32, lo damos como bueno + RETVAL=$? + [ $RETVAL -eq 32 ] && RETVAL=0 + return $RETVAL +} + + +PARM1=$(echo $PARM | cut -f1 -d" ") +PARM2=$(echo $PARM | cut -f2 -d" ") +PARM3=$(echo $PARM | cut -f3 -d" ") +PARM4=$(echo $PARM | cut -f4 -d" ") + +# Determinamos el tipo de sistema de fichero de las imagenes segun el kernel que tenga + + +case "$PARM1" in + START_MULTICAST) + #1 START_MULTICAST + #2 fichero a enviar + #3 opciones de multicast + FILE="$PARM2" + MCASTOPT="$PARM3" + echolog "Ejecutar $(which sendFileMcast) $FILE $MCASTOPT" + sendFileMcast $FILE $MCASTOPT |logger --tag $0 --priority local0.info + case $? in + 1) echolog "Parametros insuficientes" + exit 1 ;; + 2) echolog "Fichero no accesible" + exit 2 ;; + 3) echolog "Sesion multicast no valida" + exit 3 ;; + esac + ;; + CREATE_IMAGE) + # Creamos/Redimensionamos el fichero de imagen y lo montamos para que se pueda escribir sobre el + #1 CREATE_IMAGE + #2 nombre imagen + #3 tipo de imagen [ img | diff ] + #4 tamaño imagen + LOOPDEVICE=$(losetup -f) + DIRMOUNT="$REPODIR/mount/$PARM2" + if [ "$PARM3" == "img" ] ; then + IMGEXT="img" + else + IMGEXT="img.diff" + DIRMOUNT="$DIRMOUNT.diff" + fi + IMGFILE="$REPODIR/$PARM2.$IMGEXT" + IMGDIR="$(dirname $IMGFILE)" + [ -d $IMGDIR ] || mkdir -p $IMGDIR + mkdir -p "$DIRMOUNT" + + LOCKFILE="$IMGFILE.lock" + + SIZEREQUIRED="$PARM4" + + # Si existe la imagen hacemos copia de seguridad y la redimesionamos + if [ -f "$IMGFILE" ]; then + echolog "La imagen $IMGFILE ya existe." + # TODO modificar ogGetImageSize + IMGSIZE=$(ls -l --block-size=1024 $IMGFILE| cut -f5 -d" ") + + if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" -o $IMGSIZE -lt $SIZEREQUIRED ]; then + # Si la imagen esta montada la desmonto + if [ -r "$DIRMOUNT/ogimg.info" ]; then + echolog "umount $DIRMOUNT" + umount "$DIRMOUNT" + [ $? -ne 0 ] && echolog "Error: No podemos desmontar la imagen para hacer copia de seguridad o redimensionar" && exit 1 + fi + fi + + # Copia de seguridad de la imagen + if [ "$BACKUP" == "true" -o "$BACKUP" == "TRUE" ]; then + echolog "Copia de seguridad de la imagen anterior" + echolog "cp $IMGFILE $IMGFILE.ant" + cp "$IMGFILE" "$IMGFILE.ant" + echolog mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null + mv -f "$IMGFILE.torrent" "$IMGFILE.torrent.ant" 2>/dev/null + fi + + # Redimensionamos la imagen al tamaño necesario + if [ $IMGSIZE -lt $SIZEREQUIRED ];then + echolog "Redimensionamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED" + echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE" + truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info + # FS de la imagen segun el contenido del archivo .img + if file "$IMGFILE" |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then + losetup $LOOPDEVICE "$IMGFILE" + echolog "resize2fs -f $LOOPDEVICE" + resize2fs -f $LOOPDEVICE |logger --tag $0 --priority local0.info + else + mount -o compress=lzo "$IMGFILE" "$DIRMOUNT" + echolog "btrfs filesystem resize max $DIRMOUNT" + btrfs filesystem resize max "$DIRMOUNT" 2>&1 |logger --tag $0 --priority local0.info + fi + fi + + + # Si no existe la imagen creamos el fichero. + else + echolog "Creamos la imagen $IMGFILE al tamaño necesario: $SIZEREQUIRED" + touch "$IMGFILE" + echolog "truncate --size=\">$SIZEREQUIRED\"k $IMGFILE" + truncate --size=">$SIZEREQUIRED"k $IMGFILE 2>&1 |logger --tag $0 --priority local0.info + #Formateamos imagen + echo losetup $LOOPDEVICE "$IMGFILE" + losetup $LOOPDEVICE "$IMGFILE" + if [ $IMGFS == "EXT4" ] ; then + echolog " mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE" + mkfs.ext4 -i 4096 -b 4096 -L ${PARM2##*\/} $LOOPDEVICE + else + echolog mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE + mkfs.btrfs -L ${PARM2##*\/} $LOOPDEVICE #&> $OGLOGCOMMAND + fi + fi + # Montamos la imagen. + mountImage "$IMGFILE" "$DIRMOUNT" + if [ $? -ne 0 ]; then + rmdir "$DIRMOUNT" + echolog "Error al crear/redimensionar la imagen" + exit 1 + fi + + #touch "$DIRMOUNT/ogimg.info" + echo "mounted"> "$LOCKFILE" + TIME2=$[SECONDS-TIME] + echolog "Fin creación/redimension de la imagen: $[TIME2/60]m $[TIME2%60]s" + # Si existe dispositivo loop lo borramos. + [ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE + # TODO: comprobar que no se quede el losetup bloqueado. + + ;; + MOUNT_IMAGE) + # Montamos el fichero imagen para que se pueda + #1 MOUNT_IMAGE + #2 nombre imagen + #3 tipo de imagen [ img | diff ] + DIRMOUNT="$REPODIR""mount/$PARM2" + if [ "$PARM3" == "img" ] ; then + IMGEXT="img" + else + IMGEXT="img.diff" + DIRMOUNT="$DIRMOUNT.diff" + fi + IMGFILE="$REPODIR/$PARM2.$IMGEXT" + echolog "Montamos la imagen $IMGFILE " + mkdir -p "$DIRMOUNT" + mountImage "$IMGFILE" "$DIRMOUNT" ro || (echolog "Error al montar la imagen"; exit 1) + ;; + UMOUNT_IMAGE) + # Desmontamos el fichero imagen. + # Si el directorio esta ocupado no se desmontará + #1 UMOUNT_IMAGE + #2 nombre imagen + #3 tipo de imagen [ img | diff ] + IMGTYPE="$PARM3" + DIRMOUNT="$REPODIR/mount/$PARM2" + if [ "$IMGTYPE" == "img" ]; then + IMGEXT="img" + else + DIRMOUNT="$DIRMOUNT.$IMGTYPE" + IMGEXT="img.diff" + fi + LOCKFILE="$REPODIR/$PARM2.$IMGEXT.lock" + echolog "Desmontamos la imagen $PARM2 $PARM3 " + umount $DIRMOUNT + rmdir $DIRMOUNT + [ -f $LOCKFILE ] && sed -i s/mounted//g $LOCKFILE + + ;; + REDUCE_IMAGE) + # Reduce el archivo de la imagen a tamaño datos + 500M + #1 REDUCE_IMAGE + #2 Nombre Imagen + #3 Tipo de imagen [ img |diff ] + DIRMOUNT="${REPODIR}mount/${PARM2}" + if [ "$PARM3" == "img" ] ; then + IMGEXT="img" + else + IMGEXT="img.diff" + DIRMOUNT="$DIRMOUNT.diff" + fi + IMGFILE="$REPODIR$PARM2.$IMGEXT" + LOCKFILE="$IMGFILE.lock" + [ ! -f $IMGFILE ] && echolog "Imagen $IMGFILE no existe" && exit 1 + + # Para imagenes EXT4 reduzco, para BTRFS solo desmonto. + if file $IMGFILE |grep -i -e " ext4 filesystem " 2>&1 > /dev/null ; then + + [ -d $DIRMOUNT ] || mkdir $DIRMOUNT + mountImage "$IMGFILE" "$DIRMOUNT" || (echolog "Error al montar la imagen $IMGFILE"; exit 1) + + + # Si el espacio libre menor que 200Mb desmontamos la imagen y nos salimos + AVAILABLE=$(df -k|grep $DIRMOUNT|awk '{print $4}') + if [ $AVAILABLE -lt 200000 ]; then + echolog "reducir imagen REPO $PARM2 $IMGEXT. tamaño minimo, nada que hacer" + umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1) + else + + # Calculamos la diferencia entre el tamaño interno y externo + EXTSIZE=$(ls -l --block-size=1024 $IMGFILE | cut -f5 -d" ") + INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}') + let EDGESIZE=$EXTSIZE-$INTSIZE + + echolog "reducir imagen REPO $PARM2 $IMGEXT, tamaño final: $ENDSIZE" + umount $DIRMOUNT + LOOPDEVICE=$(losetup -f) + losetup $LOOPDEVICE "$IMGFILE" + + # Redimensiono sistema de ficheros + echolog "resize2fs -fpM $LOOPDEVICE " + resize2fs -fpM $LOOPDEVICE # 2>&1 |logger --tag $0 --priority local0.info + mountImage "$IMGFILE" "$DIRMOUNT" + # Calculamos el tamaño final del archivo + INTSIZE=$(df -k|grep "$DIRMOUNT"|awk '{print $2}') + let EXTSIZE=$INTSIZE+$EDGESIZE + umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1) + # Si existe dispositivo loop lo borramos. + [ $LOOPDEVICE ] && losetup -a| grep $LOOPDEVICE &> /dev/null && losetup -d $LOOPDEVICE + # Corto el archivo al tamaño del sistema de ficheros + echo "truncate --size=\"$EXTSIZE\"k $IMGFILE" + echolog "truncate --size=\"$EXTSIZE\"k $IMGFILE" + truncate --size="$EXTSIZE"k $IMGFILE + fi + else + umount $DIRMOUNT || (echolog "Error al desmontar la imagen $IMGFILE"; exit 1) + fi + rmdir $DIRMOUNT + echo "reduced" >$LOCKFILE + + ;; + default) + echolog "Solicitud con parametros \"$PARM\" no realizada, no registrada o con errores" + ;; +esac diff --git a/admin/Sources/Services/opengnsys.default b/admin/Sources/Services/opengnsys.default new file mode 100644 index 0000000..d7376cf --- /dev/null +++ b/admin/Sources/Services/opengnsys.default @@ -0,0 +1,15 @@ +# RUN_OGADMSERVER defined as OpenGnsys Admin Server +# RUN_OGADMREPO defined as OpenGnsys Repository Manager +# RUN_OGADMAGENT run task scheduler service, only if Admin Server is enabled +# RUN_BTTRACKER run Bittorrent Tracker, only if Repository is enabled +# RUN_BTSEEDER start seeding of selected torrent files, only if Repository is enabled +# BTSEEDER_PRIORITY nice priority to seed torrent files; recommended values: +# 8 for Admin Server or Repo without Torrent +# 0 for Admin Server and Repo with Torrent +# -8 for Repo with Torrent +RUN_OGADMSERVER="yes" +RUN_OGADMREPO="yes" +RUN_OGADMAGENT="yes" +RUN_BTTRACKER="yes" +RUN_BTSEEDER="yes" +BTSEEDER_PRIORITY=0 diff --git a/admin/Sources/Services/opengnsys.init b/admin/Sources/Services/opengnsys.init new file mode 100644 index 0000000..ae27593 --- /dev/null +++ b/admin/Sources/Services/opengnsys.init @@ -0,0 +1,224 @@ +#!/bin/bash + +### BEGIN INIT INFO +# Provides: opengnsys +# Required-Start: +# Required-Stop: +# Default-Start: 2 3 4 5 +# Default-Stop: 1 +# Short-Description: Servicios del sistema OpenGnsys +# Description: Servicios del sistema OpenGnsys +### END INIT INFO + +# +# Definiciones globales +# +BASEDIR=/opt/opengnsys +OPENGNSYSUSER="opengnsys" +IMAGEDIR=$BASEDIR/images +CLIENTLOGDIR=$BASEDIR/log/clients + +# +# Servidor de OpenGnsys +# +SERVERNAME=ogAdmServer +SERVERDAEMON=$BASEDIR/sbin/$SERVERNAME +SERVERCFG=$BASEDIR/etc/$SERVERNAME.cfg +SERVERLOG=$BASEDIR/log/$SERVERNAME.log +SERVERDAEMON_OPTIONS="-f $SERVERCFG -l $SERVERLOG" + +# +# Servidor de Repositorio +# +############## ADV +REPOAUXNAME=ogAdmRepoAux +REPOAUXDAEMON=$BASEDIR/sbin/$REPOAUXNAME +REPOAUXPORT=$(awk -F= '/PUERTO/ {print $2+1}' $SERVERCFG 2>/dev/null) +############## ADV +############# IRINA # para setBootMode desde el cliente +SERVERAUXNAME=ogAdmServerAux +SERVERAUXDAEMON=$BASEDIR/sbin/$SERVERAUXNAME +SERVERAUXPORT=2011 +############# IRINA + +# +# Servidor de tareas programadas +# +AGENTNAME=ogAdmAgent +AGENTDAEMON=$BASEDIR/sbin/$AGENTNAME +AGENTCFG=$BASEDIR/etc/$AGENTNAME.cfg +AGENTLOG=$BASEDIR/log/$AGENTNAME.log +AGENTDAEMON_OPTIONS="-f $AGENTCFG -l $AGENTLOG" + +# +# Opciones Bittorrent +# + +BTTRACK=/usr/bin/bttrack.bittorrent +BTSEEDER=/usr/bin/btlaunchmany.bittornado +BTTRACKPORT=6969 +BTTRACKDFILE=/tmp/dstate +BTTRACKLOG=$BASEDIR/log/bttrack.log +BTINTERVAL=30 +BTTORRENTSDIR=$BASEDIR/images +BTTRACK_OPTIONS=" --port $BTTRACKPORT --dfile $BTTRACKDFILE --reannounce_interval $BTINTERVAL --logfile $BTTRACKLOG --allowed_dir $BTTORRENTSDIR --allow_get 1" +BTTRACKPID="/var/run/bttrack.pid" +BTSEEDERPID="/var/run/btseeder.pid" + + +export PATH="${PATH:+$PATH:}/usr/sbin:/sbin:/usr/bin" + +# Read config file if it is present. +if [ -r /etc/default/opengnsys ]; then + source /etc/default/opengnsys +fi + +# Configuración de arranque según la distribución Linux usada. +config() { + if [ -f /etc/os-release ]; then + source /etc/os-release + OSDISTRIB="$ID" + else + OSDISTRIB=$(lsb_release -is 2>/dev/null) + fi + OSDISTRIB="${OSDISTRIB,,}" + case "$OSDISTRIB" in + ubuntu|debian|linuxmint) + INITFUNCTIONS=/lib/lsb/init-functions + DAEMONSTART="start-stop-daemon --start --quiet --background --exec" + EXTRAOPTS="--" + DAEMONSTOP="start-stop-daemon --stop --quiet --oknodo --name" + ACTIONMSG="log_daemon_msg" + SUCCESSMSG="log_end_msg 0" + FAILMSG="log_end_msg 1" + TRACKERSTART="start-stop-daemon --make-pidfile --pidfile $BTTRACKPID --start --quiet --background --exec" + BTTRACK_OPTIONS="$BTTRACK_OPTIONS --parse_allowed_interval 1" + TRACKERSTOP="start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $BTTRACKPID" + SEEDERSTART="start-stop-daemon --make-pidfile --pidfile $BTSEEDERPID --start --quiet --background --exec" + SEEDERSTOP="start-stop-daemon --stop --quiet --oknodo --pidfile $BTSEEDERPID" + ;; + centos|fedora) + INITFUNCTIONS=/etc/init.d/functions + DAEMONSTART="daemon" + ENDOPTS="&" + DAEMONSTOP="killproc" + ACTIONMSG="echo -n" + SUCCESSMSG="eval ( success; echo )" + FAILMSG="eval ( failure; echo )" + BTTRACK=/usr/bin/bttrack.py + BTSEEDER=/usr/bin/btlaunchmany.py + TRACKERSTART="daemon --pidfile $BTTRACKPID" + TRACKERSTOP="killproc -p $BTTRACKPID $BTTRACK" + SEEDERSTART="daemon --pidfile $BTSEEDERPID" + SEEDERSTOP="killproc -p $BTSEEDERPID $BTSEEDER" + ;; + *) echo "Distribución Linux desconcocida o no soportada." + exit ;; + esac + if [ -r $INITFUNCTIONS ]; then + source $INITFUNCTIONS + fi +} + +arranca_demonios() { + # Comprobar que está instalado OpenGnsys. + if [ ! -d $BASEDIR ]; then + $ACTIONMSG "ERROR: No existe el directorio $BASEDIR" + $FAILMSG + exit $? + fi + # Deshabilitar modo reforzado de SELinux. + [ -f /selinux/enforce ] && echo 0 > /selinux/enforce + # Verificar permisos básicos. + if [ "$(stat --printf="%A%G" $IMAGEDIR 2>/dev/null)" != "drwxrwxr-x$OPENGNSYSUSER" ]; then + mkdir $IMAGEDIR 2>/dev/null + chmod 775 $IMAGEDIR + chgrp $OPENGNSYSUSER $IMAGEDIR + fi + if [ "$(stat --printf="%A%G" $CLIENTLOGDIR 2>/dev/null)" != "drwxrwxr-x$OPENGNSYSUSER" ]; then + mkdir -p $CLIENTLOGDIR 2>/dev/null + chmod 775 $CLIENTLOGDIR + chgrp $OPENGNSYSUSER $CLIENTLOGDIR + fi + # Arrancar los servicios indicados. + if [ $RUN_OGADMSERVER = "yes" ]; then + $ACTIONMSG "Iniciando demonio: $SERVERNAME" + $DAEMONSTART $SERVERDAEMON $EXTRAOPTS $SERVERDAEMON_OPTIONS $ENDOPTS + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + # Para SetBootmode desde el cliente + $ACTIONMSG "Iniciando demonio: $SERVERAUXNAME" # + faucet $SERVERAUXPORT --daemon --in bash -c "$SERVERAUXDAEMON" # NUEVO + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + fi + if [ $RUN_OGADMREPO = "yes" ]; then + $ACTIONMSG "Iniciando demonio: $REPOAUXNAME" + faucet $REPOAUXPORT --daemon --in bash -c "$REPOAUXDAEMON" + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + fi + if [ $RUN_OGADMSERVER = "yes" ] && [ $RUN_OGADMAGENT = "yes" ]; then + sleep 5 # Damos tiempo a que ogAdmServer este funcionando + fi + if [ $RUN_OGADMAGENT = "yes" ]; then + $ACTIONMSG "Iniciando demonio: $AGENTNAME" + $DAEMONSTART $AGENTDAEMON $EXTRAOPTS $AGENTDAEMON_OPTIONS $ENDOPTS + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + fi + if [ $RUN_BTTRACKER = "yes" ]; then + $ACTIONMSG "Iniciando demonio: $BTTRACK" + $TRACKERSTART $BTTRACK $EXTRAOPTS $BTTRACK_OPTIONS $ENDOPTS + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + fi + if [ $RUN_BTSEEDER = "yes" ]; then + $ACTIONMSG "Iniciando demonio: $BTSEEDER" + $SEEDERSTART $BTSEEDER $EXTRAOPTS $BTTORRENTSDIR &>/dev/null $ENDOPTS + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + fi + +} + +para_demonios() { + if [ -e $BTSEEDERPID ]; then + $ACTIONMSG "Parando demonio: $BTSEEDER" + $SEEDERSTOP + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + rm -f $BTSEEDERPID + fi + if [ -e $BTTRACKPID ]; then + $ACTIONMSG "Parando demonio: $BTTRACK" + $TRACKERSTOP + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + rm -f $BTTRACKPID + fi + $ACTIONMSG "Parando demonio: $AGENTNAME" + $DAEMONSTOP $AGENTNAME + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG + $ACTIONMSG "Parando demonio: $REPOAUXNAME" + pkill faucet + [ $? -le 1 ] && $SUCCESSMSG || $FAILMSG + $ACTIONMSG "Parando demonio: $SERVERNAME" + $DAEMONSTOP $SERVERNAME + [ $? = 0 ] && $SUCCESSMSG || $FAILMSG +} + +config + +case "$1" in + start) + arranca_demonios + ;; + stop) + para_demonios + ;; + restart) + para_demonios + arranca_demonios + ;; + + *) + echo "Uso: $0 {start|stop|restart}" + exit 1 + ;; +esac + +exit 0 + diff --git a/py_scripts/deleteImage.py b/py_scripts/deleteImage.py index a17f71f..aac9b1a 100644 --- a/py_scripts/deleteImage.py +++ b/py_scripts/deleteImage.py @@ -202,6 +202,11 @@ def main(): # Obtenemos la ruta completa al archivo a eliminar: file_path = build_file_path() + # Si no existe el archivo de imagen, imprimimos un mensaje de error y salimos del script: + if not os.path.exists(file_path): + print("Image file doesn't exist") + sys.exit(5) + # Comprobamos si existe el directorio correspondiente a la papelera, y en caso contrario lo creamos: if not os.path.exists(trash_path): print("Creating trash folder...") diff --git a/py_scripts/getRepoInfo.py b/py_scripts/getRepoInfo.py new file mode 100644 index 0000000..4897725 --- /dev/null +++ b/py_scripts/getRepoInfo.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +""" +Este script devuelve información (en formato json) de todas las imágenes contenidas en el repositorio (incluída la papelera), + o de la imagen que se especifique como primer parámetro (debiendo especificar también el subdirectorio de OU como segundo parámetro, si procede). + + Parámetros +------------ +sys.argv[1] - Nombre completo de la imagen a consultar (con extensión y sin ruta), u "all" (para obtener información de todas las imágenes). + - Ejemplo1: all + - Ejemplo2: image1.img + +sys.argv[2] - Subdirectorio correspondiente a la OU, o "none" si no procede.. + - Ejemplo1: none + - Ejemplo2: OU_subdirectory + + Sintaxis +---------- +./getRepoInfo.py image_name|all ou_subdir|none + + Ejemplos + --------- +./getRepoInfo.py all none +./getRepoInfo.py image1.img none +./getRepoInfo.py image1.img OU_subdirectory +""" + +# -------------------------------------------------------------------------------------------- +# IMPORTS +# -------------------------------------------------------------------------------------------- + +import os +import sys +import json + + +# -------------------------------------------------------------------------------------------- +# VARIABLES +# -------------------------------------------------------------------------------------------- + +script_name = os.path.basename(__file__) +repo_file = '/opt/opengnsys/etc/repoinfo.json' +trash_file = '/opt/opengnsys/etc/trashinfo.json' + + +# -------------------------------------------------------------------------------------------- +# FUNCTIONS +# -------------------------------------------------------------------------------------------- + + +def show_help(): + """ Imprime la ayuda, cuando se ejecuta el script con el parámetro "help". + """ + help_text = f""" + Sintaxis: {script_name} image_name|all ou_subdir|none + Ejemplo1: {script_name} all none + Ejemplo2: {script_name} image1.img none + Ejemplo3: {script_name} image1.img OU_subdirectory + """ + print(help_text) + + + +def check_params(): + """ Comprueba que se haya enviado la cantidad correcta de parámetros, y en el formato correcto. + Si no es así, muestra un mensaje de error, y sale del script. + LLama a la función "show_help" cuando se ejecuta el script con el parámetro "help". + """ + # Si se ejecuta el script con el parámetro "help", se muestra la ayuda, y se sale del script: + if len(sys.argv) == 2 and sys.argv[1] == "help": + show_help() + sys.exit(0) + # Si se ejecuta el script con más o menos de 2 parámetros, se muestra un error y la ayuda, y se sale del script: + elif len(sys.argv) != 3: + print(f"{script_name} Error: Formato incorrecto: Se debe especificar 2 parámetros") + show_help() + sys.exit(1) + + + +def get_all_info(repo_data, trash_data): + """ Imprime un json con la información de todo el repositorio, con todas las imágenes que contiene, + incluyendo las imágenes que fueron eliminadas (que estarán en la papelera). + """ + # Creamos un diccionario, combinando la información del repositorio y de la papelera: + dictionary = {"REPOSITORY": repo_data, + "TRASH": trash_data} + # Convertimos el diccionario a json, y lo imprimimos: + final_json = json.dumps(dictionary, indent=2) + print(final_json) + + + +def get_image_info(repo_data, trash_data, image_name, image_ext): + """ Busca la imagen especificada en el repositorio y en la papelera, devolviendo la información asociada si la encuentra, + (o devolviendo un mensaje de error y saliendo del script si no la encuentra). + """ + dictionary = "" + # Buscamos la imagen en el repositorio, y si la encontramos creamos un diccionario con los datos: + for image in repo_data['images']: + if image['name'] == image_name and image['type'] == image_ext: + dictionary = {"directory": repo_data['directory'], + "images": [image]} + # Buscamos la imagen en la papelera, y si la encontramos creamos un diccionario con los datos: + for image in trash_data['images']: + if image['name'] == image_name: + dictionary = {"directory": trash_data['directory'], + "images": [image]} + # Si hemos obtenido datos de la imagen, los pasamos a json y los imprmimos, + # y si no, imprimimos un mensaje de error y salimos del script: + if dictionary != "": + final_json = json.dumps(dictionary, indent=2) + print(final_json) + else: + print("No se ha encontrado la imagen especificada en el repositorio") + sys.exit(2) + + + +def get_ou_image_info(repo_data, trash_data, image_name, image_ext, ou_subdir): + """ Busca la imagen basada en OU en el repositorio y en la papelera, devolviendo la información asociada si la encuentra, + (o devolviendo un mensaje de error y saliendo del script si no la encuentra). + """ + dictionary = "" + # Buscamos la OU y la imagen en el repositorio, y si los encontramos creamos un diccionario con los datos: + for ou in repo_data['ous']: + if ou['subdir'] == ou_subdir: + for image in ou['images']: + if image['name'] == image_name and image['type'] == image_ext: + dictionary = {"directory": repo_data['directory'], + "ous": [{"subdir": ou_subdir, "images": [image]}]} + # Buscamos la OU y la imagen en la papelera, y si los encontramos creamos un diccionario con los datos: + for ou in trash_data['ous']: + if ou['subdir'] == ou_subdir: + for image in ou['images']: + if image['name'] == image_name: + dictionary = {"directory": trash_data['directory'], + "ous": [{"subdir": ou_subdir, "images": [image]}]} + # Si hemos obtenido datos de la imagen, los pasamos a json y los imprmimos, + # y si no, imprimimos un mensaje de error y salimos del script: + if dictionary != "": + final_json = json.dumps(dictionary, indent=2) + print(final_json) + else: + print("No se ha encontrado la imagen especificada en el repositorio") + sys.exit(3) + + + +# -------------------------------------------------------------------------------------------- +# MAIN +# -------------------------------------------------------------------------------------------- + + +def main(): + """ + """ + # Evaluamos si se ha enviado la cantidad correcta de parámetros, y en el formato correcto: + check_params() + + # Almacenamos la información de las imágenes del repositorio, en la variable "repo_data": + with open(repo_file, 'r') as file: + repo_data = json.load(file) + + # Almacenamos la información de las imágenes de la papelera, en la variable "trash_data": + with open(trash_file, 'r') as file: + trash_data = json.load(file) + + # Dependiendo del valor de los parámetros, llamamos a la función correspondiente, para imprimir la información + # (extrayendo el nombre, la extensión de la imagen, y/o la OU cuando se necesite): + if sys.argv[1] == 'all': + get_all_info(repo_data, trash_data) + elif sys.argv[2] == 'none': + image_name = sys.argv[1].split('.')[0] + image_ext = sys.argv[1].split('.')[1] + get_image_info(repo_data, trash_data, image_name, image_ext) + else: + image_name = sys.argv[1].split('.')[0] + image_ext = sys.argv[1].split('.')[1] + ou_subdir = sys.argv[2] + get_ou_image_info(repo_data, trash_data, image_name, image_ext, ou_subdir) + + + +# -------------------------------------------------------------------------------------------- + +if __name__ == "__main__": + main() + +# --------------------------------------------------------------------------------------------