refs #208 adds dameon logic to execute commands with sudo

pull/3/head
Luis Gerardo Romero Garcia 2024-06-21 16:18:19 +02:00
parent 36c6f19cf2
commit 8ffe2cae85
4 changed files with 554 additions and 264 deletions

View File

@ -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

View File

@ -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

View File

@ -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(

View File

@ -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'
];
}
}
}