mirror of https://git.48k.eu/ogserver
Compare commits
35 Commits
Author | SHA1 | Date |
---|---|---|
|
5cecb4f294 | |
|
730d42a872 | |
|
91c042ed61 | |
|
acf9c07236 | |
|
4db69ad054 | |
|
d8b271f503 | |
|
2daa9cdb36 | |
|
41c8dec51c | |
|
31d426b018 | |
|
5e21716afb | |
|
6a63218f85 | |
|
e3188191d9 | |
|
8f52b8911e | |
|
ef3bad6e14 | |
|
da31efb4e0 | |
|
00d54325d3 | |
|
113472d5c0 | |
|
232e6eb308 | |
|
c110bd7d8d | |
|
aebf2281bf | |
|
0ea0394709 | |
|
16baa88541 | |
|
4103945785 | |
|
892a8fa2e5 | |
|
55179decb7 | |
|
1fd62a4850 | |
|
e67cdafb71 | |
|
24e70ac3ff | |
|
bff3d1dc9d | |
|
479998d76f | |
|
83b1be6589 | |
|
16cc22df3e | |
|
2febb50a92 | |
|
e679925bd0 | |
|
e960063a13 |
|
@ -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 \
|
||||
|
|
|
@ -11,6 +11,10 @@
|
|||
"user" : "mysql",
|
||||
"pass" : "mysql"
|
||||
},
|
||||
"samba" : {
|
||||
"user" : "opengnsys",
|
||||
"pass" : "test"
|
||||
},
|
||||
"wol" : {
|
||||
"interface" : "lo"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* 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 oghostname=%s\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 hostname=$oghostname 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->hostname, 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;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _OG_BOOT_H_
|
||||
#define _OG_BOOT_H_
|
||||
|
||||
struct og_boot_cfg {
|
||||
const char *hostname;
|
||||
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_ */
|
31
src/cfg.c
31
src/cfg.c
|
@ -70,6 +70,27 @@ static int parse_json_db(struct og_server_cfg *cfg, json_t *element)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int parse_json_samba(struct og_server_cfg *cfg, json_t *element)
|
||||
{
|
||||
const char *key;
|
||||
json_t *value;
|
||||
|
||||
json_object_foreach(element, key, value) {
|
||||
if (!strcmp(key, "user")) {
|
||||
if (og_json_parse_string(value, &cfg->smb.user) < 0)
|
||||
return -1;
|
||||
} else if (!strcmp(key, "pass")) {
|
||||
if (og_json_parse_string(value, &cfg->smb.pass) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
syslog(LOG_ERR, "unknown key `%s' in samba\n", key);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_json_wol(struct og_server_cfg *cfg, json_t *element)
|
||||
{
|
||||
const char *key;
|
||||
|
@ -110,6 +131,7 @@ static int parse_json_repo(struct og_server_cfg *cfg, json_t *element)
|
|||
#define OG_SERVER_CFG_DB (1 << 1)
|
||||
#define OG_SERVER_CFG_WOL (1 << 2)
|
||||
#define OG_SERVER_CFG_REPO (1 << 3)
|
||||
#define OG_SERVER_CFG_SAMBA (1 << 4)
|
||||
|
||||
int parse_json_config(const char *filename, struct og_server_cfg *cfg)
|
||||
{
|
||||
|
@ -157,6 +179,12 @@ int parse_json_config(const char *filename, struct og_server_cfg *cfg)
|
|||
break;
|
||||
}
|
||||
flags |= OG_SERVER_CFG_DB;
|
||||
} else if (!strcmp(key, "samba")) {
|
||||
if (parse_json_samba(cfg, value) < 0) {
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
flags |= OG_SERVER_CFG_SAMBA;
|
||||
} else if (!strcmp(key, "repository")) {
|
||||
if (parse_json_repo(cfg, value) < 0)
|
||||
return -1;
|
||||
|
@ -181,6 +209,9 @@ int parse_json_config(const char *filename, struct og_server_cfg *cfg)
|
|||
ret = -1;
|
||||
}
|
||||
|
||||
if (!(flags & OG_SERVER_CFG_SAMBA))
|
||||
syslog(LOG_WARNING, "Missing samba configuration in ogserver.json file");
|
||||
|
||||
if (ret < 0)
|
||||
json_decref(root);
|
||||
else
|
||||
|
|
|
@ -11,6 +11,10 @@ struct og_server_cfg {
|
|||
const char *port;
|
||||
const char *api_token;
|
||||
} rest;
|
||||
struct {
|
||||
const char *user;
|
||||
const char *pass;
|
||||
} smb;
|
||||
struct {
|
||||
const char *interface;
|
||||
} wol;
|
||||
|
|
197
src/client.c
197
src/client.c
|
@ -14,6 +14,7 @@
|
|||
#include "list.h"
|
||||
#include "rest.h"
|
||||
#include "json.h"
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <ifaddrs.h>
|
||||
|
@ -557,6 +558,7 @@ static bool og_update_client_disk_info(struct og_dbi *dbi,
|
|||
int disk_part_len = 0;
|
||||
char disk_part[1024];
|
||||
const char *msglog;
|
||||
uint64_t part_code;
|
||||
int i;
|
||||
|
||||
if (serial_number && strlen(serial_number) > 0) {
|
||||
|
@ -617,7 +619,12 @@ static bool og_update_client_disk_info(struct og_dbi *dbi,
|
|||
continue;
|
||||
}
|
||||
|
||||
reported_disk.size = strtoull(disks[i].size, NULL, 0);
|
||||
if (safe_strtoull(disks[i].size, &reported_disk.size, 10, UINT64_MAX) < 0) {
|
||||
syslog(LOG_ERR, "failed to parse disk size for disk %d (%s:%d)\n",
|
||||
i + 1, __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
cur_disk.size = dbi_result_get_longlong(result, "tamano");
|
||||
|
||||
dbi_result_free(result);
|
||||
|
@ -661,8 +668,17 @@ static bool og_update_client_disk_info(struct og_dbi *dbi,
|
|||
return false;
|
||||
}
|
||||
|
||||
reported_part.size = strtoull(partitions[i].size, NULL, 0);
|
||||
reported_part.code = strtoul(partitions[i].code, NULL, 16);
|
||||
if (safe_strtoull(partitions[i].size, &reported_part.size, 10, UINT64_MAX) < 0) {
|
||||
syslog(LOG_ERR, "failed to parse partition size %s for partition %d (%s:%d)\n",
|
||||
partitions[i].size, i + 1, __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
if (safe_strtoull(partitions[i].code, &part_code, 16, UINT32_MAX) < 0) {
|
||||
syslog(LOG_ERR, "failed to parse partition code %s for partition %d (%s:%d)\n",
|
||||
partitions[i].code, i + 1, __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
reported_part.code = part_code;
|
||||
reported_part.filesystem = get_filesystem_id(partitions[i].filesystem);
|
||||
reported_part.used_size = partitions[i].used_size;
|
||||
reported_part.free_size = partitions[i].free_size;
|
||||
|
@ -677,7 +693,7 @@ static bool og_update_client_disk_info(struct og_dbi *dbi,
|
|||
"idordenador, numdisk, numpar, codpar, tamano, uso, "
|
||||
"idsistemafichero, idnombreso, idimagen, "
|
||||
"used_size, free_size)"
|
||||
" VALUES(%d,%s,%s,0x%d,%s,0,%d,%d,0,%lu,%lu)",
|
||||
" VALUES(%d,%s,%s,%d,%s,0,%d,%d,0,%lu,%lu)",
|
||||
computer_id,
|
||||
partitions[i].disk,
|
||||
partitions[i].number,
|
||||
|
@ -833,8 +849,12 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
|
|||
* client using linux/windows mode.
|
||||
*/
|
||||
if (status) {
|
||||
if (!strncmp(status, "LINUX", strlen("LINUX"))) {
|
||||
if (!strncmp(status, "LINUXS", strlen("LINUXS"))) {
|
||||
cli->status = OG_CLIENT_STATUS_LINUX_SESSION;
|
||||
} else if (!strncmp(status, "LINUX", strlen("LINUX"))) {
|
||||
cli->status = OG_CLIENT_STATUS_LINUX;
|
||||
} else if (!strncmp(status, "WINS", strlen("WINS"))) {
|
||||
cli->status = OG_CLIENT_STATUS_WIN_SESSION;
|
||||
} else if (!strncmp(status, "WIN", strlen("WIN"))) {
|
||||
cli->status = OG_CLIENT_STATUS_WIN;
|
||||
}
|
||||
|
@ -890,38 +910,10 @@ static bool og_dbi_update_image(struct og_dbi *dbi,
|
|||
const struct og_image_legacy *img_info,
|
||||
const char *computer_id)
|
||||
{
|
||||
int repo_id, sw_id, repo_alias;
|
||||
const char *msglog;
|
||||
dbi_result result;
|
||||
uint32_t revision;
|
||||
|
||||
/* find repository identifier by repository ip and computer ID. */
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"SELECT repositorios.idrepositorio, repositorios.alias"
|
||||
" FROM repositorios"
|
||||
" LEFT JOIN ordenadores USING (idrepositorio)"
|
||||
" WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s",
|
||||
img_info->repo, computer_id);
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return false;
|
||||
}
|
||||
if (!dbi_result_next_row(result)) {
|
||||
syslog(LOG_ERR,
|
||||
"repository does not exist in database (%s:%d)\n",
|
||||
__func__, __LINE__);
|
||||
dbi_result_free(result);
|
||||
return false;
|
||||
}
|
||||
repo_alias = dbi_result_get_uint(result, "alias");
|
||||
if (repo_alias)
|
||||
repo_id = repo_alias;
|
||||
else
|
||||
repo_id = dbi_result_get_uint(result, "idrepositorio");
|
||||
|
||||
dbi_result_free(result);
|
||||
int sw_id;
|
||||
|
||||
/* find software id by computer ID, disk number and partition. */
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
|
@ -949,11 +941,11 @@ static bool og_dbi_update_image(struct og_dbi *dbi,
|
|||
result = dbi_conn_queryf(dbi->conn,
|
||||
"UPDATE imagenes"
|
||||
" SET idordenador=%s, numdisk=%s, numpar=%s, codpar=%s,"
|
||||
" idperfilsoft=%d, idrepositorio=%d,"
|
||||
" idperfilsoft=%d, "
|
||||
" fechacreacion=NOW(), revision=revision+1"
|
||||
" WHERE idimagen=%s",
|
||||
computer_id, img_info->disk, img_info->part, img_info->code,
|
||||
sw_id, repo_id, img_info->image_id);
|
||||
sw_id, img_info->image_id);
|
||||
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
|
@ -1115,8 +1107,8 @@ static int og_resp_image_create(json_t *data, struct og_client *cli)
|
|||
computer.center);
|
||||
snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
|
||||
software);
|
||||
snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
|
||||
image_id);
|
||||
snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%u",
|
||||
cli->last_cmd.ctx.image.id);
|
||||
snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
|
||||
snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
|
||||
snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
|
||||
|
@ -1132,24 +1124,27 @@ static int og_resp_image_create(json_t *data, struct og_client *cli)
|
|||
soft_legacy.center);
|
||||
if (!res) {
|
||||
og_dbi_close(dbi);
|
||||
syslog(LOG_ERR, "Problem updating client configuration\n");
|
||||
syslog(LOG_ERR, "Problem updating software inventory (%s:%u)\n",
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = og_dbi_update_image(dbi, &img_legacy, soft_legacy.id);
|
||||
if (!res) {
|
||||
og_dbi_close(dbi);
|
||||
syslog(LOG_ERR, "Problem updating client configuration\n");
|
||||
syslog(LOG_ERR, "Problem updating image (%s:%u)\n",
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = update_image_info(dbi, image_id, clonator, compressor,
|
||||
res = update_image_info(dbi, img_legacy.image_id, clonator, compressor,
|
||||
filesystem, datasize, size, lastupdate, perms,
|
||||
checksum);
|
||||
og_dbi_close(dbi);
|
||||
|
||||
if (res) {
|
||||
syslog(LOG_ERR, "Problem updating image info\n");
|
||||
syslog(LOG_ERR, "Problem updating image (%s:%u)\n",
|
||||
__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1159,37 +1154,17 @@ static int og_resp_image_create(json_t *data, struct og_client *cli)
|
|||
static int og_resp_image_restore(json_t *data, struct og_client *cli)
|
||||
{
|
||||
struct og_software_legacy soft_legacy;
|
||||
uint32_t disk, partition, image_id;
|
||||
struct og_image_legacy img_legacy;
|
||||
struct og_computer computer = {};
|
||||
const char *partition = NULL;
|
||||
const char *image_id = NULL;
|
||||
const char *disk = NULL;
|
||||
const char *msglog;
|
||||
struct og_dbi *dbi;
|
||||
dbi_result result;
|
||||
const char *key;
|
||||
json_t *value;
|
||||
int err = 0;
|
||||
|
||||
if (json_typeof(data) != JSON_OBJECT)
|
||||
return -1;
|
||||
|
||||
json_object_foreach(data, key, value) {
|
||||
if (!strcmp(key, "partition"))
|
||||
err = og_json_parse_string(value, &partition);
|
||||
else if (!strcmp(key, "disk"))
|
||||
err = og_json_parse_string(value, &disk);
|
||||
else if (!strcmp(key, "image_id"))
|
||||
err = og_json_parse_string(value, &image_id);
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!partition || !disk || !image_id) {
|
||||
syslog(LOG_ERR, "malformed response json\n");
|
||||
return -1;
|
||||
}
|
||||
err = og_resp_refresh(data, cli);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dbi = og_dbi_open(&ogconfig.db);
|
||||
if (!dbi) {
|
||||
|
@ -1198,9 +1173,13 @@ static int og_resp_image_restore(json_t *data, struct og_client *cli)
|
|||
return -1;
|
||||
}
|
||||
|
||||
image_id = cli->last_cmd.ctx.image_restore.id;
|
||||
partition = cli->last_cmd.ctx.image_restore.part;
|
||||
disk = cli->last_cmd.ctx.image_restore.disk;
|
||||
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"SELECT idperfilsoft FROM imagenes "
|
||||
" WHERE idimagen='%s'", image_id);
|
||||
" WHERE idimagen='%u'", image_id);
|
||||
if (!result) {
|
||||
og_dbi_close(dbi);
|
||||
syslog(LOG_ERR, "failed to query database\n");
|
||||
|
@ -1209,7 +1188,8 @@ static int og_resp_image_restore(json_t *data, struct og_client *cli)
|
|||
if (!dbi_result_next_row(result)) {
|
||||
dbi_result_free(result);
|
||||
og_dbi_close(dbi);
|
||||
syslog(LOG_ERR, "software profile does not exist in database\n");
|
||||
syslog(LOG_ERR, "software profile for image id %u does not exist in database\n",
|
||||
image_id);
|
||||
return -1;
|
||||
}
|
||||
snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
|
||||
|
@ -1222,20 +1202,19 @@ static int og_resp_image_restore(json_t *data, struct og_client *cli)
|
|||
return -1;
|
||||
}
|
||||
|
||||
snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
|
||||
snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%u",
|
||||
image_id);
|
||||
snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
|
||||
snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
|
||||
snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
|
||||
snprintf(img_legacy.part, sizeof(img_legacy.part), "%u", partition);
|
||||
snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%u", disk);
|
||||
snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%u", computer.id);
|
||||
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"UPDATE ordenadores_particiones"
|
||||
" SET idimagen=%s, idperfilsoft=%s, fechadespliegue=NOW(),"
|
||||
" revision=(SELECT revision FROM imagenes WHERE idimagen=%s),"
|
||||
" idnombreso=IFNULL((SELECT idnombreso FROM perfilessoft WHERE idperfilsoft=%s),0)"
|
||||
" revision=(SELECT revision FROM imagenes WHERE idimagen=%s)"
|
||||
" WHERE idordenador=%s AND numdisk=%s AND numpar=%s",
|
||||
img_legacy.image_id, img_legacy.software_id,
|
||||
img_legacy.image_id, img_legacy.software_id,
|
||||
img_legacy.image_id,
|
||||
soft_legacy.id, img_legacy.disk, img_legacy.part);
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
|
@ -1274,11 +1253,9 @@ static int og_agent_http_response_code(const char *buf)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int og_clear_image_placeholder()
|
||||
static int og_resp_image_create_error(struct og_client *cli)
|
||||
{
|
||||
uint32_t image_id = 0;
|
||||
struct og_dbi *dbi;
|
||||
dbi_result result;
|
||||
|
||||
dbi = og_dbi_open(&ogconfig.db);
|
||||
if (!dbi) {
|
||||
|
@ -1287,26 +1264,9 @@ static int og_clear_image_placeholder()
|
|||
return -1;
|
||||
}
|
||||
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"SELECT idimagen FROM imagenes WHERE fechacreacion IS NULL");
|
||||
if (!result) {
|
||||
syslog(LOG_ERR, "failed to query database\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!dbi_result_next_row(result)) {
|
||||
dbi_result_free(result);
|
||||
og_dbi_close(dbi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
image_id = dbi_result_get_uint(result, "idimagen");
|
||||
dbi_result_free(result);
|
||||
|
||||
syslog(LOG_INFO, "Trying to delete uninitialized image with id %d\n", image_id);
|
||||
|
||||
if (og_dbi_delete_image(dbi, image_id) < 0) {
|
||||
og_dbi_close(dbi);
|
||||
if (og_dbi_delete_image(dbi, cli->last_cmd.ctx.image.id) < 0) {
|
||||
syslog(LOG_WARNING, "Cannot delete image stub with id %d\n",
|
||||
cli->last_cmd.ctx.image.id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1314,9 +1274,16 @@ static int og_clear_image_placeholder()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void og_client_reset_cmd(struct og_client *cli)
|
||||
{
|
||||
cli->last_cmd.id = 0;
|
||||
cli->last_cmd.type = OG_CMD_UNSPEC;
|
||||
memset(&cli->last_cmd.ctx, 0, sizeof(cli->last_cmd.ctx));
|
||||
}
|
||||
|
||||
int og_agent_state_process_response(struct og_client *cli)
|
||||
{
|
||||
enum og_cmd_type cmd_type = cli->last_cmd;
|
||||
enum og_cmd_type cmd_type = cli->last_cmd.type;
|
||||
int ret, err = -1, code;
|
||||
json_error_t json_err;
|
||||
bool success;
|
||||
|
@ -1343,7 +1310,7 @@ int og_agent_state_process_response(struct og_client *cli)
|
|||
case 500:
|
||||
ret = 0;
|
||||
success = false;
|
||||
cli->last_cmd = OG_CMD_UNSPEC;
|
||||
cli->last_cmd.type = OG_CMD_UNSPEC;
|
||||
syslog(LOG_ERR, "Client %s:%hu reports failure to process command\n",
|
||||
inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port));
|
||||
/* ... cancel pending actions related to this task for this client here */
|
||||
|
@ -1363,21 +1330,25 @@ int og_agent_state_process_response(struct og_client *cli)
|
|||
}
|
||||
|
||||
if (success)
|
||||
cli->last_cmd_result = OG_SUCCESS;
|
||||
cli->last_cmd.result = OG_SUCCESS;
|
||||
else
|
||||
cli->last_cmd_result = OG_FAILURE;
|
||||
cli->last_cmd.result = OG_FAILURE;
|
||||
|
||||
if (!success && cmd_type == OG_CMD_IMAGE_CREATE)
|
||||
og_clear_image_placeholder();
|
||||
if (!success && cmd_type == OG_CMD_IMAGE_CREATE) {
|
||||
syslog(LOG_ERR, "Client %s:%hu reports failure when creating image with id %d\n",
|
||||
inet_ntoa(cli->addr.sin_addr), ntohs(cli->addr.sin_port),
|
||||
cli->last_cmd.ctx.image.id);
|
||||
og_resp_image_create_error(cli);
|
||||
}
|
||||
|
||||
if (code != 200 && code != 103) {
|
||||
cli->last_cmd_id = 0;
|
||||
cli->last_cmd.id = 0;
|
||||
memset(&cli->last_cmd.ctx, 0, sizeof(cli->last_cmd.ctx));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!cli->content_length) {
|
||||
cli->last_cmd_id = 0;
|
||||
cli->last_cmd = OG_CMD_UNSPEC;
|
||||
og_client_reset_cmd(cli);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1396,7 +1367,7 @@ int og_agent_state_process_response(struct og_client *cli)
|
|||
return err;
|
||||
}
|
||||
|
||||
switch (cli->last_cmd) {
|
||||
switch (cli->last_cmd.type) {
|
||||
case OG_CMD_SHELL_RUN:
|
||||
err = og_resp_shell_run(cli, root);
|
||||
break;
|
||||
|
@ -1413,6 +1384,11 @@ int og_agent_state_process_response(struct og_client *cli)
|
|||
err = og_resp_refresh(root, cli);
|
||||
break;
|
||||
case OG_CMD_IMAGE_CREATE:
|
||||
err = og_resp_image_create(root, cli);
|
||||
if (err < 0)
|
||||
og_resp_image_create_error(cli);
|
||||
break;
|
||||
case OG_CMD_IMAGE_UPDATE:
|
||||
err = og_resp_image_create(root, cli);
|
||||
break;
|
||||
case OG_CMD_IMAGE_RESTORE:
|
||||
|
@ -1436,12 +1412,11 @@ int og_agent_state_process_response(struct og_client *cli)
|
|||
if (err < 0) {
|
||||
err = 0;
|
||||
success = false;
|
||||
cli->last_cmd_result = OG_FAILURE;
|
||||
cli->last_cmd.result = OG_FAILURE;
|
||||
/* ... cancel pending actions related to this task for this client here */
|
||||
}
|
||||
|
||||
cli->last_cmd_id = 0;
|
||||
cli->last_cmd = OG_CMD_UNSPEC;
|
||||
og_client_reset_cmd(cli);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
11
src/core.c
11
src/core.c
|
@ -281,7 +281,7 @@ static void og_agent_send_refresh(struct og_client *cli)
|
|||
params.ips_array[0] = inet_ntoa(cli->addr.sin_addr);
|
||||
params.ips_array_len = 1;
|
||||
|
||||
og_send_request(OG_METHOD_GET, OG_CMD_REFRESH, ¶ms, NULL);
|
||||
og_send_request(OG_METHOD_GET, OG_CMD_REFRESH, ¶ms, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Shut down connection if there is no complete message after 10 seconds. */
|
||||
|
@ -367,6 +367,7 @@ void og_server_accept_cb(struct ev_loop *loop, struct ev_io *io, int events)
|
|||
int og_socket_server_init(const char *addr, const char *port)
|
||||
{
|
||||
struct sockaddr_in local;
|
||||
uint64_t port_num;
|
||||
uint32_t s_addr;
|
||||
int sd, on = 1;
|
||||
|
||||
|
@ -384,7 +385,13 @@ int og_socket_server_init(const char *addr, const char *port)
|
|||
|
||||
local.sin_addr.s_addr = s_addr;
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_port = htons(atoi(port));
|
||||
|
||||
if (safe_strtoull(port, &port_num, 10, UINT16_MAX) < 0) {
|
||||
syslog(LOG_ERR, "failed to parse port %s (%s:%d)\n",
|
||||
port, __func__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
local.sin_port = htons(port_num);
|
||||
|
||||
if (bind(sd, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||
close(sd);
|
||||
|
|
|
@ -75,7 +75,6 @@ struct og_msg_params {
|
|||
const char *cache;
|
||||
const char *cache_size;
|
||||
const char *comment;
|
||||
bool echo;
|
||||
struct og_partition partition_setup[OG_PARTITION_MAX];
|
||||
struct og_image image;
|
||||
uint64_t flags;
|
||||
|
@ -83,8 +82,6 @@ struct og_msg_params {
|
|||
};
|
||||
|
||||
int og_json_parse_partition_setup(json_t *element, struct og_msg_params *params);
|
||||
int og_json_parse_create_image(json_t *element, struct og_msg_params *params);
|
||||
int og_json_parse_restore_image(json_t *element, struct og_msg_params *params);
|
||||
|
||||
struct og_cmd_json {
|
||||
const char *type;
|
||||
|
|
|
@ -575,7 +575,7 @@ bool cuestionPerfilSoftware(struct og_dbi *dbi, char *idc, char *ido,
|
|||
if (idperfilsoftware != nwidperfilsoft) { // No coinciden los perfiles
|
||||
// Actualiza el identificador del perfil software del ordenador
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"UPDATE ordenadores_particiones SET idperfilsoft=%d,idimagen=0"
|
||||
"UPDATE ordenadores_particiones SET idperfilsoft=%d"
|
||||
" WHERE idordenador=%s AND numpar=%s", nwidperfilsoft, ido, par);
|
||||
if (!result) { // Error al insertar
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
|
|
1853
src/rest.c
1853
src/rest.c
File diff suppressed because it is too large
Load Diff
27
src/rest.h
27
src/rest.h
|
@ -51,6 +51,19 @@ enum og_cmd_result {
|
|||
OG_SUCCESS = 2,
|
||||
};
|
||||
|
||||
struct og_cmd_ctx {
|
||||
union {
|
||||
struct {
|
||||
uint32_t id;
|
||||
} image;
|
||||
struct {
|
||||
uint32_t id;
|
||||
uint32_t disk;
|
||||
uint32_t part;
|
||||
} image_restore;
|
||||
};
|
||||
};
|
||||
|
||||
#define OG_MSG_REQUEST_MAXLEN 131072
|
||||
|
||||
struct og_client {
|
||||
|
@ -66,9 +79,12 @@ struct og_client {
|
|||
int content_length;
|
||||
char auth_token[64];
|
||||
enum og_client_status status;
|
||||
enum og_cmd_type last_cmd;
|
||||
unsigned int last_cmd_id;
|
||||
enum og_cmd_result last_cmd_result;
|
||||
struct {
|
||||
enum og_cmd_type type;
|
||||
unsigned int id;
|
||||
enum og_cmd_result result;
|
||||
struct og_cmd_ctx ctx;
|
||||
} last_cmd;
|
||||
uint32_t speed;
|
||||
uint32_t seq;
|
||||
struct {
|
||||
|
@ -131,7 +147,10 @@ enum og_rest_uri {
|
|||
OG_URI_CACHE_FETCH,
|
||||
OG_URI_PART_SETUP,
|
||||
OG_URI_OGLIVE_LIST,
|
||||
OG_URI_OGLIVE_ADD,
|
||||
OG_URI_OGLIVE_DELETE,
|
||||
OG_URI_OGLIVE_SET,
|
||||
OG_URI_OGLIVE_DEFAULT,
|
||||
OG_URI_CENTER_ADD,
|
||||
OG_URI_CENTER_UPDATE,
|
||||
OG_URI_CENTER_DELETE,
|
||||
|
@ -157,7 +176,7 @@ enum og_rest_method {
|
|||
|
||||
int og_send_request(enum og_rest_method method, enum og_cmd_type type,
|
||||
const struct og_msg_params *params,
|
||||
const json_t *data);
|
||||
const json_t *data, const struct og_cmd_ctx *ctx);
|
||||
|
||||
int og_dbi_scope_get(struct og_dbi *dbi, json_t *array);
|
||||
|
||||
|
|
71
src/schema.c
71
src/schema.c
|
@ -464,6 +464,75 @@ static int og_dbi_schema_v11(struct og_dbi *dbi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int og_dbi_schema_v12(struct og_dbi *dbi)
|
||||
{
|
||||
const char *msglog;
|
||||
dbi_result result;
|
||||
|
||||
syslog(LOG_DEBUG, "Creating table oglive\n");
|
||||
result = dbi_conn_query(dbi->conn, "CREATE TABLE `oglive` ("
|
||||
"`id` BIGINT NOT NULL AUTO_INCREMENT,"
|
||||
"`name` VARCHAR(100),"
|
||||
"`creation_date` DATETIME NOT NULL,"
|
||||
"`is_default` BOOLEAN NOT NULL,"
|
||||
"PRIMARY KEY (`id`)"
|
||||
")");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Error when creating oglive (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 12");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int og_dbi_schema_v13(struct og_dbi *dbi)
|
||||
{
|
||||
const char *msglog;
|
||||
dbi_result result;
|
||||
|
||||
syslog(LOG_DEBUG, "Updating table oglive\n");
|
||||
result = dbi_conn_query(dbi->conn, "ALTER TABLE `oglive` DROP COLUMN `is_default`");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Error deleting column is_default in oglive table (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
result = dbi_conn_query(dbi->conn, "ALTER TABLE `oglive` ADD COLUMN `priority` INT NOT NULL DEFAULT 0");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Error adding column priority to oglive table (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 13");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct og_schema_version {
|
||||
int version;
|
||||
int (*update)(struct og_dbi *dbi);
|
||||
|
@ -479,6 +548,8 @@ static struct og_schema_version {
|
|||
{ .version = 9, .update = og_dbi_schema_v9, },
|
||||
{ .version = 10, .update = og_dbi_schema_v10,},
|
||||
{ .version = 11, .update = og_dbi_schema_v11,},
|
||||
{ .version = 12, .update = og_dbi_schema_v12,},
|
||||
{ .version = 13, .update = og_dbi_schema_v13,},
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
|
|
28
src/utils.c
28
src/utils.c
|
@ -7,7 +7,12 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include "utils.h"
|
||||
|
||||
void str_toupper(char *str)
|
||||
|
@ -29,3 +34,26 @@ void str_tolower(char *str)
|
|||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
int safe_strtoull(const char *str, uint64_t *out_value, int base, uint64_t max)
|
||||
{
|
||||
char *endptr = NULL;
|
||||
uint64_t result;
|
||||
errno = 0;
|
||||
|
||||
assert(str != NULL && out_value != NULL);
|
||||
|
||||
if (str[0] == '-')
|
||||
return -1;
|
||||
|
||||
result = strtoull(str, &endptr, base);
|
||||
|
||||
if (endptr == str ||
|
||||
*endptr != '\0' ||
|
||||
(errno == ERANGE && result == ULLONG_MAX) ||
|
||||
result > max)
|
||||
return -1;
|
||||
|
||||
*out_value = result;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef _OG_UTILS_H
|
||||
#define _OG_UTILS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void str_toupper(char *str);
|
||||
void str_tolower(char *str);
|
||||
int safe_strtoull(const char *str, uint64_t *out_value, int base, uint64_t max);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue