source: ogServer-Git/src/client.c @ a7cce8d

Last change on this file since a7cce8d was a7cce8d, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

ogServer is AGPLv3+

Update license header in files.

  • Property mode set to 100644
File size: 16.5 KB
RevLine 
[04ca20e]1/*
[a7cce8d]2 * Copyright (C) 2020-2021 Soleta Networks <info@soleta.eu>
[04ca20e]3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
[a7cce8d]6 * Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
[04ca20e]8 */
9
10#include "ogAdmServer.h"
[fe1ce97]11#include "cfg.h"
[04ca20e]12#include "dbi.h"
13#include "utils.h"
14#include "list.h"
15#include "rest.h"
16#include "json.h"
17#include "schedule.h"
18#include <syslog.h>
19#include <sys/ioctl.h>
20#include <ifaddrs.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24#include <jansson.h>
25#include <time.h>
26
27static int og_resp_probe(struct og_client *cli, json_t *data)
28{
29        const char *status = NULL;
30        const char *key;
31        json_t *value;
32        int err = 0;
33
34        if (json_typeof(data) != JSON_OBJECT)
35                return -1;
36
37        json_object_foreach(data, key, value) {
38                if (!strcmp(key, "status")) {
39                        err = og_json_parse_string(value, &status);
40                        if (err < 0)
41                                return err;
42                } else {
43                        return -1;
44                }
45        }
46
47        if (!strcmp(status, "BSY"))
48                cli->status = OG_CLIENT_STATUS_BUSY;
49        else if (!strcmp(status, "OPG"))
50                cli->status = OG_CLIENT_STATUS_OGLIVE;
[c0f5d2c]51        else if (!strcmp(status, "VDI"))
52                cli->status = OG_CLIENT_STATUS_VIRTUAL;
[04ca20e]53
54        return status ? 0 : -1;
55}
56
57static int og_resp_shell_run(struct og_client *cli, json_t *data)
58{
59        const char *output = NULL;
60        char filename[4096];
61        const char *key;
62        json_t *value;
63        int err = -1;
64        FILE *file;
65
66        if (json_typeof(data) != JSON_OBJECT)
67                return -1;
68
69        json_object_foreach(data, key, value) {
70                if (!strcmp(key, "out")) {
71                        err = og_json_parse_string(value, &output);
72                        if (err < 0)
73                                return err;
74                } else {
75                        return -1;
76                }
77        }
78
79        if (!output) {
80                syslog(LOG_ERR, "%s:%d: malformed json response\n",
81                       __FILE__, __LINE__);
82                return -1;
83        }
84
85        sprintf(filename, "/tmp/_Seconsola_%s", inet_ntoa(cli->addr.sin_addr));
86        file = fopen(filename, "wt");
87        if (!file) {
88                syslog(LOG_ERR, "cannot open file %s: %s\n",
89                       filename, strerror(errno));
90                return -1;
91        }
92
93        fprintf(file, "%s", output);
94        fclose(file);
95
96        return 0;
97}
98
99struct og_computer_legacy  {
100        char center[OG_DB_INT_MAXLEN + 1];
101        char id[OG_DB_INT_MAXLEN + 1];
102        char hardware[8192];
103};
104
105static int og_resp_hardware(json_t *data, struct og_client *cli)
106{
107        struct og_computer_legacy legacy = {};
[cbd9421]108        struct og_computer computer = {};
[04ca20e]109        const char *hardware = NULL;
110        struct og_dbi *dbi;
111        const char *key;
112        json_t *value;
113        int err = 0;
114        bool res;
115
116        if (json_typeof(data) != JSON_OBJECT)
117                return -1;
118
119        json_object_foreach(data, key, value) {
120                if (!strcmp(key, "hardware")) {
121                        err = og_json_parse_string(value, &hardware);
122                        if (err < 0)
123                                return -1;
124                } else {
125                        return -1;
126                }
127        }
128
129        if (!hardware) {
130                syslog(LOG_ERR, "malformed response json\n");
131                return -1;
132        }
133
[fe1ce97]134        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]135        if (!dbi) {
136                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
137                       __func__, __LINE__);
138                return -1;
139        }
140
[d7e2022]141        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
142        if (err < 0) {
143                og_dbi_close(dbi);
144                return -1;
145        }
146
147        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
148        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
149        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
150
[04ca20e]151        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
152                                legacy.center);
153        og_dbi_close(dbi);
154
155        if (!res) {
156                syslog(LOG_ERR, "Problem updating client configuration\n");
157                return -1;
158        }
159
160        return 0;
161}
162
163struct og_software_legacy {
164        char software[8192];
165        char center[OG_DB_INT_MAXLEN + 1];
166        char part[OG_DB_SMALLINT_MAXLEN + 1];
167        char id[OG_DB_INT_MAXLEN + 1];
168};
169
170static int og_resp_software(json_t *data, struct og_client *cli)
171{
172        struct og_software_legacy legacy = {};
[cbd9421]173        struct og_computer computer = {};
[04ca20e]174        const char *partition = NULL;
175        const char *software = NULL;
176        struct og_dbi *dbi;
177        const char *key;
178        json_t *value;
179        int err = 0;
180        bool res;
181
182        if (json_typeof(data) != JSON_OBJECT)
183                return -1;
184
185        json_object_foreach(data, key, value) {
186                if (!strcmp(key, "software"))
187                        err = og_json_parse_string(value, &software);
188                else if (!strcmp(key, "partition"))
189                        err = og_json_parse_string(value, &partition);
190                else
191                        return -1;
192
193                if (err < 0)
194                        return -1;
195        }
196
197        if (!software || !partition) {
198                syslog(LOG_ERR, "malformed response json\n");
199                return -1;
200        }
201
[fe1ce97]202        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]203        if (!dbi) {
204                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
205                       __func__, __LINE__);
206                return -1;
207        }
208
[d7e2022]209        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
210        if (err < 0) {
211                og_dbi_close(dbi);
212                return -1;
213        }
214
215        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
216        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
217        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
218        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
219
[04ca20e]220        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
221                                computer.name, legacy.center);
222        og_dbi_close(dbi);
223
224        if (!res) {
225                syslog(LOG_ERR, "Problem updating client configuration\n");
226                return -1;
227        }
228
229        return 0;
230}
231
232#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
233                                 OG_PARAM_PART_NUMBER |         \
234                                 OG_PARAM_PART_CODE |           \
235                                 OG_PARAM_PART_FILESYSTEM |     \
236                                 OG_PARAM_PART_OS |             \
237                                 OG_PARAM_PART_SIZE |           \
238                                 OG_PARAM_PART_USED_SIZE)
239
240static int og_json_parse_partition_array(json_t *value,
241                                         struct og_partition *partitions)
242{
243        json_t *element;
244        int i, err;
245
246        if (json_typeof(value) != JSON_ARRAY)
247                return -1;
248
249        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
250                element = json_array_get(value, i);
251
252                err = og_json_parse_partition(element, &partitions[i],
253                                              OG_PARAMS_RESP_REFRESH);
254                if (err < 0)
255                        return err;
256        }
257
258        return 0;
259}
260
261static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
262{
263        struct og_task dummy_task = {
264                .scope          = computer_id,
265                .type_scope     = AMBITO_ORDENADORES,
266                .procedure_id   = proc_id,
267        };
268        struct og_dbi *dbi;
269
[fe1ce97]270        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]271        if (!dbi) {
272                syslog(LOG_ERR, "cannot open connection database "
273                                "(%s:%d)\n", __func__, __LINE__);
274                return -1;
275        }
276        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
277                og_dbi_close(dbi);
278                return -1;
279        }
280        og_dbi_close(dbi);
281
282        return 0;
283}
284
285static int og_resp_refresh(json_t *data, struct og_client *cli)
286{
287        struct og_partition partitions[OG_PARTITION_MAX] = {};
[24e6fbf]288        struct og_partition disks[OG_DISK_MAX] = {};
[04ca20e]289        const char *serial_number = NULL;
290        struct og_computer computer = {};
[24e6fbf]291        char cfg[4096] = {};
[04ca20e]292        struct og_dbi *dbi;
293        const char *key;
294        unsigned int i;
295        json_t *value;
296        int err = 0;
297        bool res;
298
299        if (json_typeof(data) != JSON_OBJECT)
300                return -1;
301
302        json_object_foreach(data, key, value) {
303                if (!strcmp(key, "disk_setup")) {
[24e6fbf]304                        err = og_json_parse_partition_array(value, disks);
[04ca20e]305                } else if (!strcmp(key, "partition_setup")) {
306                        err = og_json_parse_partition_array(value, partitions);
307                } else if (!strcmp(key, "serial_number")) {
308                        err = og_json_parse_string(value, &serial_number);
309                } else {
310                        return -1;
311                }
312
313                if (err < 0)
314                        return err;
315        }
316
317        if (strlen(serial_number) > 0)
318                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
319
[24e6fbf]320        for (i = 0; i < OG_DISK_MAX; i++) {
321                if (!disks[i].disk || !disks[i].number ||
322                    !disks[i].code || !disks[i].filesystem ||
323                    !disks[i].os || !disks[i].size ||
324                    !disks[i].used_size)
325                        continue;
326
327                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
328                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
329                         disks[i].disk, disks[i].number,
330                         disks[i].code, disks[i].filesystem,
331                         disks[i].os, disks[i].size,
332                         disks[i].used_size);
333        }
[04ca20e]334
335        for (i = 0; i < OG_PARTITION_MAX; i++) {
336                if (!partitions[i].disk || !partitions[i].number ||
337                    !partitions[i].code || !partitions[i].filesystem ||
338                    !partitions[i].os || !partitions[i].size ||
339                    !partitions[i].used_size)
340                        continue;
341
342                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
343                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
344                         partitions[i].disk, partitions[i].number,
345                         partitions[i].code, partitions[i].filesystem,
346                         partitions[i].os, partitions[i].size,
347                         partitions[i].used_size);
348        }
349
[fe1ce97]350        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]351        if (!dbi) {
352                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
353                                  __func__, __LINE__);
354                return -1;
355        }
[d7e2022]356
357        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
358        if (err < 0) {
359                og_dbi_close(dbi);
360                return -1;
361        }
362
[04ca20e]363        res = actualizaConfiguracion(dbi, cfg, computer.id);
364        og_dbi_close(dbi);
365
366        if (!res) {
367                syslog(LOG_ERR, "Problem updating client configuration\n");
368                return -1;
369        }
370
371        if (!cli->autorun && computer.procedure_id) {
372                cli->autorun = true;
373
[f537daf]374                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
[04ca20e]375                        return -1;
376        }
377
378        return 0;
379}
380
[0efc182]381static int update_image_info(struct og_dbi *dbi, const char *image_id,
382                             const char *clonator, const char *compressor,
383                             const char *filesystem, const uint64_t datasize)
384{
385        const char *msglog;
386        dbi_result result;
387
388        result = dbi_conn_queryf(dbi->conn,
389                "UPDATE imagenes"
390                "   SET clonator='%s', compressor='%s',"
[a67f27a]391                "       filesystem='%s', datasize=%lld"
[0efc182]392                " WHERE idimagen=%s", clonator, compressor, filesystem,
393                datasize, image_id);
394
395        if (!result) {
396                dbi_conn_error(dbi->conn, &msglog);
397                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
398                       __func__, __LINE__, msglog);
399                return -1;
400        }
401        dbi_result_free(result);
402
403        return 0;
404}
405
[04ca20e]406static int og_resp_image_create(json_t *data, struct og_client *cli)
407{
408        struct og_software_legacy soft_legacy;
409        struct og_image_legacy img_legacy;
[cbd9421]410        struct og_computer computer = {};
[0efc182]411        const char *compressor = NULL;
412        const char *filesystem = NULL;
[04ca20e]413        const char *partition = NULL;
414        const char *software = NULL;
415        const char *image_id = NULL;
[0efc182]416        const char *clonator = NULL;
[04ca20e]417        const char *disk = NULL;
418        const char *code = NULL;
419        const char *name = NULL;
420        const char *repo = NULL;
[0efc182]421        uint64_t datasize = 0;
[04ca20e]422        struct og_dbi *dbi;
423        const char *key;
424        json_t *value;
425        int err = 0;
426        bool res;
427
428        if (json_typeof(data) != JSON_OBJECT)
429                return -1;
430
431        json_object_foreach(data, key, value) {
432                if (!strcmp(key, "software"))
433                        err = og_json_parse_string(value, &software);
434                else if (!strcmp(key, "partition"))
435                        err = og_json_parse_string(value, &partition);
436                else if (!strcmp(key, "disk"))
437                        err = og_json_parse_string(value, &disk);
438                else if (!strcmp(key, "code"))
439                        err = og_json_parse_string(value, &code);
440                else if (!strcmp(key, "id"))
441                        err = og_json_parse_string(value, &image_id);
442                else if (!strcmp(key, "name"))
443                        err = og_json_parse_string(value, &name);
444                else if (!strcmp(key, "repository"))
445                        err = og_json_parse_string(value, &repo);
[0efc182]446                else if (!strcmp(key, "clonator"))
447                        err = og_json_parse_string(value, &clonator);
448                else if (!strcmp(key, "compressor"))
449                        err = og_json_parse_string(value, &compressor);
450                else if (!strcmp(key, "filesystem"))
451                        err = og_json_parse_string(value, &filesystem);
452                else if (!strcmp(key, "datasize"))
453                        err = og_json_parse_uint64(value, &datasize);
[04ca20e]454                else
455                        return -1;
456
457                if (err < 0)
458                        return err;
459        }
460
461        if (!software || !partition || !disk || !code || !image_id || !name ||
[0efc182]462            !repo || !clonator || !compressor || !filesystem || !datasize) {
[04ca20e]463                syslog(LOG_ERR, "malformed response json\n");
464                return -1;
465        }
466
[fe1ce97]467        dbi = og_dbi_open(&ogconfig.db);
[d7e2022]468        if (!dbi) {
469                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
470                       __func__, __LINE__);
471                return -1;
472        }
473
474        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
475        if (err < 0) {
476                og_dbi_close(dbi);
[04ca20e]477                return -1;
[d7e2022]478        }
[04ca20e]479
480        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
481                 computer.center);
482        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
483                 software);
484        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
485                 image_id);
486        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
487        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
488        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
489        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
490        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
491        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
492
493        res = actualizaSoftware(dbi,
494                                soft_legacy.software,
495                                img_legacy.part,
496                                soft_legacy.id,
497                                computer.name,
498                                soft_legacy.center);
499        if (!res) {
500                og_dbi_close(dbi);
501                syslog(LOG_ERR, "Problem updating client configuration\n");
502                return -1;
503        }
504
505        res = actualizaCreacionImagen(dbi,
506                                      img_legacy.image_id,
507                                      img_legacy.disk,
508                                      img_legacy.part,
509                                      img_legacy.code,
510                                      img_legacy.repo,
511                                      soft_legacy.id);
512        if (!res) {
[0efc182]513                og_dbi_close(dbi);
[04ca20e]514                syslog(LOG_ERR, "Problem updating client configuration\n");
515                return -1;
516        }
517
[0efc182]518        res = update_image_info(dbi, image_id, clonator, compressor,
519                                filesystem, datasize);
520        og_dbi_close(dbi);
521
522        if (res) {
523                syslog(LOG_ERR, "Problem updating image info\n");
524                return -1;
525        }
526
[04ca20e]527        return 0;
528}
529
530static int og_resp_image_restore(json_t *data, struct og_client *cli)
531{
532        struct og_software_legacy soft_legacy;
533        struct og_image_legacy img_legacy;
[cbd9421]534        struct og_computer computer = {};
[04ca20e]535        const char *partition = NULL;
536        const char *image_id = NULL;
537        const char *disk = NULL;
538        dbi_result query_result;
539        struct og_dbi *dbi;
540        const char *key;
541        json_t *value;
542        int err = 0;
543        bool res;
544
545        if (json_typeof(data) != JSON_OBJECT)
546                return -1;
547
548        json_object_foreach(data, key, value) {
549                if (!strcmp(key, "partition"))
550                        err = og_json_parse_string(value, &partition);
551                else if (!strcmp(key, "disk"))
552                        err = og_json_parse_string(value, &disk);
553                else if (!strcmp(key, "image_id"))
554                        err = og_json_parse_string(value, &image_id);
555                else
556                        return -1;
557
558                if (err < 0)
559                        return err;
560        }
561
562        if (!partition || !disk || !image_id) {
563                syslog(LOG_ERR, "malformed response json\n");
564                return -1;
565        }
566
[fe1ce97]567        dbi = og_dbi_open(&ogconfig.db);
[04ca20e]568        if (!dbi) {
569                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
570                       __func__, __LINE__);
571                return -1;
572        }
573
574        query_result = dbi_conn_queryf(dbi->conn,
575                                       "SELECT idperfilsoft FROM imagenes "
576                                       " WHERE idimagen='%s'",
577                                       image_id);
578        if (!query_result) {
579                og_dbi_close(dbi);
580                syslog(LOG_ERR, "failed to query database\n");
581                return -1;
582        }
583        if (!dbi_result_next_row(query_result)) {
584                dbi_result_free(query_result);
585                og_dbi_close(dbi);
586                syslog(LOG_ERR, "software profile does not exist in database\n");
587                return -1;
588        }
589        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
590                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
591        dbi_result_free(query_result);
592
[d7e2022]593        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
594        if (err < 0) {
595                og_dbi_close(dbi);
596                return -1;
597        }
598
599        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
600                 image_id);
601        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
602        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
603        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
604
[04ca20e]605        res = actualizaRestauracionImagen(dbi,
606                                          img_legacy.image_id,
607                                          img_legacy.disk,
608                                          img_legacy.part,
609                                          soft_legacy.id,
610                                          img_legacy.software_id);
611        og_dbi_close(dbi);
612
613        if (!res) {
614                syslog(LOG_ERR, "Problem updating client configuration\n");
615                return -1;
616        }
617
618        return 0;
619}
620
621int og_agent_state_process_response(struct og_client *cli)
622{
623        json_error_t json_err;
624        json_t *root;
625        int err = -1;
626        char *body;
627
628        if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted",
629                     strlen("HTTP/1.0 202 Accepted"))) {
630                og_dbi_update_action(cli->last_cmd_id, true);
631                cli->last_cmd_id = 0;
632                return 1;
633        }
634
635        if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
636                og_dbi_update_action(cli->last_cmd_id, false);
637                cli->last_cmd_id = 0;
638                return -1;
639        }
640        og_dbi_update_action(cli->last_cmd_id, true);
641        cli->last_cmd_id = 0;
642
643        if (!cli->content_length) {
644                cli->last_cmd = OG_CMD_UNSPEC;
645                return 0;
646        }
647
648        body = strstr(cli->buf, "\r\n\r\n") + 4;
649
650        root = json_loads(body, 0, &json_err);
651        if (!root) {
652                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
653                       __FILE__, __LINE__, json_err.line, json_err.text);
654                return -1;
655        }
656
657        switch (cli->last_cmd) {
658        case OG_CMD_PROBE:
659                err = og_resp_probe(cli, root);
660                break;
661        case OG_CMD_SHELL_RUN:
662                err = og_resp_shell_run(cli, root);
663                break;
664        case OG_CMD_HARDWARE:
665                err = og_resp_hardware(root, cli);
666                break;
667        case OG_CMD_SOFTWARE:
668                err = og_resp_software(root, cli);
669                break;
670        case OG_CMD_REFRESH:
671                err = og_resp_refresh(root, cli);
672                break;
673        case OG_CMD_SETUP:
674                err = og_resp_refresh(root, cli);
675                break;
676        case OG_CMD_IMAGE_CREATE:
677                err = og_resp_image_create(root, cli);
678                break;
679        case OG_CMD_IMAGE_RESTORE:
680                err = og_resp_image_restore(root, cli);
681                break;
682        default:
683                err = -1;
684                break;
685        }
686
[0d9d72e]687        json_decref(root);
[04ca20e]688        cli->last_cmd = OG_CMD_UNSPEC;
689
690        return err;
691}
Note: See TracBrowser for help on using the repository browser.