]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/qt-console/tray-monitor/tray_conf.cpp
Big backport from Enterprise
[bacula/bacula] / bacula / src / qt-console / tray-monitor / tray_conf.cpp
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20 *   Main configuration file parser for Bacula Tray Monitor.
21 *
22 *   Adapted from dird_conf.c
23 *
24 *   Note, the configuration file parser consists of three parts
25 *
26 *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
27 *
28 *   2. The generic config  scanner in lib/parse_config.c and
29 *       lib/parse_config.h.
30 *       These files contain the parser code, some utility
31 *       routines, and the common store routines (name, int,
32 *       string).
33 *
34 *   3. The daemon specific file, which contains the Resource
35 *       definitions as well as any specific store routines
36 *       for the resource records.
37 *
38 *     Nicolas Boichat, August MMIV
39 *
40 */
41
42 #include "common.h"
43 #include "tray_conf.h"
44
45 worker *worker_start();
46 void worker_stop(worker *);
47
48 /* Define the first and last resource ID record
49 * types. Note, these should be unique for each
50 * daemon though not a requirement.
51 */
52 int32_t r_first = R_FIRST;
53 int32_t r_last  = R_LAST;
54 RES_HEAD **res_head;
55
56 /* We build the current resource here as we are
57 * scanning the resource configuration definition,
58 * then move it to allocated memory when the resource
59 * scan is complete.
60 */
61 URES res_all;
62 int32_t res_all_size = sizeof(res_all);
63
64
65 /* Definition of records permitted within each
66 * resource with the routine to process the record
67 * information.  NOTE! quoted names must be in lower case.
68 */
69 /*
70 *    Monitor Resource
71 *
72 *   name           handler     value                 code flags    default_value
73 */
74 static RES_ITEM mon_items[] = {
75    {"Name",        store_name,     ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0},
76    {"Description", store_str,      ITEM(res_monitor.hdr.desc), 0, 0, 0},
77    {"requiressl",  store_bool,     ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0},
78    {"RefreshInterval",  store_time,ITEM(res_monitor.RefreshInterval),    0, ITEM_DEFAULT, 60},
79    {"CommCompression",  store_bool, ITEM(res_monitor.comm_compression), 0, ITEM_DEFAULT, true},
80    {"CommandDirectory", store_dir, ITEM(res_monitor.command_dir), 0, 0, 0},
81    {"DisplayAdvancedOptions", store_bool, ITEM(res_monitor.display_advanced_options), 0, 0, 0},
82    {NULL, NULL, {0}, 0, 0, 0}
83 };
84
85 /*  Director's that we can contact */
86 static RES_ITEM dir_items[] = {
87    {"Name",        store_name,     ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
88    {"Description", store_str,      ITEM(res_main.hdr.desc), 0, 0, 0},
89    {"Port",        store_pint32,   ITEM(res_main.port),     0, ITEM_DEFAULT, 9101},
90    {"Address",     store_str,      ITEM(res_main.address),  0, ITEM_REQUIRED, 0},
91    {"Password",    store_password, ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
92    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
93    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
94    {"UseSetIp", store_bool,      ITEM(res_main.use_setip),  0, 0, 0},
95    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
96    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
97    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
98    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
99    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
100
101    {NULL, NULL, {0}, 0, 0, 0}
102 };
103
104 /*
105 *    Client or File daemon resource
106 *
107 *   name           handler     value                 code flags    default_value
108 */
109
110 static RES_ITEM cli_items[] = {
111    {"Name",     store_name,       ITEM(res_main.hdr.name), 0, ITEM_REQUIRED, 0},
112    {"Description", store_str,     ITEM(res_main.hdr.desc), 0, 0, 0},
113    {"Address",  store_str,        ITEM(res_main.address),  0, ITEM_REQUIRED, 0},
114    {"Port",     store_pint32,     ITEM(res_main.port),   0, ITEM_DEFAULT, 9102},
115    {"Password", store_password,   ITEM(res_main.password), 0, ITEM_REQUIRED, 0},
116    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
117    {"Remote",   store_bool,       ITEM(res_main.use_remote), 0, ITEM_DEFAULT, 0},
118    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
119    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
120    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
121    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
122    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
123    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
124    {NULL, NULL, {0}, 0, 0, 0}
125 };
126
127 /* Storage daemon resource
128 *
129 *   name           handler     value                 code flags    default_value
130 */
131 static RES_ITEM store_items[] = {
132    {"Name",        store_name,     ITEM(res_main.hdr.name),   0, ITEM_REQUIRED, 0},
133    {"Description", store_str,      ITEM(res_main.hdr.desc),   0, 0, 0},
134    {"Port",      store_pint32,   ITEM(res_main.port),     0, ITEM_DEFAULT, 9103},
135    {"Address",     store_str,      ITEM(res_main.address),    0, ITEM_REQUIRED, 0},
136    {"Password",    store_password, ITEM(res_main.password),   0, ITEM_REQUIRED, 0},
137    {"ConnectTimeout", store_time,ITEM(res_main.connect_timeout),   0, ITEM_DEFAULT, 10},
138    {"Monitor",  store_bool,       ITEM(res_main.use_monitor), 0, ITEM_DEFAULT, 0},
139    {"TlsEnable",      store_bool,    ITEM(res_main.tls_enable), 0, 0, 0},
140    {"TlsCaCertificateFile", store_dir, ITEM(res_main.tls_ca_certfile), 0, 0, 0},
141    {"TlsCaCertificateDir", store_dir,  ITEM(res_main.tls_ca_certdir), 0, 0, 0},
142    {"TlsCertificate", store_dir,       ITEM(res_main.tls_certfile), 0, 0, 0},
143    {"TlsKey",         store_dir,       ITEM(res_main.tls_keyfile), 0, 0, 0},
144    {NULL, NULL, {0}, 0, 0, 0}
145 };
146
147 /*
148 * This is the master resource definition.
149 * It must have one item for each of the resources.
150 *
151 *  NOTE!!! keep it in the same order as the R_codes
152 *    or eliminate all resources[rindex].name
153 *
154 *  name      items        rcode        res_head
155 */
156 RES_TABLE resources[] = {
157    {"monitor",      mon_items,    R_MONITOR},
158    {"director",     dir_items,    R_DIRECTOR},
159    {"client",       cli_items,    R_CLIENT},
160    {"storage",      store_items,  R_STORAGE},
161    {NULL,           NULL,         0}
162 };
163
164 /* Dump contents of resource */
165 void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock)
166 {
167    RES *next;
168    URES *res = (URES *)ares;
169    bool recurse = true;
170
171    if (res == NULL) {
172       sendit(sock, _("No %s resource defined\n"), res_to_str(type));
173       return;
174    }
175    if (type < 0) {                    /* no recursion */
176       type = - type;
177       recurse = false;
178    }
179    switch (type) {
180    case R_MONITOR:
181       sendit(sock, _("Monitor: name=%s\n"), ares->name);
182       break;
183    case R_DIRECTOR:
184       sendit(sock, _("Director: name=%s address=%s port=%d\n"),
185              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
186       break;
187    case R_CLIENT:
188       sendit(sock, _("Client: name=%s address=%s port=%d\n"),
189              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
190       break;
191    case R_STORAGE:
192       sendit(sock, _("Storage: name=%s address=%s port=%d\n"),
193              res->res_main.hdr.name, res->res_main.address, res->res_main.port);
194       break;
195    default:
196       sendit(sock, _("Unknown resource type %d in dump_resource.\n"), type);
197       break;
198    }
199    if (recurse) {
200       next = GetNextRes(0, (RES *)res);
201       if (next) {
202          dump_resource(type, next, sendit, sock);
203       }
204    }
205 }
206
207 /*
208 * Free memory of resource -- called when daemon terminates.
209 * NB, we don't need to worry about freeing any references
210 * to other resources as they will be freed when that
211 * resource chain is traversed.  Mainly we worry about freeing
212 * allocated strings (names).
213 */
214 void free_resource(RES *sres, int type)
215 {
216    URES *res = (URES *)sres;
217
218    if (res == NULL)
219       return;
220    /* common stuff -- free the resource name and description */
221    if (res->res_monitor.hdr.name) {
222       free(res->res_monitor.hdr.name);
223    }
224    if (res->res_monitor.hdr.desc) {
225       free(res->res_monitor.hdr.desc);
226    }
227
228    switch (type) {
229    case R_MONITOR:
230       if (res->res_monitor.password) {
231          free(res->res_monitor.password);
232       }
233       if (res->res_monitor.command_dir) {
234          free(res->res_monitor.command_dir);
235       }
236       break;
237    case R_DIRECTOR:
238    case R_CLIENT:
239    case R_STORAGE:
240       delete res->res_main.mutex;
241       free_bsock(res->res_main.bs);
242       if (res->res_main.wrk) {
243          worker_stop(res->res_main.wrk);
244          res->res_main.wrk = NULL;
245       }
246       if (res->res_main.address) {
247          free(res->res_main.address);
248       }
249       if (res->res_main.tls_ctx) {
250          free_tls_context(res->res_main.tls_ctx);
251       }
252       if (res->res_main.tls_ca_certfile) {
253          free(res->res_main.tls_ca_certfile);
254       }
255       if (res->res_main.tls_ca_certdir) {
256          free(res->res_main.tls_ca_certdir);
257       }
258       if (res->res_main.tls_certfile) {
259          free(res->res_main.tls_certfile);
260       }
261       if (res->res_main.tls_keyfile) {
262          free(res->res_main.tls_keyfile);
263       }
264       if (res->res_main.jobs) {
265          delete res->res_main.jobs;
266       }
267       if (res->res_main.clients) {
268          delete res->res_main.clients;
269       }
270       if (res->res_main.filesets) {
271          delete res->res_main.filesets;
272       }
273       if (res->res_main.pools) {
274          delete res->res_main.pools;
275       }
276       if (res->res_main.storages) {
277          delete res->res_main.storages;
278       }
279       if (res->res_main.running_jobs) {
280          delete res->res_main.terminated_jobs;
281       }
282       break;
283    default:
284       printf(_("Unknown resource type %d in free_resource.\n"), type);
285    }
286
287    /* Common stuff again -- free the resource, recurse to next one */
288    if (res) {
289       free(res);
290    }
291 }
292
293 /*
294 * Save the new resource by chaining it into the head list for
295 * the resource. If this is pass 2, we update any resource
296 * pointers because they may not have been defined until
297 * later in pass 1.
298 */
299 bool save_resource(CONFIG *config, int type, RES_ITEM *items, int pass)
300 {
301    int rindex = type - r_first;
302    int i, size;
303    int error = 0;
304
305    /*
306    * Ensure that all required items are present
307    */
308    for (i=0; items[i].name; i++) {
309       if (items[i].flags & ITEM_REQUIRED) {
310          if (!bit_is_set(i, res_all.res_monitor.hdr.item_present)) {
311             Mmsg(config->m_errmsg, _("\"%s\" directive is required in \"%s\" resource, but not found.\n"),
312                  items[i].name, resources[rindex].name);
313             return false;
314          }
315       }
316       /* If this triggers, take a look at lib/parse_conf.h */
317       if (i >= MAX_RES_ITEMS) {
318          Mmsg(config->m_errmsg, _("Too many directives in \"%s\" resource\n"), resources[rindex].name);
319          return false;
320       }
321    }
322
323    /*
324    * During pass 2 in each "store" routine, we looked up pointers
325    * to all the resources referrenced in the current resource, now we
326    * must copy their addresses from the static record to the allocated
327    * record.
328    */
329    if (pass == 2) {
330       switch (type) {
331       /* Resources not containing a resource */
332       case R_STORAGE:
333       case R_DIRECTOR:
334       case R_CLIENT:
335       case R_MONITOR:
336          break;
337       default:
338          Emsg1(M_ERROR, 0, _("Unknown resource type %d in save_resource.\n"), type);
339          error = 1;
340          break;
341       }
342       /* Note, the resource name was already saved during pass 1,
343       * so here, we can just release it.
344       */
345       if (res_all.res_monitor.hdr.name) {
346          free(res_all.res_monitor.hdr.name);
347          res_all.res_monitor.hdr.name = NULL;
348       }
349       if (res_all.res_monitor.hdr.desc) {
350          free(res_all.res_monitor.hdr.desc);
351          res_all.res_monitor.hdr.desc = NULL;
352       }
353       return true;
354    }
355
356    /*
357    * The following code is only executed during pass 1
358    */
359    switch (type) {
360    case R_MONITOR:
361       size = sizeof(MONITOR);
362       break;
363    case R_CLIENT:
364    case R_STORAGE:
365    case R_DIRECTOR:
366       // We need to initialize the mutex
367       res_all.res_main.mutex = new QMutex();
368       res_all.res_main.wrk = worker_start();
369       size = sizeof(RESMON);
370       break;
371    default:
372       printf(_("Unknown resource type %d in save_resource.\n"), type);
373       error = 1;
374       size = 1;
375       break;
376    }
377    /* Common */
378    if (!error) {
379       res_all.res_main.type = type;
380       if (!config->insert_res(rindex, size)) {
381          return false;
382       }
383    }
384    return true;
385 }
386
387 bool parse_tmon_config(CONFIG *config, const char *configfile, int exit_code)
388 {
389    config->init(configfile, error_handler, exit_code,
390                 (void *)&res_all, res_all_size,
391       r_first, r_last, resources, &res_head);
392    return config->parse_config();
393 }