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

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

#988 remove legacy configuration

Use og_server_cfg everywhere. Convert port to string to make it easy for the
dbi API since it expects a string. Remove legacy example configuration file.

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