#include "timestamp.h"
#include "amxml.h"
#include "physmem.h"
+#include <getopt.h>
#define BUFFER_SIZE 32768
void
usage(void)
{
- g_printf(_("Usage: amcheck [-am] [-w] [-sclt] [-M <address>] [-o configoption]* <conf> [host [disk]* ]*\n"));
+ g_printf(_("Usage: amcheck [--version] [-am] [-w] [-sclt] [-M <address>] [--client-verbose] [-o configoption]* <conf> [host [disk]* ]*\n"));
exit(1);
/*NOTREACHED*/
}
static char *displayunit;
static long int unitdivisor;
+static int client_verbose = FALSE;
+static struct option long_options[] = {
+ {"client-verbose", 0, NULL, 1},
+ {"version" , 0, NULL, 2},
+ {NULL, 0, NULL, 0}
+};
+
int
main(
int argc,
int do_clientchk, client_probs;
int do_localchk, do_tapechk, server_probs;
pid_t clientchk_pid, serverchk_pid;
- int opt, tempfd, mainfd;
+ int tempfd, mainfd;
size_t size;
amwait_t retstat;
pid_t pid;
/* process arguments */
cfg_ovr = new_config_overrides(argc/2);
- while((opt = getopt(argc, argv, "M:mawsclto:")) != EOF) {
- switch(opt) {
+ while (1) {
+ int option_index = 0;
+ int c;
+ c = getopt_long (argc, argv, "M:mawsclto:", long_options, &option_index);
+ if (c == -1) {
+ break;
+ }
+
+ switch(c) {
+ case 1: client_verbose = TRUE;
+ break;
+ case 2: printf("amcheck-%s\n", VERSION);
+ return(0);
+ break;
case 'M': if (mailto) {
g_printf(_("Multiple -M options\n"));
exit(1);
tapetype_t *tp = NULL;
char *quoted;
int res;
- intmax_t kb_avail;
+ intmax_t kb_avail, kb_needed;
off_t tape_size;
+ gboolean printed_small_part_size_warning = FALSE;
+ char *small_part_size_warning =
+ _(" This may create > 1000 parts, severely degrading backup/restore performance.\n"
+ " See http://wiki.zmanda.com/index.php/Splitsize_too_small for more information.\n");
switch(pid = fork()) {
case -1:
startclock();
+ /* server does not need root privileges, and the access() calls below use the real userid,
+ * so totally drop privileges at this point (making the userid equal to the dumpuser) */
+ set_root_privs(-1);
+
if((outf = fdopen(fd, "w")) == NULL) {
error(_("fdopen %d: %s"), fd, strerror(errno));
/*NOTREACHED*/
if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
getconf_int(CNF_FLUSH_THRESHOLD_DUMPED)) {
- g_fprintf(outf, _("WARNING: flush_threshold_dumped (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"),
+ g_fprintf(outf, _("WARNING: flush-threshold-dumped (%d) must be less than or equal to flush-threshold-scheduled (%d).\n"),
getconf_int(CNF_FLUSH_THRESHOLD_DUMPED),
getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
}
if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
getconf_int(CNF_TAPERFLUSH)) {
- g_fprintf(outf, _("WARNING: taperflush (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"),
+ g_fprintf(outf, _("WARNING: taperflush (%d) must be less than or equal to flush-threshold-scheduled (%d).\n"),
getconf_int(CNF_TAPERFLUSH),
getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
}
if (getconf_int(CNF_TAPERFLUSH) > 0 &&
- !getconf_boolean(CNF_AUTOFLUSH)) {
- g_fprintf(outf, _("WARNING: autoflush must be set to 'yes' if taperflush (%d) is greater that 0.\n"),
+ !getconf_no_yes_all(CNF_AUTOFLUSH)) {
+ g_fprintf(outf, _("WARNING: autoflush must be set to 'yes' or 'all' if taperflush (%d) is greater that 0.\n"),
getconf_int(CNF_TAPERFLUSH));
}
"the 'tapetype' parameter\n"));
confbad = 1;
}
-
}
/*
char *holdfile;
char * tapename;
struct stat statbuf;
-
+ guint64 part_size, part_cache_max_size, tape_size;
+ part_cache_type_t part_cache_type;
+ char *part_cache_dir;
+
tapefile = config_dir_relative(getconf_str(CNF_TAPELIST));
/*
* XXX There Really Ought to be some error-checking here... dhw
do_tapechk = 0;
}
}
+
+ /* check tapetype-based splitting parameters */
+ part_size = tapetype_get_part_size(tp);
+ part_cache_type = tapetype_get_part_cache_type(tp);
+ part_cache_dir = tapetype_get_part_cache_dir(tp);
+ part_cache_max_size = tapetype_get_part_cache_max_size(tp);
+
+ if (!tapetype_seen(tp, TAPETYPE_PART_SIZE)) {
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_TYPE)) {
+ g_fprintf(outf, "ERROR: part-cache-type specified, but no part-size\n");
+ tapebad = 1;
+ }
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)) {
+ g_fprintf(outf, "ERROR: part-cache-dir specified, but no part-size\n");
+ tapebad = 1;
+ }
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ g_fprintf(outf, "ERROR: part-cache-max-size specified, but no part-size\n");
+ tapebad = 1;
+ }
+ } else {
+ switch (part_cache_type) {
+ case PART_CACHE_TYPE_DISK:
+ if (!tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)
+ || !part_cache_dir || !*part_cache_dir) {
+ g_fprintf(outf,
+ "ERROR: part-cache-type is DISK, but no part-cache-dir specified\n");
+ tapebad = 1;
+ } else {
+ if(get_fs_usage(part_cache_dir, NULL, &fsusage) == -1) {
+ g_fprintf(outf, "ERROR: part-cache-dir '%s': %s\n",
+ part_cache_dir, strerror(errno));
+ tapebad = 1;
+ } else {
+ kb_avail = fsusage.fsu_bavail_top_bit_set?
+ 0 : fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize;
+ kb_needed = part_size;
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ kb_needed = part_cache_max_size;
+ }
+ if (kb_avail < kb_needed) {
+ g_fprintf(outf,
+ "ERROR: part-cache-dir has %ju %sB available, but needs %ju %sB\n",
+ kb_avail/(uintmax_t)unitdivisor, displayunit,
+ kb_needed/(uintmax_t)unitdivisor, displayunit);
+ tapebad = 1;
+ }
+ }
+ }
+ break;
+
+ case PART_CACHE_TYPE_MEMORY:
+ kb_avail = physmem_total() / 1024;
+ kb_needed = part_size;
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ kb_needed = part_cache_max_size;
+ }
+ if (kb_avail < kb_needed) {
+ g_fprintf(outf,
+ "ERROR: system has %ju %sB memory, but part cache needs %ju %sB\n",
+ kb_avail/(uintmax_t)unitdivisor, displayunit,
+ kb_needed/(uintmax_t)unitdivisor, displayunit);
+ tapebad = 1;
+ }
+
+ /* FALL THROUGH */
+
+ case PART_CACHE_TYPE_NONE:
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_DIR)) {
+ g_fprintf(outf,
+ "ERROR: part-cache-dir specified, but part-cache-type is not DISK\n");
+ tapebad = 1;
+ }
+ break;
+ }
+ }
+
+ if (tapetype_seen(tp, TAPETYPE_PART_SIZE) && part_size == 0
+ && part_cache_type != PART_CACHE_TYPE_NONE) {
+ g_fprintf(outf,
+ "ERROR: part_size is zero, but part-cache-type is not 'none'\n");
+ tapebad = 1;
+ }
+
+ if (tapetype_seen(tp, TAPETYPE_PART_CACHE_MAX_SIZE)) {
+ if (part_cache_type == PART_CACHE_TYPE_NONE) {
+ g_fprintf(outf,
+ "ERROR: part-cache-max-size is specified but no part cache is in use\n");
+ tapebad = 1;
+ }
+
+ if (part_cache_max_size > part_size) {
+ g_fprintf(outf,
+ "WARNING: part-cache-max-size is greater than part-size\n");
+ }
+ }
+
+ tape_size = tapetype_get_length(tp);
+ if (part_size && part_size * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: part-size of %ju %sB < 0.1%% of tape length.\n"),
+ (uintmax_t)part_size/(uintmax_t)unitdivisor, displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ } else if (part_cache_max_size && part_cache_max_size * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: part-cache-max-size of %ju %sB < 0.1%% of tape length.\n"),
+ (uintmax_t)part_cache_max_size/(uintmax_t)unitdivisor, displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
+ }
}
/* check available disk space */
char *disk;
int conf_tapecycle, conf_runspercycle;
identlist_t pp_scriptlist;
- gboolean printed_small_tape_splitsize_warning = FALSE;
- char *small_tape_splitsize_warning =
- _(" This may create > 1000 parts, severely degrading backup/restore performance.\n"
- " To remedy, increase tape_splitsize or disable splitting by setting it to 0\n"
- " See http://wiki.zmanda.com/index.php/Splitsize_too_small for more information.\n");
-
- gboolean printed_small_fallback_splitsize_warning = FALSE;
- char *small_fallback_splitsize_warning =
- _(" This may create > 1000 parts, severely degrading backup/restore performance.\n"
- " To remedy, create/set a split_diskbuffer or increase fallback_splitsize\n"
- " See http://wiki.zmanda.com/index.php/Splitsize_too_small for more information.\n");
-
conf_tapecycle = getconf_int(CNF_TAPECYCLE);
conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE);
if ( dp->encrypt == ENCRYPT_SERV_CUST ) {
if ( dp->srv_encrypt[0] == '\0' ) {
g_fprintf(outf, _("ERROR: server encryption program not specified\n"));
- g_fprintf(outf, _("Specify \"server_custom_encrypt\" in the dumptype\n"));
+ g_fprintf(outf, _("Specify \"server-custom-encrypt\" in the dumptype\n"));
pgmbad = 1;
}
else if(access(dp->srv_encrypt, X_OK) == -1) {
if ( dp->srvcompprog[0] == '\0' ) {
g_fprintf(outf, _("ERROR: server custom compression program "
"not specified\n"));
- g_fprintf(outf, _("Specify \"server_custom_compress\" in "
+ g_fprintf(outf, _("Specify \"server-custom-compress\" in "
"the dumptype\n"));
pgmbad = 1;
}
}
}
- /* check tape_splitsize */
- tape_size = tapetype_get_length(tp);
- if (dp->tape_splitsize > tape_size) {
- g_fprintf(outf,
- _("ERROR: %s %s: tape_splitsize > tape size\n"),
- hostp->hostname, dp->name);
- pgmbad = 1;
- }
- if (dp->tape_splitsize && dp->fallback_splitsize * 1024 > physmem_total()) {
- g_fprintf(outf,
- _("ERROR: %s %s: fallback_splitsize > total available memory\n"),
- hostp->hostname, dp->name);
- pgmbad = 1;
- }
- if (dp->tape_splitsize && dp->fallback_splitsize > tape_size) {
- g_fprintf(outf,
- _("ERROR: %s %s: fallback_splitsize > tape size\n"),
- hostp->hostname, dp->name);
- pgmbad = 1;
- }
+ /* check deprecated splitting parameters */
+ if (dumptype_seen(dp->config, DUMPTYPE_TAPE_SPLITSIZE)
+ || dumptype_seen(dp->config, DUMPTYPE_SPLIT_DISKBUFFER)
+ || dumptype_seen(dp->config, DUMPTYPE_FALLBACK_SPLITSIZE)) {
+ tape_size = tapetype_get_length(tp);
+ if (dp->tape_splitsize > tape_size) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: tape-splitsize > tape size\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->tape_splitsize && dp->fallback_splitsize * 1024 > physmem_total()) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: fallback-splitsize > total available memory\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
+ if (dp->tape_splitsize && dp->fallback_splitsize > tape_size) {
+ g_fprintf(outf,
+ _("ERROR: %s %s: fallback-splitsize > tape size\n"),
+ hostp->hostname, dp->name);
+ pgmbad = 1;
+ }
- /* also check for part sizes that are too small */
- if (dp->tape_splitsize && dp->tape_splitsize * 1000 < tape_size) {
- g_fprintf(outf,
- _("WARNING: %s %s: tape_splitsize of %ju %sB < 0.1%% of tape length.\n"),
- hostp->hostname, dp->name,
- (uintmax_t)dp->tape_splitsize/(uintmax_t)unitdivisor,
- displayunit);
- if (!printed_small_tape_splitsize_warning) {
- printed_small_tape_splitsize_warning = TRUE;
- g_fprintf(outf, "%s", small_tape_splitsize_warning);
+ /* also check for part sizes that are too small */
+ if (dp->tape_splitsize && dp->tape_splitsize * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: %s %s: tape-splitsize of %ju %sB < 0.1%% of tape length.\n"),
+ hostp->hostname, dp->name,
+ (uintmax_t)dp->tape_splitsize/(uintmax_t)unitdivisor,
+ displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
}
- }
- /* fallback splitsize will be used if split_diskbuffer is empty or NULL */
- if (dp->tape_splitsize != 0 && dp->fallback_splitsize != 0 &&
- (dp->split_diskbuffer == NULL ||
- dp->split_diskbuffer[0] == '\0') &&
- dp->fallback_splitsize * 1000 < tape_size) {
- g_fprintf(outf,
- _("WARNING: %s %s: fallback_splitsize of %ju %sB < 0.1%% of tape length.\n"),
- hostp->hostname, dp->name,
- (uintmax_t)dp->fallback_splitsize/(uintmax_t)unitdivisor,
- displayunit);
- if (!printed_small_fallback_splitsize_warning) {
- printed_small_fallback_splitsize_warning = TRUE;
- g_fprintf(outf, "%s", small_fallback_splitsize_warning);
+ /* fallback splitsize will be used if split_diskbuffer is empty or NULL */
+ if (dp->tape_splitsize != 0 && dp->fallback_splitsize != 0 &&
+ (dp->split_diskbuffer == NULL ||
+ dp->split_diskbuffer[0] == '\0') &&
+ dp->fallback_splitsize * 1000 < tape_size) {
+ g_fprintf(outf,
+ _("WARNING: %s %s: fallback-splitsize of %ju %sB < 0.1%% of tape length.\n"),
+ hostp->hostname, dp->name,
+ (uintmax_t)dp->fallback_splitsize/(uintmax_t)unitdivisor,
+ displayunit);
+ if (!printed_small_part_size_warning) {
+ printed_small_part_size_warning = TRUE;
+ g_fprintf(outf, "%s", small_part_size_warning);
+ }
}
}
_("ERROR: %s %s: Holding disk can't be use for directtcp data-path\n"),
hostp->hostname, dp->name);
pgmbad = 1;
- } else if (dp->to_holdingdisk == HOLD_AUTO) {
- g_fprintf(outf,
- _("WARNING: %s %s: Holding disk can't be use for directtcp data-path\n"),
- hostp->hostname, dp->name);
- pgmbad = 1;
}
}
g_fprintf(outf,
_("ERROR: application '%s' not found.\n"), dp->application);
} else {
+ char *client_name = application_get_client_name(application);
+ if (client_name && strlen(client_name) > 0 &&
+ !am_has_feature(hostp->features, fe_application_client_name)) {
+ g_fprintf(outf,
+ _("WARNING: %s:%s does not support client-name in application.\n"),
+ hostp->hostname, qname);
+ }
xml_app = xml_application(dp, application, hostp->features);
vstrextend(&l, xml_app, NULL);
amfree(xml_app);
g_fprintf(outf,
_("ERROR: %s:%s does not support SCRIPT-API.\n"),
hostp->hostname, qname);
+ } else {
+ 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);
+ char *client_name = pp_script_get_client_name(pp_script);;
+ if (client_name && strlen(client_name) > 0 &&
+ !am_has_feature(hostp->features, fe_script_client_name)) {
+ g_fprintf(outf,
+ _("WARNING: %s:%s does not support client-name in script.\n"),
+ hostp->hostname, dp->name);
+ }
+ }
}
}
es = xml_estimate(dp->estimatelist, hostp->features);
}
amfree(qname);
amfree(qdevice);
+ amfree(b64disk);
+ amfree(b64device);
l_len = strlen(l);
amfree(o);
g_fprintf(outf, _("\nAmanda Backup Client Hosts Check\n"));
g_fprintf(outf, "--------------------------------\n");
+ run_server_global_scripts(EXECUTE_ON_PRE_AMCHECK, get_config_name());
protocol_init();
hostcount = remote_errors = 0;
for(dp = origq.head; dp != NULL; dp = dp->next) {
hostp = dp->host;
if(hostp->up == HOST_READY && dp->todo == 1) {
+ run_server_host_scripts(EXECUTE_ON_PRE_HOST_AMCHECK,
+ get_config_name(), hostp);
for(dp1 = hostp->disks; dp1 != NULL; dp1 = dp1->hostnext) {
- run_server_scripts(EXECUTE_ON_PRE_HOST_AMCHECK,
- get_config_name(), dp1, -1);
- }
- for(dp1 = hostp->disks; dp1 != NULL; dp1 = dp1->hostnext) {
- run_server_scripts(EXECUTE_ON_PRE_DLE_AMCHECK,
+ run_server_dle_scripts(EXECUTE_ON_PRE_DLE_AMCHECK,
get_config_name(), dp1, -1);
}
start_host(hostp);
}
protocol_run();
+ run_server_global_scripts(EXECUTE_ON_POST_AMCHECK, get_config_name());
g_fprintf(outf, plural(_("Client check: %d host checked in %s seconds."),
_("Client check: %d hosts checked in %s seconds."),
char *t;
int ch;
int tch;
+ gboolean printed_hostname = FALSE;
hostp = (am_host_t *)datap;
hostp->up = HOST_READY;
continue;
}
+ if (client_verbose && !printed_hostname) {
+ g_fprintf(outf, "HOST %s\n", hostp->hostname);
+ printed_hostname = TRUE;
+ }
+
if(strncmp_const(line, "OK ") == 0) {
+ if (client_verbose) {
+ g_fprintf(outf, "%s\n", line);
+ }
continue;
}
if(hostp->up == HOST_DONE) {
security_close_connection(sech, hostp->hostname);
for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
- run_server_scripts(EXECUTE_ON_POST_DLE_AMCHECK,
- get_config_name(), dp, -1);
- }
- for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
- run_server_scripts(EXECUTE_ON_POST_HOST_AMCHECK,
+ run_server_dle_scripts(EXECUTE_ON_POST_DLE_AMCHECK,
get_config_name(), dp, -1);
}
+ run_server_host_scripts(EXECUTE_ON_POST_HOST_AMCHECK,
+ get_config_name(), hostp);
}
/* try to clean up any defunct processes, since Amanda doesn't wait() for
them explicitly */