src: port setclientmode code to C

Implement most of the code from the script setclientmode into
ogServer to improve error handling and logs.

Use a reduced version legacy script to replace the contents of
the base PXE template. This file is now called updategrubprofile.
Add updategrubprofile to the new extras/ folder.

Create BIOS and UEFI files for PXE boot configuration. Each file
is located in a different directory and requires a different name
pattern.

-BIOS-
File format:
/opt/opengnsys/tftpboot/menu.lst/01-XX-XX-XX-XX-XX-XX

Template dir:
/opt/opengnsys/tftpboot/menu.lst/templates/

-UEFI-
File format:
/opt/opengnsys/tftpboot/grub/01-xx:xx:xx:xx:xx:xx

Template dir:
/opt/opengnsys/tftpboot/grub/templates/
master
Alejandro Sirgo Rica 2024-07-15 16:38:07 +02:00
parent df52acba04
commit e62a55ae37
2 changed files with 210 additions and 36 deletions

View File

@ -0,0 +1,14 @@
#!/bin/bash
[ $# -gt 1 ] && exit 1
source "$1" || exit 1
# Obtener directorio ogLive a partir de los datos.
OGLIVEDIR=$(echo "$DATA" | awk -F= 'BEGIN {RS=" "} $1=="oglivedir" {print $2}')
# Elimina "oglivedir" de los parametros si ya esta en la plantilla.
if grep -q "oglivedir=" ${TEMPLATE_PATH} 2>/dev/null; then
DATA="${DATA/oglivedir=$OGLIVEDIR/}"
fi
sed -e "s,vga=[0-9]*,,g; s,INFOHOST,${DATA//,/\\,},g; s,set ISODIR=.*,set ISODIR=$OGLIVEDIR,g" ${TEMPLATE_PATH} >${PXEFILE_PATH}

View File

@ -1286,18 +1286,204 @@ static bool og_boot_mode_is_valid(const char *name)
return found;
}
enum {
OG_TFTP_BOOT_BIOS,
OG_TFTP_BOOT_UEFI,
PXE_BOOT_TYPE_MAX,
};
const char *pxe_boot_type_to_dir[] = {
[OG_TFTP_BOOT_BIOS] = "/opt/opengnsys/tftpboot/menu.lst",
[OG_TFTP_BOOT_UEFI] = "/opt/opengnsys/tftpboot/grub"
};
static const char *pxe_boot_type(const int boot_type)
{
if (boot_type < 0 || boot_type >= PXE_BOOT_TYPE_MAX)
return NULL;
return pxe_boot_type_to_dir[boot_type];
}
static int get_grub_filename(unsigned int boot_type, const char *mac,
char *pxe_filename, size_t pxe_filename_size)
{
const char *fmt;
switch (boot_type) {
case OG_TFTP_BOOT_BIOS:
fmt = "01-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c";
break;
case OG_TFTP_BOOT_UEFI:
fmt = "01-%c%c:%c%c:%c%c:%c%c:%c%c:%c%c";
break;
default:
syslog(LOG_ERR, "unknown boot type %d", boot_type);
return -1;
}
snprintf(pxe_filename, pxe_filename_size, fmt,
mac[0], mac[1],
mac[2], mac[3],
mac[4], mac[5],
mac[6], mac[7],
mac[8], mac[9],
mac[10], mac[11]);
switch (boot_type) {
case OG_TFTP_BOOT_BIOS:
str_toupper(pxe_filename);
break;
case OG_TFTP_BOOT_UEFI:
str_tolower(pxe_filename);
break;
default:
syslog(LOG_ERR, "unknown boot type %d", boot_type);
return -1;
}
return 0;
}
static int get_grub_file_path(unsigned int boot_type, const char *mac,
char *pxe_path, size_t pxe_path_size)
{
char pxe_filename[PATH_MAX + 1];
const char *pxe_dir;
int ret;
pxe_dir = pxe_boot_type(boot_type);
if (!pxe_dir) {
syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n",
__func__, __LINE__);
return -1;
}
ret = get_grub_filename(boot_type, mac, pxe_filename, sizeof(pxe_filename));
if (ret < 0)
return -1;
ret = snprintf(pxe_path, pxe_path_size,
"%s/%s", pxe_dir, pxe_filename);
if (ret >= pxe_path_size) {
syslog(LOG_ERR, "failed to generate pxe file path (%s:%d)\n",
__func__, __LINE__);
return -1;
}
return 0;
}
static int og_remove_tftpboot_file(unsigned int boot_type, const char *mac)
{
char pxe_file_path[PATH_MAX + 1];
int ret;
ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path));
if (ret < 0)
return -1;
if (unlink(pxe_file_path) < 0) {
syslog(LOG_ERR, "failed to delete file (%s:%d) %s\n",
__func__, __LINE__, pxe_file_path);
return -1;
}
return 0;
}
static int og_create_boot_file(unsigned int boot_type, const char *mac,
const char *mode, char *params)
{
char tmp_filename[] = "/tmp/mode_params_XXXXXX";
char pxe_template_path[PATH_MAX + 1];
char pxe_file_path[PATH_MAX + 1];
char cmd_params[16384] = {};
const char *pxe_dir;
int status;
pid_t pid;
int ret;
int fd;
pxe_dir = pxe_boot_type(boot_type);
if (!pxe_dir) {
syslog(LOG_ERR, "Invalid boot type parameter (%s:%d)\n",
__func__, __LINE__);
return -1;
}
snprintf(pxe_template_path, sizeof(pxe_template_path),
"%s/templates/%s", pxe_dir, mode);
ret = get_grub_file_path(boot_type, mac, pxe_file_path, sizeof(pxe_file_path));
if (ret < 0)
return -1;
if (unlink(pxe_file_path) < 0)
syslog(LOG_INFO, "failed to delete file %s (%s:%d)\n",
pxe_file_path, __func__, __LINE__);
snprintf(cmd_params, sizeof(cmd_params),
"DATA='%s'\nTEMPLATE_PATH='%s'\nPXEFILE_PATH='%s'",
params, pxe_template_path, pxe_file_path);
fd = mkstemp(tmp_filename);
if (fd < 0) {
syslog(LOG_ERR, "cannot generate temp file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
return -1;
}
ret = write(fd, cmd_params, strlen(cmd_params) + 1);
close(fd);
if (ret < 0) {
syslog(LOG_ERR, "cannot write file %s: %s (%s:%d)\n",
tmp_filename, strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
pid = fork();
if (pid < 0) {
syslog(LOG_ERR, "fork failed (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
unlink(tmp_filename);
return -1;
}
if (pid == 0) {
execlp("/bin/bash", "/bin/bash",
"/opt/opengnsys/bin/updategrubprofile", tmp_filename, NULL);
syslog(LOG_ERR, "failed script execution (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
_exit(-1);
} else if (waitpid(pid, &status, 0) < 0) {
syslog(LOG_ERR, "waitpid failed (%s:%d) %s\n",
__func__, __LINE__, strerror(errno));
unlink(tmp_filename);
return -1;
}
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
syslog(LOG_ERR, "failed script execution %s (%s:%d)\n",
strerror(errno), __func__, __LINE__);
unlink(tmp_filename);
return -1;
}
unlink(tmp_filename);
return 0;
}
static int og_set_client_mode(struct og_dbi *dbi, const char *mac,
const char *mode)
{
char filename[PATH_MAX + 1] = "/tmp/mode_params_XXXXXX";
char cmd_params[16384] = {};
char params[4096] = "\0";
const char *msglog;
dbi_result result;
unsigned int i;
int numbytes;
int status;
int fd;
if (!og_boot_mode_is_valid(mode)) {
syslog(LOG_ERR, "invalid boot mode in client (%s:%d)\n",
@ -1360,40 +1546,14 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *mac,
dbi_result_free(result);
snprintf(cmd_params, sizeof(cmd_params),
"MODE_FILE='%s'\nMAC='%s'\nDATA='%s'\nMODE='PERM'",
mode, mac, params);
fd = mkstemp(filename);
if (fd < 0) {
syslog(LOG_ERR, "cannot generate temp file (%s:%d)\n",
__func__, __LINE__);
if (og_create_boot_file(OG_TFTP_BOOT_BIOS, mac, mode, params) < 0) {
syslog(LOG_ERR, "failed to create BIOS boot file (%s:%d)\n", __FILE__, __LINE__);
return -1;
}
numbytes = write(fd, cmd_params, strlen(cmd_params) + 1);
close(fd);
if (numbytes < 0) {
syslog(LOG_ERR, "cannot write file\n");
unlink(filename);
return -1;
}
if (fork() == 0) {
execlp("/bin/bash", "/bin/bash",
"/opt/opengnsys/bin/setclientmode", filename, NULL);
syslog(LOG_ERR, "failed script execution (%s:%d)\n",
__func__, __LINE__);
return -1;
} else {
wait(&status);
}
unlink(filename);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
syslog(LOG_ERR, "failed script execution (%s:%d)\n",
__func__, __LINE__);
if (og_create_boot_file(OG_TFTP_BOOT_UEFI, mac, mode, params) < 0) {
og_remove_tftpboot_file(OG_TFTP_BOOT_BIOS, mac);
syslog(LOG_ERR, "failed to create UEFI boot file (%s:%d)\n", __FILE__, __LINE__);
return -1;
}