summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOpenGnSys Support Team <soporte-og@soleta.eu>2024-11-21 14:36:20 +0100
committerOpenGnSys Support Team <soporte-og@soleta.eu>2024-11-25 12:18:34 +0100
commit113472d5c0115d53d2fb99288759502d196a8e93 (patch)
tree7e3d77cedb5afb1f505d3df51848f79dda37db0a
parent232e6eb30830eb74aac63e22e766f0f0848fb878 (diff)
src: add built-in ogrelive grub2 boot mode templateHEADv1.2.5-26master
Add built-in ogrelive grub2 boot mode template and use it to generate the grub2 boot file for each computer for the new live system. Use grub2 http to download vmlinuz, initrd.img. Use live support to download filesystem.squashfs through http. check for vmlinuz in cache, as usual, otherwise fallback to network boot.
-rw-r--r--Makefile.am1
-rw-r--r--src/boot.c119
-rw-r--r--src/boot.h14
-rw-r--r--src/rest.c59
4 files changed, 181 insertions, 12 deletions
diff --git a/Makefile.am b/Makefile.am
index 159f85c..cf0c7b5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,6 +3,7 @@ sbin_PROGRAMS = ogserver
AM_CFLAGS = ${LIBDBI_CFLAGS} ${LIBJANSSON_CFLAGS} ${LIBEVENT_CFLAGS} -g -Wall
ogserver_SOURCES= src/ogAdmServer.c \
+ src/boot.c \
src/cfg.c \
src/core.c \
src/dbi.c \
diff --git a/src/boot.c b/src/boot.c
new file mode 100644
index 0000000..c58f332
--- /dev/null
+++ b/src/boot.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2020-2024 Soleta Networks <info@soleta.eu>
+ *
+ * This program is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Affero General Public License as published by the
+ * Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include "boot.h"
+#include "utils.h"
+
+#define OGRELIVE_TEMPLATE \
+"# Autogenerated by ogserver on %s - do not edit this file!\n" \
+"set ogserver=%s\n" \
+"set ogrepo=%s\n" \
+"set ogreliveversion=%s\n" \
+"set ogrelivedir=ogrelive/$ogreliveversion\n" \
+"set username=%s\n" \
+"set passwd=%s\n" \
+"\n" \
+"set timeout=0\n" \
+"set timeout_style=hidden\n" \
+"\n" \
+"echo \"checking for vmlinuz in cache...\"\n" \
+"set root=''\n" \
+"search --file --set root /boot/$ogreliveversion/vmlinuz\n" \
+"if [ \"$root\" == \"\" ]; then\n" \
+" echo \"no vmlinuz found in cache, booting from network\"\n" \
+" set default=1;\n" \
+"else\n" \
+" echo \"vmlinuz found, booting from cache\"\n" \
+" set default=0;\n" \
+"fi\n" \
+"\n" \
+"menuentry \"ogReLive HTTP boot\" {\n" \
+" insmod http\n" \
+" insmod net\n" \
+" net_bootp\n" \
+" linux (http,$ogrepo)/$ogrelivedir/vmlinuz ro boot=live quiet splash oglivedir=$ogrelivedir ip=$ogserver ogrepo=$ogrepo username=$username passwd=$passwd fetch=http://$ogrepo/$ogrelivedir/filesystem.squashfs\n" \
+" initrd (http,$ogrepo)/$ogrelivedir/initrd.img\n" \
+" boot\n" \
+"}\n"
+
+/* Same as OG_TFTP_BOOT_UEFI. */
+#define OG_BOOT_GRUB_DIR "/opt/opengnsys/tftpboot/grub"
+
+static void ogrelive_grub2_file_path(char *grub2_filename,
+ size_t grub2_filename_size,
+ const char *mac)
+{
+ snprintf(grub2_filename, grub2_filename_size,
+ OG_BOOT_GRUB_DIR"/01-%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ mac[6], mac[7], mac[8], mac[9], mac[10], mac[11]);
+ str_tolower(grub2_filename);
+}
+
+int ogrelive_generate_grub2_file(const struct og_boot_cfg *cfg, const char *mac)
+{
+ char grub2_tmp_filename[] = "/tmp/grub_template_XXXXXX";
+ char grub2_filename[FILENAME_MAX] = {};
+ time_t now = time(NULL);
+ char *date;
+ FILE *fp;
+ int fd;
+
+ date = asctime(localtime(&now));
+ date[strlen(date) - 1] = '\0';
+
+ fd = mkstemp(grub2_tmp_filename);
+ if (fd < 0) {
+ syslog(LOG_ERR, "Cannot open %s to %s (%s:%u)\n",
+ grub2_tmp_filename, grub2_filename, __FILE__, __LINE__);
+ return -1;
+ }
+
+ fp = fdopen(fd, "w+");
+ if (!fp) {
+ close(fd);
+ syslog(LOG_ERR, "Cannot open %s to %s (%s:%u)\n",
+ grub2_tmp_filename, grub2_filename, __FILE__, __LINE__);
+ return -1;
+ }
+
+ fprintf(fp, OGRELIVE_TEMPLATE, date,
+ cfg->ogserver, cfg->ogrepo, cfg->ogrelivedir, cfg->username, cfg->passwd);
+
+ fclose(fp);
+
+ if (unlink(grub2_filename) < 0) {
+ if (errno != ENOENT) {
+ syslog(LOG_ERR, "Failed to delete %s (%s:%u)\n",
+ grub2_filename, __FILE__, __LINE__);
+ return -1;
+ }
+ }
+
+ ogrelive_grub2_file_path(grub2_filename, sizeof(grub2_filename), mac);
+
+ if (rename(grub2_tmp_filename, grub2_filename) < 0) {
+ unlink(grub2_tmp_filename);
+ syslog(LOG_ERR, "Failed to rename %s to %s (%s:%u)\n",
+ grub2_tmp_filename, grub2_filename, __FILE__, __LINE__);
+ return -1;
+ }
+
+ chmod(grub2_filename, 0644);
+
+ return 0;
+}
diff --git a/src/boot.h b/src/boot.h
new file mode 100644
index 0000000..4e3ff45
--- /dev/null
+++ b/src/boot.h
@@ -0,0 +1,14 @@
+#ifndef _OG_BOOT_H_
+#define _OG_BOOT_H_
+
+struct og_boot_cfg {
+ const char *ogserver;
+ const char *ogrepo;
+ const char *ogrelivedir;
+ const char *username;
+ const char *passwd;
+};
+
+int ogrelive_generate_grub2_file(const struct og_boot_cfg *cfg, const char *mac);
+
+#endif /* _OG_BOOT_H_ */
diff --git a/src/rest.c b/src/rest.c
index 336c65d..db6f829 100644
--- a/src/rest.c
+++ b/src/rest.c
@@ -16,6 +16,7 @@
#include "wol.h"
#include "cfg.h"
#include "repo.h"
+#include "boot.h"
#include <ev.h>
#include <syslog.h>
#include <sys/ioctl.h>
@@ -1168,6 +1169,16 @@ static int og_get_boot_modes(struct list_head *boot_mode_list)
}
closedir(d);
+ /* ogrelive built-in grub2 template. */
+ mode = calloc(1, sizeof(struct og_boot_mode));
+ if (!mode) {
+ og_boot_mode_free(boot_mode_list);
+ return -1;
+ }
+
+ snprintf(mode->name, FILENAME_MAX, "ogrelive");
+ list_add_tail(&mode->list, boot_mode_list);
+
return 0;
}
@@ -1657,20 +1668,44 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *client_ip,
return -1;
}
- if (og_get_client_mode_params(dbi, mac, params, sizeof(params)) < 0) {
- syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__);
- return -1;
- }
+ if (!strcmp(mode, "ogrelive")) {
+ struct og_boot_mode_params boot_params = {};
+ struct og_boot_cfg boot_cfg = {};
- 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;
- }
+ if (og_boot_params_find(dbi, &boot_params, mac) < 0) {
+ syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__);
+ return -1;
+ }
- 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;
+ boot_cfg.ogserver = boot_params.server_ip;
+ boot_cfg.ogrepo = boot_params.repo_ip;
+ boot_cfg.ogrelivedir = boot_params.oglivedir;
+ boot_cfg.username = "opengnsys";
+ boot_cfg.passwd = ogconfig.db.pass;
+
+ if (ogrelive_generate_grub2_file(&boot_cfg, mac) < 0) {
+ syslog(LOG_ERR, "failed to create HTTP boot file (%s:%d)\n", __FILE__, __LINE__);
+ og_boot_params_free(&boot_params);
+ return -1;
+ }
+
+ og_boot_params_free(&boot_params);
+ } else {
+ if (og_get_client_mode_params(dbi, mac, params, sizeof(params)) < 0) {
+ syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__);
+ return -1;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
}
if (og_change_db_mode(dbi, mac, mode) < 0) {