mirror of https://git.48k.eu/ogserver
Compare commits
24 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 |
|
@ -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;
|
||||
|
|
59
src/client.c
59
src/client.c
|
@ -673,7 +673,7 @@ static bool og_update_client_disk_info(struct og_dbi *dbi,
|
|||
partitions[i].size, i + 1, __func__, __LINE__);
|
||||
return false;
|
||||
}
|
||||
if (safe_strtoull(partitions[i].code, &part_code, 32, UINT32_MAX) < 0) {
|
||||
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;
|
||||
|
@ -693,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,
|
||||
|
@ -849,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;
|
||||
}
|
||||
|
@ -1150,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);
|
||||
|
||||
err = og_resp_refresh(data, cli);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!partition || !disk || !image_id) {
|
||||
syslog(LOG_ERR, "malformed response json\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbi = og_dbi_open(&ogconfig.db);
|
||||
if (!dbi) {
|
||||
|
@ -1189,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");
|
||||
|
@ -1200,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),
|
||||
|
@ -1213,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);
|
||||
|
@ -1400,6 +1388,9 @@ int og_agent_state_process_response(struct og_client *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:
|
||||
err = og_resp_image_restore(root, cli);
|
||||
if (!err)
|
||||
|
|
|
@ -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);
|
||||
|
|
1719
src/rest.c
1719
src/rest.c
File diff suppressed because it is too large
Load Diff
|
@ -56,6 +56,11 @@ struct og_cmd_ctx {
|
|||
struct {
|
||||
uint32_t id;
|
||||
} image;
|
||||
struct {
|
||||
uint32_t id;
|
||||
uint32_t disk;
|
||||
uint32_t part;
|
||||
} image_restore;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -142,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,
|
||||
|
|
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 },
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue