rest: remove scheduler code

Put ogserver into diet, remove this feature, including pending command queue.
master
OpenGnSys Support Team 2024-09-17 17:21:14 +02:00
parent 32b9a53f57
commit ad31c3832d
15 changed files with 439 additions and 3827 deletions

View File

@ -7,13 +7,12 @@ ogserver_SOURCES= src/ogAdmServer.c \
src/core.c \
src/dbi.c \
src/main.c \
src/schedule.c \
src/schema.c \
src/utils.c \
src/repo.c \
src/rest.c \
src/scope.c \
src/client.c \
src/json.c \
src/ogAdmLib.c \
src/wol.c \
src/legacy.c
src/wol.c

View File

@ -14,7 +14,6 @@
#include "list.h"
#include "rest.h"
#include "json.h"
#include "schedule.h"
#include <syslog.h>
#include <sys/ioctl.h>
#include <ifaddrs.h>
@ -371,30 +370,6 @@ static int og_json_parse_partition_array(json_t *value,
return 0;
}
static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
{
struct og_task dummy_task = {
.scope = computer_id,
.type_scope = AMBITO_ORDENADORES,
.procedure_id = proc_id,
};
struct og_dbi *dbi;
dbi = og_dbi_open(&ogconfig.db);
if (!dbi) {
syslog(LOG_ERR, "cannot open connection database "
"(%s:%d)\n", __func__, __LINE__);
return -1;
}
if (og_dbi_queue_procedure(dbi, &dummy_task)) {
og_dbi_close(dbi);
return -1;
}
og_dbi_close(dbi);
return 0;
}
static int og_update_cache_info(struct og_dbi *dbi, struct list_head *cache_list, int clientid)
{
struct og_cache_image *cache_image;
@ -651,13 +626,6 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
goto err_out;
}
if (!cli->autorun && computer.procedure_id) {
cli->autorun = true;
if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
goto err_out;
}
og_cache_image_free(&cache_list);
og_boot_entry_free(&boot_entry_list);
return 0;
@ -1108,13 +1076,11 @@ int og_agent_state_process_response(struct og_client *cli)
cli->last_cmd_result = OG_FAILURE;
if (code != 200 && code != 103) {
og_dbi_update_action(cli->last_cmd_id, success);
cli->last_cmd_id = 0;
return ret;
}
if (!cli->content_length) {
og_dbi_update_action(cli->last_cmd_id, true);
cli->last_cmd_id = 0;
cli->last_cmd = OG_CMD_UNSPEC;
return 0;
@ -1182,7 +1148,6 @@ int og_agent_state_process_response(struct og_client *cli)
/* ... cancel pending actions related to this task for this client here */
}
og_dbi_update_action(cli->last_cmd_id, success);
cli->last_cmd_id = 0;
cli->last_cmd = OG_CMD_UNSPEC;

View File

@ -15,7 +15,6 @@
#include "wol.h"
#include "client.h"
#include "json.h"
#include "schedule.h"
#include <syslog.h>
#include <sys/ioctl.h>
#include <ifaddrs.h>
@ -207,30 +206,6 @@ static void og_agent_reset_state(struct og_client *cli)
#define OG_AGENT_CMD_TIMEOUT 900
static void og_agent_deliver_pending_cmd(struct og_client *cli)
{
struct timeval now, elapsed;
const struct og_cmd *cmd;
cmd = og_cmd_find(inet_ntoa(cli->addr.sin_addr));
if (!cmd)
return;
gettimeofday(&now, NULL);
timersub(&now, &cmd->tv, &elapsed);
if (elapsed.tv_sec >= OG_AGENT_CMD_TIMEOUT) {
og_dbi_update_action(cmd->id, false);
og_cmd_free(cmd);
return;
}
json_incref(cmd->json);
og_send_request(cmd->method, cmd->type, &cmd->params, cmd->json);
cli->last_cmd_id = cmd->id;
og_cmd_free(cmd);
}
static void og_agent_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
{
struct og_client *cli;
@ -270,11 +245,8 @@ static void og_agent_read_cb(struct ev_loop *loop, struct ev_io *io, int events)
/* fall through. */
case OG_AGENT_PROCESSING_RESPONSE:
ret = og_agent_state_process_response(cli);
if (ret < 0) {
if (ret < 0)
goto close;
} else if (ret == 0) {
og_agent_deliver_pending_cmd(cli);
}
og_agent_reset_state(cli);
break;

View File

@ -4,6 +4,7 @@
#include <dbi/dbi.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <stdint.h>
struct og_dbi_config {
const char *user;

View File

@ -9,6 +9,7 @@
#include "json.h"
#include <stdint.h>
#include <string.h>
int og_json_parse_string(const json_t *element, const char **str)
{

View File

@ -3,7 +3,9 @@
#include <jansson.h>
#include <stdint.h>
#include "schedule.h"
#include <stdbool.h>
#include "list.h"
#include "dbi.h"
int og_json_parse_string(const json_t *element, const char **str);
int og_json_parse_string_copy(const json_t *element, char *str, size_t size);
@ -41,21 +43,6 @@ int og_json_parse_partition(json_t *element, struct og_partition *part,
#define OG_CLIENTS_MAX 4096
struct og_sync_params {
const char *sync;
const char *diff;
const char *remove;
const char *compress;
const char *cleanup;
const char *cache;
const char *cleanup_cache;
const char *remove_dst;
const char *diff_id;
const char *diff_name;
const char *path;
const char *method;
};
#define OG_PARAM_SCOPE_ID (1UL << 0)
#define OG_PARAM_SCOPE_TYPE (1UL << 1)
@ -87,10 +74,7 @@ struct og_msg_params {
const char *comment;
bool echo;
struct og_partition partition_setup[OG_PARTITION_MAX];
struct og_sync_params sync_setup;
struct og_schedule_time time;
struct og_image image;
const char *task_id;
struct og_image image;
uint64_t flags;
bool backup;
};

View File

@ -1,278 +0,0 @@
/*
* Copyright (C) 2020-2021 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 <jansson.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <syslog.h>
#include "json.h"
#include "rest.h"
#include "legacy.h"
#define LEGACY_CMD_MAX 4096
static const char *og_cmd_wol_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
const json_t *root = cmd->json;
const char *wol_type;
uint32_t type;
int len;
wol_type = json_string_value(json_object_get(root, "type"));
if (!wol_type)
return NULL;
if (!strcmp(wol_type, "broadcast"))
type = 1;
else
type = 2;
len = snprintf(legacy_cmd, sizeof(legacy_cmd), "nfn=Arrancar\rmar=%u", type);
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_poweroff_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
int len;
len = snprintf(legacy_cmd, sizeof(legacy_cmd), "nfn=Apagar");
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_reboot_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
int len;
len = snprintf(legacy_cmd, sizeof(legacy_cmd), "nfn=Reiniciar");
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_session_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
const json_t *root = cmd->json;
const char *dsk, *par;
int len;
dsk = json_string_value(json_object_get(root, "disk"));
if (!dsk)
return NULL;
par = json_string_value(json_object_get(root, "part"));
if (!par)
return NULL;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=IniciarSesion\rdsk=%s\rpar=%s",
dsk, par);
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_software_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
const json_t *root = cmd->json;
const char *dsk, *par;
int len;
dsk = json_string_value(json_object_get(root, "disk"));
if (!dsk)
return NULL;
par = json_string_value(json_object_get(root, "partition"));
if (!par)
return NULL;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=InventarioSoftware\rdsk=%s\rpar=%s",
dsk, par);
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_hardware_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
int len;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=InventarioHardware");
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_shell_run_to_legacy(struct og_cmd_json *cmd)
{
const json_t *root = cmd->json;
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
const char *scp;
int len;
scp = json_string_value(json_object_get(root, "run"));
if (!scp)
return NULL;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=EjecutarScript\rscp=%s", scp);
if (len >= (int)sizeof(legacy_cmd)) {
syslog(LOG_ERR, "script payload too large (%s:%d)\n",
__func__, __LINE__);
return NULL;
}
return strdup(legacy_cmd);
}
static char *og_cmd_image_create_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
struct og_msg_params params = {};
json_t *root = cmd->json;
int len;
if (og_json_parse_create_image(root, &params) < 0)
return NULL;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=CrearImagen\rdsk=%s\rpar=%s\rcpt=%s\ridi=%s\rnci=%s\ripr=%s",
params.disk, params.partition, params.code, params.id,
params.name, params.repository);
if (len >= (int)sizeof(legacy_cmd))
return NULL;
return strdup(legacy_cmd);
}
static const char *og_cmd_image_restore_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
struct og_msg_params params = {};
json_t *root = cmd->json;
int len;
if (og_json_parse_restore_image(root, &params) < 0)
return NULL;
len = snprintf(legacy_cmd, sizeof(legacy_cmd),
"nfn=RestaurarImagen\rdsk=%s\rpar=%s\ridi=%s\rnci=%s\ripr=%s\rifs=%s\rptc=%s",
params.disk, params.partition, params.id, params.name,
params.repository, params.profile, params.type);
if (len >= (int)sizeof(legacy_cmd)) {
return NULL;
}
return strdup(legacy_cmd);
}
static const char *og_cmd_setup_to_legacy(struct og_cmd_json *cmd)
{
char legacy_cmd[LEGACY_CMD_MAX + 1] = {};
uint32_t bufsiz = sizeof(legacy_cmd);
const char *dsk, *ttp, *che, *tch;
struct og_msg_params params = {};
json_t *partition_setup, *value;
const json_t *root = cmd->json;
uint32_t consumed = 0;
size_t index;
int len;
dsk = json_string_value(json_object_get(root, "disk"));
if (!dsk)
return NULL;
ttp = json_string_value(json_object_get(root, "type"));
if (!ttp)
return NULL;
che = json_string_value(json_object_get(root, "cache"));
if (!che)
return NULL;
tch = json_string_value(json_object_get(root, "cache_size"));
if (!tch)
return NULL;
len = snprintf(legacy_cmd + consumed, bufsiz, "nfn=Configurar\rttp=%s\rdsk=%s\rcfg=dis=%s*che=%s*tch=%s!",
ttp, dsk, dsk, che, tch);
if (len >= bufsiz)
return NULL;
consumed += len;
if (consumed < bufsiz)
bufsiz -= len;
partition_setup = json_object_get(root, "partition_setup");
if (!partition_setup)
return NULL;
if (og_json_parse_partition_setup(partition_setup, &params) < 0)
return NULL;
json_array_foreach(partition_setup, index, value) {
len = snprintf(legacy_cmd + consumed, bufsiz, "par=%s*cpt=%s*sfi=%s*tam=%s*ope=%s%%",
params.partition_setup[index].number,
params.partition_setup[index].code,
params.partition_setup[index].filesystem,
params.partition_setup[index].size,
params.partition_setup[index].format);
if (len >= bufsiz)
return NULL;
consumed += len;
if (consumed < bufsiz)
bufsiz -= len;
}
return strdup(legacy_cmd);
}
const char *og_msg_params_to_legacy(struct og_cmd_json *cmd)
{
const char *legacy_cmd = NULL;
if (!strncmp(cmd->type, "wol", strlen("wol")))
legacy_cmd = og_cmd_wol_to_legacy(cmd);
else if (!strncmp(cmd->type, "poweroff", strlen("poweroff")))
legacy_cmd = og_cmd_poweroff_to_legacy(cmd);
else if (!strncmp(cmd->type, "reboot", strlen("reboot")))
legacy_cmd = og_cmd_reboot_to_legacy(cmd);
else if (!strncmp(cmd->type, "session", strlen("session")))
legacy_cmd = og_cmd_session_to_legacy(cmd);
else if (!strncmp(cmd->type, "software", strlen("software")))
legacy_cmd = og_cmd_software_to_legacy(cmd);
else if (!strncmp(cmd->type, "hardware", strlen("hardware")))
legacy_cmd = og_cmd_hardware_to_legacy(cmd);
else if (!strncmp(cmd->type, "run", strlen("run")))
legacy_cmd = og_cmd_shell_run_to_legacy(cmd);
else if (!strncmp(cmd->type, "image_create", strlen("image_create")))
legacy_cmd = og_cmd_image_create_to_legacy(cmd);
else if (!strncmp(cmd->type, "image_restore", strlen("image_restore")))
legacy_cmd = og_cmd_image_restore_to_legacy(cmd);
else if (!strncmp(cmd->type, "setup", strlen("setup")))
legacy_cmd = og_cmd_setup_to_legacy(cmd);
if (!legacy_cmd) {
syslog(LOG_ERR, "failed to translate command %s (%s:%d)\n",
cmd->type, __func__, __LINE__);
}
return legacy_cmd;
}

View File

@ -1,6 +0,0 @@
#ifndef _OG_LEGACY_H
#define _OG_LEGACY_H
const char *og_msg_params_to_legacy(struct og_cmd_json *cmd);
#endif

View File

@ -14,7 +14,6 @@
#include "rest.h"
#include "client.h"
#include "json.h"
#include "schedule.h"
#include "core.h"
#include "cfg.h"
#include <syslog.h>
@ -97,13 +96,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
if (og_dbi_schedule_get() < 0) {
syslog(LOG_ERR, "Cannot connect to database\n");
exit(EXIT_FAILURE);
}
og_schedule_next(og_loop);
syslog(LOG_INFO, "Waiting for connections\n");
while (1)

View File

@ -13,7 +13,6 @@
#include "rest.h"
#include "client.h"
#include "json.h"
#include "schedule.h"
#include "wol.h"
#include <syslog.h>
#include <sys/ioctl.h>

2871
src/rest.c

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
#include <ev.h>
#include <sys/time.h>
#include <netinet/in.h>
extern struct ev_loop *og_loop;
@ -39,7 +40,6 @@ enum og_cmd_type {
OG_CMD_IMAGE_RESTORE,
OG_CMD_IMAGE_RESTRICT,
OG_CMD_SETUP,
OG_CMD_RUN_SCHEDULE,
OG_CMD_IMAGES,
OG_CMD_CACHE_DELETE,
OG_CMD_CACHE_FETCH,
@ -70,7 +70,6 @@ struct og_client {
enum og_cmd_type last_cmd;
unsigned int last_cmd_id;
enum og_cmd_result last_cmd_result;
bool autorun;
uint32_t speed;
uint32_t seq;
struct {
@ -132,12 +131,6 @@ enum og_rest_uri {
OG_URI_CACHE_DELETE,
OG_URI_CACHE_FETCH,
OG_URI_PART_SETUP,
OG_URI_RUN_SCHEDULE,
OG_URI_TASK_RUN,
OG_URI_SCHEDULE_CREATE,
OG_URI_SCHEDULE_DELETE,
OG_URI_SCHEDULE_UPDATE,
OG_URI_SCHEDULE_GET,
OG_URI_OGLIVE_LIST,
OG_URI_OGLIVE_SET,
OG_URI_CENTER_ADD,
@ -148,12 +141,6 @@ enum og_rest_uri {
OG_URI_ROOM_UPDATE,
OG_URI_ROOM_DELETE,
OG_URI_ROOM_INFO,
OG_URI_PROC_ADD,
OG_URI_PROC_UPDATE,
OG_URI_PROC_RUN,
OG_URI_SCHEDULE_RUN,
OG_URI_PROC_DEL,
OG_URI_TASK_ADD,
OG_URI_SERVER,
OG_URI_STATS,
OG_URI_FOLDER_ADD,
@ -173,20 +160,6 @@ int og_send_request(enum og_rest_method method, enum og_cmd_type type,
const struct og_msg_params *params,
const json_t *data);
struct og_cmd {
uint32_t id;
struct list_head list;
uint32_t client_id;
const char *ip;
const char *mac;
enum og_cmd_type type;
enum og_rest_method method;
struct og_msg_params params;
json_t *json;
struct timeval tv;
};
const struct og_cmd *og_cmd_find(const char *client_ip);
void og_cmd_free(const struct og_cmd *cmd);
int og_dbi_scope_get(struct og_dbi *dbi, json_t *array);
#endif

View File

@ -1,482 +0,0 @@
/*
* Copyright (C) 2020-2021 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 "schedule.h"
#include "list.h"
#include <sys/types.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <syslog.h>
#include <time.h>
#include <ev.h>
struct og_schedule *current_schedule = NULL;
static LIST_HEAD(schedule_list);
static void og_schedule_add(struct og_schedule *new)
{
struct og_schedule *schedule, *next;
list_for_each_entry_safe(schedule, next, &schedule_list, list) {
if (new->seconds < schedule->seconds) {
list_add_tail(&new->list, &schedule->list);
return;
}
}
list_add_tail(&new->list, &schedule_list);
}
/* Returns the days in a month from the weekday. */
static void get_days_from_weekday(struct tm *tm, int wday, int *days, int *j)
{
int i, mday = 0;
tm->tm_mday = 1;
//Shift week to start on Sunday instead of Monday
if (wday == 6)
wday = 0;
else
wday++;
/* A bit bruteforce, but simple. */
for (i = 0; i <= 30; i++) {
mktime(tm);
/* Not this weekday, skip. */
if (tm->tm_wday != wday) {
tm->tm_mday++;
continue;
}
/* Not interested in next month. */
if (tm->tm_mday < mday)
break;
/* Found a matching. */
mday = tm->tm_mday;
days[(*j)++] = tm->tm_mday;
tm->tm_mday++;
}
}
/* Returns the days in the given week. */
static void get_days_from_week(struct tm *tm, int week, int *days, int *k)
{
int i, j, week_counter = 0;
bool week_over = false;
tm->tm_mday = 1;
/* Remaining days of this month. */
for (i = 0; i <= 30; i++) {
mktime(tm);
/* Last day of this week? */
if (tm->tm_wday == 6)
week_over = true;
/* Not the week we are searching for. */
if (week != week_counter) {
tm->tm_mday++;
if (week_over) {
week_counter++;
week_over = false;
}
continue;
}
/* Found matching. */
for (j = tm->tm_wday; j <= 6; j++) {
days[(*k)++] = tm->tm_mday++;
mktime(tm);
}
break;
}
}
static int monthdays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
static int last_month_day(struct tm *tm)
{
/* Leap year? Adjust it. */
if (tm->tm_mon == 1) {
tm->tm_mday = 29;
mktime(tm);
if (tm->tm_mday == 29)
return 29;
tm->tm_mon = 1;
}
return monthdays[tm->tm_mon];
}
/* Returns the days in the given week. */
static void get_last_week(struct tm *tm, int *days, int *j)
{
int i, last_day;
last_day = last_month_day(tm);
tm->tm_mday = last_day;
for (i = last_day; i >= last_day - 6; i--) {
mktime(tm);
days[(*j)++] = tm->tm_mday;
/* Last day of this week? */
if (tm->tm_wday == 1)
break;
tm->tm_mday--;
}
}
static void og_parse_years(uint16_t years_mask, int years[])
{
int i, j = 0;
for (i = 0; i < 16; i++) {
if ((1 << i) & years_mask)
years[j++] = 2010 + i - 1900;
}
}
static void og_parse_months(uint16_t months_mask, int months[])
{
int i, j = 0;
for (i = 0; i < 12; i++) {
if ((1 << i) & months_mask)
months[j++] = i + 1;
}
}
static void og_parse_days(uint32_t days_mask, int *days)
{
int i, j = 0;
for (i = 0; i < 31; i++) {
if ((1 << i) & days_mask)
days[j++] = i + 1;
}
}
static void og_parse_hours(uint16_t hours_mask, uint8_t am_pm, int hours[])
{
int pm = 12 * am_pm;
int i, j = 0;
for (i = 0; i < 12; i++) {
if ((1 << i) & hours_mask)
hours[j++] = i + pm + 1;
}
}
static void og_schedule_remove_duplicates()
{
struct og_schedule *schedule, *next, *prev = NULL;
list_for_each_entry_safe(schedule, next, &schedule_list, list) {
if (!prev) {
prev = schedule;
continue;
}
if (prev->seconds == schedule->seconds &&
prev->task_id == schedule->task_id) {
list_del(&prev->list);
free(prev);
}
prev = schedule;
}
}
static bool og_schedule_stale(time_t seconds)
{
time_t now;
now = time(NULL);
if (seconds < now)
return true;
return false;
}
static void og_schedule_create_weekdays(int month, int year,
int *hours, int minutes, int week_days,
uint32_t task_id, uint32_t schedule_id,
enum og_schedule_type type,
bool check_stale)
{
struct og_schedule *schedule;
int month_days[5];
int n_month_days;
time_t seconds;
uint32_t wday;
struct tm tm;
int k, l;
for (wday = 0; wday < 7; wday++) {
if (!((1 << wday) & week_days))
continue;
memset(&tm, 0, sizeof(tm));
tm.tm_mon = month;
tm.tm_year = year;
n_month_days = 0;
memset(month_days, 0, sizeof(month_days));
get_days_from_weekday(&tm, wday, month_days, &n_month_days);
for (k = 0; month_days[k] != 0 && k < n_month_days; k++) {
for (l = 0; hours[l] != 0 && l < 31; l++) {
memset(&tm, 0, sizeof(tm));
tm.tm_year = year;
tm.tm_mon = month;
tm.tm_mday = month_days[k];
tm.tm_hour = hours[l] - 1;
tm.tm_min = minutes;
tm.tm_isdst = -1;
seconds = mktime(&tm);
if (check_stale && og_schedule_stale(seconds))
continue;
schedule = (struct og_schedule *)
calloc(1, sizeof(struct og_schedule));
if (!schedule)
return;
schedule->seconds = seconds;
schedule->task_id = task_id;
schedule->schedule_id = schedule_id;
schedule->type = type;
og_schedule_add(schedule);
}
}
}
}
static void og_schedule_create_weeks(int month, int year,
int *hours, int minutes, int weeks,
uint32_t task_id, uint32_t schedule_id,
enum og_schedule_type type, bool check_stale)
{
struct og_schedule *schedule;
int month_days[7];
int n_month_days;
time_t seconds;
struct tm tm;
int week;
int k, l;
for (week = 0; week < 5; week++) {
if (!((1 << week) & weeks))
continue;
memset(&tm, 0, sizeof(tm));
tm.tm_mon = month;
tm.tm_year = year;
n_month_days = 0;
memset(month_days, 0, sizeof(month_days));
if (week == 5)
get_last_week(&tm, month_days, &n_month_days);
else
get_days_from_week(&tm, week, month_days, &n_month_days);
for (k = 0; month_days[k] != 0 && k < n_month_days; k++) {
for (l = 0; hours[l] != 0 && l < 31; l++) {
memset(&tm, 0, sizeof(tm));
tm.tm_year = year;
tm.tm_mon = month;
tm.tm_mday = month_days[k];
tm.tm_hour = hours[l] - 1;
tm.tm_min = minutes;
tm.tm_isdst = -1;
seconds = mktime(&tm);
if (check_stale && og_schedule_stale(seconds))
continue;
schedule = (struct og_schedule *)
calloc(1, sizeof(struct og_schedule));
if (!schedule)
return;
schedule->seconds = seconds;
schedule->task_id = task_id;
schedule->schedule_id = schedule_id;
schedule->type = type;
og_schedule_add(schedule);
}
}
}
}
static void og_schedule_create_days(int month, int year,
int *hours, int minutes, int *days,
uint32_t task_id, uint32_t schedule_id,
enum og_schedule_type type, bool check_stale)
{
struct og_schedule *schedule;
time_t seconds;
struct tm tm;
int k, l;
for (k = 0; days[k] != 0 && k < 31; k++) {
for (l = 0; hours[l] != 0 && l < 31; l++) {
memset(&tm, 0, sizeof(tm));
tm.tm_year = year;
tm.tm_mon = month;
tm.tm_mday = days[k];
tm.tm_hour = hours[l] - 1;
tm.tm_min = minutes;
tm.tm_isdst = -1;
seconds = mktime(&tm);
if (check_stale && og_schedule_stale(seconds))
continue;
schedule = (struct og_schedule *)
calloc(1, sizeof(struct og_schedule));
if (!schedule)
return;
schedule->seconds = seconds;
schedule->task_id = task_id;
schedule->schedule_id = schedule_id;
schedule->type = type;
og_schedule_add(schedule);
}
}
}
void og_schedule_create(unsigned int schedule_id, unsigned int task_id,
enum og_schedule_type type,
struct og_schedule_time *time)
{
int year, month, minutes;
int months[12] = {};
int years[12] = {};
int hours[12] = {};
int days[31] = {};
int i, j;
og_parse_years(time->years, years);
og_parse_months(time->months, months);
og_parse_days(time->days, days);
og_parse_hours(time->hours, time->am_pm, hours);
minutes = time->minutes;
for (i = 0; years[i] != 0 && i < 12; i++) {
for (j = 0; months[j] != 0 && j < 12; j++) {
month = months[j] - 1;
year = years[i];
if (time->week_days)
og_schedule_create_weekdays(month, year,
hours, minutes,
time->week_days,
task_id,
schedule_id,
type,
time->check_stale);
if (time->weeks)
og_schedule_create_weeks(month, year,
hours, minutes,
time->weeks,
task_id,
schedule_id,
type, time->check_stale);
if (time->days)
og_schedule_create_days(month, year,
hours, minutes,
days,
task_id,
schedule_id,
type, time->check_stale);
}
}
og_schedule_remove_duplicates();
}
void og_schedule_delete(struct ev_loop *loop, uint32_t schedule_id)
{
struct og_schedule *schedule, *next;
list_for_each_entry_safe(schedule, next, &schedule_list, list) {
if (schedule->schedule_id != schedule_id)
continue;
list_del(&schedule->list);
if (current_schedule == schedule) {
ev_timer_stop(loop, &schedule->timer);
current_schedule = NULL;
og_schedule_refresh(loop);
}
free(schedule);
}
}
void og_schedule_update(struct ev_loop *loop, unsigned int schedule_id,
unsigned int task_id, struct og_schedule_time *time)
{
og_schedule_delete(loop, schedule_id);
og_schedule_create(schedule_id, task_id, OG_SCHEDULE_TASK, time);
}
static void og_agent_timer_cb(struct ev_loop *loop, ev_timer *timer, int events)
{
struct og_schedule *current;
current = container_of(timer, struct og_schedule, timer);
og_schedule_run(current->task_id, current->schedule_id, current->type);
ev_timer_stop(loop, timer);
list_del(&current->list);
free(current);
og_schedule_next(loop);
}
void og_schedule_next(struct ev_loop *loop)
{
struct og_schedule *schedule;
time_t now, seconds;
if (list_empty(&schedule_list)) {
current_schedule = NULL;
return;
}
schedule = list_first_entry(&schedule_list, struct og_schedule, list);
now = time(NULL);
if (schedule->seconds <= now)
seconds = 0;
else
seconds = schedule->seconds - now;
ev_timer_init(&schedule->timer, og_agent_timer_cb, seconds, 0.);
ev_timer_start(loop, &schedule->timer);
current_schedule = schedule;
}
void og_schedule_refresh(struct ev_loop *loop)
{
if (current_schedule)
ev_timer_stop(loop, &current_schedule->timer);
og_schedule_next(loop);
}

View File

@ -1,66 +0,0 @@
#ifndef _OG_SCHEDULE_H_
#define _OG_SCHEDULE_H_
#include <stdint.h>
#include <stdbool.h>
#include "dbi.h"
#include "list.h"
#include <ev.h>
struct og_schedule_time {
uint32_t years;
uint32_t months;
uint32_t weeks;
uint32_t week_days;
uint32_t days;
uint32_t hours;
uint32_t am_pm;
uint32_t minutes;
bool check_stale;
};
enum og_schedule_type {
OG_SCHEDULE_TASK,
OG_SCHEDULE_PROCEDURE,
OG_SCHEDULE_COMMAND,
};
struct og_schedule {
struct list_head list;
struct ev_timer timer;
time_t seconds;
unsigned int task_id;
unsigned int schedule_id;
enum og_schedule_type type;
};
void og_schedule_create(unsigned int schedule_id, unsigned int task_id,
enum og_schedule_type type,
struct og_schedule_time *time);
void og_schedule_update(struct ev_loop *loop, unsigned int schedule_id,
unsigned int task_id, struct og_schedule_time *time);
void og_schedule_delete(struct ev_loop *loop, uint32_t schedule_id);
void og_schedule_next(struct ev_loop *loop);
void og_schedule_refresh(struct ev_loop *loop);
void og_schedule_run(unsigned int task_id, unsigned int schedule_id,
enum og_schedule_type type);
int og_dbi_schedule_get(void);
int og_dbi_update_action(uint32_t id, bool success);
struct og_task {
uint32_t task_id;
uint32_t procedure_id;
uint32_t command_id;
uint32_t center_id;
uint32_t schedule_id;
uint32_t type_scope;
uint32_t session;
uint32_t scope;
const char *filtered_scope;
const char *params;
};
int og_dbi_queue_procedure(struct og_dbi *dbi, struct og_task *task);
#endif

427
src/scope.c 100644
View File

@ -0,0 +1,427 @@
/*
* Copyright (C) 2020-2021 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 <syslog.h>
#include "dbi.h"
#include "utils.h"
#include "list.h"
#include "rest.h"
#define OG_QUERY_MAXLEN 4096
static int og_dbi_scope_get_computer(const struct og_dbi *dbi, json_t *array,
const char* query)
{
const char *computer_name, *computer_ip;
uint32_t computer_id;
const char *msglog;
dbi_result result;
json_t *computer;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
computer_id = dbi_result_get_uint(result, "idordenador");
computer_name = dbi_result_get_string(result, "nombreordenador");
computer_ip = dbi_result_get_string(result, "ip");
computer = json_object();
if (!computer) {
dbi_result_free(result);
return -1;
}
json_object_set_new(computer, "name", json_string(computer_name));
json_object_set_new(computer, "type", json_string("computer"));
json_object_set_new(computer, "id", json_integer(computer_id));
json_object_set_new(computer, "scope", json_array());
json_object_set_new(computer, "ip", json_string(computer_ip));
json_array_append(array, computer);
json_decref(computer);
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_computer_from_room(const struct og_dbi *dbi,
json_t *array, char *query,
const uint32_t room_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idordenador, nombreordenador, ip "
"FROM ordenadores WHERE idaula=%d and grupoid=0",
room_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computer(dbi, array, query);
}
static int og_dbi_scope_get_computer_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t computers_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idordenador, nombreordenador, ip "
"FROM ordenadores WHERE grupoid=%d",
computers_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computer(dbi, array, query);
}
#define OG_COMPUTER_FOLDER_MARKER 0x00010000
static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id);
static int og_dbi_scope_get_computers(const struct og_dbi *dbi, json_t *array,
char *query, bool in_room)
{
const char *msglog, *computers_name;
json_t *computers, *scope_array;
uint32_t computers_id;
uint32_t marker = 0;
dbi_result result;
if (in_room)
marker = OG_COMPUTER_FOLDER_MARKER;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
computers_id = dbi_result_get_uint(result, "idgrupo");
computers_name = dbi_result_get_string(result,
"nombregrupoordenador");
computers = json_object();
if (!computers) {
dbi_result_free(result);
return -1;
}
json_object_set_new(computers, "name",
json_string(computers_name));
json_object_set_new(computers, "type", json_string("folder"));
json_object_set_new(computers, "id",
json_integer(computers_id | marker));
json_object_set_new(computers, "scope", json_array());
json_array_append(array, computers);
json_decref(computers);
scope_array = json_object_get(computers, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computers_from_computers(dbi,
scope_array,
query,
computers_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computer_from_computers(dbi,
scope_array,
query,
computers_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_computers_from_room(const struct og_dbi *dbi,
json_t *array, char *query,
const uint32_t room_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupoordenador "
"FROM gruposordenadores "
"WHERE idaula=%d AND grupoid=0",
room_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computers(dbi, array, query, true);
}
static int og_dbi_scope_get_computers_from_computers(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupoordenador "
"FROM gruposordenadores WHERE grupoid=%d",
group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_computers(dbi, array, query, false);
}
static int og_dbi_scope_get_room(const struct og_dbi *dbi, json_t *array,
char *query)
{
const char *msglog, *room_name;
json_t *room, *scope_array;
dbi_result result;
uint32_t room_id;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
room_id = dbi_result_get_uint(result, "idaula");
room_name = dbi_result_get_string(result, "nombreaula");
room = json_object();
if (!room) {
dbi_result_free(result);
return -1;
}
json_object_set_new(room, "name", json_string(room_name));
json_object_set_new(room, "type", json_string("room"));
json_object_set_new(room, "id", json_integer(room_id));
json_object_set_new(room, "scope", json_array());
json_array_append(array, room);
json_decref(room);
scope_array = json_object_get(room, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computers_from_room(dbi, scope_array,
query, room_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_computer_from_room(dbi, scope_array,
query, room_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_room_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idaula, nombreaula "
"FROM aulas WHERE grupoid=%d", group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_room(dbi, array, query);
}
static int og_dbi_scope_get_room_from_center(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t center_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idaula, nombreaula "
"FROM aulas WHERE idcentro=%d AND grupoid=0",
center_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_room(dbi, array, query);
}
static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id);
static int og_dbi_scope_get_group(const struct og_dbi *dbi,
json_t *array,
char *query)
{
const char *msglog, *group_name;
json_t *group, *scope_array;
dbi_result result;
uint32_t group_id;
result = dbi_conn_queryf(dbi->conn, query);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
group_id = dbi_result_get_uint(result, "idgrupo");
group_name = dbi_result_get_string(result, "nombregrupo");
group = json_object();
if (!group) {
dbi_result_free(result);
return -1;
}
json_object_set_new(group, "name", json_string(group_name));
json_object_set_new(group, "type", json_string("folder"));
json_object_set_new(group, "id", json_integer(group_id));
json_object_set_new(group, "scope", json_array());
json_array_append(array, group);
json_decref(group);
scope_array = json_object_get(group, "scope");
if (!scope_array) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_group_from_group(dbi, scope_array, query,
group_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_room_from_group(dbi, scope_array, query,
group_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}
static int og_dbi_scope_get_group_from_group(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t group_id)
{
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupo "
"FROM grupos WHERE grupoid=%d", group_id);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_group(dbi, array, query);
}
static int og_dbi_scope_get_group_from_center(const struct og_dbi *dbi,
json_t *array,
char *query,
const uint32_t center_id)
{
int group_type_room = 2;
int ret = snprintf(query, OG_QUERY_MAXLEN,
"SELECT idgrupo, nombregrupo "
"FROM grupos "
"WHERE idcentro=%d AND grupoid=0 AND tipo=%d",
center_id, group_type_room);
if (ret <= 0 || ret >= OG_QUERY_MAXLEN)
return -1;
return og_dbi_scope_get_group(dbi, array, query);
}
int og_dbi_scope_get(struct og_dbi *dbi, json_t *array)
{
const char *msglog, *center_name;
json_t *center, *scope_array;
char query[OG_QUERY_MAXLEN];
uint32_t center_id;
dbi_result result;
result = dbi_conn_queryf(dbi->conn,
"SELECT nombrecentro, idcentro FROM centros");
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
__func__, __LINE__, msglog);
return -1;
}
while (dbi_result_next_row(result)) {
center_id = dbi_result_get_uint(result, "idcentro");
center_name = dbi_result_get_string(result, "nombrecentro");
center = json_object();
if (!center) {
dbi_result_free(result);
return -1;
}
scope_array = json_array();
if (!scope_array) {
dbi_result_free(result);
json_decref(center);
return -1;
}
json_object_set_new(center, "name", json_string(center_name));
json_object_set_new(center, "type", json_string("center"));
json_object_set_new(center, "id", json_integer(center_id));
json_object_set_new(center, "scope", scope_array);
json_array_append(array, center);
json_decref(center);
if (og_dbi_scope_get_group_from_center(dbi, scope_array, query,
center_id)) {
dbi_result_free(result);
return -1;
}
if (og_dbi_scope_get_room_from_center(dbi, scope_array, query,
center_id)) {
dbi_result_free(result);
return -1;
}
}
dbi_result_free(result);
return 0;
}