X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Fserver_util.c;h=72462a3668479c7a7bad348f997bb868145be15b;hb=HEAD;hp=b238f1217a6f8bb64d389cf6c5be26cf0dd033f2;hpb=310f09c0f55a2fb6f3f3746d6ded20099792b773;p=debian%2Famanda diff --git a/server-src/server_util.c b/server-src/server_util.c index b238f12..72462a3 100644 --- a/server-src/server_util.c +++ b/server-src/server_util.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1999 University of Maryland at College Park + * Copyright (c) 2007-2012 Zmanda, Inc. All Rights Reserved. * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its @@ -24,44 +25,48 @@ * file named AUTHORS, in the root directory of this distribution. */ /* - * $Id: server_util.c,v 1.17.2.1 2006/11/24 18:05:07 martinea Exp $ + * $Id: server_util.c,v 1.17 2006/05/25 01:47:20 johnfranks Exp $ * */ #include "amanda.h" #include "server_util.h" #include "arglist.h" -#include "token.h" #include "logfile.h" #include "util.h" #include "conffile.h" #include "diskfile.h" +#include "pipespawn.h" +#include "conffile.h" +#include "infofile.h" +#include "sys/wait.h" const char *cmdstr[] = { "BOGUS", "QUIT", "QUITTING", "DONE", "PARTIAL", "START", "FILE-DUMP", "PORT-DUMP", "CONTINUE", "ABORT",/* dumper cmds */ "FAILED", "TRY-AGAIN", "NO-ROOM", "RQ-MORE-DISK", /* dumper results */ "ABORT-FINISHED", "BAD-COMMAND", /* dumper results */ - "START-TAPER", "FILE-WRITE", "PORT-WRITE", /* taper cmds */ - "PORT", "TAPE-ERROR", "TAPER-OK", "SPLIT-NEEDNEXT", /* taper results */ - "SPLIT-CONTINUE", + "START-TAPER", "FILE-WRITE", "NEW-TAPE", "NO-NEW-TAPE", + + "PARTDONE", "PORT-WRITE", "DUMPER-STATUS", /* taper cmds */ + "PORT", "TAPE-ERROR", "TAPER-OK", /* taper results */ + "REQUEST-NEW-TAPE", "DIRECTTCP-PORT", "TAKE-SCRIBE-FROM", + "START-SCAN", "CLOSE-VOLUME", "LAST_TOK", NULL }; -cmd_t -getcmd( - struct cmdargs * cmdargs) +struct cmdargs * +getcmd(void) { char *line; cmd_t cmd_i; - - assert(cmdargs != NULL); + struct cmdargs *cmdargs = g_new0(struct cmdargs, 1); if (isatty(0)) { - printf("%s> ", get_pname()); + g_printf("%s> ", get_pname()); fflush(stdout); - line = readline(NULL); + line = agets(stdin); } else { line = agets(stdin); } @@ -69,36 +74,65 @@ getcmd( line = stralloc("QUIT"); } - cmdargs->argc = split(line, cmdargs->argv, - (int)(sizeof(cmdargs->argv) / sizeof(cmdargs->argv[0])), " "); + dbprintf(_("getcmd: %s\n"), line); + + cmdargs->argv = split_quoted_strings(line); + cmdargs->argc = g_strv_length(cmdargs->argv); + cmdargs->cmd = BOGUS; + amfree(line); -#if DEBUG - { - int i; - fprintf(stderr,"argc = %d\n", cmdargs->argc); - for (i = 0; i < cmdargs->argc+1; i++) - fprintf(stderr,"argv[%d] = \"%s\"\n", i, cmdargs->argv[i]); + if (cmdargs->argc < 1) { + return cmdargs; } -#endif - - if (cmdargs->argc < 1) - return (BOGUS); for(cmd_i=BOGUS; cmdstr[cmd_i] != NULL; cmd_i++) - if(strcmp(cmdargs->argv[1], cmdstr[cmd_i]) == 0) - return (cmd_i); - return (BOGUS); + if(strcmp(cmdargs->argv[0], cmdstr[cmd_i]) == 0) { + cmdargs->cmd = cmd_i; + return cmdargs; + } + return cmdargs; } +struct cmdargs * +get_pending_cmd(void) +{ + SELECT_ARG_TYPE ready; + struct timeval to; + int nfound; + + FD_ZERO(&ready); + FD_SET(0, &ready); + to.tv_sec = 0; + to.tv_usec = 0; + + nfound = select(1, &ready, NULL, NULL, &to); + if (nfound && FD_ISSET(0, &ready)) { + return getcmd(); + } else { + return NULL; + } +} + +void +free_cmdargs( + struct cmdargs *cmdargs) +{ + if (!cmdargs) + return; + if (cmdargs->argv) + g_strfreev(cmdargs->argv); + g_free(cmdargs); +} printf_arglist_function1(void putresult, cmd_t, result, const char *, format) { va_list argp; arglist_start(argp, format); - printf("%s ",cmdstr[result]); - vprintf(format, argp); + dbprintf(_("putresult: %d %s\n"), result, cmdstr[result]); + g_printf("%s ", cmdstr[result]); + g_vprintf(format, argp); fflush(stdout); arglist_end(argp); } @@ -122,6 +156,8 @@ amhost_get_security_conf( return ((am_host_t *)arg)->disks->amandad_path; else if(strcmp(string, "client_username")==0) return ((am_host_t *)arg)->disks->client_username; + else if(strcmp(string, "client_port")==0) + return ((am_host_t *)arg)->disks->client_port; else if(strcmp(string, "ssh_keys")==0) return ((am_host_t *)arg)->disks->ssh_keys; @@ -171,16 +207,494 @@ int check_infofile( } } if (other_dle_match == 0) { - if(mkpdir(infofile, (mode_t)02755, (uid_t)-1, - (gid_t)-1) == -1) + if(mkpdir(infofile, (mode_t)0755, (uid_t)-1, + (gid_t)-1) == -1) { *errmsg = vstralloc("Can't create directory for ", infofile, NULL); return -1; + } if(copy_file(infofile, old_infofile, errmsg) == -1) return -1; } } + amfree(old_hostinfodir); + amfree(old_diskdir); + amfree(old_infofile); } + amfree(diskdir); + amfree(hostinfodir); + amfree(infofile); } return 0; } + +void +run_server_script( + pp_script_t *pp_script, + execute_on_t execute_on, + char *config, + disk_t *dp, + int level) +{ + pid_t scriptpid; + int scriptin, scriptout, scripterr; + char *cmd; + char *command = NULL; + GPtrArray *argv_ptr = g_ptr_array_new(); + FILE *streamout; + char *line; + char *plugin; + char level_number[NUM_STR_SIZE]; + struct stat cmd_stat; + int result; + + if ((pp_script_get_execute_on(pp_script) & execute_on) == 0) + return; + if (pp_script_get_execute_where(pp_script) != ES_SERVER) + return; + + plugin = pp_script_get_plugin(pp_script); + + cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL); + result = stat(cmd, &cmd_stat); + if (result == -1) { + dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno)); + amfree(cmd); + cmd = vstralloc(get_config_dir(), "/application/", plugin, NULL); + result = stat(cmd, &cmd_stat); + if (result == -1) { + dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno)); + amfree(cmd); + cmd = vstralloc(CONFIG_DIR, "/application/", plugin, NULL); + result = stat(cmd, &cmd_stat); + if (result == -1) { + dbprintf("Can't stat script '%s': %s\n", cmd, strerror(errno)); + amfree(cmd); + cmd = vstralloc(APPLICATION_DIR, "/", plugin, NULL); + } + } + } + + g_ptr_array_add(argv_ptr, stralloc(plugin)); + + switch (execute_on) { + case EXECUTE_ON_PRE_AMCHECK: + command = "PRE-AMCHECK"; + break; + case EXECUTE_ON_PRE_DLE_AMCHECK: + command = "PRE-DLE-AMCHECK"; + break; + case EXECUTE_ON_PRE_HOST_AMCHECK: + command = "PRE-HOST-AMCHECK"; + break; + case EXECUTE_ON_POST_AMCHECK: + command = "POST-AMCHECK"; + break; + case EXECUTE_ON_POST_DLE_AMCHECK: + command = "POST-DLE-AMCHECK"; + break; + case EXECUTE_ON_POST_HOST_AMCHECK: + command = "POST-HOST-AMCHECK"; + break; + case EXECUTE_ON_PRE_ESTIMATE: + command = "PRE-ESTIMATE"; + break; + case EXECUTE_ON_PRE_DLE_ESTIMATE: + command = "PRE-DLE-ESTIMATE"; + break; + case EXECUTE_ON_PRE_HOST_ESTIMATE: + command = "PRE-HOST-ESTIMATE"; + break; + case EXECUTE_ON_POST_ESTIMATE: + command = "POST-ESTIMATE"; + break; + case EXECUTE_ON_POST_DLE_ESTIMATE: + command = "POST-DLE-ESTIMATE"; + break; + case EXECUTE_ON_POST_HOST_ESTIMATE: + command = "POST-HOST-ESTIMATE"; + break; + case EXECUTE_ON_PRE_BACKUP: + command = "PRE-BACKUP"; + break; + case EXECUTE_ON_PRE_DLE_BACKUP: + command = "PRE-DLE-BACKUP"; + break; + case EXECUTE_ON_PRE_HOST_BACKUP: + command = "PRE-HOST-BACKUP"; + break; + case EXECUTE_ON_POST_BACKUP: + command = "POST-BACKUP"; + break; + case EXECUTE_ON_POST_DLE_BACKUP: + command = "POST-DLE-BACKUP"; + break; + case EXECUTE_ON_POST_HOST_BACKUP: + command = "POST-HOST-BACKUP"; + break; + case EXECUTE_ON_PRE_RECOVER: + case EXECUTE_ON_POST_RECOVER: + case EXECUTE_ON_PRE_LEVEL_RECOVER: + case EXECUTE_ON_POST_LEVEL_RECOVER: + case EXECUTE_ON_INTER_LEVEL_RECOVER: + { + // ERROR these script can't be executed on server. + return; + } + } + + g_ptr_array_add(argv_ptr, stralloc(command)); + g_ptr_array_add(argv_ptr, stralloc("--execute-where")); + g_ptr_array_add(argv_ptr, stralloc("server")); + + if (config) { + g_ptr_array_add(argv_ptr, stralloc("--config")); + g_ptr_array_add(argv_ptr, stralloc(config)); + } + if (dp->host->hostname) { + g_ptr_array_add(argv_ptr, stralloc("--host")); + g_ptr_array_add(argv_ptr, stralloc(dp->host->hostname)); + } + if (dp->name) { + g_ptr_array_add(argv_ptr, stralloc("--disk")); + g_ptr_array_add(argv_ptr, stralloc(dp->name)); + } + if (dp->device) { + g_ptr_array_add(argv_ptr, stralloc("--device")); + g_ptr_array_add(argv_ptr, stralloc(dp->device)); + } + if (level >= 0) { + g_snprintf(level_number, SIZEOF(level_number), "%d", level); + g_ptr_array_add(argv_ptr, stralloc("--level")); + g_ptr_array_add(argv_ptr, stralloc(level_number)); + } + + property_add_to_argv(argv_ptr, pp_script_get_property(pp_script)); + g_ptr_array_add(argv_ptr, NULL); + + scripterr = fileno(stderr); + scriptpid = pipespawnv(cmd, STDIN_PIPE|STDOUT_PIPE, 0, &scriptin, + &scriptout, &scripterr, + (char **)argv_ptr->pdata); + close(scriptin); + + streamout = fdopen(scriptout, "r"); + if (streamout) { + while((line = agets(streamout)) != NULL) { + dbprintf("script: %s\n", line); + amfree(line); + } + } + fclose(streamout); + waitpid(scriptpid, NULL, 0); + g_ptr_array_free_full(argv_ptr); + amfree(cmd); +} + + +void +run_server_dle_scripts( + execute_on_t execute_on, + char *config, + disk_t *dp, + int level) +{ + identlist_t pp_scriptlist; + + for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL; + pp_scriptlist = pp_scriptlist->next) { + pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data); + g_assert(pp_script != NULL); + run_server_script(pp_script, execute_on, config, dp, level); + } +} + +void +run_server_host_scripts( + execute_on_t execute_on, + char *config, + am_host_t *hostp) +{ + identlist_t pp_scriptlist; + disk_t *dp; + + GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, NULL); + for (dp = hostp->disks; dp != NULL; dp = dp->hostnext) { + if (dp->todo) { + for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL; + pp_scriptlist = pp_scriptlist->next) { + int todo = 1; + pp_script_t *pp_script = lookup_pp_script((char *)pp_scriptlist->data); + g_assert(pp_script != NULL); + if (pp_script_get_single_execution(pp_script)) { + todo = g_hash_table_lookup(executed, + pp_script_get_plugin(pp_script)) + == NULL; + } + if (todo) { + run_server_script(pp_script, execute_on, config, dp, -1); + if (pp_script_get_single_execution(pp_script)) { + g_hash_table_insert(executed, + pp_script_get_plugin(pp_script), + GINT_TO_POINTER(1)); + } + } + } + } + } + + g_hash_table_destroy(executed); +} + +void +run_server_global_scripts( + execute_on_t execute_on, + char *config) +{ + identlist_t pp_scriptlist; + disk_t *dp; + am_host_t *host; + + GHashTable* executed = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, NULL); + for (host = get_hostlist(); host != NULL; host = host->next) { + for (dp = host->disks; dp != NULL; dp = dp->hostnext) { + if (dp->todo) { + for (pp_scriptlist = dp->pp_scriptlist; pp_scriptlist != NULL; + pp_scriptlist = pp_scriptlist->next) { + int todo = 1; + pp_script_t *pp_script = + lookup_pp_script((char *)pp_scriptlist->data); + g_assert(pp_script != NULL); + if (pp_script_get_single_execution(pp_script)) { + todo = g_hash_table_lookup(executed, + pp_script_get_plugin(pp_script)) == NULL; + } + if (todo) { + run_server_script(pp_script, execute_on, config, + dp, -1); + if (pp_script_get_single_execution(pp_script)) { + g_hash_table_insert(executed, + pp_script_get_plugin(pp_script), + GINT_TO_POINTER(1)); + } + } + } + } + } + } + g_hash_table_destroy(executed); +} + +void +run_amcleanup( + char *config_name) +{ + pid_t amcleanup_pid; + char *amcleanup_program; + char *amcleanup_options[4]; + + switch(amcleanup_pid = fork()) { + case -1: + return; + break; + case 0: /* child process */ + amcleanup_program = vstralloc(sbindir, "/", "amcleanup", NULL); + amcleanup_options[0] = amcleanup_program; + amcleanup_options[1] = "-p"; + amcleanup_options[2] = config_name; + amcleanup_options[3] = NULL; + execve(amcleanup_program, amcleanup_options, safe_env()); + error("exec %s: %s", amcleanup_program, strerror(errno)); + /*NOTREACHED*/ + default: + break; + } + waitpid(amcleanup_pid, NULL, 0); +} + +char * +get_master_process( + char *logfile) +{ + FILE *log; + char line[1024]; + char *s, ch; + char *process_name; + + log = fopen(logfile, "r"); + if (!log) + return stralloc("UNKNOWN"); + + while(fgets(line, 1024, log)) { + if (strncmp_const(line, "INFO ") == 0) { + s = line+5; + ch = *s++; + process_name = s-1; + skip_non_whitespace(s, ch); + s[-1] = '\0'; + skip_whitespace(s, ch); + skip_non_whitespace(s, ch); + s[-1] = '\0'; + skip_whitespace(s, ch); + if (strncmp_const(s-1, "pid ") == 0) { + process_name = stralloc(process_name); + fclose(log); + return process_name; + } + } + } + fclose(log); + return stralloc("UNKNOWN"); +} + + +gint64 +internal_server_estimate( + disk_t *dp, + info_t *info, + int level, + int *stats) +{ + int j; + gint64 size = 0; + + *stats = 0; + + if (level == 0) { /* use latest level 0, should do extrapolation */ + gint64 est_size = (gint64)0; + int nb_est = 0; + + for (j=NB_HISTORY-2; j>=0; j--) { + if (info->history[j].level == 0) { + if (info->history[j].size < (gint64)0) continue; + est_size = info->history[j].size; + nb_est++; + } + } + if (nb_est > 0) { + size = est_size; + *stats = 1; + } else if (info->inf[level].size > (gint64)1000) { /* stats */ + size = info->inf[level].size; + *stats = 1; + } else { + char *conf_tapetype = getconf_str(CNF_TAPETYPE); + tapetype_t *tape = lookup_tapetype(conf_tapetype); + size = (gint64)1000000; + if (size > tapetype_get_length(tape)/2) + size = tapetype_get_length(tape)/2; + *stats = 0; + } + } else if (level == info->last_level) { + /* means of all X day at the same level */ + #define NB_DAY 30 + int nb_day = 0; + gint64 est_size_day[NB_DAY]; + int nb_est_day[NB_DAY]; + + for (j=0; j=0; j--) { + if (info->history[j].level <= 0) continue; + if (info->history[j].size < (gint64)0) continue; + if (info->history[j].level == info->history[j+1].level) { + if (nb_day history[j].size; + nb_est_day[nb_day]++; + } else { + nb_day=0; + } + } + nb_day = info->consecutive_runs + 1; + if (nb_day > NB_DAY-1) nb_day = NB_DAY-1; + + while (nb_day > 0 && nb_est_day[nb_day] == 0) nb_day--; + + if (nb_est_day[nb_day] > 0) { + size = est_size_day[nb_day] / (gint64)nb_est_day[nb_day]; + *stats = 1; + } + else if (info->inf[level].size > (gint64)1000) { /* stats */ + size = info->inf[level].size; + *stats = 1; + } + else { + int level0_stat; + gint64 level0_size; + char *conf_tapetype = getconf_str(CNF_TAPETYPE); + tapetype_t *tape = lookup_tapetype(conf_tapetype); + + level0_size = internal_server_estimate(dp, info, 0, &level0_stat); + size = (gint64)10000; + if (size > tapetype_get_length(tape)/2) + size = tapetype_get_length(tape)/2; + if (level0_size > 0 && dp->strategy != DS_NOFULL) { + if (size > level0_size/2) + size = level0_size/2; + } + *stats = 0; + } + } + else if (level == info->last_level + 1) { + /* means of all first day at a new level */ + gint64 est_size = (gint64)0; + int nb_est = 0; + + for (j=NB_HISTORY-2; j>=0; j--) { + if (info->history[j].level <= 0) continue; + if (info->history[j].size < (gint64)0) continue; + if (info->history[j].level == info->history[j+1].level + 1 ) { + est_size += info->history[j].size; + nb_est++; + } + } + if (nb_est > 0) { + size = est_size / (gint64)nb_est; + *stats = 1; + } else if (info->inf[level].size > (gint64)1000) { /* stats */ + size = info->inf[level].size; + *stats = 1; + } else { + int level0_stat; + gint64 level0_size; + char *conf_tapetype = getconf_str(CNF_TAPETYPE); + tapetype_t *tape = lookup_tapetype(conf_tapetype); + + level0_size = internal_server_estimate(dp, info, 0, &level0_stat); + size = (gint64)100000; + if (size > tapetype_get_length(tape)/2) + size = tapetype_get_length(tape)/2; + if (level0_size > 0 && dp->strategy != DS_NOFULL) { + if (size > level0_size/2) + size = level0_size/2; + } + *stats = 0; + } + } else { + char *conf_tapetype = getconf_str(CNF_TAPETYPE); + tapetype_t *tape = lookup_tapetype(conf_tapetype); + size = (gint64)100000; + if (size > tapetype_get_length(tape)/2) + size = tapetype_get_length(tape)/2; + } + + return size; +} + +int +server_can_do_estimate( + disk_t *dp, + info_t *info, + int level) +{ + int stats; + + internal_server_estimate(dp, info, level, &stats); + return stats; +} +