2 * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3 * Copyright (c) 1991-1999 University of Maryland at College Park
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of U.M. not be used in advertising or
11 * publicity pertaining to distribution of the software without specific,
12 * written prior permission. U.M. makes no representations about the
13 * suitability of this software for any purpose. It is provided "as is"
14 * without express or implied warranty.
16 * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Authors: the Amanda Development Team. Its members are listed in a
24 * file named AUTHORS, in the root directory of this distribution.
27 * $Id: server_util.c,v 1.17 2006/05/25 01:47:20 johnfranks Exp $
32 #include "server_util.h"
38 #include "pipespawn.h"
43 const char *cmdstr[] = {
44 "BOGUS", "QUIT", "QUITTING", "DONE", "PARTIAL",
45 "START", "FILE-DUMP", "PORT-DUMP", "CONTINUE", "ABORT",/* dumper cmds */
46 "FAILED", "TRY-AGAIN", "NO-ROOM", "RQ-MORE-DISK", /* dumper results */
47 "ABORT-FINISHED", "BAD-COMMAND", /* dumper results */
48 "START-TAPER", "FILE-WRITE", "NEW-TAPE", "NO-NEW-TAPE",
50 "PARTDONE", "PORT-WRITE", "DUMPER-STATUS", /* taper cmds */
51 "PORT", "TAPE-ERROR", "TAPER-OK", /* taper results */
52 "REQUEST-NEW-TAPE", "DIRECTTCP-PORT", "TAKE-SCRIBE-FROM",
53 "START-SCAN", "CLOSE-VOLUME", "LAST_TOK",
63 struct cmdargs *cmdargs = g_new0(struct cmdargs, 1);
66 g_printf("%s> ", get_pname());
73 line = stralloc("QUIT");
76 dbprintf(_("getcmd: %s\n"), line);
78 cmdargs->argv = split_quoted_strings(line);
79 cmdargs->argc = g_strv_length(cmdargs->argv);
84 if (cmdargs->argc < 1) {
88 for(cmd_i=BOGUS; cmdstr[cmd_i] != NULL; cmd_i++)
89 if(strcmp(cmdargs->argv[0], cmdstr[cmd_i]) == 0) {
99 SELECT_ARG_TYPE ready;
108 nfound = select(1, &ready, NULL, NULL, &to);
109 if (nfound && FD_ISSET(0, &ready)) {
118 struct cmdargs *cmdargs)
123 g_strfreev(cmdargs->argv);
127 printf_arglist_function1(void putresult, cmd_t, result, const char *, format)
131 arglist_start(argp, format);
132 dbprintf(_("putresult: %d %s\n"), result, cmdstr[result]);
133 g_printf("%s ", cmdstr[result]);
134 g_vprintf(format, argp);
140 amhost_get_security_conf(
144 if(!string || !*string)
147 if(strcmp(string, "krb5principal")==0)
148 return(getconf_str(CNF_KRB5PRINCIPAL));
149 else if(strcmp(string, "krb5keytab")==0)
150 return(getconf_str(CNF_KRB5KEYTAB));
152 if(!arg || !((am_host_t *)arg)->disks) return(NULL);
154 if(strcmp(string, "amandad_path")==0)
155 return ((am_host_t *)arg)->disks->amandad_path;
156 else if(strcmp(string, "client_username")==0)
157 return ((am_host_t *)arg)->disks->client_username;
158 else if(strcmp(string, "client_port")==0)
159 return ((am_host_t *)arg)->disks->client_port;
160 else if(strcmp(string, "ssh_keys")==0)
161 return ((am_host_t *)arg)->disks->ssh_keys;
172 char *hostinfodir, *old_hostinfodir, *Xhostinfodir;
173 char *diskdir, *old_diskdir, *Xdiskdir;
174 char *infofile, *old_infofile, *Xinfofile;
178 if (stat(infodir, &statbuf) != 0) {
182 for (dp = dl->head; dp != NULL; dp = dp->next) {
183 hostinfodir = sanitise_filename(dp->host->hostname);
184 diskdir = sanitise_filename(dp->name);
185 infofile = vstralloc(infodir, "/", hostinfodir, "/", diskdir,
187 if (stat(infofile, &statbuf) == -1 && errno == ENOENT) {
188 old_hostinfodir = old_sanitise_filename(dp->host->hostname);
189 old_diskdir = old_sanitise_filename(dp->name);
190 old_infofile = vstralloc(infodir, old_hostinfodir, "/",
191 old_diskdir, "/info", NULL);
192 if (stat(old_infofile, &statbuf) == 0) {
195 while (diskp != NULL) {
196 Xhostinfodir = sanitise_filename(diskp->host->hostname);
197 Xdiskdir = sanitise_filename(diskp->name);
198 Xinfofile = vstralloc(infodir, "/", Xhostinfodir, "/",
199 Xdiskdir, "/info", NULL);
200 if (strcmp(old_infofile, Xinfofile) == 0) {
208 if (other_dle_match == 0) {
209 if(mkpdir(infofile, (mode_t)0755, (uid_t)-1,
211 *errmsg = vstralloc("Can't create directory for ",
215 if(copy_file(infofile, old_infofile, errmsg) == -1)
219 amfree(old_hostinfodir);
221 amfree(old_infofile);
232 pp_script_t *pp_script,
233 execute_on_t execute_on,
239 int scriptin, scriptout, scripterr;
241 char *command = NULL;
242 GPtrArray *argv_ptr = g_ptr_array_new();
246 char level_number[NUM_STR_SIZE];
247 struct stat cmd_stat;
250 if ((pp_script_get_execute_on(pp_script) & execute_on) == 0)
252 if (pp_script_get_execute_where(pp_script) != ES_SERVER)
255 plugin = pp_script_get_plugin(pp_script);
257 cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL);
258 result = stat(cmd, &cmd_stat);
260 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
262 cmd = vstralloc(get_config_dir(), "/application/", plugin, NULL);
263 result = stat(cmd, &cmd_stat);
265 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
267 cmd = vstralloc(CONFIG_DIR, "/application/", plugin, NULL);
268 result = stat(cmd, &cmd_stat);
270 dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno));
272 cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL);
277 g_ptr_array_add(argv_ptr, stralloc(plugin));
279 switch (execute_on) {
280 case EXECUTE_ON_PRE_AMCHECK:
281 command = "PRE-AMCHECK";
283 case EXECUTE_ON_PRE_DLE_AMCHECK:
284 command = "PRE-DLE-AMCHECK";
286 case EXECUTE_ON_PRE_HOST_AMCHECK:
287 command = "PRE-HOST-AMCHECK";
289 case EXECUTE_ON_POST_AMCHECK:
290 command = "POST-AMCHECK";
292 case EXECUTE_ON_POST_DLE_AMCHECK:
293 command = "POST-DLE-AMCHECK";
295 case EXECUTE_ON_POST_HOST_AMCHECK:
296 command = "POST-HOST-AMCHECK";
298 case EXECUTE_ON_PRE_ESTIMATE:
299 command = "PRE-ESTIMATE";
301 case EXECUTE_ON_PRE_DLE_ESTIMATE:
302 command = "PRE-DLE-ESTIMATE";
304 case EXECUTE_ON_PRE_HOST_ESTIMATE:
305 command = "PRE-HOST-ESTIMATE";
307 case EXECUTE_ON_POST_ESTIMATE:
308 command = "POST-ESTIMATE";
310 case EXECUTE_ON_POST_DLE_ESTIMATE:
311 command = "POST-DLE-ESTIMATE";
313 case EXECUTE_ON_POST_HOST_ESTIMATE:
314 command = "POST-HOST-ESTIMATE";
316 case EXECUTE_ON_PRE_BACKUP:
317 command = "PRE-BACKUP";
319 case EXECUTE_ON_PRE_DLE_BACKUP:
320 command = "PRE-DLE-BACKUP";
322 case EXECUTE_ON_PRE_HOST_BACKUP:
323 command = "PRE-HOST-BACKUP";
325 case EXECUTE_ON_POST_BACKUP:
326 command = "POST-BACKUP";
328 case EXECUTE_ON_POST_DLE_BACKUP:
329 command = "POST-DLE-BACKUP";
331 case EXECUTE_ON_POST_HOST_BACKUP:
332 command = "POST-HOST-BACKUP";
334 case EXECUTE_ON_PRE_RECOVER:
335 case EXECUTE_ON_POST_RECOVER:
336 case EXECUTE_ON_PRE_LEVEL_RECOVER:
337 case EXECUTE_ON_POST_LEVEL_RECOVER:
338 case EXECUTE_ON_INTER_LEVEL_RECOVER:
340 // ERROR these script can't be executed on server.
345 g_ptr_array_add(argv_ptr, stralloc(command));
346 g_ptr_array_add(argv_ptr, stralloc("--execute-where"));
347 g_ptr_array_add(argv_ptr, stralloc("server"));
350 g_ptr_array_add(argv_ptr, stralloc("--config"));
351 g_ptr_array_add(argv_ptr, stralloc(config));
353 if (dp->host->hostname) {
354 g_ptr_array_add(argv_ptr, stralloc("--host"));
355 g_ptr_array_add(argv_ptr, stralloc(dp->host->hostname));
358 g_ptr_array_add(argv_ptr, stralloc("--disk"));
359 g_ptr_array_add(argv_ptr, stralloc(dp->name));
362 g_ptr_array_add(argv_ptr, stralloc("--device"));
363 g_ptr_array_add(argv_ptr, stralloc(dp->device));
366 g_snprintf(level_number, SIZEOF(level_number), "%d", level);
367 g_ptr_array_add(argv_ptr, stralloc("--level"));
368 g_ptr_array_add(argv_ptr, stralloc(level_number));
371 property_add_to_argv(argv_ptr, pp_script_get_property(pp_script));
372 g_ptr_array_add(argv_ptr, NULL);
374 scripterr = fileno(stderr);
375 scriptpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE, 0, &scriptin,
376 &scriptout, &scripterr,
377 (char **)argv_ptr->pdata);
380 streamout = fdopen(scriptout, "r");
382 while((line = agets(streamout)) != NULL) {
383 dbprintf("script: %s\n", line);
388 waitpid(scriptpid, NULL, 0);
389 g_ptr_array_free_full(argv_ptr);
395 run_server_dle_scripts(
396 execute_on_t execute_on,
401 identlist_t pp_scriptlist;
403 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
404 pp_scriptlist = pp_scriptlist->next) {
405 pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
406 g_assert(pp_script != NULL);
407 run_server_script(pp_script, execute_on, config, dp, level);
412 run_server_host_scripts(
413 execute_on_t execute_on,
417 identlist_t pp_scriptlist;
420 GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal,
422 for (dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
424 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
425 pp_scriptlist = pp_scriptlist->next) {
427 pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data);
428 g_assert(pp_script != NULL);
429 if (pp_script_get_single_execution(pp_script)) {
430 todo = g_hash_table_lookup(executed,
431 pp_script_get_plugin(pp_script))
435 run_server_script(pp_script, execute_on, config, dp, -1);
436 if (pp_script_get_single_execution(pp_script)) {
437 g_hash_table_insert(executed,
438 pp_script_get_plugin(pp_script),
446 g_hash_table_destroy(executed);
450 run_server_global_scripts(
451 execute_on_t execute_on,
454 identlist_t pp_scriptlist;
458 GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal,
460 for (host = get_hostlist(); host != NULL; host = host->next) {
461 for (dp = host->disks; dp != NULL; dp = dp->hostnext) {
463 for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL;
464 pp_scriptlist = pp_scriptlist->next) {
466 pp_script_t *pp_script =
467 lookup_pp_script((char *)pp_scriptlist->data);
468 g_assert(pp_script != NULL);
469 if (pp_script_get_single_execution(pp_script)) {
470 todo = g_hash_table_lookup(executed,
471 pp_script_get_plugin(pp_script)) == NULL;
474 run_server_script(pp_script, execute_on, config,
476 if (pp_script_get_single_execution(pp_script)) {
477 g_hash_table_insert(executed,
478 pp_script_get_plugin(pp_script),
486 g_hash_table_destroy(executed);
494 char *amcleanup_program;
495 char *amcleanup_options[4];
497 switch(amcleanup_pid = fork()) {
501 case 0: /* child process */
502 amcleanup_program = vstralloc(sbindir, "/", "amcleanup", NULL);
503 amcleanup_options[0] = amcleanup_program;
504 amcleanup_options[1] = "-p";
505 amcleanup_options[2] = config_name;
506 amcleanup_options[3] = NULL;
507 execve(amcleanup_program, amcleanup_options, safe_env());
508 error("exec %s: %s", amcleanup_program, strerror(errno));
513 waitpid(amcleanup_pid, NULL, 0);
525 log = fopen(logfile, "r");
527 return stralloc("UNKNOWN");
529 while(fgets(line, 1024, log)) {
530 if (strncmp_const(line, "INFO ") == 0) {
534 skip_non_whitespace(s, ch);
536 skip_whitespace(s, ch);
537 skip_non_whitespace(s, ch);
539 skip_whitespace(s, ch);
540 if (strncmp_const(s-1, "pid ") == 0) {
541 process_name = stralloc(process_name);
548 return stralloc("UNKNOWN");
553 internal_server_estimate(
564 if (level == 0) { /* use latest level 0, should do extrapolation */
565 gint64 est_size = (gint64)0;
568 for (j=NB_HISTORY-2; j>=0; j--) {
569 if (info->history[j].level == 0) {
570 if (info->history[j].size < (gint64)0) continue;
571 est_size = info->history[j].size;
578 } else if (info->inf[level].size > (gint64)1000) { /* stats */
579 size = info->inf[level].size;
582 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
583 tapetype_t *tape = lookup_tapetype(conf_tapetype);
584 size = (gint64)1000000;
585 if (size > tapetype_get_length(tape)/2)
586 size = tapetype_get_length(tape)/2;
589 } else if (level == info->last_level) {
590 /* means of all X day at the same level */
593 gint64 est_size_day[NB_DAY];
594 int nb_est_day[NB_DAY];
596 for (j=0; j<NB_DAY; j++) {
597 est_size_day[j] = (gint64)0;
601 for (j=NB_HISTORY-2; j>=0; j--) {
602 if (info->history[j].level <= 0) continue;
603 if (info->history[j].size < (gint64)0) continue;
604 if (info->history[j].level == info->history[j+1].level) {
605 if (nb_day <NB_DAY-1) nb_day++;
606 est_size_day[nb_day] += info->history[j].size;
607 nb_est_day[nb_day]++;
612 nb_day = info->consecutive_runs + 1;
613 if (nb_day > NB_DAY-1) nb_day = NB_DAY-1;
615 while (nb_day > 0 && nb_est_day[nb_day] == 0) nb_day--;
617 if (nb_est_day[nb_day] > 0) {
618 size = est_size_day[nb_day] / (gint64)nb_est_day[nb_day];
621 else if (info->inf[level].size > (gint64)1000) { /* stats */
622 size = info->inf[level].size;
628 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
629 tapetype_t *tape = lookup_tapetype(conf_tapetype);
631 level0_size = internal_server_estimate(dp, info, 0, &level0_stat);
632 size = (gint64)10000;
633 if (size > tapetype_get_length(tape)/2)
634 size = tapetype_get_length(tape)/2;
635 if (level0_size > 0 && dp->strategy != DS_NOFULL) {
636 if (size > level0_size/2)
637 size = level0_size/2;
642 else if (level == info->last_level + 1) {
643 /* means of all first day at a new level */
644 gint64 est_size = (gint64)0;
647 for (j=NB_HISTORY-2; j>=0; j--) {
648 if (info->history[j].level <= 0) continue;
649 if (info->history[j].size < (gint64)0) continue;
650 if (info->history[j].level == info->history[j+1].level + 1 ) {
651 est_size += info->history[j].size;
656 size = est_size / (gint64)nb_est;
658 } else if (info->inf[level].size > (gint64)1000) { /* stats */
659 size = info->inf[level].size;
664 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
665 tapetype_t *tape = lookup_tapetype(conf_tapetype);
667 level0_size = internal_server_estimate(dp, info, 0, &level0_stat);
668 size = (gint64)100000;
669 if (size > tapetype_get_length(tape)/2)
670 size = tapetype_get_length(tape)/2;
671 if (level0_size > 0 && dp->strategy != DS_NOFULL) {
672 if (size > level0_size/2)
673 size = level0_size/2;
678 char *conf_tapetype = getconf_str(CNF_TAPETYPE);
679 tapetype_t *tape = lookup_tapetype(conf_tapetype);
680 size = (gint64)100000;
681 if (size > tapetype_get_length(tape)/2)
682 size = tapetype_get_length(tape)/2;
689 server_can_do_estimate(
696 internal_server_estimate(dp, info, level, &stats);