Imported Upstream version 3.3.0
[debian/amanda] / server-src / amcheck.c
index 3b41c700e2b1a6d89ffd8521002f58fd6e8753b2..3acb9919fa04b97aa54e1350ab73f369fb34ad71 100644 (file)
@@ -660,8 +660,12 @@ start_server_check(
     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:
@@ -682,6 +686,10 @@ start_server_check(
     
     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*/
@@ -727,21 +735,21 @@ start_server_check(
 
        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));
        }
 
@@ -757,7 +765,6 @@ start_server_check(
                        "the 'tapetype' parameter\n"));
            confbad = 1;
        }
-
     }
 
     /*
@@ -829,7 +836,10 @@ start_server_check(
        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
@@ -902,6 +912,121 @@ start_server_check(
                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 */
@@ -1103,18 +1228,6 @@ start_server_check(
        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);
@@ -1342,7 +1455,7 @@ start_server_check(
                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) {
@@ -1356,7 +1469,7 @@ start_server_check(
                  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;
                  }
@@ -1372,53 +1485,57 @@ start_server_check(
                  }
                }
 
-               /* 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);
+                       }
                    }
                }
 
@@ -1440,11 +1557,6 @@ start_server_check(
                                  _("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;
                    }
                }
 
@@ -1816,6 +1928,13 @@ start_host(
                            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);
@@ -1826,6 +1945,19 @@ start_host(
                            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);
@@ -1839,6 +1971,8 @@ start_host(
            }
            amfree(qname);
            amfree(qdevice);
+           amfree(b64disk);
+           amfree(b64device);
            l_len = strlen(l);
            amfree(o);
 
@@ -1921,6 +2055,7 @@ start_client_checks(
     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;
@@ -1928,12 +2063,10 @@ start_client_checks(
     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);
@@ -1943,6 +2076,7 @@ start_client_checks(
     }
 
     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."),
@@ -2068,13 +2202,11 @@ handle_result(
     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 */