X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=server-src%2Famadmin.c;h=f51b17e7f8cc5b9eb88559e641c542039c2d6a96;hb=HEAD;hp=b7069b4c9b2cfacdc6988e606da832d0a8baac68;hpb=2627875b7d18858bc1f9f7652811e4d8c15a23eb;p=debian%2Famanda diff --git a/server-src/amadmin.c b/server-src/amadmin.c index b7069b4..f51b17e 100644 --- a/server-src/amadmin.c +++ b/server-src/amadmin.c @@ -1,6 +1,7 @@ /* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1991-1998 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 @@ -41,11 +42,15 @@ #include "find.h" #include "util.h" #include "timestamp.h" +#include "server_util.h" +#include disklist_t diskq; int main(int argc, char **argv); void usage(void); +static void estimate(int argc, char **argv); +static void estimate_one(disk_t *dp); void force(int argc, char **argv); void force_one(disk_t *dp); void unforce(int argc, char **argv); @@ -75,6 +80,8 @@ static int next_level0(disk_t *dp, info_t *info); int bump_thresh(int level); void export_db(int argc, char **argv); void import_db(int argc, char **argv); +void hosts(int argc, char **argv); +void dles(int argc, char **argv); void disklist(int argc, char **argv); void disklist_one(disk_t *dp); void show_version(int argc, char **argv); @@ -83,6 +90,13 @@ static void show_config(int argc, char **argv); static char *conf_tapelist = NULL; static char *displayunit; static long int unitdivisor; +static gboolean print_default = 1; +static gboolean print_source = 0; +static int opt_days = -1; +static char *opt_sort = NULL; +static gboolean exact_match = FALSE; +static gboolean opt_long = 0; +static gboolean opt_outdated = 0; static const struct { const char *name; @@ -93,6 +107,8 @@ static const struct { T_("\t\t\t\t\t# Show version info.") }, { "config", show_config, T_("\t\t\t\t\t# Show configuration.") }, + { "estimate", estimate, + T_(" [ []* ]*\t# Print server estimate.") }, { "force", force, T_(" [ []* ]+\t\t# Force level 0 at next run.") }, { "unforce", unforce, @@ -105,6 +121,10 @@ static const struct { T_(" [ []* ]+\t# Clear bump command.") }, { "disklist", disklist, T_(" [ []* ]*\t# Debug disklist entries.") }, + { "hosts", hosts, + T_("\t\t\t\t\t# Show all distinct hosts in disklist.") }, + { "dles", dles, + T_("\t\t\t\t\t# Show all dles in disklist, one per line.") }, { "reuse", reuse, T_(" ...\t\t # re-use this tape.") }, { "no-reuse", noreuse, @@ -132,6 +152,16 @@ static const struct { }; #define NCMDS (int)(sizeof(cmdtab) / sizeof(cmdtab[0])) +static struct option long_options[] = { + {"version" , 0, NULL, 1}, + {"no-default" , 0, NULL, 2}, + {"print-source" , 0, NULL, 3}, + {"days" , 1, NULL, 4}, + {"sort" , 1, NULL, 5}, + {"exact-match" , 0, NULL, 6}, + {NULL, 0, NULL, 0} +}; + int main( int argc, @@ -140,7 +170,7 @@ main( int i; char *conf_diskfile; char *conf_infofile; - config_overwrites_t *cfg_ovr = NULL; + config_overrides_t *cfg_ovr = NULL; /* * Configure program for internationalization: @@ -161,20 +191,51 @@ main( dbopen(DBG_SUBDIR_SERVER); - erroutput_type = ERR_INTERACTIVE; + add_amanda_log_handler(amanda_log_stderr); + + cfg_ovr = extract_commandline_config_overrides(&argc, &argv); + + while (1) { + int option_index = 0; + int c; + c = getopt_long(argc, argv, "ld", long_options, &option_index); + + if (c == -1) { + break; + } - cfg_ovr = extract_commandline_config_overwrites(&argc, &argv); + switch(c) { + case 1: printf("amadmin-%s\n", VERSION); + return 0; + case 2: print_default = 0; + break; + case 3: print_source = 1; + break; + case 4: opt_days = atoi(optarg); + break; + case 5: opt_sort = g_strdup(optarg); + break; + case 6: exact_match = TRUE; + break; + case 'l': opt_long = TRUE; + break; + case 'd': opt_outdated = TRUE; + break; + default: usage(); + } + } + argc -= optind-1, argv += optind-1; if(argc < 3) usage(); + set_config_overrides(cfg_ovr); + config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]); + if(strcmp(argv[2],"version") == 0) { show_version(argc, argv); goto done; } - config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]); - apply_config_overwrites(cfg_ovr); - conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE)); read_diskfile(conf_diskfile, &diskq); amfree(conf_diskfile); @@ -235,8 +296,8 @@ usage(void) { int i; - g_fprintf(stderr, _("\nUsage: %s%s {} [-o configoption]* ...\n"), - get_pname(), versionsuffix()); + g_fprintf(stderr, _("\nUsage: %s [--version] [--exact-match] [--no-default] [--print-source] [-o configoption]*\n {} ...\n"), + get_pname()); g_fprintf(stderr, _(" Valid s are:\n")); for (i = 0; i < NCMDS; i++) g_fprintf(stderr, "\t%s%s\n", cmdtab[i].name, _(cmdtab[i].usage)); @@ -313,7 +374,7 @@ diskloop( usage(); } - errstr = match_disklist(&diskq, argc-3, argv+3); + errstr = match_disklist(&diskq, exact_match, argc-3, argv+3); if (errstr) { g_printf("%s", errstr); amfree(errstr); @@ -333,6 +394,64 @@ diskloop( /* ----------------------------------------------- */ +static void +estimate_one( + disk_t * dp) +{ + char *hostname = dp->host->hostname; + char *diskname = dp->name; + char *qhost = quote_string(hostname); + char *qdisk = quote_string(diskname); + info_t info; + int stats; + gint64 size; + + get_info(hostname, diskname, &info); + + size = internal_server_estimate(dp, &info, 0, &stats); + if (stats) { + printf("%s %s %d %jd\n", qhost, qdisk, 0, (intmax_t)size); + } + + if (info.last_level > 0) { + size = internal_server_estimate(dp, &info, info.last_level, &stats); + if (stats) { + printf("%s %s %d %jd\n", qhost, qdisk, info.last_level, + (intmax_t)size); + } + } + + if (info.last_level > -1) { + size = internal_server_estimate(dp, &info, info.last_level+1, &stats); + if (stats) { + printf("%s %s %d %jd\n", qhost, qdisk, info.last_level+1, + (intmax_t)size); + } + } + + amfree(qhost); + amfree(qdisk); +} + + +static void +estimate( + int argc, + char ** argv) +{ + disk_t *dp; + + if(argc >= 4) + diskloop(argc, argv, "estimate", estimate_one); + else + for(dp = diskq.head; dp != NULL; dp = dp->next) + estimate_one(dp); +} + + +/* ----------------------------------------------- */ + + void force_one( disk_t * dp) @@ -829,8 +948,8 @@ tape( void balance( - int argc, - char ** argv) + int argc G_GNUC_UNUSED, + char ** argv G_GNUC_UNUSED) { disk_t *dp; struct balance_stats { @@ -852,9 +971,10 @@ balance( overdue = 0; max_overdue = 0; - if(argc > 4 && strcmp(argv[3],"--days") == 0) { - later = atoi(argv[4]); - if(later < 0) later = conf_dumpcycle; + if (opt_days > 0) { + later = opt_days; + } else if (opt_days == 0) { + later = conf_dumpcycle; } if(later > 10000) later = 10000; @@ -1037,6 +1157,8 @@ find( char *sort_order = NULL; find_result_t *output_find; char *errstr; + char **output_find_log; + char **name; if(argc < 3) { g_fprintf(stderr, @@ -1047,11 +1169,11 @@ find( sort_order = newstralloc(sort_order, DEFAULT_SORT_ORDER); - if(argc > 4 && strcmp(argv[3],"--sort") == 0) { + if (opt_sort) { size_t i, valid_sort=1; - for(i = strlen(argv[4]); i > 0; i--) { - switch (argv[4][i - 1]) { + for(i = strlen(opt_sort); i > 0; i--) { + switch (opt_sort[i - 1]) { case 'h': case 'H': case 'k': @@ -1073,31 +1195,51 @@ find( } } if(valid_sort) { - sort_order = newstralloc(sort_order, argv[4]); + sort_order = newstralloc(sort_order, opt_sort); } else { - g_printf(_("Invalid sort order: %s\n"), argv[4]); + g_printf(_("Invalid sort order: %s\n"), opt_sort); g_printf(_("Use default sort order: %s\n"), sort_order); } - start_argc=6; - } else { - start_argc=4; } - errstr = match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1)); - if (errstr) { - g_printf("%s", errstr); - amfree(errstr); + start_argc=4; + errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1), + argv+(start_argc-1)); + + /* check all log file exists */ + output_find_log = find_log(); + for (name = output_find_log; *name != NULL; name++) { + amfree(*name); } + amfree(output_find_log); - output_find = find_dump(&diskq); + output_find = find_dump(&diskq); /* Add deleted dump to diskq */ if(argc-(start_argc-1) > 0) { - free_find_result(&output_find); - errstr = match_disklist(&diskq, argc-(start_argc-1), - argv+(start_argc-1)); + find_result_t *afind = NULL; + find_result_t *afind_next = NULL; + find_result_t *new_output_find = NULL; + disk_t *dp; + + amfree(errstr); + errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1), + argv+(start_argc-1)); if (errstr) { g_printf("%s", errstr); amfree(errstr); } - output_find = find_dump(NULL); + for (afind = output_find; afind; afind = afind_next) { + afind_next = afind->next; + dp = lookup_disk(afind->hostname, afind->diskname); + if (dp->todo) { + afind->next = new_output_find; + new_output_find = afind; + } else { + amfree(afind); + } + } + output_find = new_output_find; + } else if (errstr) { + g_printf("%s", errstr); + amfree(errstr); } sort_find_result(sort_order, &output_find); @@ -1114,7 +1256,8 @@ static GSList * get_file_list( int argc, char **argv, - int allow_empty) + int allow_empty, + gboolean exact_match) { GSList * file_list = NULL; GSList * dumplist; @@ -1122,6 +1265,7 @@ get_file_list( flags = CMDLINE_PARSE_DATESTAMP; if (allow_empty) flags |= CMDLINE_EMPTY_TO_WILDCARD; + if (exact_match) flags |= CMDLINE_EXACT_MATCH; dumplist = cmdline_parse_dumpspecs(argc, argv, flags); file_list = cmdline_match_holding(dumplist); @@ -1362,22 +1506,9 @@ holding( return; case HOLDING_LIST: + long_list = opt_long; + outdated_list = opt_outdated; argc -= 4; argv += 4; - while (argc && argv[0][0] == '-') { - switch (argv[0][1]) { - case 'l': - long_list = 1; - break; - case 'd': /* have to use '-d', and not '-o', because of parse_config */ - outdated_list = 1; - break; - default: - g_fprintf(stderr, _("Unknown option -%c\n"), argv[0][1]); - usage(); - return; - } - argc--; argv++; - } /* header */ if (long_list) { @@ -1385,7 +1516,7 @@ holding( _("size (kB)"), _("lv"), _("outd"), _("dump specification")); } - file_list = get_file_list(argc, argv, 1); + file_list = get_file_list(argc, argv, 1, exact_match); for (li = file_list; li != NULL; li = li->next) { char *dumpstr; int is_outdated; @@ -1414,13 +1545,13 @@ holding( amfree(dumpstr); dumpfile_free_data(&file); } - g_slist_free_full(file_list); + slist_free_full(file_list, g_free); break; case HOLDING_DELETE: argc -= 4; argv += 4; - file_list = get_file_list(argc, argv, 0); + file_list = get_file_list(argc, argv, 0, exact_match); for (li = file_list; li != NULL; li = li->next) { g_fprintf(stderr, _("Deleting '%s'\n"), (char *)li->data); /* remove it from the catalog */ @@ -1432,7 +1563,7 @@ holding( error(_("Could not delete '%s'"), (char *)li->data); } } - g_slist_free_full(file_list); + slist_free_full(file_list, g_free); break; } } @@ -1447,7 +1578,7 @@ int bump_thresh( int level) { - int bump = getconf_int(CNF_BUMPSIZE); + gint64 bump = getconf_int64(CNF_BUMPSIZE); double mult = getconf_real(CNF_BUMPMULT); while(--level) @@ -1469,8 +1600,8 @@ bumpsize( g_printf(_("Current bump parameters:\n")); if(conf_bumppercent == 0) { - g_printf(_(" bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n"), - getconf_int(CNF_BUMPSIZE)); + g_printf(_(" bumpsize %5jd KB\t- minimum savings (threshold) to bump level 1 -> 2\n"), + (intmax_t)getconf_int64(CNF_BUMPSIZE)); g_printf(_(" bumpdays %5d\t- minimum days at each level\n"), getconf_int(CNF_BUMPDAYS)); g_printf(_(" bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n"), @@ -1514,7 +1645,7 @@ export_db( char hostname[MAX_HOSTNAME_LENGTH+1]; int i; - g_printf(_("CURINFO Version %s CONF %s\n"), version(), getconf_str(CNF_ORG)); + g_printf(_("CURINFO Version %s CONF %s\n"), VERSION, getconf_str(CNF_ORG)); curtime = time(0); if(gethostname(hostname, SIZEOF(hostname)-1) == -1) { @@ -1544,13 +1675,16 @@ export_one( { info_t info; int i,l; + char *qhost, *qdisk; if(get_info(dp->host->hostname, dp->name, &info)) { g_fprintf(stderr, _("Warning: no curinfo record for %s:%s\n"), dp->host->hostname, dp->name); return; } - g_printf(_("host: %s\ndisk: %s\n"), dp->host->hostname, dp->name); + qhost = quote_string(dp->host->hostname); + qdisk = quote_string(dp->name); + g_printf(_("host: %s\ndisk: %s\n"), qhost, qdisk); g_printf(_("command: %u\n"), info.command); g_printf(_("last_level: %d\n"),info.last_level); g_printf(_("consecutive_runs: %d\n"),info.consecutive_runs); @@ -1582,6 +1716,8 @@ export_one( (intmax_t)info.history[l].date); } g_printf("//\n"); + amfree(qhost); + amfree(qdisk); } /* ----------------------------------------------- */ @@ -1626,7 +1762,10 @@ import_db( skip_whitespace(s, ch); if(ch == '\0' || sscanf(s - 1, "%d.%d.%d", &vers_maj, &vers_min, &vers_patch) != 3) { - goto bad_header; + vers_patch = -1; + if (sscanf(s - 1, "%d.%d", &vers_maj, &vers_min) != 2) { + goto bad_header; + } } skip_integer(s, ch); /* skip over major */ @@ -1635,11 +1774,15 @@ import_db( } ch = *s++; skip_integer(s, ch); /* skip over minor */ - if(ch != '.') { - goto bad_header; + if (vers_patch != -1) { + if (ch != '.') { + goto bad_header; + } + ch = *s++; + skip_integer(s, ch); /* skip over patch */ + } else { + vers_patch = 0; } - ch = *s++; - skip_integer(s, ch); /* skip over patch */ hdr = "comment"; if(ch == '\0') { @@ -1728,9 +1871,9 @@ import_one(void) skip_whitespace(s, ch); if(ch == '\0') goto parse_err; fp = s-1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; - hostname = stralloc(fp); + hostname = unquote_string(fp); s[-1] = (char)ch; skip_whitespace(s, ch); @@ -1745,9 +1888,9 @@ import_one(void) skip_whitespace(s, ch); if(ch == '\0') goto parse_err; fp = s-1; - skip_non_whitespace(s, ch); + skip_quoted_string(s, ch); s[-1] = '\0'; - diskname = stralloc(fp); + diskname = unquote_string(fp); s[-1] = (char)ch; amfree(line); @@ -1988,13 +2131,12 @@ disklist_one( { am_host_t *hp; netif_t *ip; - sle_t *excl; - pp_scriptlist_t pp_scriptlist; + dumptype_t *dtype = lookup_dumptype(dp->dtype_name); hp = dp->host; ip = hp->netif; - g_printf("line %d:\n", dp->line); + g_printf("line %d (%s):\n", dp->line, dp->filename); g_printf(" host %s:\n", hp->hostname); g_printf(" interface %s\n", @@ -2004,177 +2146,11 @@ disklist_one( g_printf(" program \"%s\"\n", dp->program); if (dp->application) - g_printf(" application \"%s\"\n", application_name(dp->application)); - if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) { - g_printf(" exclude file"); - for(excl = dp->exclude_file->first; excl != NULL; excl = excl->next) { - g_printf(" \"%s\"", excl->name); - } - g_printf("\n"); - } - if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) { - g_printf(" exclude list"); - if(dp->exclude_optional) g_printf(" optional"); - for(excl = dp->exclude_list->first; excl != NULL; excl = excl->next) { - g_printf(" \"%s\"", excl->name); - } - g_printf("\n"); - } - if (dp->include_file != NULL && dp->include_file->nb_element > 0) { - g_printf(" include file"); - for(excl = dp->include_file->first; excl != NULL; excl = excl->next) { - g_printf(" \"%s\"", excl->name); - } - g_printf("\n"); - } - if (dp->include_list != NULL && dp->include_list->nb_element > 0) { - g_printf(" include list"); - if (dp->include_optional) g_printf(" optional"); - for(excl = dp->include_list->first; excl != NULL; excl = excl->next) { - g_printf(" \"%s\"", excl->name); - } - g_printf("\n"); - } - g_printf(" priority %d\n", dp->priority); - g_printf(" dumpcycle %d\n", dp->dumpcycle); - g_printf(" maxdumps %d\n", dp->maxdumps); - g_printf(" maxpromoteday %d\n", dp->maxpromoteday); - if (dp->bumppercent > 0) { - g_printf(" bumppercent %d\n", dp->bumppercent); - } - else { - g_printf(" bumpsize %lld\n", - (long long)dp->bumpsize); - } - g_printf(" bumpdays %d\n", dp->bumpdays); - g_printf(" bumpmult %lf\n", dp->bumpmult); - - g_printf(" strategy "); - switch(dp->strategy) { - case DS_SKIP: - g_printf("SKIP\n"); - break; - case DS_STANDARD: - g_printf("STANDARD\n"); - break; - case DS_NOFULL: - g_printf("NOFULL\n"); - break; - case DS_NOINC: - g_printf("NOINC\n"); - break; - case DS_HANOI: - g_printf("HANOI\n"); - break; - case DS_INCRONLY: - g_printf("INCRONLY\n"); - break; - } - g_printf(" ignore %s\n", (dp->ignore? "YES" : "NO")); - g_printf(" estimate "); - switch(dp->estimate) { - case ES_CLIENT: - g_printf("CLIENT\n"); - break; - case ES_SERVER: - g_printf("SERVER\n"); - break; - case ES_CALCSIZE: - g_printf("CALCSIZE\n"); - break; - } - - g_printf(" compress "); - switch(dp->compress) { - case COMP_NONE: - g_printf("NONE\n"); - break; - case COMP_FAST: - g_printf("CLIENT FAST\n"); - break; - case COMP_BEST: - g_printf("CLIENT BEST\n"); - break; - case COMP_SERVER_FAST: - g_printf("SERVER FAST\n"); - break; - case COMP_SERVER_BEST: - g_printf("SERVER BEST\n"); - break; - } - if(dp->compress != COMP_NONE) { - g_printf(" comprate %.2lf %.2lf\n", - dp->comprate[0], dp->comprate[1]); - } - - g_printf(" encrypt "); - switch(dp->encrypt) { - case ENCRYPT_NONE: - g_printf("NONE\n"); - break; - case ENCRYPT_CUST: - g_printf("CLIENT\n"); - break; - case ENCRYPT_SERV_CUST: - g_printf("SERVER\n"); - break; - } - - g_printf(" auth %s\n", dp->security_driver); - g_printf(" kencrypt %s\n", (dp->kencrypt? "YES" : "NO")); - g_printf(" amandad_path %s\n", dp->amandad_path); - g_printf(" client_username %s\n", dp->client_username); - g_printf(" ssh_keys %s\n", dp->ssh_keys); - - g_printf(" holdingdisk "); - switch(dp->to_holdingdisk) { - case HOLD_NEVER: - g_printf("NEVER\n"); - break; - case HOLD_AUTO: - g_printf("AUTO\n"); - break; - case HOLD_REQUIRED: - g_printf("REQUIRED\n"); - break; - } - - g_printf(" record %s\n", (dp->record? "YES" : "NO")); - g_printf(" index %s\n", (dp->index? "YES" : "NO")); - g_printf(" starttime %04d\n", (int)dp->starttime); - if(dp->tape_splitsize > (off_t)0) { - g_printf(" tape_splitsize %lld\n", - (long long)dp->tape_splitsize); - } - if(dp->split_diskbuffer) { - g_printf(" split_diskbuffer %s\n", dp->split_diskbuffer); - } - if(dp->fallback_splitsize > (off_t)0) { - g_printf(" fallback_splitsize %lldMb\n", - (long long)(dp->fallback_splitsize / (off_t)1024)); - } - g_printf(" skip-incr %s\n", (dp->skip_incr? "YES" : "NO")); - g_printf(" skip-full %s\n", (dp->skip_full? "YES" : "NO")); + g_printf(" application \"%s\"\n", dp->application); + + dump_dumptype(dtype, " ", print_default, print_source); + g_printf(" spindle %d\n", dp->spindle); - pp_scriptlist = dp->pp_scriptlist; - while (pp_scriptlist != NULL) { - g_printf(" script \"%s\"\n", (pp_script_name(pp_scriptlist->data))); - pp_scriptlist = pp_scriptlist->next; - } - - { - dumptype_t *dtype; - char **prop, **p1;; - - dtype = lookup_dumptype(dp->dtype_name); - prop = val_t_display_strs(dumptype_getconf((dtype), DUMPTYPE_PROPERTY), - 0); - for(p1 = prop; *p1 != NULL; p1++) { - g_printf(" property %s\n", *p1); - free(*p1); - } - amfree(prop); - } g_printf("\n"); } @@ -2193,6 +2169,44 @@ disklist( disklist_one(dp); } +/* ----------------------------------------------- */ + +void +hosts( + int argc G_GNUC_UNUSED, + char ** argv G_GNUC_UNUSED) +{ + disk_t *dp; + gint sentinel = 1; + GHashTable *seen = g_hash_table_new(g_str_hash, g_str_equal); + + /* enumerate all hosts, skipping those that have been seen (since + * there may be more than one DLE on a host */ + for(dp = diskq.head; dp != NULL; dp = dp->next) { + char *hostname = dp->host->hostname; + if (g_hash_table_lookup(seen, hostname)) + continue; + g_printf("%s\n", hostname); + g_hash_table_insert(seen, hostname, &sentinel); + } + g_hash_table_destroy(seen); +} + +/* ----------------------------------------------- */ + +void +dles( + int argc G_GNUC_UNUSED, + char ** argv G_GNUC_UNUSED) +{ + disk_t *dp; + + for(dp = diskq.head; dp != NULL; dp = dp->next) + g_printf("%s %s\n", dp->host->hostname, dp->name); +} + +/* ----------------------------------------------- */ + void show_version( int argc, @@ -2212,6 +2226,6 @@ void show_config( int argc G_GNUC_UNUSED, char **argv G_GNUC_UNUSED) { - dump_configuration(); + dump_configuration(print_default, print_source); }