refs #208 adds dameon logic to execute commands with sudo
parent
36c6f19cf2
commit
8ffe2cae85
116
bin/oglivecli
116
bin/oglivecli
|
@ -40,7 +40,7 @@
|
|||
|
||||
# Global constants definition.
|
||||
PROG=$(basename "$(realpath "$0")") # Program name.
|
||||
OPENGNSYS=/home/qindel/ogboot # OpenGnsys main directory.
|
||||
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.
|
||||
|
@ -316,84 +316,112 @@ function download_old() {
|
|||
function install() {
|
||||
local OGLIVEFILE OGLIVEDIST OGLIVEREV OGLIVEKRNL OGLIVEDIR OGINITRD OGSQFS OGCLIENT=ogclient
|
||||
local COMPRESS SAMBAPASS TMPDIR RSYNCSERV RSYNCCLNT
|
||||
[ $# -ne 1 ] && raiseError usage
|
||||
[ $# -ne 1 ] && { echo "{\"error\": \"usage\"}"; exit 1; }
|
||||
|
||||
OGLIVEFILE=$(realpath $DOWNLOADDIR/$1)
|
||||
# Only 1 file in pathname expansion.
|
||||
[ $(echo $OGLIVEFILE | wc -w) -gt 1 ] && raiseError usage
|
||||
[ ! -f $OGLIVEFILE ] && raiseError notfound "Downloaded file: \"$1\"."
|
||||
[ ! -r $OGLIVEFILE ] && raiseError access "Downloaded file: \"$1\"."
|
||||
[ ! -w $(dirname $INFOFILE) ] && raiseError access "Configuration directory."
|
||||
[ ! -w $TFTPDIR ] && raiseError access "Installation directory."
|
||||
[ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && raiseError access "File is not an ogLive ISO image."
|
||||
# Working directory:
|
||||
# 64-bit: ogLive-KernelVersion-rCodeRelease
|
||||
# 32-bit: ogLive-KernelVersion-i386-rCodeRelease
|
||||
[ $(echo $OGLIVEFILE | wc -w) -gt 1 ] && { echo "{\"error\": \"usage\"}"; exit 1; }
|
||||
[ ! -f $OGLIVEFILE ] && { echo "{\"error\": \"not found \"$1\".\"}"; exit 1; }
|
||||
[ ! -r $OGLIVEFILE ] && { echo "{\"error\": \"access \"$1\".\"}"; exit 1; }
|
||||
[ ! -w $(dirname $INFOFILE) ] && { echo "{\"error\": \"access configuration directory.\"}"; exit 1; }
|
||||
[ ! -w $TFTPDIR ] && { echo "{\"error\": \"access installation directory.\"}"; exit 1; }
|
||||
[ -z "$(file -b $OGLIVEFILE | grep "ISO.*ogClient")" ] && { echo "{\"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) # Get architecture.
|
||||
i386|amd64)
|
||||
OGLIVEKRNL="${OGLIVEKRNL%-$OGLIVEARCH}" ;;
|
||||
*) # 32-bit by default.
|
||||
*)
|
||||
OGLIVEARCH="i386" ;;
|
||||
esac
|
||||
OGLIVEDIR="$TFTPDIR/$DEFOGLIVE-${OGLIVEKRNL%%-*}-$OGLIVEARCH-$OGLIVEREV"
|
||||
OGLIVEDIR="${OGLIVEDIR/amd64-/}"
|
||||
# Get current or default Samba key.
|
||||
|
||||
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>&1 | \
|
||||
sed -n '/^[ ].*OPTIONS=/s/.*pass=\(\w*\).*/\1/p')
|
||||
sed -n '/^[ \t].*OPTIONS=/s/.*pass=\(\w*\).*/\1/p')
|
||||
fi
|
||||
# Make ogLive backup.
|
||||
|
||||
rm -fr ${OGLIVEDIR}.old
|
||||
mv -fv $OGLIVEDIR ${OGLIVEDIR}.old 2>/dev/null
|
||||
# Mount ogLive ISO image, update its files and unmount it.
|
||||
|
||||
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
|
||||
cp -va $TMPDIR/ogclient/* $OGLIVEDIR || raiseError access "Cannot copy files to ogLive directory."
|
||||
mount -o loop,ro $OGLIVEFILE $TMPDIR || { echo "{\"error\": \"mount failed.\"}"; exit 1; }
|
||||
cp -va $TMPDIR/ogclient/* $OGLIVEDIR || { echo "{\"error\": \"Cannot copy files to ogLive directory.\"}"; exit 1; }
|
||||
umount $TMPDIR
|
||||
# Link to default directory if it's the first ogLive.
|
||||
|
||||
if [ ! -f $INFOFILE ]; then
|
||||
rm -f $TFTPDIR/$DEFOGLIVE $TFTPDIR/$OGCLIENT
|
||||
ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE
|
||||
ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT
|
||||
ln -vfs $(basename $OGLIVEDIR) $TFTPDIR/$DEFOGLIVE || { echo "{\"error\": \"Linking to $TFTPDIR/$DEFOGLIVE failed.\"}"; exit 1; }
|
||||
ln -vfs $DEFOGLIVE $TFTPDIR/$OGCLIENT || { echo "{\"error\": \"Linking to $TFTPDIR/$OGCLIENT failed.\"}"; exit 1; }
|
||||
fi
|
||||
# Recover or ask for a new Samba access key.
|
||||
|
||||
if [ -n "$SAMBAPASS" ]; then
|
||||
echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)"
|
||||
echo -ne "$SAMBAPASS\n$SAMBAPASS\n" | $OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" || { echo "{\"error\": \"setsmbpass failed.\"}"; exit 1; }
|
||||
else
|
||||
$OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)"
|
||||
$OPENGNSYS/bin/setsmbpass "$(basename $OGLIVEDIR)" || { echo "{\"error\": \"setsmbpass failed.\"}"; exit 1; }
|
||||
fi
|
||||
# Set permissions.
|
||||
find -L $OGLIVEDIR -type d -exec chmod 755 {} \;
|
||||
find -L $OGLIVEDIR -type f -exec chmod 644 {} \;
|
||||
chown -R :opengnsys $OGLIVEDIR
|
||||
# Mount SquashFS and check Rsync version.
|
||||
|
||||
find -L $OGLIVEDIR -type d -exec chmod 755 {} \; || { echo "{\"error\": \"chmod directories failed.\"}"; exit 1; }
|
||||
find -L $OGLIVEDIR -type f -exec chmod 644 {} \; || { echo "{\"error\": \"chmod files failed.\"}"; exit 1; }
|
||||
chown -R :opengnsys $OGLIVEDIR || { echo "{\"error\": \"chown failed.\"}"; exit 1; }
|
||||
|
||||
echo "Mounting SquashFS and checking Rsync version..."
|
||||
OGSQFS=$OGLIVEDIR/ogclient.sqfs
|
||||
mount -o loop,ro $OGSQFS $TMPDIR
|
||||
# If Rsync server version > client version, link to compiled file.
|
||||
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" -o ${RSYNCSERV:-0} -gt ${RSYNCCLNT:-1} ]; then
|
||||
[ -e $OPENGNSYS/client/bin/rsync-$RSYNCSERV ] && mv -f $OPENGNSYS/client/bin/rsync-$RSYNCSERV $OPENGNSYS/client/bin/rsync
|
||||
|
||||
# Intentar montar SquashFS
|
||||
if mount -o loop,ro $OGSQFS $TMPDIR; then
|
||||
# Obtener versiones de rsync
|
||||
RSYNCSERV=$(rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
|
||||
RSYNCCLNT=$(chroot $TMPDIR /usr/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
|
||||
|
||||
# Lógica para manejar rsync
|
||||
if [ -z "$RSYNCSERV" ] || [ "$RSYNCSERV" -gt "${RSYNCCLNT:-1}" ]; then
|
||||
[ -e "$OPENGNSYS/client/bin/rsync-$RSYNCSERV" ] && \
|
||||
mv -f "$OPENGNSYS/client/bin/rsync-$RSYNCSERV" "$OPENGNSYS/client/bin/rsync" || \
|
||||
{ echo "{\"error\": \"mv rsync failed.\"}"; umount $TMPDIR; exit 1; }
|
||||
else
|
||||
[ -e "$OPENGNSYS/client/bin/rsync" ] && \
|
||||
mv -f "$OPENGNSYS/client/bin/rsync" "$OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')" || \
|
||||
{ echo "{\"error\": \"mv rsync client failed.\"}"; umount $TMPDIR; exit 1; }
|
||||
fi
|
||||
|
||||
echo "Unmounting SquashFS..."
|
||||
if umount $TMPDIR; then
|
||||
echo "Unmounted successfully"
|
||||
# Espera antes de intentar eliminar el directorio
|
||||
sleep 1
|
||||
|
||||
# Intentar eliminar el directorio TMPDIR
|
||||
if rmdir $TMPDIR; then
|
||||
echo "Cleaned up successfully"
|
||||
else
|
||||
echo "Warning: rmdir $TMPDIR failed. Attempting force removal."
|
||||
rm -rf $TMPDIR || echo "{\"error\": \"rm -rf $TMPDIR failed.\"}"
|
||||
fi
|
||||
else
|
||||
echo "{\"error\": \"umount SquashFS failed.\"}"
|
||||
fi
|
||||
else
|
||||
# Else, rename compiled file using Rsync protocol number.
|
||||
[ -e $OPENGNSYS/client/bin/rsync ] && mv -f $OPENGNSYS/client/bin/rsync $OPENGNSYS/client/bin/rsync-$($OPENGNSYS/client/bin/rsync --version 2>/dev/null | awk '/protocol/ {print $6}')
|
||||
echo "{\"error\": \"mount SquashFS failed.\"}"
|
||||
fi
|
||||
# Unmount SquashFS.
|
||||
umount $TMPDIR
|
||||
rmdir $TMPDIR
|
||||
# Update JSON file.
|
||||
addToJson "$OGLIVEDIST" "$OGLIVEKRNL" "$OGLIVEARCH" "$OGLIVEREV" "$OGLIVEDIR" "$OGLIVEFILE"
|
||||
|
||||
local 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")" \
|
||||
'{distribution: $dist, kernel: $krnl, architecture: $arch, revision: $rev, directory: $dir, iso: $iso}')
|
||||
|
||||
echo "$json_output"
|
||||
}
|
||||
|
||||
|
||||
# Uninstall an ogLive client.
|
||||
function uninstall() {
|
||||
local ISO DIR INDEX DEFINDEX
|
||||
|
|
|
@ -80,8 +80,25 @@ for OGLIVE in $LIST; do
|
|||
# descomprimir Initrd, sustituir clave y recomprimir Initrd).
|
||||
echo "Configurando cliente \"$OGLIVE\" ..."
|
||||
mkdir -p $TMPDIR
|
||||
cd $TMPDIR || exit 3
|
||||
gzip -dc "$CLIENTINITRD" | cpio -im
|
||||
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).
|
||||
|
@ -97,7 +114,10 @@ EOT
|
|||
chown root.root scripts/passrsync scripts/client.cfg
|
||||
chmod 400 scripts/passrsync scripts/client.cfg
|
||||
# Generar Initrd del cliente.
|
||||
find . | cpio -H newc -oa | gzip -9c > "$CLIENTINITRD"
|
||||
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
|
||||
|
|
|
@ -168,7 +168,7 @@ Regenerar plantilla - PUT /ogboot/pxe-templates
|
|||
* @Route("/ogboot/v1/oglives", name="getOglives", methods={"GET"})
|
||||
* @OA\Get(
|
||||
* path="/ogboot/v1/oglives",
|
||||
* summary="Get information of all installed ogLive clients",
|
||||
* summary="Get list of all installed ogLive clients",
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Successful operation",
|
||||
|
@ -177,57 +177,261 @@ Regenerar plantilla - PUT /ogboot/pxe-templates
|
|||
* @OA\Items(
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="id",
|
||||
* type="string",
|
||||
* description="Unique identifier for the ogLive client, generated from linuxISO.sum",
|
||||
* example="9e49a085ba74f97a81bdf9b3d0785094"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="distribution",
|
||||
* type="string",
|
||||
* description="Distribution name of the ogLive client"
|
||||
* description="Distribution name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="kernel",
|
||||
* type="string",
|
||||
* description="Kernel version of the ogLive client"
|
||||
* description="Kernel version of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="architecture",
|
||||
* type="string",
|
||||
* description="Architecture of the ogLive client"
|
||||
* description="Architecture of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="revision",
|
||||
* type="string",
|
||||
* description="Revision of the ogLive client"
|
||||
* description="Revision of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="directory",
|
||||
* type="string",
|
||||
* description="Directory name of the ogLive client"
|
||||
* description="Directory name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="iso",
|
||||
* type="string",
|
||||
* description="ISO file name of the ogLive client"
|
||||
* description="ISO file name of the installed ogLive client"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=500,
|
||||
* description="Failed to retrieve information of installed ogLive clients"
|
||||
* response=404,
|
||||
* description="No ogLive clients found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getOglives(): Response
|
||||
{
|
||||
public function getOglives(): Response
|
||||
{
|
||||
$directoryPath = '/opt/ogboot/tftpboot/';
|
||||
$pattern = '/^ogLive-([\w.-]+)-r(\d+)$/';
|
||||
|
||||
# $result = $this->curlRequestService->common_request(OG_REST_CMD_POWEROFF, POST, [OG_REST_PARAM_CLIENTS => $ips]);
|
||||
$result = $this->curlRequestService->callOgLive("show all");
|
||||
$ogLives = [];
|
||||
|
||||
if ($handle = opendir($directoryPath)) {
|
||||
error_log("Opened directory: $directoryPath");
|
||||
|
||||
if ($result) {
|
||||
return new Response($result, Response::HTTP_OK);
|
||||
} else {
|
||||
return new Response('Failed', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
error_log("Processing entry: $entry");
|
||||
|
||||
if ($entry != "." && $entry != ".." && is_dir($directoryPath . $entry)) {
|
||||
if (preg_match($pattern, $entry, $matches)) {
|
||||
error_log("Entry matches pattern: $entry");
|
||||
|
||||
// Evitar directorios .old
|
||||
if (substr($entry, -4) === '.old') {
|
||||
error_log("Ignoring old directory: $entry");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Extraer detalles
|
||||
$distribution = $matches[1];
|
||||
$revision = $matches[2];
|
||||
$directory = $entry;
|
||||
$ogLivePath = $directoryPath . $entry;
|
||||
|
||||
// Obtener el ID del archivo linuxISO.sum
|
||||
$sumFile = $ogLivePath . '/linuxISO.sum';
|
||||
$id = '';
|
||||
if (file_exists($sumFile)) {
|
||||
$id = trim(file_get_contents($sumFile));
|
||||
}
|
||||
|
||||
// Obtener el nombre del archivo ISO
|
||||
$iso = '';
|
||||
$oldInfoFile = $ogLivePath . '/OLDINFOFILE';
|
||||
if (file_exists($oldInfoFile)) {
|
||||
$iso = trim(file($oldInfoFile, FILE_USE_INCLUDE_PATH | FILE_IGNORE_NEW_LINES)[0]);
|
||||
}
|
||||
|
||||
// Obtener la versión del kernel
|
||||
$kernelFile = $ogLivePath . '/ogvmlinuz';
|
||||
$kernel = '';
|
||||
if (file_exists($kernelFile)) {
|
||||
$fileOutput = shell_exec("file -bkr $kernelFile");
|
||||
if (preg_match('/Linux kernel.*version (\d+\.\d+\.\d+)/', $fileOutput, $kernelMatches)) {
|
||||
$kernel = $kernelMatches[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Asumir arquitectura como 'amd64'; puedes refinar esto si se necesita más lógica
|
||||
$architecture = 'amd64';
|
||||
|
||||
// Construir el objeto
|
||||
$ogLives[] = [
|
||||
'id' => $id,
|
||||
'distribution' => $distribution,
|
||||
'kernel' => $kernel,
|
||||
'architecture' => $architecture,
|
||||
'revision' => $revision,
|
||||
'directory' => $directory,
|
||||
'iso' => $iso
|
||||
];
|
||||
} else {
|
||||
error_log("Entry does not match pattern: $entry");
|
||||
}
|
||||
} else {
|
||||
error_log("Entry is not a directory: $directoryPath$entry");
|
||||
}
|
||||
}
|
||||
|
||||
closedir($handle);
|
||||
error_log("Closed directory: $directoryPath");
|
||||
}
|
||||
|
||||
if (!empty($ogLives)) {
|
||||
error_log("Returning ogLives data");
|
||||
return new JsonResponse($ogLives, Response::HTTP_OK);
|
||||
} else {
|
||||
error_log("No ogLive clients found");
|
||||
return new JsonResponse(['error' => 'No ogLive clients found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/{id}", name="getOglive", methods={"GET"})
|
||||
* @OA\Get(
|
||||
* path="/ogboot/v1/oglives/{id}",
|
||||
* summary="Get information of an installed ogLive client",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="path",
|
||||
* description="Checksum of the installed ogLive client",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string",
|
||||
* example="9e49a085ba74f97a81bdf9b3d0785094"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Successful operation",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="id",
|
||||
* type="string",
|
||||
* description="Checksum of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="distribution",
|
||||
* type="string",
|
||||
* description="Distribution name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="kernel",
|
||||
* type="string",
|
||||
* description="Kernel version of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="architecture",
|
||||
* type="string",
|
||||
* description="Architecture of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="revision",
|
||||
* type="string",
|
||||
* description="Revision of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="directory",
|
||||
* type="string",
|
||||
* description="Directory name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="iso",
|
||||
* type="string",
|
||||
* description="ISO file name of the installed ogLive client"
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="ogLive client not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getOglive(Request $request, string $id): Response
|
||||
{
|
||||
$directoryPath = '/opt/ogboot/tftpboot/';
|
||||
$pattern = '/^ogLive-([\w.-]+)-([\w.-]+)-r(\d{4,8})$/';
|
||||
|
||||
$found = false;
|
||||
$result = [];
|
||||
|
||||
if ($handle = opendir($directoryPath)) {
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
if ($entry != "." && $entry != ".." && is_dir($directoryPath . $entry)) {
|
||||
if (preg_match($pattern, $entry, $matches)) {
|
||||
$checksumFilePath = $directoryPath . $entry . '/linuxISO.sum';
|
||||
if (file_exists($checksumFilePath)) {
|
||||
$checksum = trim(file_get_contents($checksumFilePath));
|
||||
if ($checksum === $id) {
|
||||
// Extract details
|
||||
$distribution = explode('-', $matches[1])[0];
|
||||
$kernel = substr($matches[1], strlen($distribution) + 1);
|
||||
$architecture = 'amd64'; // Assuming architecture, refine as needed
|
||||
$revision = $matches[3];
|
||||
$directory = $entry;
|
||||
$iso = $this->findIsoFile($directoryPath . $entry);
|
||||
|
||||
// Construct the result
|
||||
$result = [
|
||||
'id' => $id,
|
||||
'distribution' => $distribution,
|
||||
'kernel' => $kernel,
|
||||
'architecture' => $architecture,
|
||||
'revision' => $revision,
|
||||
'directory' => $directory,
|
||||
'iso' => $iso
|
||||
];
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
return new JsonResponse($result, Response::HTTP_OK);
|
||||
} else {
|
||||
return new JsonResponse(['error' => 'ogLive client not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
}
|
||||
|
||||
private function findIsoFile(string $directory): string
|
||||
{
|
||||
$files = glob($directory . '/*.iso');
|
||||
return count($files) > 0 ? basename($files[0]) : '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/default", name="getOgliveDefault", methods={"GET"})
|
||||
* @OA\Get(
|
||||
|
@ -289,89 +493,26 @@ Regenerar plantilla - PUT /ogboot/pxe-templates
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/{name}", name="getOglive", methods={"GET"})
|
||||
* @OA\Get(
|
||||
* path="/ogboot/v1/oglives/{name}",
|
||||
* summary="Get information of an installed ogLive client",
|
||||
* @OA\Parameter(
|
||||
* name="name",
|
||||
* in="path",
|
||||
* description="Name or Directory of the installed ogLive client",
|
||||
* @Route("/ogboot/v1/oglives/default", name="setOgliveDefault", methods={"POST"})
|
||||
* @OA\Post(
|
||||
* path="/ogboot/v1/oglives/default",
|
||||
* summary="Set default ogLive client",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="Successful operation",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="distribution",
|
||||
* property="name",
|
||||
* type="string",
|
||||
* description="Distribution name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="kernel",
|
||||
* type="string",
|
||||
* description="Kernel version of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="architecture",
|
||||
* type="string",
|
||||
* description="Architecture of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="revision",
|
||||
* type="string",
|
||||
* description="Revision of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="directory",
|
||||
* type="string",
|
||||
* description="Directory name of the installed ogLive client"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="iso",
|
||||
* type="string",
|
||||
* description="ISO file name of the installed ogLive client"
|
||||
* example="ogLive-5.11.0-r20210413",
|
||||
* description="Name of the ogLive client to set as default"
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=404,
|
||||
* description="ogLive client not found"
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getOglive(Request $request, string $name): Response
|
||||
{
|
||||
$result = $this->curlRequestService->callOgLive("show " . escapeshellarg($name));
|
||||
|
||||
if ($result) {
|
||||
return new Response($result, Response::HTTP_OK);
|
||||
} else {
|
||||
return new Response('Failed', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/default/{name}", name="setOgliveDefault", methods={"POST"})
|
||||
* @OA\Post(
|
||||
* path="/ogboot/v1/oglives/default/{name}",
|
||||
* summary="Set default ogLive client",
|
||||
* @OA\Parameter(
|
||||
* name="name",
|
||||
* in="path",
|
||||
* description="Name of the ogLive client to set as default",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="ogLive client set as default successfully",
|
||||
* @OA\JsonContent(
|
||||
|
@ -389,8 +530,16 @@ public function getOglive(Request $request, string $name): Response
|
|||
* )
|
||||
* )
|
||||
*/
|
||||
public function setOgliveDefault(Request $request, string $name): Response
|
||||
public function setOgliveDefault(Request $request): Response
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['name'])) {
|
||||
return new JsonResponse(['error' => 'Invalid input data'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$name = $data['name'];
|
||||
|
||||
// Obtener la lista de ogLives
|
||||
$listResult = $this->curlRequestService->callOgLive("list");
|
||||
|
||||
|
@ -409,7 +558,7 @@ public function setOgliveDefault(Request $request, string $name): Response
|
|||
}
|
||||
|
||||
if ($id === null) {
|
||||
return new Response('ogLive client not found', Response::HTTP_NOT_FOUND);
|
||||
return new JsonResponse(['error' => 'ogLive client not found'], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Establecer el ogLive como predeterminado utilizando el ID encontrado
|
||||
|
@ -423,6 +572,7 @@ public function setOgliveDefault(Request $request, string $name): Response
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
@ -447,113 +597,129 @@ public function setOgliveDefault(Request $request, string $name): Response
|
|||
* )
|
||||
*/
|
||||
|
||||
public function getDownloadMenu(): Response
|
||||
{
|
||||
public function getDownloadMenu(): Response
|
||||
{
|
||||
|
||||
$downloadsOutput = $this->curlRequestService->callOgLive("download");
|
||||
$downloadsOutput = $this->curlRequestService->callOgLive("download");
|
||||
|
||||
|
||||
$downloads = explode("\n", trim($downloadsOutput));
|
||||
$result = [];
|
||||
|
||||
foreach ($downloads as $download) {
|
||||
$downloads = explode("\n", trim($downloadsOutput));
|
||||
$result = [];
|
||||
|
||||
foreach ($downloads as $download) {
|
||||
|
||||
$pattern = '/^(\d+)\) (\(\*\))?\s?(\(\+\))?\s?(.+\.iso)$/';
|
||||
|
||||
$pattern = '/^(\d+)\) (\(\*\))?\s?(\(\+\))?\s?(.+\.iso)$/';
|
||||
|
||||
|
||||
preg_match($pattern, $download, $matches);
|
||||
preg_match($pattern, $download, $matches);
|
||||
|
||||
if (!empty($matches)) {
|
||||
$id = $matches[1];
|
||||
$installed = !empty($matches[2]);
|
||||
$compatible = !empty($matches[3]);
|
||||
$filename = $matches[4];
|
||||
if (!empty($matches)) {
|
||||
$id = $matches[1];
|
||||
$installed = !empty($matches[2]);
|
||||
$compatible = !empty($matches[3]);
|
||||
$filename = $matches[4];
|
||||
|
||||
$result[] = [
|
||||
'id' => $id,
|
||||
'filename' => $filename,
|
||||
'installed' => $installed,
|
||||
'compatible' => $compatible
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$jsonDownloads = json_encode($result);
|
||||
|
||||
|
||||
return new Response($jsonDownloads, Response::HTTP_OK, [
|
||||
'Content-Type' => 'application/json'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives", name="installOglive", methods={"POST"})
|
||||
* @OA\Post(
|
||||
* path="/ogboot/v1/oglives",
|
||||
* summary="Install an ogLive client",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="isoName",
|
||||
* type="string",
|
||||
* description="Name of the ogLive ISO to install",
|
||||
* example="ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso"
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="ogLive client installed successfully",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="message", type="string")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=500,
|
||||
* description="Failed to install ogLive client",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function installOglive(Request $request): Response
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$isoName = $data['isoName'] ?? null;
|
||||
#$isoName = $request->get('isoName');
|
||||
var_dump($isoName);
|
||||
if (!$isoName) {
|
||||
return new Response('ISO name is required', Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$result = $this->curlRequestService->callOgLive("download " . escapeshellarg($isoName));
|
||||
|
||||
if ($result) {
|
||||
return new Response($result, Response::HTTP_OK);
|
||||
} else {
|
||||
return new Response('Failed', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
$result[] = [
|
||||
'id' => $id,
|
||||
'filename' => $filename,
|
||||
'installed' => $installed,
|
||||
'compatible' => $compatible
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$jsonDownloads = json_encode($result);
|
||||
|
||||
|
||||
return new Response($jsonDownloads, Response::HTTP_OK, [
|
||||
'Content-Type' => 'application/json'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/{name}", name="uninstallOglive", methods={"DELETE"})
|
||||
* @Route("/ogboot/v1/oglives", name="installOglive", methods={"POST"})
|
||||
* @OA\Post(
|
||||
* path="/ogboot/v1/oglives",
|
||||
* summary="Install an ogLive client",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(
|
||||
* property="isoname",
|
||||
* type="string",
|
||||
* example="ogLive-focal-5.13.0-27-beta-amd64-r20210706.5b4bf5f.iso",
|
||||
* description="Name of the ogLive ISO to install"
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
* description="ogLive client installed successfully",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="distribution", type="string"),
|
||||
* @OA\Property(property="kernel", type="string"),
|
||||
* @OA\Property(property="architecture", type="string"),
|
||||
* @OA\Property(property="revision", type="string"),
|
||||
* @OA\Property(property="directory", type="string"),
|
||||
* @OA\Property(property="iso", type="string")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=400,
|
||||
* description="Invalid input data",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string")
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=500,
|
||||
* description="Failed to install ogLive client",
|
||||
* @OA\JsonContent(
|
||||
* type="object",
|
||||
* @OA\Property(property="error", type="string"),
|
||||
* @OA\Property(property="details", type="string")
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
|
||||
|
||||
public function installOglive(Request $request): Response
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['isoname'])) {
|
||||
return new JsonResponse(['error' => 'Invalid input data'], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
$isoname = $data['isoname'];
|
||||
$result = $this->curlRequestService->callOgLive("download " . escapeshellarg($isoname));
|
||||
|
||||
if (is_array($result) && isset($result['success']) && $result['success'] === false) {
|
||||
return new JsonResponse(['error' => 'Failed to install ogLive client', 'details' => $result['error']], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return new JsonResponse(['message' => 'ogLive client installed successfully', 'details' => $result['output']], Response::HTTP_OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/oglives/{checksum}", name="uninstallOglive", methods={"DELETE"})
|
||||
* @OA\Delete(
|
||||
* path="/ogboot/v1/oglives/{name}",
|
||||
* path="/ogboot/v1/oglives/{checksum}",
|
||||
* summary="Uninstall an ogLive client",
|
||||
* @OA\Parameter(
|
||||
* name="name",
|
||||
* name="checksum",
|
||||
* in="path",
|
||||
* description="Name of the ogLive client to uninstall",
|
||||
* description="Checksum of the ogLive client to uninstall",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* @OA\Schema(type="string", example="9e49a085ba74f97a81bdf9b3d0785094")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response=200,
|
||||
|
@ -577,39 +743,25 @@ public function setOgliveDefault(Request $request, string $name): Response
|
|||
* )
|
||||
* )
|
||||
*/
|
||||
public function uninstallOglive(Request $request, string $name): Response
|
||||
public function uninstallOglive(string $checksum): Response
|
||||
{
|
||||
// Obtener la lista de ogLives
|
||||
$listResult = $this->curlRequestService->callOgLive("list");
|
||||
|
||||
if (!$listResult) {
|
||||
return new Response('Failed to retrieve ogLive list', Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
// Buscar el ID correspondiente al nombre proporcionado
|
||||
$lines = explode("\n", trim($listResult));
|
||||
$id = null;
|
||||
foreach ($lines as $line) {
|
||||
if (strpos($line, $name) !== false) {
|
||||
$id = explode(" ", trim($line))[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($id === null) {
|
||||
return new Response('ogLive client not found', Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
// Desinstalar el ogLive utilizando el ID encontrado
|
||||
$result = $this->curlRequestService->callOgLive("uninstall $id");
|
||||
$result = $this->curlRequestService->callOgLive("uninstall " . escapeshellarg($checksum));
|
||||
|
||||
if ($result) {
|
||||
return new JsonResponse(['message' => 'ogLive client uninstalled successfully'], Response::HTTP_OK);
|
||||
// Decodifica la respuesta JSON del demonio
|
||||
$response = json_decode($result, true);
|
||||
|
||||
if (isset($response['error'])) {
|
||||
return new JsonResponse(['error' => $response['error']], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
return new JsonResponse(['message' => 'ogLive client uninstalled successfully', 'details' => $response['details']], Response::HTTP_OK);
|
||||
} else {
|
||||
return new JsonResponse(['error' => 'Failed to uninstall ogLive client'], Response::HTTP_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Route("/ogboot/v1/pxes", name="get_boot_files", methods={"GET"})
|
||||
* @OA\Get(
|
||||
|
|
|
@ -18,15 +18,105 @@ class CurlRequestService
|
|||
return $bits;
|
||||
}
|
||||
|
||||
public function callOgLive($parameter)
|
||||
{
|
||||
$ogLiveCliPath = sprintf("%s/bin/oglivecli", dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
$command = sprintf("%s %s", $ogLiveCliPath, $parameter);
|
||||
|
||||
syslog(LOG_INFO, 'command '.$command);
|
||||
$output = shell_exec($command);
|
||||
|
||||
return $output;
|
||||
// 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 = '/tmp/oglive_daemon.sock'; // Path to the UNIX socket
|
||||
$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,
|
||||
'error' => '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,
|
||||
'error' => 'Error al conectar con el socket'
|
||||
];
|
||||
}
|
||||
|
||||
$args = explode(' ', $parameter);
|
||||
$action = array_shift($args); // Toma la primera palabra como la acción
|
||||
$command = [
|
||||
'action' => $action,
|
||||
'args' => $args
|
||||
];
|
||||
|
||||
syslog(LOG_INFO, 'Sending command to daemon: ' . json_encode($command));
|
||||
socket_write($socket, json_encode($command), strlen(json_encode($command)));
|
||||
|
||||
$response = '';
|
||||
while ($buffer = socket_read($socket, 2048)) {
|
||||
$response .= $buffer;
|
||||
}
|
||||
|
||||
socket_close($socket);
|
||||
|
||||
$decodedResponse = json_decode($response, true);
|
||||
|
||||
if (isset($decodedResponse['success']) && $decodedResponse['success']) {
|
||||
return $decodedResponse['output'];
|
||||
} else {
|
||||
syslog(LOG_ERR, 'Error al ejecutar el comando: ' . $decodedResponse['error']);
|
||||
return [
|
||||
'success' => false,
|
||||
'error' => $decodedResponse['error'] ?? 'Unknown error'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue