commit
3dd95881d4
|
@ -0,0 +1,40 @@
|
|||
# In all environments, the following files are loaded if they exist,
|
||||
# the latter taking precedence over the former:
|
||||
#
|
||||
# * .env contains default values for the environment variables needed by the app
|
||||
# * .env.local uncommitted file with local overrides
|
||||
# * .env.$APP_ENV committed environment-specific defaults
|
||||
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||
#
|
||||
# Real environment variables win over .env files.
|
||||
#
|
||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||
# https://symfony.com/doc/current/configuration/secrets.html
|
||||
#
|
||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
APP_SECRET=d423d1302b974417d415b10bcde25767
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
|
||||
#
|
||||
# DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8&charset=utf8mb4"
|
||||
DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/messenger ###
|
||||
# Choose one of the transports below
|
||||
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@localhost:5672/%2f/messages
|
||||
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
|
||||
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
|
||||
###< symfony/messenger ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
# MAILER_DSN=null://null
|
||||
###< symfony/mailer ###
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
###> symfony/framework-bundle ###
|
||||
/.env.local
|
||||
/.env.local.php
|
||||
/.env.*.local
|
||||
/config/secrets/prod/prod.decrypt.private.php
|
||||
/public/bundles/
|
||||
/var/
|
||||
/vendor/
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> phpunit/phpunit ###
|
||||
/phpunit.xml
|
||||
.phpunit.result.cache
|
||||
###< phpunit/phpunit ###
|
||||
|
||||
###> symfony/phpunit-bridge ###
|
||||
.phpunit.result.cache
|
||||
/phpunit.xml
|
||||
###< symfony/phpunit-bridge ###
|
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
use App\Kernel;
|
||||
use Symfony\Bundle\FrameworkBundle\Console\Application;
|
||||
|
||||
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
|
||||
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
|
||||
}
|
||||
|
||||
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
|
||||
|
||||
return function (array $context) {
|
||||
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
|
||||
|
||||
return new Application($kernel);
|
||||
};
|
|
@ -0,0 +1,85 @@
|
|||
import os
|
||||
import socket
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
import stat
|
||||
|
||||
# Configuración de logging
|
||||
logging.basicConfig(level=logging.INFO, filename='/var/log/oglive_daemon.log', filemode='a', format='%(asctime)s - %(levelname)s - %(message)s')
|
||||
|
||||
def handle_command(command):
|
||||
action = command.get('action')
|
||||
args = command.get('args', [])
|
||||
cleaned_args = [arg.strip('\'"') for arg in args]
|
||||
logging.info(f'Handling command: {action} with args: {cleaned_args}')
|
||||
|
||||
try:
|
||||
if action in ['config', 'install', 'download', 'show', 'check', 'uninstall', 'disk_usage','list_installed_oglives','get_info','get_default','set_default','check_services_status']:
|
||||
command_to_run = ['sudo', '/opt/ogboot/bin/oglivecli', action] + cleaned_args
|
||||
logging.info(f'Running command: {" ".join(command_to_run)}')
|
||||
process = subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
stdout, stderr = process.communicate()
|
||||
logging.info(f'Command stdout: {stdout}')
|
||||
logging.error(f'Command stderr: {stderr}')
|
||||
|
||||
# Asumimos que `stdout` contendrá el JSON válido
|
||||
try:
|
||||
json_output = json.loads(stdout)
|
||||
return {"success": True, "output": json_output}
|
||||
except json.JSONDecodeError as e:
|
||||
logging.error(f'Error parsing JSON: {e} - Raw output: {stdout}')
|
||||
return {"success": False, "error": f'Error parsing JSON: {str(e)} - Raw output: {stdout}'}
|
||||
|
||||
else:
|
||||
return {"success": False, "error": "Unknown command"}
|
||||
except Exception as e:
|
||||
logging.error(f'Error handling command {action}: {e}')
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
def main():
|
||||
# Crea el directorio si no existe
|
||||
if not os.path.exists('/var/run/oglive'):
|
||||
os.makedirs('/var/run/oglive', exist_ok=True)
|
||||
|
||||
socket_path = '/var/run/oglive/oglive_daemon.sock'
|
||||
|
||||
# Elimina el socket si existe
|
||||
if os.path.exists(socket_path):
|
||||
os.remove(socket_path)
|
||||
|
||||
server = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
||||
server.bind(socket_path)
|
||||
|
||||
# Establece los permisos del socket
|
||||
os.chmod(socket_path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # Permisos para todos los usuarios
|
||||
|
||||
server.listen()
|
||||
|
||||
try:
|
||||
while True:
|
||||
logging.info('Daemon ready to accept connections')
|
||||
conn, _ = server.accept()
|
||||
with conn:
|
||||
logging.info('Accepted connection')
|
||||
data = conn.recv(1024)
|
||||
if not data:
|
||||
continue
|
||||
try:
|
||||
command = json.loads(data.decode('utf-8'))
|
||||
logging.info(f'Received command: {command}')
|
||||
except json.JSONDecodeError:
|
||||
logging.error('Failed to decode JSON')
|
||||
conn.sendall(json.dumps({"success": False, "error": "Invalid JSON"}).encode('utf-8'))
|
||||
continue
|
||||
|
||||
response = handle_command(command)
|
||||
conn.sendall(json.dumps(response).encode('utf-8'))
|
||||
finally:
|
||||
server.close()
|
||||
if os.path.exists(socket_path):
|
||||
os.remove(socket_path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,734 @@
|
|||
#!/bin/bash
|
||||
|
||||
#/**
|
||||
#@file oglivecli
|
||||
#@brief Command line tool to manage ogLive clients.
|
||||
#@usage oglivecli Command [Options ...]
|
||||
#@param Command:
|
||||
#@param help show this help
|
||||
#@param version show script version
|
||||
#@param config [Parameter] show configuration parameters
|
||||
#@param check check system consistency
|
||||
#@param convert convert old ogclient to new default ogLive client
|
||||
#@param list list installed ogLive clients
|
||||
#@param show all show JSON information about all installed ogLive clients
|
||||
#@param show default show JSON information about ogLive client marked as default
|
||||
#@param show Index|Dir show JSON information about an installed ogLive client
|
||||
#@param search Index|Dir show corresponding index or directory
|
||||
#@param download show a menu to download an ogLive ISO image from the OpenGnsys website
|
||||
#@param download Iso download an specific ogLive ISO image from the OpenGnsys website
|
||||
#@param install Iso install a new ogLive client from a downloaded ISO image
|
||||
#@param uninstall Iso remove ISO image and uninstall its ogLive client
|
||||
#@param uninstall Index|Dir uninstall an ogLive client
|
||||
#@param get-default get index value for default ogLive client
|
||||
#@param set-default Index set default ogLive client
|
||||
#@param rebuild rebuild a lost configuration file
|
||||
#@param assign Iso Index assign an ISO file to a JSON entry
|
||||
#@param Options:
|
||||
#@param Index a number, starting by 0
|
||||
#@param Dir directory (relative to installation directory)
|
||||
#@param Iso ISO file name (relative to download URL or download directory)
|
||||
#@warning This script needs "jq" command.
|
||||
#@version 1.1.0 - Initial version.
|
||||
#@author Ramón M. Gómez - ETSII Univ. Sevilla
|
||||
#@date 2016-12-05
|
||||
#@version 1.1.1b - Use reduced directory names.
|
||||
#@author Ramón M. Gómez - ETSII Univ. Sevilla
|
||||
#@date 2020-01-17
|
||||
#*/ ##
|
||||
|
||||
|
||||
# Global constants definition.
|
||||
PROG=$(basename "$(realpath "$0")") # Program name.
|
||||
OPENGNSYS=/opt/ogboot # OpenGnsys main directory.
|
||||
DOWNLOADDIR=$OPENGNSYS/lib # Directory to store ogLive images.
|
||||
DOWNLOADURL="https://ognproject.evlt.uma.es/trac/downloads" # Download URL.
|
||||
TFTPDIR=$OPENGNSYS/tftpboot # TFTP directory.
|
||||
DEFOGLIVE="ogLive" # Default ogLive directory.
|
||||
MINREL=20190601 # Mininum ogLive compatibility release.
|
||||
INFOFILE=$OPENGNSYS/etc/ogliveinfo.json # Configuration file.
|
||||
|
||||
|
||||
# Global and secondary functions.
|
||||
|
||||
source $OPENGNSYS/lib/ogfunctions.sh || exit 1
|
||||
|
||||
# Create/edit JSON file about installed ogLive clients.
|
||||
function addToJson() {
|
||||
local i DATA OGLIVEDIST="$1" OGLIVEKRNL="$2" OGLIVEARCH="$3" OGLIVEREV="$4"
|
||||
local OGLIVEDIR=$(basename $5 2>/dev/null) OGLIVEISO=$(basename $6 2>/dev/null)
|
||||
# JSON data for installed ogLive.
|
||||
DATA=$(cat << EOT | jq .
|
||||
{"distribution":"$OGLIVEDIST","kernel":"$OGLIVEKRNL","architecture":"$OGLIVEARCH","revision":"$OGLIVEREV","directory":"$OGLIVEDIR","iso":"$OGLIVEISO"}
|
||||
EOT
|
||||
)
|
||||
# Check JSON file consistency.
|
||||
if [ "$(jq -c keys $INFOFILE 2>/dev/null)" == '["default","oglive"]' ]; then
|
||||
# Check if ogLive is defined into JSON file.
|
||||
n=$(jq ".oglive | length" $INFOFILE)
|
||||
for ((i=0; i<n; i++)); do
|
||||
[ "$(jq ".check=$DATA | .check==.oglive[$i]" $INFOFILE)" == "true" ] && INDEX=$i
|
||||
done
|
||||
# Check if it needs to insert data.
|
||||
if [ -z "$INDEX" ]; then
|
||||
INDEX=$n
|
||||
jq ".oglive |= (. + [$DATA])" $INFOFILE | sponge $INFOFILE
|
||||
fi
|
||||
# Show JSON entry.
|
||||
jq ".oglive[$INDEX]" $INFOFILE
|
||||
else
|
||||
# Create new JSON file.
|
||||
cat << EOT | jq . | tee $INFOFILE
|
||||
{"oglive":[$DATA],"default":0}
|
||||
EOT
|
||||
fi
|
||||
}
|
||||
|
||||
# Command functions.
|
||||
|
||||
# Convert default ogclient to a new ogLive format.
|
||||
function convert() {
|
||||
local OGCLIENT=ogclient OLDINFOFILE=$OPENGNSYS/doc/veroglive.txt
|
||||
local OGLIVEKRNL OGLIVEDIR OGLIVEISO
|
||||
[ $# -ne 0 ] && raiseError usage
|
||||
[ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration file."
|
||||
[ -n "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ] && raiseError access "ogLive is already converted."
|
||||
pushd $TFTPDIR >/dev/null || raiseError access "Installation directory."
|
||||
[ ! -f $OGCLIENT/ogvmlinuz ] && raiseError notfound "\"ogclient\"."
|
||||
# Add entry to JSON file using ogclient kernel version.
|
||||
OGLIVEKRNL=$(file -bkr $OGCLIENT/ogvmlinuz | awk '/Linux/ {for(i=1;i<=NF;i++) if($i~/version/) {v=$(i+1);sub(/-.*/,"",v);print v}}')
|
||||
OGLIVEDIR=$DEFOGLIVE-$OGLIVEKRNL
|
||||
[ -r $OLDINFOFILE ] && OGLIVEISO="$(head -1 $OLDINFOFILE)"
|
||||
addToJson "$(echo $OGLIVEISO|cut -f2 -d-)" "$OGLIVEKRNL" "i386" "${OGLIVEISO##*-}" "$OGLIVEDIR" "$OGLIVEISO.iso"
|
||||
# Rename directory, link to default and clean old files.
|
||||
mv -v $OGCLIENT $OGLIVEDIR
|
||||
ln -vfs $OGLIVEDIR $DEFOGLIVE
|
||||
rm -f $OGCLIENT
|
||||
ln -vfs $DEFOGLIVE $OGCLIENT
|
||||
mv -v $OGCLIENT.old $OGLIVEDIR.old 2>/dev/null
|
||||
rm -fv {ogvmlinuz,oginitrd.img}{,.sum} $OLDINFOFILE
|
||||
popd >/dev/null
|
||||
# Delete old config file.
|
||||
rm -f $OLDINFOFILE
|
||||
}
|
||||
|
||||
# Show script configuration parameters.
|
||||
function config() {
|
||||
local DATA
|
||||
DATA=$(cat << EOT
|
||||
[
|
||||
{ "param": "config-file", "description": "Configuration file", "value": "$INFOFILE" },
|
||||
{ "param": "download-url", "description": "ogLive download URL", "value": "$DOWNLOADURL" },
|
||||
{ "param": "download-dir", "description": "ogLive download directory", "value": "$DOWNLOADDIR" },
|
||||
{ "param": "install-dir", "description": "ogLive installation directory", "value": "$TFTPDIR" },
|
||||
{ "param": "default-name", "description": "Default ogLive name", "value": "$DEFOGLIVE" },
|
||||
{ "param": "min-release", "description": "Minimum compatibility release", "value": "r$MINREL" }
|
||||
]
|
||||
EOT
|
||||
)
|
||||
case $# in
|
||||
0) # Show all parameters.
|
||||
echo "$DATA" | jq -r '.[] | .description + " (" + .param + ")," + .value' | column -ts,
|
||||
;;
|
||||
1) # Show specified parameter.
|
||||
DATA=$(echo "$DATA" | jq -r ".[] | select(.param==\"$1\").value")
|
||||
[ "$DATA" ] || raiseError notfound "\"$1\"."
|
||||
echo "$DATA"
|
||||
;;
|
||||
*) # Usage error.
|
||||
raiseError usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Check consistency, showing configuration problems.
|
||||
function check() {
|
||||
local ERR=0 AUX INST DEF
|
||||
[ $# -ne 0 ] && raiseError usage
|
||||
# Check for old system that needs conversion.
|
||||
if [ -z "$(stat -c "%N" $TFTPDIR/ogclient | awk '$3~/'$DEFOGLIVE'/ {print}')" ]; then
|
||||
echo "This server uses old ogclient, please run \"$PROG convert\" to update."
|
||||
let ERR++
|
||||
[ ! -f $INFOFILE ] && return $ERR
|
||||
fi
|
||||
# Check for other problems.
|
||||
[ ! -f $INFOFILE ] && echo "Configuration file does not exists: $INFOFILE" && let ERR++
|
||||
[ -f $INFOFILE -a "$(jq -c keys $INFOFILE 2>/dev/null)" != "[\"default\",\"oglive\"]" ] && echo "Format error in configuration file: $INFOFILE" && let ERR++
|
||||
[ ! -e $TFTPDIR ] && echo "TFTP directory does not exist: $TFTPDIR." && let ERR++
|
||||
# Check for installed ogLive clients.
|
||||
INST=( $(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort) )
|
||||
[[ ${#INST[@]} -eq 0 ]] && echo "No ogLive clients are installed." && let ERR++
|
||||
DEF=( $(jq -r .oglive[].directory $INFOFILE 2>/dev/null | sort) )
|
||||
# Compare installed and defined ogLive clients.
|
||||
AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
|
||||
[ -n "$AUX" ] && echo "Some ogLive are installed but not defined: ${AUX//$'\n'/, }" && let ERR++
|
||||
AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
|
||||
[ -n "$AUX" ] && echo "Some ogLive are defined but not installed: ${AUX//$'\n'/, }" && let ERR++
|
||||
# Compare downloaded and defined ISO images.
|
||||
INST=( $(find $DOWNLOADDIR/ -type f -name "$DEFOGLIVE-*.iso" -printf "%f\n" | sort) )
|
||||
DEF=( $(jq -r .oglive[].iso $INFOFILE 2>/dev/null | sort) )
|
||||
AUX=$(comm -23 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
|
||||
[ -n "$AUX" ] && echo "Some ISOs are downloaded but not defined: ${AUX//$'\n'/, }" && let ERR++
|
||||
AUX=$(comm -13 <(printf "%s\n" ${INST[*]}) <(printf "%s\n" ${DEF[*]}))
|
||||
[ -n "$AUX" ] && echo "Some ISOs are defined but not downloaded: ${AUX//$'\n'/, }" && let ERR++
|
||||
# Check for new ISO files downloaded after installation.
|
||||
AUX=$(jq -r '.oglive[] as $og | $og.iso + ":" + $og.directory' $INFOFILE 2>/dev/null | \
|
||||
while IFS=":" read -r DEF INST; do
|
||||
[ $DOWNLOADDIR/$DEF -nt $TFTPDIR/$INST ] && echo "$DEF"
|
||||
done)
|
||||
[ -n "$AUX" ] && echo "Some ISOs are downloaded after installation: ${AUX//$'\n'/, }" && let ERR++
|
||||
AUX=$(jq -r '.oglive[] as $og | if ($og.revision[1:9] | tonumber) < '$MINREL' then $og.directory else "" end' $INFOFILE 2>/dev/null)
|
||||
[ -n "$AUX" ] && echo "Some installed ogLive aren't fully compatible: ${AUX//$'\n'/, }" && let ERR++
|
||||
DEF=$(jq -r ".oglive[$(getdefault)].directory" $INFOFILE 2>/dev/null)
|
||||
INST=$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | cut -f4 -d\')
|
||||
[ "$DEF" != "$INST" ] && echo "Default ogLive is not linked to right directory: $DEF <> $INST" && let ERR++
|
||||
# Print result.
|
||||
[ $ERR -eq 0 ] && echo "OK!" || echo "Problems detected: $ERR"
|
||||
return $ERR
|
||||
}
|
||||
|
||||
# List installed ogLive clients.
|
||||
function list() {
|
||||
[ $# -ne 0 ] && raiseError usage
|
||||
[ ! -r $INFOFILE ] && raiseError access "Configuration file."
|
||||
# List all defined indexes, directories and check if missing.
|
||||
jq -r .oglive[].directory $INFOFILE | nl -v 0 | \
|
||||
awk '{system("echo -n "$0"; test -d '$TFTPDIR'/"$2" || echo -n \" (missing)\"; echo")}' | column -t
|
||||
}
|
||||
|
||||
# Show information about an installed ogLive client.
|
||||
function show() {
|
||||
local INDEX
|
||||
[ $# -ne 1 ] && raiseError usage
|
||||
[ ! -r $INFOFILE ] && raiseError access "Configuration file."
|
||||
# Show JSON entries.
|
||||
case "$1" in
|
||||
default) # Default index.
|
||||
INDEX="[$(jq -r .default $INFOFILE)]" ;;
|
||||
all) # All intries.
|
||||
;;
|
||||
[0-9]*) # Index.
|
||||
INDEX="[$1]" ;;
|
||||
*) # Directory.
|
||||
INDEX="[$(search "$1" 2>/dev/null)]" || raiseError notfound "Directory \"$1\"."
|
||||
;;
|
||||
esac
|
||||
jq ".oglive$INDEX" $INFOFILE || raiseError notfound "Index \"$1\"."
|
||||
}
|
||||
|
||||
# Show index or directory corresponding to searching parameter.
|
||||
function search() {
|
||||
[ $# -ne 1 ] && raiseError usage
|
||||
[ ! -r $INFOFILE ] && raiseError access "Configuration file."
|
||||
# Show corresponding index or directory.
|
||||
list | awk -v d="$1" '{if ($2==d) print $1; if ($1==d) print $2}' | grep . || raiseError notfound "Index/Directory \"$1\"."
|
||||
}
|
||||
|
||||
function download() {
|
||||
local OGLIVE NISOS i HTTPCODE ISOREL
|
||||
|
||||
# Verificar si el directorio de descarga existe y tiene permisos de escritura.
|
||||
[ ! -d "$DOWNLOADDIR" ] && raiseError notfound "Directorio de descarga."
|
||||
[ ! -w "$DOWNLOADDIR" ] && raiseError access "Directorio de descarga."
|
||||
|
||||
# Si no se proporciona ningún parámetro, mostrar el menú de descargas.
|
||||
if [ -z "$1" ]; then
|
||||
downloadMenu
|
||||
else
|
||||
local selected_name="$1"
|
||||
|
||||
# Obtener la lista de archivos disponibles.
|
||||
OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
|
||||
|
||||
# Buscar el archivo seleccionado por nombre.
|
||||
OGLIVEFILE=""
|
||||
for iso in "${OGLIVE[@]}"; do
|
||||
if [[ "$iso" == *"$selected_name"* ]]; then
|
||||
OGLIVEFILE=$iso
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
[ -n "$OGLIVEFILE" ] || raiseError download "Nombre \"$selected_name\" inválido."
|
||||
|
||||
# Obtener el tamaño de descarga.
|
||||
local SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 "$DOWNLOADURL/$OGLIVEFILE" | awk -F: '/Content-Length:/ {print $2}')
|
||||
[ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
|
||||
|
||||
# Descargar ogLive.
|
||||
local TARGETFILE="$DOWNLOADDIR/$OGLIVEFILE"
|
||||
trap "rm -f $TARGETFILE" 1 2 3 6 9 15
|
||||
curl -k --retry 5 --retry-delay 5 "$DOWNLOADURL/$OGLIVEFILE" -o "$TARGETFILE" || raiseError download "\"$OGLIVEFILE\"."
|
||||
install "$OGLIVEFILE"
|
||||
fi
|
||||
}
|
||||
# Muestra un menú para seleccionar y descargar un archivo ogLive ISO del sitio web de OpenGnsys.
|
||||
function downloadMenu() {
|
||||
local OGLIVE NISOS i HTTPCODE ISOREL
|
||||
OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
|
||||
NISOS=${#OGLIVE[@]}
|
||||
|
||||
local downloads=()
|
||||
|
||||
for i in $(seq 1 $NISOS); do
|
||||
local installed=false
|
||||
local compatible=false
|
||||
|
||||
[ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && installed=true
|
||||
ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*}
|
||||
[ $ISOREL -ge $MINREL ] && compatible=true
|
||||
|
||||
local DATA=$(jq -n \
|
||||
--arg id "$i" \
|
||||
--arg filename "${OGLIVE[i-1]}" \
|
||||
--argjson installed "$installed" \
|
||||
--argjson compatible "$compatible" \
|
||||
'{id: $id, filename: $filename, installed: $installed, compatible: $compatible}')
|
||||
|
||||
downloads+=("$DATA")
|
||||
done
|
||||
|
||||
jq -n --argjson downloads "$(printf '%s\n' "${downloads[@]}" | jq -s .)" \
|
||||
'{downloads: $downloads}'
|
||||
}
|
||||
|
||||
# Show a menu to select and download an ogLive ISO image from the OpenGnsys website.
|
||||
function download_old() {
|
||||
local OGLIVE NISOS i HTTPCODE TARGETFILE
|
||||
local ISOREL
|
||||
[ $# -gt 1 ] && raiseError usage
|
||||
[ ! -d $DOWNLOADDIR ] && raiseError notfound "Download directory."
|
||||
[ ! -w $DOWNLOADDIR ] && raiseError access "Download directory."
|
||||
# Check parameter.
|
||||
if [ -n "$1" ]; then
|
||||
# ogLive to download.
|
||||
OGLIVEFILE="$1"
|
||||
else
|
||||
# Show download menu.
|
||||
OGLIVE=( $(curl -k --silent $DOWNLOADURL | grep "$DEFOGLIVE.*iso") )
|
||||
NISOS=${#OGLIVE[@]}
|
||||
echo "Available downloads (+ = installed, * = full compatibility):"
|
||||
for i in $(seq 1 $NISOS); do
|
||||
[ -e $DOWNLOADDIR/${OGLIVE[i-1]} ] && OGLIVE[i-1]="(+) ${OGLIVE[i-1]}"
|
||||
ISOREL=${OGLIVE[i-1]##*-r}; ISOREL=${ISOREL%%.*}
|
||||
[ $ISOREL -ge $MINREL ] && OGLIVE[i-1]="(*) ${OGLIVE[i-1]}"
|
||||
done
|
||||
select opt in "${OGLIVE[@]}"; do
|
||||
[ -n "$opt" ] && OGLIVEFILE=${opt##* } && break
|
||||
done
|
||||
fi
|
||||
# Get download size.
|
||||
SOURCELENGTH=$(curl -k --head --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE | awk -F: '/Content-Length:/ {print $2}')
|
||||
[ -n "$SOURCELENGTH" ] || raiseError download "$OGLIVEFILE"
|
||||
# Download ogLive.
|
||||
TARGETFILE=$DOWNLOADDIR/$OGLIVEFILE
|
||||
trap "rm -f $TARGETFILE" 1 2 3 6 9 15
|
||||
curl -k --retry 5 --retry-delay 5 --max-time 30 $DOWNLOADURL/$OGLIVEFILE -o $TARGETFILE || raiseError download "\"$OGLIVEFILE\"."
|
||||
}
|
||||
|
||||
update_json() {
|
||||
local key=$1
|
||||
local value=$2
|
||||
result_json=$(jq --arg key "$key" --arg value "$value" '.[$key] = $value' <<< "$result_json")
|
||||
}
|
||||
|
||||
add_message() {
|
||||
local message=$1
|
||||
result_json=$(jq --arg message "$message" '.messages += [$message]' <<< "$result_json")
|
||||
}
|
||||
|
||||
# Install an ogLive client from a previously downloaded ISO image.
|
||||
function install() {
|
||||
local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS OGCLIENT=ogclient
|
||||
local COMPRESS SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT JSON_OUTPUT
|
||||
[ $# -ne 1 ] && { echo "{\"status\": \"error\", \"error\": \"usage\"}"; exit 1; }
|
||||
|
||||
OGLIVEFILE=$(realpath $DOWNLOADDIR/$1)
|
||||
[ $(echo $OGLIVEFILE | wc -w) -gt 1 ] && { echo "{\"status\": \"error\", \"error\": \"usage\"}"; exit 1; }
|
||||
[ ! -f $OGLIVEFILE ] && { echo "{\"status\": \"error\", \"error\": \"not found $1.\"}"; exit 1; }
|
||||
[ ! -r $OGLIVEFILE ] && { echo "{\"status\": \"error\", \"error\": \"access $1.\"}"; exit 1; }
|
||||
[ ! -w $(dirname $INFOFILE) ] && { echo "{\"status\": \"error\", \"error\": \"access configuration directory.\"}"; exit 1; }
|
||||
[ ! -w $TFTPDIR ] && { echo "{\"status\": \"error\", \"error\": \"access installation directory.\"}"; exit 1; }
|
||||
[ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && { echo "{\"status\": \"error\", \"error\": \"File is not an ogLive ISO image.\"}"; exit 1; }
|
||||
|
||||
OGLIVEDIST="$(echo $OGLIVEFILE|cut -f2 -d-)"
|
||||
OGLIVEREV="${OGLIVEFILE##*-}"; OGLIVEREV="${OGLIVEREV%%.*}"
|
||||
OGLIVEKRNL="$(echo $OGLIVEFILE|cut -f3- -d-)"; OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEREV.*}"
|
||||
OGLIVEARCH="$(echo $OGLIVEFILE|awk -F- '{print $(NF-1)}')"
|
||||
case "$OGLIVEARCH" in
|
||||
i386|amd64)
|
||||
OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEARCH}" ;;
|
||||
*)
|
||||
OGLIVEARCH="i386" ;;
|
||||
esac
|
||||
OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-${OGLIVEKRNL%%-*}-$OGLIVEARCH-$OGLIVEREV"
|
||||
OGLIVEDIR="${OGLIVEDIR/amd64-/}"
|
||||
|
||||
OGINITRD=$OGLIVEDIR/oginitrd.img
|
||||
[ ! -r $OGINITRD ] && OGINITRD=$TFTPDIR/$DEFOGLIVE/oginitrd.img
|
||||
if [ -r $OGINITRD ]; then
|
||||
COMPRESS=$(file -b "$OGINITRD" | awk '{print tolower($1);}')
|
||||
SAMBAPASS=$($COMPRESS -dc $OGINITRD | \
|
||||
cpio -i --to-stdout scripts/ogfunctions 2>/dev/null | \
|
||||
sed -n '/^[ \t].*OPTIONS=/s/.*pass=\(\w*\).*/\1/p')
|
||||
fi
|
||||
|
||||
rm -fr ${OGLIVEDIR}.old
|
||||
mv -f $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null
|
||||
|
||||
TMPDIR=/tmp/${OGLIVEFILE%.iso}
|
||||
mkdir -p $OGLIVEDIR $TMPDIR
|
||||
trap "umount $TMPDIR; rm -fr $TMPDIR" 1 2 3 6 9 15
|
||||
mount -o loop,ro $OGLIVEFILE $TMPDIR >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"mount failed.\"}"; exit 1; }
|
||||
cp -va $TMPDIR/ogclient/* $OGLIVEDIR >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"Cannot copy files to ogLive directory.\"}"; exit 1; }
|
||||
umount $TMPDIR >/dev/null 2>&1
|
||||
|
||||
if [ ! -f $INFOFILE ]; then
|
||||
rm -f $TFTPDIR/$DEFOGLIVE $TFTPDIR/$OGCLIENT
|
||||
ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"Linking to $TFTPDIR/$DEFOGLIVE failed.\"}"; exit 1; }
|
||||
ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"Linking to $TFTPDIR/$OGCLIENT failed.\"}"; exit 1; }
|
||||
fi
|
||||
|
||||
if [ -n "$SAMBAPASS" ]; then
|
||||
echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"setsmbpass failed.\"}"; exit 1; }
|
||||
else
|
||||
$OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"setsmbpass failed.\"}"; exit 1; }
|
||||
fi
|
||||
|
||||
find -L $OGLIVEDIR -type d -exec chmod 755 {} \; >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"chmod directories failed.\"}"; exit 1; }
|
||||
find -L $OGLIVEDIR -type f -exec chmod 644 {} \; >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"chmod files failed.\"}"; exit 1; }
|
||||
chown -R :opengnsys $OGLIVEDIR >/dev/null 2>&1 || { echo "{\"status\": \"error\", \"error\": \"chown failed.\"}"; exit 1; }
|
||||
|
||||
OGSQFS=$OGLIVEDIR/ogclient.sqfs
|
||||
|
||||
if mount -o loop,ro $OGSQFS $TMPDIR >/dev/null 2>&1; then
|
||||
RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
|
||||
RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
|
||||
|
||||
if [ -z "$RSYNCSERV" ] || [ "$RSYNCSERV" -gt "${RSYNCCLNT:-1}" ]; then
|
||||
if [ -e "$OPENGNSYS/client/bin/rsync-$RSYNCSERV" ]; then
|
||||
mv -f "$OPENGNSYS/client/bin/rsync-$RSYNCSERV" "$OPENGNSYS/client/bin/rsync" 2>/dev/null
|
||||
fi
|
||||
else
|
||||
if [ -e "$OPENGNSYS/client/bin/rsync" ]; then
|
||||
mv -f "$OPENGNSYS/client/bin/rsync" "$OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')"
|
||||
fi
|
||||
fi
|
||||
|
||||
umount $TMPDIR >/dev/null 2>&1
|
||||
rmdir $TMPDIR >/dev/null 2>&1 || rm -rf $TMPDIR >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
# Crear JSON output
|
||||
JSON_OUTPUT=$(jq -n \
|
||||
--arg dist "$OGLIVEDIST" \
|
||||
--arg krnl "$OGLIVEKRNL" \
|
||||
--arg arch "$OGLIVEARCH" \
|
||||
--arg rev "$OGLIVEREV" \
|
||||
--arg dir "$OGLIVEDIR" \
|
||||
--arg iso "$(basename "$OGLIVEFILE")" \
|
||||
'{status: "success", messages: [], result: {distribution: $dist, kernel: $krnl, architecture: $arch, revision: $rev, directory: $dir, iso: $iso}}')
|
||||
|
||||
echo "$JSON_OUTPUT"
|
||||
}
|
||||
|
||||
|
||||
|
||||
# Uninstall an ogLive client.
|
||||
function uninstall() {
|
||||
local CHECKSUM DIR
|
||||
|
||||
# Validar que se proporcionó exactamente un argumento (el checksum)
|
||||
[ $# -ne 1 ] && { echo "{\"error\": \"usage: uninstall {checksum}\"}"; exit 1; }
|
||||
|
||||
CHECKSUM=$1
|
||||
|
||||
# Verificar acceso a los directorios necesarios
|
||||
[ ! -w $TFTPDIR ] && { echo "{\"error\": \"access installation directory.\"}"; exit 1; }
|
||||
|
||||
# Buscar el directorio correspondiente al checksum
|
||||
DIR=$(find $TFTPDIR -type f -name 'ogclient.sqfs.sum' -exec grep -l "$CHECKSUM" {} \; | xargs -I{} dirname {})
|
||||
|
||||
# Si no se encuentra el directorio, devolver error
|
||||
if [ -z "$DIR" ]; then
|
||||
echo "{\"error\": \"ogLive client with checksum $CHECKSUM not found.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Eliminar archivos y directorio, redirigiendo la salida a /dev/null
|
||||
rm -vfr $DIR > /dev/null 2>&1
|
||||
|
||||
# Comprobar si la eliminación tuvo éxito
|
||||
if [ -d "$DIR" ]; then
|
||||
echo "{\"error\": \"Failed to uninstall ogLive client in $DIR.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Devolver mensaje de éxito
|
||||
echo "{\"message\": \"ogLive client uninstalled successfully.\", \"details\": \"Removed directory: $DIR\"}"
|
||||
}
|
||||
|
||||
# Get information about the default ogLive client.
|
||||
function get_default() {
|
||||
local DEFAULT_LINK="$TFTPDIR/$DEFOGLIVE"
|
||||
local DIR OGLIVEDIST OGLIVEKRNL OGLIVEARCH OGLIVEREV OGLIVEISO OGLIVEDIR
|
||||
|
||||
# Verificar que el enlace simbólico del ogLive por defecto existe.
|
||||
if [ ! -L "$DEFAULT_LINK" ]; then
|
||||
echo "{\"error\": \"Default ogLive client link not found.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Obtener el directorio real al que apunta el enlace simbólico.
|
||||
DIR=$(readlink -f "$DEFAULT_LINK")
|
||||
|
||||
# Si no se encuentra el directorio, devolver error.
|
||||
if [ -z "$DIR" ]; then
|
||||
echo "{\"error\": \"Default ogLive client directory not found.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Obtener la información del ogLive a partir del nombre del directorio.
|
||||
OGLIVEDIR=$(basename "$DIR")
|
||||
OGLIVEDIST="$(echo $OGLIVEDIR | cut -d- -f2)"
|
||||
OGLIVEKRNL="$(echo $OGLIVEDIR | cut -d- -f3)"
|
||||
OGLIVEARCH="amd64" # Suponiendo que siempre es amd64
|
||||
OGLIVEREV="$(echo $OGLIVEDIR | cut -d- -f4)"
|
||||
OGLIVEISO="" # No tenemos la información del ISO aquí, podría necesitarse un ajuste si se requiere
|
||||
|
||||
# Construir el JSON con la información.
|
||||
local INFO=$(cat << EOT
|
||||
{
|
||||
"distribution": "$OGLIVEDIST",
|
||||
"kernel": "$OGLIVEKRNL",
|
||||
"architecture": "$OGLIVEARCH",
|
||||
"revision": "$OGLIVEREV",
|
||||
"directory": "$DIR",
|
||||
"iso": "$OGLIVEISO"
|
||||
}
|
||||
EOT
|
||||
)
|
||||
|
||||
# Devolver la información en formato JSON.
|
||||
echo "$INFO"
|
||||
}
|
||||
|
||||
# Set default ogLive client by checksum.
|
||||
function set_default() {
|
||||
local CHECKSUM=$1
|
||||
local DIR
|
||||
|
||||
# Validar que se proporcionó exactamente un argumento (el checksum)
|
||||
[ $# -ne 1 ] && { echo "{\"error\": \"usage: set-default {checksum}\"}"; exit 1; }
|
||||
|
||||
# Verificar acceso a los directorios necesarios
|
||||
[ ! -w $TFTPDIR ] && { echo "{\"error\": \"access installation directory.\"}"; exit 1; }
|
||||
|
||||
# Buscar el directorio correspondiente al checksum
|
||||
DIR=$(find $TFTPDIR -type f -name 'ogclient.sqfs.sum' -exec grep -l "$CHECKSUM" {} \; | xargs -I{} dirname {} | grep -v ".old")
|
||||
|
||||
# Si no se encuentra el directorio, devolver error
|
||||
if [ -z "$DIR" ]; then
|
||||
echo "{\"error\": \"ogLive client with checksum $CHECKSUM not found.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Eliminar el enlace simbólico existente y crear uno nuevo
|
||||
rm -f $TFTPDIR/$DEFOGLIVE > /dev/null 2>&1
|
||||
ln -vfs $(basename $DIR) $TFTPDIR/$DEFOGLIVE > /dev/null 2>&1
|
||||
|
||||
# Comprobar si el enlace simbólico se creó correctamente
|
||||
if [ "$(readlink -f $TFTPDIR/$DEFOGLIVE)" == "$(readlink -f $DIR)" ]; then
|
||||
echo "{\"message\": \"ogLive client set as default successfully.\", \"details\": \"$DIR\"}"
|
||||
else
|
||||
echo "{\"error\": \"Failed to set default ogLive client.\"}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Rebuild a lost configuration file.
|
||||
function rebuild() {
|
||||
local i INST NF DEF
|
||||
[ $# -ne 0 ] && raiseError usage
|
||||
[ -f $INFOFILE ] && raiseError access "Configuration file exists."
|
||||
INST=$(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort)
|
||||
for i in $INST; do
|
||||
NF=$(echo $i | awk -F- '{print NF-1}')
|
||||
case $NF in
|
||||
1) addToJson "" "$(echo $i|cut -f2 -d-)" "i386" "" "$i" "" ;;
|
||||
2) eval addToJson $(echo $i | awk -F- '{printf "\"\" %s amd64 %s %s \"\"",$2,$3,$0}') ;;
|
||||
3) eval addToJson $(echo $i | awk -F- '{if ($3=="i386") printf "\"\" %s %s %s %s \"\"",$2,$3,$4,$0; else printf "%s %s i386 %s %s \"\"",$2,$3,$4,$0}') ;;
|
||||
4) eval addToJson $(echo $i | awk -F- '{printf "%s %s %s %s %s \"\"",$2,$3,$4,$5,$0}') ;;
|
||||
esac
|
||||
# Check for is default oglive.
|
||||
[ -n "$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | awk '$3~/'$i'/ {print}')" ] && DEF="$i"
|
||||
done
|
||||
# Set default ogLive.
|
||||
[ -n "$DEF" ] && setdefault $(search $DEF)
|
||||
}
|
||||
|
||||
# Assign an ISO file to a JSON entry.
|
||||
function assign() {
|
||||
local ISOFILE DIR
|
||||
[ $# -ne 2 ] && raiseError usage
|
||||
[ ! -w $INFOFILE ] && raiseError access "Configuration file."
|
||||
# Check if ISO file and index directory exist.
|
||||
ISOFILE=$DOWNLOADFILE/$1
|
||||
[ ! -f $DOWNLOADDIR/$ISOFILE ] && raiseError notfound "ISO file \"$1\"."
|
||||
DIR=$(search $2 2>/dev/null)
|
||||
[ ! -d $TFTPDIR/$DIR ] && raiseError notfound "Directory for index \"$2\"."
|
||||
# Assign ISO file to JSON entry.
|
||||
jq ".oglive[$2].iso=\"$1\"" $INFOFILE | sponge $INFOFILE && jq ".oglive[$2]" $INFOFILE
|
||||
}
|
||||
|
||||
# Get disk usage information
|
||||
function disk_usage() {
|
||||
DISK_INFO=$(df -h / | awk 'NR==2{print "{\"total\":\""$2"\", \"used\":\""$3"\", \"available\":\""$4"\", \"percentage\":\""$5"\"}"}')
|
||||
echo $DISK_INFO
|
||||
}
|
||||
|
||||
# Function to list installed ogLive clients and the default ogLive client
|
||||
function list_installed_oglives() {
|
||||
local INST NF DEF
|
||||
INST=$(find $TFTPDIR/ -type d -name "$DEFOGLIVE-*" -a ! -name "*.old" -printf "%f\n" | sort)
|
||||
local installed_ogLives=()
|
||||
|
||||
for i in $INST; do
|
||||
NF=$(echo $i | awk -F- '{print NF-1}')
|
||||
local OGLIVEDIST=""
|
||||
local OGLIVEKRNL=""
|
||||
local OGLIVEARCH=""
|
||||
local OGLIVEREV=""
|
||||
local CHECKSUM=""
|
||||
local CHECKSUM_FILE="$TFTPDIR/$i/ogclient.sqfs.sum"
|
||||
|
||||
if [ -f "$CHECKSUM_FILE" ]; then
|
||||
CHECKSUM=$(cat "$CHECKSUM_FILE" | cut -d ' ' -f 1)
|
||||
fi
|
||||
|
||||
case $NF in
|
||||
1) OGLIVEDIST="" OGLIVEKRNL=$(echo $i|cut -f2 -d-) OGLIVEARCH="i386" OGLIVEREV="" ;;
|
||||
2) eval $(echo $i | awk -F- '{printf "OGLIVEDIST=\"\" OGLIVEKRNL=%s OGLIVEARCH=amd64 OGLIVEREV=%s OGLIVEDIR=%s",$2,$3,$0}') ;;
|
||||
3) eval $(echo $i | awk -F- '{if ($3=="i386") printf "OGLIVEDIST=\"\" OGLIVEKRNL=%s OGLIVEARCH=%s OGLIVEREV=%s OGLIVEDIR=%s",$2,$3,$4,$0; else printf "OGLIVEDIST=%s OGLIVEKRNL=%s OGLIVEARCH=i386 OGLIVEREV=%s OGLIVEDIR=%s",$2,$3,$4,$0}') ;;
|
||||
4) eval $(echo $i | awk -F- '{printf "OGLIVEDIST=%s OGLIVEKRNL=%s OGLIVEARCH=%s OGLIVEREV=%s OGLIVEDIR=%s",$2,$3,$4,$5,$0}') ;;
|
||||
esac
|
||||
|
||||
local DATA=$(jq -n \
|
||||
--arg id "$CHECKSUM" \
|
||||
--arg dist "$OGLIVEDIST" \
|
||||
--arg krnl "$OGLIVEKRNL" \
|
||||
--arg arch "$OGLIVEARCH" \
|
||||
--arg rev "$OGLIVEREV" \
|
||||
--arg dir "$TFTPDIR/$OGLIVEDIR" \
|
||||
--arg iso "" \
|
||||
'{id: $id, distribution: $dist, kernel: $krnl, architecture: $arch, revision: $rev, directory: $dir, iso: $iso}')
|
||||
|
||||
installed_ogLives+=("$DATA")
|
||||
|
||||
[ -n "$(stat -c "%N" $TFTPDIR/$DEFOGLIVE | awk '$3~/'$i'/ {print}')" ] && DEF="$i"
|
||||
done
|
||||
|
||||
local default_oglive=$(basename $(readlink -f $TFTPDIR/$DEFOGLIVE))
|
||||
|
||||
jq -n \
|
||||
--arg default_oglive "$default_oglive" \
|
||||
--argjson installed_ogLives "$(printf '%s\n' "${installed_ogLives[@]}" | jq -s .)" \
|
||||
'{
|
||||
default_oglive: $default_oglive,
|
||||
installed_ogLives: $installed_ogLives
|
||||
}'
|
||||
}
|
||||
|
||||
# Get information about an installed ogLive client.
|
||||
function get_info() {
|
||||
local CHECKSUM="$1"
|
||||
local DIR OGLIVEDIST OGLIVEKRNL OGLIVEARCH OGLIVEREV OGLIVEISO OGLIVEDIR
|
||||
|
||||
# Verificar que se proporcionó un checksum.
|
||||
[ -z "$CHECKSUM" ] && { echo "{\"error\": \"usage: get_info {checksum}\"}"; exit 1; }
|
||||
|
||||
# Verificar acceso al directorio de instalación.
|
||||
[ ! -w $TFTPDIR ] && { echo "{\"error\": \"access installation directory.\"}"; exit 1; }
|
||||
|
||||
# Buscar el directorio correspondiente al checksum, excluyendo los que terminan en .old.
|
||||
DIR=$(find $TFTPDIR -type f -name 'ogclient.sqfs.sum' -exec grep -l "$CHECKSUM" {} \; | grep -v '.old' | xargs -I{} dirname {})
|
||||
|
||||
# Si no se encuentra el directorio, devolver error.
|
||||
if [ -z "$DIR" ]; then
|
||||
echo "{\"error\": \"ogLive client with checksum $CHECKSUM not found.\"}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Obtener la información del ogLive a partir del nombre del directorio.
|
||||
OGLIVEDIR=$(basename "$DIR")
|
||||
OGLIVEDIST="$(echo $OGLIVEDIR | cut -d- -f2)"
|
||||
OGLIVEKRNL="$(echo $OGLIVEDIR | cut -d- -f3)"
|
||||
OGLIVEARCH="amd64" # Suponiendo que siempre es amd64
|
||||
OGLIVEREV="$(echo $OGLIVEDIR | cut -d- -f4)"
|
||||
OGLIVEISO="" # No tenemos la información del ISO aquí, podría necesitarse un ajuste si se requiere
|
||||
|
||||
# Construir el JSON con la información.
|
||||
local INFO=$(cat << EOT
|
||||
{
|
||||
"distribution": "$OGLIVEDIST",
|
||||
"kernel": "$OGLIVEKRNL",
|
||||
"architecture": "$OGLIVEARCH",
|
||||
"revision": "$OGLIVEREV",
|
||||
"directory": "$DIR",
|
||||
"iso": "$OGLIVEISO"
|
||||
}
|
||||
EOT
|
||||
)
|
||||
|
||||
# Devolver la información en formato JSON.
|
||||
echo "$INFO"
|
||||
}
|
||||
|
||||
# Function to check the status of services
|
||||
function check_services_status() {
|
||||
local SERVICES=("oglive_daemon.service" "tftpd-hpa.service" "nginx.service")
|
||||
declare -A STATUS_MAP
|
||||
|
||||
for service in "${SERVICES[@]}"; do
|
||||
if systemctl list-units --type=service --all | grep -q "$service"; then
|
||||
STATUS=$(systemctl is-active "$service")
|
||||
STATUS_MAP[$service]=$STATUS
|
||||
else
|
||||
STATUS_MAP[$service]="not installed"
|
||||
fi
|
||||
done
|
||||
|
||||
local json_output=$(jq -n \
|
||||
--arg oglive_daemon "${STATUS_MAP['oglive_daemon.service']}" \
|
||||
--arg tftpboot "${STATUS_MAP['tftpd-hpa.service']}" \
|
||||
--arg nginx "${STATUS_MAP['nginx.service']}" \
|
||||
'{
|
||||
oglive_daemon: $oglive_daemon,
|
||||
tftpboot: $tftpboot,
|
||||
nginx: $nginx
|
||||
}')
|
||||
|
||||
echo "$json_output"
|
||||
}
|
||||
|
||||
# Main progrram.
|
||||
|
||||
# Access control.
|
||||
[ -r $OPENGNSYS/www/controlacceso.php ] && ACCESS="web"
|
||||
[ "$USER" = "root" ] && ACCESS="root"
|
||||
[ -z "$ACCESS" ] && raiseError access "Need to be root."
|
||||
# Check dependencies.
|
||||
which sponge &>/dev/null || raiseError notfound "Need to install \"moreutils\"."
|
||||
# Commands control.
|
||||
shopt -s extglob
|
||||
case "$ACCESS" in
|
||||
root) CMDS='+(help|version|convert|config|check|list|show|search|download|install|uninstall|get-default|set-default|rebuild|assign|disk_usage|list_installed_oglives|get_info|get_default|set_default|check_services_status)' ;;
|
||||
web) CMDS='+(list|show|search|get-default)' ;;
|
||||
esac
|
||||
case "$1" in
|
||||
$CMDS) COMMAND="${1/-/}"; shift; $COMMAND "$@" ;;
|
||||
*) raiseError usage ;;
|
||||
esac
|
||||
|
||||
exit $?
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
if (!ini_get('date.timezone')) {
|
||||
ini_set('date.timezone', 'UTC');
|
||||
}
|
||||
|
||||
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
|
||||
if (PHP_VERSION_ID >= 80000) {
|
||||
require dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit';
|
||||
} else {
|
||||
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
|
||||
require PHPUNIT_COMPOSER_INSTALL;
|
||||
PHPUnit\TextUI\Command::main();
|
||||
}
|
||||
} else {
|
||||
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
|
||||
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
#!/bin/bash
|
||||
|
||||
#/**
|
||||
# setsmbpass
|
||||
#@file setsmbpass [ogLive]
|
||||
#@brief Cambia la contraseña del usuario del cliente para acceder a los servicios Samba.
|
||||
#@warning Se modifica el Initrd del cliente y se cambia la clave en el servidor.
|
||||
#@warning No se modifica el usuario de acceso (usuario "opengnsys").
|
||||
#@version 1.0.2 - Versión inicial.
|
||||
#@author Ramón M. Gómez - ETSII Univ. Sevilla
|
||||
#@date 2011-07-28
|
||||
#@version 1.1.0 - Soporte para varios clientes ogLive.
|
||||
#@author Ramón M. Gómez - ETSII Univ. Sevilla
|
||||
#@date 2017-06-20
|
||||
#*/ ##
|
||||
|
||||
|
||||
# Variables.
|
||||
PROG=$(basename "$0")
|
||||
PATH=$PATH:$(dirname "$(realpath "$0")")
|
||||
OPENGNSYS=${OPENGNSYS:-"/opt/opengnsys"}
|
||||
OGCFGFILE=$OPENGNSYS/etc/opengnsys.json
|
||||
SAMBAUSER="opengnsys" # Usuario por defecto.
|
||||
TFTPDIR=$OPENGNSYS/tftpboot
|
||||
INITRD=oginitrd.img
|
||||
TMPDIR=/tmp/oglive$$
|
||||
let CHANGES=0
|
||||
|
||||
# Control básico de errores.
|
||||
if [ "$USER" != "root" ]; then
|
||||
echo "$PROG: Error: solo ejecutable por root" >&2
|
||||
exit 1
|
||||
fi
|
||||
case $# in
|
||||
0) # Cambios en todos los clientes ogLive instalados.
|
||||
if which oglivecli &>/dev/null; then
|
||||
LIST=$(oglivecli list | awk '{print $2}')
|
||||
else
|
||||
LIST="ogclient"
|
||||
fi ;;
|
||||
1) # Cambios en único ogLive (AVISO: puede crear inconsistencias con otros ogLive).
|
||||
LIST="$1" ;;
|
||||
*) # Error de formato.
|
||||
echo "$PROG: Error de ejecución" >&2
|
||||
echo "Formato: $PROG ogLive"
|
||||
exit 1 ;;
|
||||
esac
|
||||
|
||||
# Recuperar eco de consola si se corta el proceso.
|
||||
trap "stty echo 2>/dev/null" KILL
|
||||
# Buscar todos los clients ogLive instalados.
|
||||
for OGLIVE in $LIST; do
|
||||
# Crear clave para usuario de acceso a los recursos.
|
||||
CLIENTINITRD="$TFTPDIR/$OGLIVE/$INITRD"
|
||||
if [ -r "$CLIENTINITRD" ]; then
|
||||
if [ -z "$SAMBAPASS" ]; then
|
||||
# Obtener clave del teclado sin eco en pantalla.
|
||||
stty -echo 2>/dev/null
|
||||
echo -n "Clave del usuario Samba: "
|
||||
read -r SAMBAPASS
|
||||
# Solo se deben aceptar números y letras para la clave de acceso.
|
||||
if [[ "$SAMBAPASS" =~ [^a-zA-Z0-9] ]]; then
|
||||
echo
|
||||
echo "$PROG: Error: la clave solo debe contener caracteres alfanuméricos" >&2
|
||||
stty echo 2>/dev/null
|
||||
exit 2
|
||||
fi
|
||||
echo
|
||||
# Obtener confirmación clave sin eco en pantalla.
|
||||
echo -n "Confirmar clave: "
|
||||
read -r SAMBAPASS2
|
||||
echo
|
||||
stty echo 2>/dev/null
|
||||
if [ "$SAMBAPASS" != "$SAMBAPASS2" ]; then
|
||||
echo "$PROG: Error: las claves no coinciden" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
# Editar la parte de acceso del cliente:
|
||||
# descomprimir Initrd, sustituir clave y recomprimir Initrd).
|
||||
echo "Configurando cliente \"$OGLIVE\" ..."
|
||||
mkdir -p $TMPDIR
|
||||
cd $TMPDIR || { echo "Error: no se pudo cambiar al directorio temporal."; exit 3; }
|
||||
|
||||
# Verificar si el archivo es gzip o lz4 antes de descomprimir.
|
||||
if file "$CLIENTINITRD" | grep -q "gzip compressed data"; then
|
||||
if ! gzip -dc "$CLIENTINITRD" | cpio -im; then
|
||||
echo "Error: No se pudo descomprimir y extraer $CLIENTINITRD con gzip."
|
||||
exit 4
|
||||
fi
|
||||
COMPRESS_CMD="gzip -9c"
|
||||
elif file "$CLIENTINITRD" | grep -q "LZ4 compressed data"; then
|
||||
if ! lz4 -d "$CLIENTINITRD" | cpio -im; then
|
||||
echo "Error: No se pudo descomprimir y extraer $CLIENTINITRD con lz4."
|
||||
exit 4
|
||||
fi
|
||||
COMPRESS_CMD="lz4 -c"
|
||||
else
|
||||
echo "Error: $CLIENTINITRD no está en formato gzip o lz4."
|
||||
exit 4
|
||||
fi
|
||||
if [ -f scripts/ogfunctions ]; then
|
||||
sed -i "s/OPTIONS=\(.*\)user=\w*\(.*\)pass=\w*\(.*\)/OPTIONS=\1user=$SAMBAUSER\2pass=$SAMBAPASS\3/" scripts/ogfunctions
|
||||
# TEMPORAL: solución ticket 554, actualizar cliente en caché (ogLive r3257).
|
||||
sed -i "s/busybox reboot/reboot/" scripts/ogfunctions
|
||||
# FIN CÓDIGO TEMPORAL.
|
||||
# Ticket 565, preparar acceso Rsync cliente.
|
||||
echo "$SAMBAPASS" > scripts/passrsync
|
||||
# Guardar tokens de seguridad.
|
||||
cat << EOT > scripts/client.cfg
|
||||
CLIENTID=$(jq -r .client.id $OGCFGFILE)
|
||||
CLIENTSECRET=$(jq -r .client.secret $OGCFGFILE)
|
||||
EOT
|
||||
chown root.root scripts/passrsync scripts/client.cfg
|
||||
chmod 400 scripts/passrsync scripts/client.cfg
|
||||
# Generar Initrd del cliente.
|
||||
if ! find . | cpio -H newc -oa | $COMPRESS_CMD > "$CLIENTINITRD"; then
|
||||
echo "Error: No se pudo recomprimir $CLIENTINITRD."
|
||||
exit 5
|
||||
fi
|
||||
else
|
||||
echo "$PROG: Aviso: no se ha modificado la clave del cliente \"$OGLIVE\"."
|
||||
fi
|
||||
rm -fr $TMPDIR
|
||||
# Calcular suma de comprobación.
|
||||
md5sum "$CLIENTINITRD" | cut -f1 -d" " > "$CLIENTINITRD.sum"
|
||||
let CHANGES++
|
||||
else
|
||||
echo "$PROG: Cliente \"$OGLIVE\" no accesible."
|
||||
fi
|
||||
done
|
||||
if [[ $CHANGES != 0 ]]; then
|
||||
# Ticket 565, preparar acceso Rsync servidor.
|
||||
echo "$SAMBAUSER:$SAMBAPASS" > /etc/rsyncd.secrets
|
||||
chown root.root /etc/rsyncd.secrets
|
||||
chmod 600 /etc/rsyncd.secrets
|
||||
# Cambiar clave Samba.
|
||||
echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | smbpasswd -a -s $SAMBAUSER
|
||||
else
|
||||
echo "$PROG: Aviso: no se ha modificado la clave de ningún cliente."
|
||||
fi
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
{
|
||||
"type": "project",
|
||||
"license": "proprietary",
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"doctrine/annotations": "^1.6",
|
||||
"doctrine/doctrine-bundle": "^2.0",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.0",
|
||||
"doctrine/orm": "^2.7",
|
||||
"phpdocumentor/reflection-docblock": "^5.0",
|
||||
"phpstan/phpdoc-parser": "^0.4",
|
||||
"zircote/swagger-php": "3.*",
|
||||
"symfony/runtime": "5.*",
|
||||
"symfony/asset": "5.*",
|
||||
"symfony/console": "5.*",
|
||||
"symfony/doctrine-messenger": "5.*",
|
||||
"symfony/dotenv": "5.*",
|
||||
"symfony/expression-language": "5.*",
|
||||
"symfony/flex": "^1.17",
|
||||
"symfony/form": "5.*",
|
||||
"symfony/framework-bundle": "5.*",
|
||||
"symfony/http-client": "5.*",
|
||||
"symfony/intl": "5.*",
|
||||
"symfony/mailer": "5.*",
|
||||
"symfony/mime": "5.*",
|
||||
"symfony/monolog-bundle": "^3.0",
|
||||
"symfony/notifier": "5.*",
|
||||
"symfony/process": "5.*",
|
||||
"symfony/property-access": "5.*",
|
||||
"symfony/property-info": "5.*",
|
||||
"symfony/security-bundle": "5.*",
|
||||
"symfony/serializer": "5.*",
|
||||
"symfony/string": "5.*",
|
||||
"symfony/translation": "5.*",
|
||||
"symfony/twig-bundle": "5.*",
|
||||
"symfony/validator": "5.*",
|
||||
"symfony/web-link": "5.*",
|
||||
"symfony/yaml": "5.*",
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"symfony/browser-kit": "5.*",
|
||||
"symfony/css-selector": "5.*",
|
||||
"symfony/debug-bundle": "5.*",
|
||||
"symfony/maker-bundle": "^1.0",
|
||||
"symfony/phpunit-bridge": "^5.0",
|
||||
"symfony/stopwatch": "5.*",
|
||||
"symfony/web-profiler-bundle": "5.*"
|
||||
},
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "7.2.24"
|
||||
},
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"symfony/flex": true,
|
||||
"symfony/runtime": true
|
||||
},
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": {
|
||||
"*": "dist"
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"App\\Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"replace": {
|
||||
"symfony/polyfill-ctype": "*",
|
||||
"symfony/polyfill-iconv": "*",
|
||||
"symfony/polyfill-php72": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"auto-scripts": {
|
||||
"cache:clear": "symfony-cmd",
|
||||
"assets:install %PUBLIC_DIR%": "symfony-cmd"
|
||||
},
|
||||
"post-install-cmd": [
|
||||
"@auto-scripts"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@auto-scripts"
|
||||
]
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"extra": {
|
||||
"symfony": {
|
||||
"allow-contrib": false,
|
||||
"require": "5.*"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
|
||||
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
|
||||
App\OgBootBundle\OgBootBundle::class => ['all' => true],
|
||||
];
|
|
@ -0,0 +1,6 @@
|
|||
controllers:
|
||||
resource: ../../src/OgBootBundle/Controller/
|
||||
type: annotation
|
||||
kernel:
|
||||
resource: ../../src/Kernel.php
|
||||
type: annotation
|
|
@ -0,0 +1,27 @@
|
|||
# This file is the entry point to configure your own services.
|
||||
# Files in the packages/ subdirectory configure your dependencies.
|
||||
|
||||
# Put parameters here that don't need to change on each machine where the app is deployed
|
||||
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
||||
parameters:
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
autowire: true # Automatically injects dependencies in your services.
|
||||
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
||||
|
||||
# makes classes in src/ available to be used as services
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/'
|
||||
exclude:
|
||||
- '../src/DependencyInjection/'
|
||||
- '../src/Entity/'
|
||||
- '../src/Kernel.php'
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
App\OgBootBundle\Controller\:
|
||||
resource: '../src/OgBootBundle/Controller'
|
||||
tags: ['controller.service_arguments']
|
|
@ -0,0 +1,795 @@
|
|||
## Diseño de la Lógica y Comunicación entre los Endpoints del Componente `ogboot` y el Servidor `ogCore`
|
||||
|
||||
### Introducción
|
||||
|
||||
El componente `ogboot` se encarga de la gestión y configuración de archivos de arranque (iPXE) y plantillas en un entorno de despliegue de imágenes. El servidor `ogCore` es el núcleo que interactúa con `ogboot` para realizar operaciones de administración y configuración. Este documento describe la lógica y la comunicación entre los endpoints del componente `ogboot` y el servidor `ogCore`.
|
||||
|
||||
### Endpoints del Componente `ogboot`
|
||||
|
||||
|
||||
#### Endpoints del Recurso `oglive`
|
||||
|
||||
1. **Ver todos los ogLives instalados**
|
||||
- **URL**: `/ogboot/v1/oglives`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene información sobre todos los ogLives instalados.
|
||||
- **Respuesta**:
|
||||
```json
|
||||
[
|
||||
"ogLive-5.0.0-r20190605",
|
||||
"ogLive-5.11.0-r20210413",
|
||||
"ogLive-5.13.0-27-r20210706"
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
2. **Obtener Información de un ogLive**
|
||||
- **URL**: `/ogboot/v1/oglives/{uuid}`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene información sobre un cliente ogLive instalado utilizando su nombre.
|
||||
- **Parámetros**:
|
||||
- `uuid` (string): uuid del ogLive.
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"distribution": "uuid",
|
||||
"distribution": "focal",
|
||||
"kernel": "5.13.0-27",
|
||||
"architecture": "amd64",
|
||||
"revision": "r20210706.5b4bf5f",
|
||||
"directory": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f",
|
||||
"iso": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso"
|
||||
}
|
||||
```
|
||||
- **Respuestas**:
|
||||
- **200 OK**: Información del ogLive obtenida exitosamente.
|
||||
- **404 Not Found**: ogLive no encontrado.
|
||||
|
||||
3. **Obtener Información del ogLive Predeterminado**
|
||||
- **URL**: `/ogboot/v1/oglives/default`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene información sobre el cliente ogLive predeterminado.
|
||||
- **Ejemplo de Solicitud**:
|
||||
```bash
|
||||
curl -X GET -H "Authorization: $API_KEY" http://example.com/ogboot/v1/oglives/default
|
||||
```
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"distribution": "focal",
|
||||
"kernel": "5.13.0-27",
|
||||
"architecture": "amd64",
|
||||
"revision": "r20210706.5b4bf5f",
|
||||
"directory": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f",
|
||||
"iso": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso"
|
||||
}
|
||||
```
|
||||
|
||||
- **Respuestas**:
|
||||
- **200 OK**: Información del ogLive predeterminado obtenida exitosamente.
|
||||
- **500 Internal Server Error**: Error al obtener la información del ogLive predeterminado.
|
||||
|
||||
|
||||
4. **Establecer ogLive Predeterminado**
|
||||
- **URL**: `/ogboot/v1/oglives/default/{uuid}`
|
||||
- **Método HTTP**: POST
|
||||
- **Descripción**: Establece un cliente ogLive como predeterminado utilizando su nombre.
|
||||
- **Parámetros**:
|
||||
- `uuid` (string): uuid del ogLive a establecer como predeterminado.
|
||||
- **Respuestas**:
|
||||
- **200 OK**: ogLive establecido como predeterminado exitosamente.
|
||||
- **404 Not Found**: ogLive no encontrado.
|
||||
- **500 Internal Server Error**: Error al establecer el ogLive como predeterminado.
|
||||
|
||||
|
||||
|
||||
5. **Ver la lista de ogLives disponibles para descargar**
|
||||
- **URL**: `/ogboot/v1/oglives/isos`
|
||||
- **Método HTTP**: GET
|
||||
- **Respuesta**:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"filename": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso",
|
||||
"installed": false,
|
||||
"compatible": true
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"filename": "ogLive-focal-5.11.0-22-generic-amd64-r20210413.992ebb9.iso",
|
||||
"installed": false,
|
||||
"compatible": true
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"filename": "ogLive-focal-5.8.0-50-generic-amd64-r20210413.992ebb9.iso",
|
||||
"installed": false,
|
||||
"compatible": true
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"filename": "ogLive-bionic-5.4.0-40-generic-amd64-r20200629.85eceaf.iso",
|
||||
"installed": false,
|
||||
"compatible": true
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
```
|
||||
- **500 Internal Server Error**: Error en la conexión.
|
||||
|
||||
|
||||
6. **Crear un ogLive**
|
||||
- **URL**: `/ogboot/v1/oglives`
|
||||
- **Método HTTP**: POST
|
||||
- **Descripción**: Crea un nuevo ogLive utilizando el nombre del ISO proporcionado.
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"isoName": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso"
|
||||
}
|
||||
```
|
||||
- **Ejemplo de Solicitud**:
|
||||
```bash
|
||||
curl -X POST -H "Authorization: $API_KEY" -d '{"isoName": "ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso"}' http://example.com/ogboot/v1/oglives
|
||||
```
|
||||
- **Respuestas**:
|
||||
- **200 OK**: ogLive creado exitosamente.
|
||||
- **400 Bad Request**: Error en los datos proporcionados.
|
||||
- **500 Internal Server Error**: Error al crear el ogLive.
|
||||
|
||||
7. **Eliminar un ogLive**
|
||||
- **URL**: `/ogboot/v1/oglives/{uuid}`
|
||||
- **Método HTTP**: DELETE
|
||||
- **Descripción**: Elimina un ogLive específico utilizando su nombre.
|
||||
- **Parámetros**:
|
||||
- `name` (string): Nombre del ogLive.
|
||||
- **Respuestas**:
|
||||
- **200 OK**: ogLive eliminado exitosamente.
|
||||
- **404 Not Found**: ogLive no encontrado.
|
||||
- **500 Internal Server Error**: Error al eliminar el ogLive.
|
||||
|
||||
|
||||
|
||||
#### Endpoints del Recurso `pxe` y `pxe-template`
|
||||
|
||||
1. **Obtener Todos los Archivos de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene una lista de todos los archivos de arranque disponibles.
|
||||
- **Respuesta**: Lista de archivos de arranque en formato JSON.
|
||||
|
||||
2. **Obtener Configuración de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes/{mac}`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene el contenido del archivo de configuración de arranque específico para un cliente utilizando su dirección MAC.
|
||||
- **Respuesta**: Archivo de arranque en formato adecuado.
|
||||
```json
|
||||
{
|
||||
"template_name": "pxe",
|
||||
"mac": "00:50:56:22:11:12",
|
||||
"lang": "es_ES.UTF-8",
|
||||
"ip": "192.168.2.11",
|
||||
"server_ip": "192.168.2.1",
|
||||
"router": "192.168.2.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"computer_name": "pc11",
|
||||
"netiface": "eth0",
|
||||
"group": "Aula_virtual",
|
||||
"ogrepo": "192.168.2.1",
|
||||
"oglive": "192.168.2.1",
|
||||
"oglog": "192.168.2.1",
|
||||
"ogshare": "192.168.2.1",
|
||||
"oglivedir": "ogLive",
|
||||
"ogprof": "false",
|
||||
"hardprofile": "",
|
||||
"ogntp": "",
|
||||
"ogdns": "",
|
||||
"ogproxy": "",
|
||||
"ogunit": "",
|
||||
"resolution": "788"
|
||||
}
|
||||
|
||||
```
|
||||
3. **Crear Archivo de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes`
|
||||
- **Método HTTP**: POST
|
||||
- **Descripción**: Crea un nuevo archivo de arranque utilizando los parámetros proporcionados.
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"template_name": "pxe",
|
||||
"mac": "00:50:56:22:11:12",
|
||||
"lang": "es_ES.UTF-8",
|
||||
"ip": "192.168.2.11",
|
||||
"server_ip": "192.168.2.1",
|
||||
"router": "192.168.2.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"computer_name": "pc11",
|
||||
"netiface": "eth0",
|
||||
"group": "Aula_virtual",
|
||||
"ogrepo": "192.168.2.1",
|
||||
"oglive": "192.168.2.1",
|
||||
"oglog": "192.168.2.1",
|
||||
"ogshare": "192.168.2.1",
|
||||
"oglivedir": "ogLive",
|
||||
"ogprof": "false",
|
||||
"hardprofile": "",
|
||||
"ogntp": "",
|
||||
"ogdns": "",
|
||||
"ogproxy": "",
|
||||
"ogunit": "",
|
||||
"resolution": "788"
|
||||
}
|
||||
|
||||
```
|
||||
- **Respuesta**: Mensaje de éxito o error.
|
||||
|
||||
4. **Eliminar Archivo de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes/{name}`
|
||||
- **Método HTTP**: DELETE
|
||||
- **Descripción**: Elimina un archivo de arranque específico utilizando su dirección MAC.
|
||||
- **Respuesta**: Mensaje de éxito o error.
|
||||
|
||||
5. **Obtener Todas las Plantillas de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxe-templates`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene una lista de todas las plantillas de arranque disponibles.
|
||||
- **Respuesta**: Lista de plantillas en formato JSON.
|
||||
```json
|
||||
{
|
||||
"templates": [
|
||||
"pxe",
|
||||
"pxe2",
|
||||
"pxe_default"
|
||||
]
|
||||
}
|
||||
```
|
||||
6. **Obtener Contenido de una Plantilla**
|
||||
- **URL**: `/ogboot/v1/pxe-templates/{name}`
|
||||
- **Método HTTP**: GET
|
||||
- **Descripción**: Obtiene el contenido de una plantilla de arranque específica utilizando su nombre.
|
||||
- **Respuesta**: Contenido de la plantilla en formato adecuado.
|
||||
|
||||
7. **Crear Plantilla de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxe-templates`
|
||||
- **Método HTTP**: POST
|
||||
- **Descripción**: Crea una nueva plantilla de arranque utilizando los datos proporcionados.
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"name_template": "pxe",
|
||||
"content_template": "contenido_de_la_plantilla"
|
||||
}
|
||||
```
|
||||
- **Respuesta**: Mensaje de éxito o error.
|
||||
|
||||
8. **Eliminar Plantilla de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxe-templates/{name}`
|
||||
- **Método HTTP**: DELETE
|
||||
- **Descripción**: Elimina una plantilla de arranque específica utilizando su nombre.
|
||||
- **Respuesta**: Mensaje de éxito o error.
|
||||
|
||||
|
||||
|
||||
|
||||
## Flujos de Trabajo
|
||||
|
||||
Para los nuevos flujos de trabajo, asumimos que habrá al menos una nueva tabla en ogCore para almacenar la información de los ogLives y su estado. Esta tabla permitirá a ogCore gestionar y sincronizar la información con ogBoot.
|
||||
|
||||
|
||||
### Propuesta de definición de la tabla `ogLive`
|
||||
|
||||
|
||||
| Atributo | Tipo de Dato | Descripción |
|
||||
|----------------|----------------|-----------------------------------------------------------------|
|
||||
| `id` | `SERIAL` | Identificador del ogLive que corresponde a su suma de comprobación |
|
||||
| `distribution` | `VARCHAR(50)` | Nombre de la distribución del ogLive (por ejemplo, "focal"). |
|
||||
| `kernel` | `VARCHAR(100)` | Versión del kernel del ogLive. |
|
||||
| `architecture` | `VARCHAR(10)` | Arquitectura del ogLive (por ejemplo, "amd64"). |
|
||||
| `revision` | `VARCHAR(50)` | Revisión del ogLive (por ejemplo, "r20210706"). |
|
||||
| `directory` | `VARCHAR(100)` | Nombre del directorio del ogLive en el sistema de archivos. |
|
||||
| `iso` | `VARCHAR(255)` | Nombre del archivo ISO del ogLive. |
|
||||
| `is_default` | `BOOLEAN` | Indica si el ogLive es el predeterminado (`true` o `false`). |
|
||||
|
||||
### Ejemplo de Registro
|
||||
|
||||
| `id` | `distribution` | `kernel` | `architecture` | `revision` | `directory` | `iso` | `is_default` |
|
||||
|------|----------------|---------------------|----------------|-------------|--------------------------|-------------------------------------------------------|--------------|
|
||||
| 1 | focal | 5.13.0-27-beta | amd64 | r20210706 | ogLive-5.13.0-r20210706 | ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso | true |
|
||||
|
||||
|
||||
|
||||
|
||||
### Flujo de trabajo para instalar un `ogLive`
|
||||
|
||||
#### 1. Consultar los `ogLives` Instalados
|
||||
|
||||
- **Descripción**: Obtener la lista de `ogLives` que están actualmente instalados en el sistema.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario navega a la sección de `ogLives` en el panel de administración.
|
||||
- Hace clic en "Ver `ogLives` instalados".
|
||||
- El sistema realiza una llamada a la API para obtener la lista de `ogLives` instalados.
|
||||
|
||||
**Realización**: Puede realizarse directamente desde **`ogCore`** mediante una consulta a la base de datos `oglives`.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives;
|
||||
```
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/oglives`
|
||||
- **Método**: `GET`
|
||||
|
||||
#### 2. Consultar los `ogLives` disponibles para descargar
|
||||
|
||||
- **Descripción**: Obtener una lista de `ogLives` disponibles para descargar desde el servidor.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario selecciona "Descargar nuevos `ogLives`" en la interfaz.
|
||||
- Aparece una lista de `ogLives` disponibles, obtenida mediante una consulta al servidor.
|
||||
|
||||
**Realización**: Necesita comunicación con **`ogBoot`**. Nota: Este proceso requiere de una consulta a Trac (o web) que se podría llevar a cabo desde el ogCore.
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/isos`
|
||||
- **Método**: `GET`
|
||||
|
||||
#### 3. Instalar un `ogLive`
|
||||
|
||||
- **Descripción**: Instalar un `ogLive` seleccionado en el sistema.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario selecciona un `ogLive` de la lista de disponibles y hace clic en "Instalar".
|
||||
- El sistema muestra un cuadro de confirmación, y al confirmar, se inicia el proceso de instalación.
|
||||
|
||||
**Realización**: Requiere comunicación con **`ogBoot`** para iniciar la instalación. Primero, se construye el JSON con los parámetros necesarios. La inserción en la base de datos `ogCore` solo se realiza después de que la instalación en `ogBoot` sea confirmada como exitosa.
|
||||
|
||||
- **Proceso de Instalación**:
|
||||
1. **Generación de JSON**: `ogCore` genera un JSON con los detalles del `ogLive`, incluyendo un UUID temporal.
|
||||
2. **Solicitud de Instalación**:
|
||||
- **Endpoint**: `/ogboot/v1/oglives`
|
||||
- **Método**: `POST`
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"uuid": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"directory": "ogLive-5.11.0-r20210413",
|
||||
"distribution": "focal",
|
||||
"kernel": "5.11.0-22-generic",
|
||||
"architecture": "amd64",
|
||||
"revision": "r20210413",
|
||||
"iso": "ogLive-focal-5.11.0-22-generic-amd64-r20210413.992ebb9.iso"
|
||||
}
|
||||
```
|
||||
3. **Validación de Instalación**: `ogBoot` intenta instalar el `ogLive` y devuelve un estado de éxito o fallo.
|
||||
4. **Actualización de Base de Datos**:
|
||||
- **Instalación Exitosa**: Si `ogBoot` confirma el éxito, `ogCore` inserta el nuevo `ogLive` en la base de datos:
|
||||
```sql
|
||||
INSERT INTO oglives (uuid, distribution, kernel, architecture, revision, directory, iso, is_default)
|
||||
VALUES ('550e8400-e29b-41d4-a716-446655440000', 'focal', '5.11.0-22-generic', 'amd64', 'r20210413', 'ogLive-5.11.0-r20210413', 'ogLive-focal-5.11.0-22-generic-amd64-r20210413.992ebb9.iso', false);
|
||||
```
|
||||
- **Instalación Fallida**: Si `ogBoot` reporta un fallo, no se realiza ninguna inserción y se maneja el error adecuadamente en la interfaz de usuario.
|
||||
|
||||
#### 4. Revisar un `ogLive` Instalado
|
||||
|
||||
- **Descripción**: Obtener detalles sobre un `ogLive` específico que está instalado.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario selecciona un `ogLive` de la lista de instalados para ver detalles.
|
||||
- Se muestra la información detallada del `ogLive` seleccionado.
|
||||
|
||||
**Realización**: Puede realizarse desde **`ogCore`** mediante una consulta a la base de datos `oglives`.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives WHERE directory = 'ogLive-5.13.0-r20210706';
|
||||
```
|
||||
|
||||
|
||||
### Flujo de trabajo para cambiar el `oglive` por defecto
|
||||
|
||||
#### 1. Consultar los `ogLives` Instalados
|
||||
|
||||
- **Descripción**: Obtener la lista de `ogLives` que están actualmente instalados en el sistema.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario navega a la sección de `ogLives` en el panel de administración.
|
||||
- Hace clic en "Ver `ogLives` instalados".
|
||||
- El sistema realiza una llamada a la API para obtener la lista de `ogLives` instalados.
|
||||
|
||||
**Realización**: Puede realizarse directamente desde **`ogCore`** mediante una consulta a la base de datos `oglives`. Lo ideal sería hacerlo hacia **`ogBoot`** ya que tiene la fuente de información fidedigna del estado de los `ogLives` en el componente.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives;
|
||||
```
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/oglives`
|
||||
- **Método**: `GET`
|
||||
|
||||
#### 2. Ver el `ogLive` por Defecto
|
||||
|
||||
- **Descripción**: Obtener el `ogLive` que está configurado como predeterminado.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario navega a la sección de configuración de `ogLives` en el panel de administración.
|
||||
- Hace clic en en el `ogLive` que está marcado por defecto.
|
||||
- El sistema realiza una consulta a la base de datos para obtener el `ogLive` predeterminado.
|
||||
|
||||
**Realización**: Puede realizarse desde **`ogCore`** mediante una consulta a la base de datos `oglives`.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives WHERE directory = 'ogLive-5.13.0-r20210706';
|
||||
```
|
||||
|
||||
|
||||
|
||||
#### 3. Asignar `ogLive` por Defecto
|
||||
|
||||
- **Descripción**: Configurar un `ogLive` instalado como el predeterminado.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario selecciona un `ogLive` de la lista de instalados.
|
||||
- Hace clic en "Configurar como `ogLive` por defecto".
|
||||
- Tras la confirmación, el sistema envía una solicitud para actualizar el `ogLive` por defecto.
|
||||
- El sistema actualiza la base de datos y comunica el cambio a `ogBoot`.
|
||||
|
||||
**Realización**: Requiere comunicación con **`ogBoot`** para modificar el `ogLive` por defecto en el TFTP boot del **`ogBoot`**.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives WHERE directory = 'ogLive-5.13.0-r20210706';
|
||||
```
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/oglives/default/550e8400-e29b-41d4-a716-446655440000`
|
||||
- **Método**: `POST`
|
||||
|
||||
**Actualizar Base de Datos**:
|
||||
- Tras la actualización en `ogBoot`, se debe actualizar la base de datos para reflejar el nuevo `ogLive` por defecto:
|
||||
```sql
|
||||
UPDATE oglives SET is_default = false WHERE is_default = true;
|
||||
UPDATE oglives SET is_default = true WHERE uuid = '550e8400-e29b-41d4-a716-446655440000';
|
||||
```
|
||||
|
||||
|
||||
### Flujo de trabajo para desinstalar un `ogLive`
|
||||
|
||||
#### 1. Consultar los `ogLives` Instalados
|
||||
|
||||
- **Descripción**: Obtener la lista de `ogLives` que están actualmente instalados en el sistema.
|
||||
- **Interacción en la Web**:
|
||||
- El usuario navega a la sección de `ogLives` en el panel de administración.
|
||||
- Hace clic en "Ver `ogLives` instalados".
|
||||
- El sistema realiza una llamada a la API para obtener la lista de `ogLives` instalados.
|
||||
|
||||
**Realización**: Puede realizarse directamente desde **`ogCore`** mediante una consulta a la base de datos `oglives`.
|
||||
|
||||
**Consulta SQL**:
|
||||
```sql
|
||||
SELECT * FROM oglives;
|
||||
```
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/oglives`
|
||||
- **Método**: `GET`
|
||||
|
||||
|
||||
#### 2. Desinstalar `ogLive`
|
||||
|
||||
- **Descripción**: Iniciar el proceso de desinstalación del `ogLive` seleccionado en `ogBoot`.
|
||||
- **Interacción en la Web**:
|
||||
- En la lista de `ogLives` instalados, el usuario elige el `ogLive` a desinstalar.
|
||||
- Hace clic en el botón "Desinstalar" junto al `ogLive` seleccionado.
|
||||
- El sistema muestra un cuadro de confirmación preguntando si el usuario está seguro de desinstalar el `ogLive`.
|
||||
- El usuario hace clic en "Confirmar" para proceder.
|
||||
- El sistema envía una solicitud a `ogBoot` para desinstalar el `ogLive`.
|
||||
|
||||
**Realización**:
|
||||
- **Endpoint**: `/ogboot/v1/oglives/550e8400-e29b-41d4-a716-446655440000`
|
||||
- **Método**: `DELETE`
|
||||
- **Validación de Instalación**: `ogBoot` intenta desinstalar el `ogLive` y devuelve un estado de éxito o fallo.
|
||||
- **Actualización de Base de Datos**:
|
||||
- **Desinstalación Exitosa**: Si `ogBoot` confirma el éxito, `ogCore` elimina el `ogLive` en la base de datos:
|
||||
```sql
|
||||
DELETE FROM oglives WHERE uuid = '550e8400-e29b-41d4-a716-446655440000';
|
||||
```
|
||||
- **Instalación Fallida**: Si `ogBoot` reporta un fallo, no se realiza ningún borrado y se maneja el error adecuadamente en la interfaz de usuario.
|
||||
|
||||
|
||||
### Flujo de trabajo para corregir las incongruencias entre `ogCore` y `ogBoot`
|
||||
|
||||
|
||||
|
||||
#### 8. Revisar estado de ogboot
|
||||
|
||||
- **Descripción**: Comparar el estado actual de `ogboot` con la base de datos de `ogCore`, generando un informe de discrepancias.
|
||||
- **Realización**: Requiere comunicación con **`ogBoot`** para obtener el estado actual de los `ogLives` instalados, el `ogLive` por defecto, y las plantillas de arranque (`pxes`). Luego, `ogCore` compara estos datos con su base de datos y devuelve un informe de discrepancias.
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/oglive/status`
|
||||
- **Método**: `GET`
|
||||
- **Resultado de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"installed_oglives": [
|
||||
{
|
||||
"name": "ogLive-5.13.0-r20210706",
|
||||
"kernel": "5.13.0-27-beta",
|
||||
"revision": "r20210706",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "ogLive-5.11.0-r20210413",
|
||||
"kernel": "5.11.0-22-generic",
|
||||
"revision": "r20210413",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"installed_pxe_templates": [
|
||||
"default.ipxe",
|
||||
"template1.ipxe"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Informe de Discrepancias** (Ejemplo):
|
||||
```json
|
||||
{
|
||||
"discrepancies": {
|
||||
"oglives": [
|
||||
{
|
||||
"expected": {
|
||||
"name": "ogLive-5.13.0-r20210706",
|
||||
"default": true
|
||||
},
|
||||
"actual": {
|
||||
"name": "ogLive-5.11.0-r20210413",
|
||||
"default": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"pxe_templates": [
|
||||
{
|
||||
"expected": "default.ipxe",
|
||||
"actual": "template1.ipxe"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### 9. Sincronizar Datos de `ogboot` con `ogCore`
|
||||
|
||||
- **Descripción**: `ogCore` sincroniza su base de datos con el estado actual de `ogboot`. Este proceso solo actualiza las discrepancias detectadas.
|
||||
- **Realización**: Requiere comunicación con **`ogBoot`** para obtener el estado actual. Luego, `ogCore` actualiza su base de datos con cualquier cambio detectado en los `ogLives` instalados, el `ogLive` por defecto, y las plantillas de arranque (`pxes`).
|
||||
|
||||
**Endpoint**:
|
||||
- **`ogBoot`**: `/ogboot/v1/sync`
|
||||
- **Método**: `GET`
|
||||
- **Resultado de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"installed_oglives": [
|
||||
{
|
||||
"name": "ogLive-5.13.0-r20210706",
|
||||
"kernel": "5.13.0-27-beta",
|
||||
"revision": "r20210706",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"name": "ogLive-5.11.0-r20210413",
|
||||
"kernel": "5.11.0-22-generic",
|
||||
"revision": "r20210413",
|
||||
"default": false
|
||||
}
|
||||
],
|
||||
"installed_pxe_templates": [
|
||||
"default.ipxe",
|
||||
"template1.ipxe"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
### Flujo de Trabajo: `pxe y pxe-template`
|
||||
|
||||
#### NOTA
|
||||
|
||||
En la implementación actual de OpenGnsys, se realiza una consulta SQL a la tabla `ordenadores`, haciendo joins con tablas como `aulas`, `centros`, `entidades`, etc. (consultar fichero `opengnsys/server/bin/setclientmode`) para obtener todos los parámetros necesarios para la creación de archivos PXE. Es necesario estudiar si existe la necesidad de crear una tabla `pxe` para almacenar estos parámetros. En caso de decidirse la creación de dicha tabla, podría tener los siguientes atributos:
|
||||
|
||||
- `template_name` (nombre de la plantilla)
|
||||
- `mac` (dirección MAC)
|
||||
- `lang` (idioma)
|
||||
- `ip` (dirección IP)
|
||||
- `server_ip` (dirección IP del servidor)
|
||||
- `router` (router)
|
||||
- `netmask` (máscara de red)
|
||||
- `computer_name` (nombre del equipo)
|
||||
- `netiface` (interfaz de red)
|
||||
- `group` (grupo)
|
||||
- `ogrepo` (IP del repositorio)
|
||||
- `oglive` (IP del servidor en vivo)
|
||||
- `oglog` (IP del servidor de logs)
|
||||
- `ogshare` (IP del servidor compartido)
|
||||
- `oglivedir` (directorio en vivo)
|
||||
- `ogprof` (es profesor)
|
||||
- `hardprofile` (perfil de hardware)
|
||||
- `ogntp` (servidor NTP)
|
||||
- `ogdns` (servidor DNS)
|
||||
- `ogproxy` (servidor proxy)
|
||||
- `ogunit` (directorio de unidad)
|
||||
- `resolution` (resolución de pantalla)
|
||||
|
||||
---
|
||||
|
||||
#### NOTA 2
|
||||
|
||||
¿Tiene sentido hacer una tabla para las plantillas pxe-templates? Solo tendrian dos atributos: template-name y content. ¿No sería mejor que quedasen guardadas en el ogboot y se usen cuando se vaya a crear un fichero de arranque?
|
||||
|
||||
|
||||
Para estos flujos asumiremos que NO se han creado tablas a mayores de pxe ni de pxe-templates. Este es el flujo original que se produce actualmente en ogboot.
|
||||
|
||||
|
||||
|
||||
1. **Obtener Todos los Archivos de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes`
|
||||
- **Método HTTP**: GET
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
{
|
||||
"boot_files": [
|
||||
"01-00:50:56:20:69:11",
|
||||
"01-00:50:56:20:69:12"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
2. **Obtener Configuración de Arranque por MAC**
|
||||
- **URL**: `/ogboot/v1/pxes/{mac}`
|
||||
- **Método HTTP**: GET
|
||||
- **Cuerpo de la Solicitud**:
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"template_name": "pxe",
|
||||
"mac": "00:50:56:22:11:12",
|
||||
"lang": "es_ES.UTF-8",
|
||||
"ip": "192.168.2.11",
|
||||
"server_ip": "192.168.2.1",
|
||||
"router": "192.168.2.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"computer_name": "pc11",
|
||||
"netiface": "eth0",
|
||||
"group": "Aula_virtual",
|
||||
"ogrepo": "192.168.2.1",
|
||||
"oglive": "192.168.2.1",
|
||||
"oglog": "192.168.2.1",
|
||||
"ogshare": "192.168.2.1",
|
||||
"oglivedir": "ogLive",
|
||||
"ogprof": "false",
|
||||
"hardprofile": "",
|
||||
"ogntp": "",
|
||||
"ogdns": "",
|
||||
"ogproxy": "",
|
||||
"ogunit": "",
|
||||
"resolution": "788"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
3. **Obtener Todas las Plantillas de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxe-templates`
|
||||
- **Método HTTP**: GET
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"templates": [
|
||||
"pxe",
|
||||
"pxe_default"
|
||||
]
|
||||
}
|
||||
```
|
||||
4. **Crear Plantilla de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes-templates`
|
||||
- **Método HTTP**: POST
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
"name_template": "pxe2",
|
||||
"content_template": "#!ipxe\\nset timeout 0\\nset timeout-style hidden\\n\\nset ISODIR ogLive\\nset default 0\\nset kernelargs INFOHOST\\nkernel tftp://SERVERIP/ogLive/ogvmlinuz ${kernelargs}\\ninitrd tftp://SERVERIP/ogLive/oginitrd.img\\nboot"
|
||||
}
|
||||
```
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"message": "Plantilla creada exitosamente.",
|
||||
"template": "#!ipxe\\nset timeout 0\\nset timeout-style hidden\\n\\nset ISODIR ogLive\\nset default 0\\nset kernelargs INFOHOST\\nkernel tftp://SERVERIP/ogLive/ogvmlinuz ${kernelargs}\\ninitrd tftp://SERVERIP/ogLive/oginitrd.img\\nboot"
|
||||
}
|
||||
```
|
||||
|
||||
5. **Obtener Todas las Plantillas de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxe-templates`
|
||||
- **Método HTTP**: GET
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"templates": [
|
||||
"pxe",
|
||||
"pxe2"
|
||||
"pxe_default"
|
||||
]
|
||||
}
|
||||
```
|
||||
6. **Crear archivo de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes`
|
||||
- **Método HTTP**: POST
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"template_name": "pxe2",
|
||||
"mac": "00:50:56:22:11:13",
|
||||
"lang": "es_ES.UTF-8",
|
||||
"ip": "192.168.2.11",
|
||||
"server_ip": "192.168.2.1",
|
||||
"router": "192.168.2.1",
|
||||
"netmask": "255.255.255.0",
|
||||
"computer_name": "pc13",
|
||||
"netiface": "eth0",
|
||||
"group": "Aula_virtual",
|
||||
"ogrepo": "192.168.2.1",
|
||||
"oglive": "192.168.2.1",
|
||||
"oglog": "192.168.2.1",
|
||||
"ogshare": "192.168.2.1",
|
||||
"oglivedir": "ogLive",
|
||||
"ogprof": "false",
|
||||
"hardprofile": "",
|
||||
"ogntp": "",
|
||||
"ogdns": "",
|
||||
"ogproxy": "",
|
||||
"ogunit": "",
|
||||
"resolution": "788"
|
||||
}
|
||||
```
|
||||
7. **Obtener Todos los Archivos de Arranque**
|
||||
- **URL**: `/ogboot/v1/pxes`
|
||||
- **Método HTTP**: GET
|
||||
- **Cuerpo de la Solicitud**:
|
||||
```json
|
||||
{
|
||||
{
|
||||
"boot_files": [
|
||||
"01-00:50:56:20:69:11",
|
||||
"01-00:50:56:20:69:12",
|
||||
"01-00:50:56:20:69:13"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
8. **Borrado de un fichero de arranque**
|
||||
- **URL**: `/ogboot/v1/pxes/{mac}`
|
||||
- **Método HTTP**: DELETE
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"message": "El archivo de arranque se eliminó correctamente"
|
||||
}
|
||||
```
|
||||
|
||||
9. **Borrado de una plantilla**
|
||||
- **URL**: `/ogboot/v1/pxe-templates/{name}`
|
||||
- **Método HTTP**: DELETE
|
||||
- **Respuesta**:
|
||||
```json
|
||||
{
|
||||
"message": "Plantilla eliminada correctamente."
|
||||
}
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/bin/bash
|
||||
#/**
|
||||
#@file ogfunctions.sh
|
||||
#@brief Generic functions for OpenGnsys Server and OpenGnsys Repository.
|
||||
#@version 1.1.1 - Initial version
|
||||
#@author Ramón M. Gómez, ETSII Universidad de Sevilla
|
||||
#@date 2017-10-08
|
||||
#*/
|
||||
|
||||
|
||||
# Showing an error message.
|
||||
function raiseError() {
|
||||
case "$1" in
|
||||
usage)
|
||||
echo "$PROG: Usage error: Type \"$PROG help\"" >&2
|
||||
exit 1 ;;
|
||||
notfound)
|
||||
echo "$PROG: Resource not found: $2" >&2
|
||||
exit 2 ;;
|
||||
access)
|
||||
echo "$PROG: Access error: $2" >&2
|
||||
exit 3 ;;
|
||||
download)
|
||||
echo "$PROG: Download error: $2" >&2
|
||||
exit 4 ;;
|
||||
*)
|
||||
echo "$PROG: Unknown error" >&2
|
||||
exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Showing help message.
|
||||
function help() {
|
||||
[ -n "$1" ] && DESCRIPTION="$1" || DESCRIPTION=$(grep "^#@brief" "$0" | cut -f2- -d" ")
|
||||
shift
|
||||
if [ -n "$1" ]; then
|
||||
USAGE="$1"
|
||||
shift
|
||||
else
|
||||
USAGE=$(grep "^#@usage" "$0" | cut -f2- -d" ")
|
||||
[ -n "$USAGE" ] && PARAMS=$(awk '$1=="#@param" {sub($1,""); print "\t",$0}' "$0")
|
||||
fi
|
||||
# Showing help.
|
||||
echo "$PROG: ${DESCRIPTION:-"no description"}"
|
||||
echo "Usage: ${USAGE:-"no usage info"}"
|
||||
[ -n "$PARAMS" ] && echo -e "$PARAMS"
|
||||
if [ -n "$*" ]; then
|
||||
echo "Examples:"
|
||||
while (( "$#" )); do
|
||||
echo -e "\t$1"
|
||||
shift
|
||||
done
|
||||
fi
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Metafunction to check if JSON result exists.
|
||||
JQ=$(which jq 2>/dev/null) || raiseError notfound "Need to install \"jq\"."
|
||||
function jq() {
|
||||
local OUTPUT
|
||||
OUTPUT=$($JQ "$@") || return $?
|
||||
[[ "$OUTPUT" = "null" ]] && return 1
|
||||
echo "$OUTPUT"
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
|
||||
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
|
||||
|
||||
class Kernel extends BaseKernel
|
||||
{
|
||||
use MicroKernelTrait;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
// src/OgBootBundle/OgBootBundle.php
|
||||
|
||||
namespace App\OgBootBundle;
|
||||
|
||||
use Symfony\Component\HttpKernel\Bundle\Bundle;
|
||||
|
||||
class OgBootBundle extends Bundle
|
||||
{
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
// src/OgBootBundle/Service/CurlRequestService.php
|
||||
|
||||
namespace App\OgBootBundle\Service;
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class CurlRequestService
|
||||
{
|
||||
|
||||
public function convertMaskToCIDR($mask)
|
||||
{
|
||||
$bits = 0;
|
||||
$mask = explode(".", $mask);
|
||||
|
||||
foreach ($mask as $octect)
|
||||
$bits += strlen(str_replace("0", "", decbin($octect)));
|
||||
|
||||
return $bits;
|
||||
}
|
||||
|
||||
// src/Service/CurlRequestService.php
|
||||
|
||||
public function installOglive($isoname)
|
||||
{
|
||||
$socketPath = '/tmp/oglive_daemon.sock';
|
||||
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
if ($socket === false) {
|
||||
syslog(LOG_ERR, 'Error al crear el socket: ' . socket_strerror(socket_last_error()));
|
||||
return ['success' => false, 'output' => 'Error al crear el socket'];
|
||||
}
|
||||
|
||||
$result = socket_connect($socket, $socketPath);
|
||||
if ($result === false) {
|
||||
syslog(LOG_ERR, 'Error al conectar con el socket: ' . socket_strerror(socket_last_error($socket)));
|
||||
socket_close($socket);
|
||||
return ['success' => false, 'output' => 'Error al conectar con el socket'];
|
||||
}
|
||||
|
||||
$command = [
|
||||
'action' => 'download',
|
||||
'args' => [$isoname]
|
||||
];
|
||||
|
||||
socket_write($socket, json_encode($command), strlen(json_encode($command)));
|
||||
|
||||
$response = '';
|
||||
$status = [];
|
||||
|
||||
while ($buffer = socket_read($socket, 2048)) {
|
||||
$response .= $buffer;
|
||||
$status[] = json_decode($buffer, true);
|
||||
}
|
||||
|
||||
socket_close($socket);
|
||||
|
||||
// Analiza el último estado recibido
|
||||
$lastStatus = end($status);
|
||||
if ($lastStatus && $lastStatus['status'] === 'completed') {
|
||||
return ['success' => true, 'output' => $lastStatus];
|
||||
} else {
|
||||
return ['success' => false, 'output' => $status];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function callOgLive($parameter)
|
||||
{
|
||||
$socketPath = '/var/run/oglive/oglive_daemon.sock';
|
||||
|
||||
file_put_contents('/tmp/serviceOglive.log', 'callOgLive called with parameter: ' . $parameter . PHP_EOL, FILE_APPEND);
|
||||
|
||||
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
|
||||
if ($socket === false) {
|
||||
$error = 'Error al crear el socket: ' . socket_strerror(socket_last_error());
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Socket creation error: ' . $error . PHP_EOL, FILE_APPEND);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
|
||||
$result = socket_connect($socket, $socketPath);
|
||||
if ($result === false) {
|
||||
$error = 'Error al conectar con el socket: ' . socket_strerror(socket_last_error($socket));
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Socket connection error: ' . $error . PHP_EOL, FILE_APPEND);
|
||||
socket_close($socket);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
|
||||
$args = array_map('trim', explode(' ', $parameter));
|
||||
$action = array_shift($args);
|
||||
$command = [
|
||||
'action' => $action,
|
||||
'args' => $args
|
||||
];
|
||||
|
||||
socket_write($socket, json_encode($command), strlen(json_encode($command)));
|
||||
|
||||
$response = '';
|
||||
while ($buffer = socket_read($socket, 2048)) {
|
||||
$response .= $buffer;
|
||||
}
|
||||
|
||||
socket_close($socket);
|
||||
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Raw response: ' . $response . PHP_EOL, FILE_APPEND);
|
||||
|
||||
if (empty($response)) {
|
||||
$error = 'Respuesta vacía del demonio';
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Empty response error: ' . $error . PHP_EOL, FILE_APPEND);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
|
||||
$decodedResponse = json_decode($response, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
$error = 'Error al decodificar JSON: ' . json_last_error_msg();
|
||||
file_put_contents('/tmp/serviceOglive.log', 'JSON decode error: ' . $error . PHP_EOL, FILE_APPEND);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
|
||||
if (isset($decodedResponse['success']) && $decodedResponse['success']) {
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Decoded successful response: ' . json_encode($decodedResponse['output']) . PHP_EOL, FILE_APPEND);
|
||||
return $decodedResponse['output'];
|
||||
} else {
|
||||
$error = $decodedResponse['error'] ?? 'Unknown error';
|
||||
file_put_contents('/tmp/serviceOglive.log', 'Error in response: ' . $error . PHP_EOL, FILE_APPEND);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $error
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue