Exemple #1
0
bool get_or_create_fileset_record(JCR *jcr)
{
   FILESET_DBR fsr;
   /*
    * Get or Create FileSet record
    */
   memset(&fsr, 0, sizeof(FILESET_DBR));
   bstrncpy(fsr.FileSet, jcr->res.fileset->hdr.name, sizeof(fsr.FileSet));
   if (jcr->res.fileset->have_MD5) {
      struct MD5Context md5c;
      unsigned char digest[MD5HashSize];
      memcpy(&md5c, &jcr->res.fileset->md5c, sizeof(md5c));
      MD5Final(digest, &md5c);
      /*
       * Keep the flag (last arg) set to false otherwise old FileSets will
       * get new MD5 sums and the user will get Full backups on everything
       */
      bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
      bstrncpy(jcr->res.fileset->MD5, fsr.MD5, sizeof(jcr->res.fileset->MD5));
   } else {
      Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
   }
   if (!jcr->res.fileset->ignore_fs_changes ||
       !db_get_fileset_record(jcr, jcr->db, &fsr)) {
      if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
         Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
            fsr.FileSet, db_strerror(jcr->db));
         return false;
      }
   }
   jcr->jr.FileSetId = fsr.FileSetId;
   bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
   Dmsg2(119, "Created FileSet %s record %u\n", jcr->res.fileset->hdr.name,
      jcr->jr.FileSetId);
   return true;
}
Exemple #2
0
/*
 * Do a verification of the specified files against the Catlaog
 *
 *  Returns:  false on failure
 *            true  on success
 */
bool do_verify(JCR *jcr)
{
   const char *level;
   BSOCK *fd, *sd;
   int stat;
   char ed1[100];
   JOB_DBR jr;
   JobId_t verify_jobid = 0;
   char *store_address;
   uint32_t store_port;
   const char *Name;

   free_wstorage(jcr);                   /* we don't write */

   memset(&jcr->previous_jr, 0, sizeof(jcr->previous_jr));

   /*
    * Find JobId of last job that ran. Note, we do this when
    *   the job actually starts running, not at schedule time,
    *   so that we find the last job that terminated before
    *   this job runs rather than before it is scheduled. This
    *   permits scheduling a Backup and Verify at the same time,
    *   but with the Verify at a lower priority.
    *
    *   For VERIFY_CATALOG we want the JobId of the last INIT.
    *   For VERIFY_VOLUME_TO_CATALOG, we want the JobId of the
    *       last backup Job.
    */
   if (jcr->getJobLevel() == L_VERIFY_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA) {
      memcpy(&jr, &jcr->jr, sizeof(jr));
      if (jcr->verify_job &&
          (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
           jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG   ||
           jcr->getJobLevel() == L_VERIFY_DATA)) {
         Name = jcr->verify_job->name();
      } else {
         Name = NULL;
      }
      Dmsg1(100, "find last jobid for: %s\n", NPRT(Name));

      /* see if user supplied a jobid= as run argument or from menu */
      if (jcr->RestoreJobId) {
         verify_jobid = jcr->RestoreJobId;
         Dmsg1(100, "Supplied jobid=%d\n", verify_jobid);

      } else {
         if (!db_find_last_jobid(jcr, jcr->db, Name, &jr)) {
            if (jcr->getJobLevel() == L_VERIFY_CATALOG) {
               Jmsg(jcr, M_FATAL, 0, _(
                       "Unable to find JobId of previous InitCatalog Job.\n"
                       "Please run a Verify with Level=InitCatalog before\n"
                       "running the current Job.\n"));
            } else {
               Jmsg(jcr, M_FATAL, 0, _(
                       "Unable to find JobId of previous Job for this client.\n"));
            }
            return false;
         }
         verify_jobid = jr.JobId;
      }
      Dmsg1(100, "Last full jobid=%d\n", verify_jobid);
   }
   /*
    * Now get the job record for the previous backup that interests
    *   us. We use the verify_jobid that we found above.
    */
   if (jcr->getJobLevel() == L_VERIFY_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA) {
      jcr->previous_jr.JobId = verify_jobid;
      if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) {
         Jmsg(jcr, M_FATAL, 0, _("Could not get job record for previous Job. ERR=%s"),
              db_strerror(jcr->db));
         return false;
      }
      if (!(jcr->previous_jr.JobStatus == JS_Terminated ||
            jcr->previous_jr.JobStatus == JS_Warnings)) {
         Jmsg(jcr, M_FATAL, 0, _("Last Job %d did not terminate normally. JobStatus=%c\n"),
            verify_jobid, jcr->previous_jr.JobStatus);
         return false;
      }
      Jmsg(jcr, M_INFO, 0, _("Verifying against JobId=%d Job=%s\n"),
         jcr->previous_jr.JobId, jcr->previous_jr.Job);
   }

   /*
    * If we are verifying a Volume, we need the Storage
    *   daemon, so open a connection, otherwise, just
    *   create a dummy authorization key (passed to
    *   File daemon but not used).
    */
   if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG || jcr->getJobLevel() == L_VERIFY_DATA) {
      int stat;
      /*
       * Note: negative status is an error, zero status, means
       *  no files were backed up, so skip calling SD and
       *  client.
       */
      stat = create_restore_bootstrap_file(jcr);
      if (stat < 0) {                      /* error */
         return false;
      } else if (stat == 0) {              /* No files, nothing to do */
         verify_cleanup(jcr, JS_Terminated); /* clean up */
         return true;                      /* get out */
      }
   } else {
      jcr->sd_auth_key = bstrdup("dummy");    /* dummy Storage daemon key */
   }

   /* Pass the original fileset to the client */
   if (jcr->getJobLevel() == L_VERIFY_DATA) {
      FILESET_DBR fdbr;
      memset(&fdbr, 0, sizeof(fdbr));
      fdbr.FileSetId = jcr->previous_jr.FileSetId;
      if (!db_get_fileset_record(jcr, jcr->db, &fdbr)) {
         Jmsg(jcr, M_FATAL, 0,
              _("Could not get fileset record from previous Job. ERR=%s"),
              db_strerror(jcr->db));
         return false;
      }

      jcr->fileset = (FILESET *)GetResWithName(R_FILESET, fdbr.FileSet);
      if (!jcr->fileset) {
         if (jcr->verify_job) {
            jcr->fileset = jcr->verify_job->fileset;
            Jmsg(jcr, M_WARNING, 0,
                 _("Could not find FileSet resource \"%s\" from previous Job\n"),
                 fdbr.FileSet);
            Jmsg(jcr, M_INFO, 0,
                 _("Using FileSet \"%\"\n"), jcr->fileset->name());

         } else {
            Jmsg(jcr, M_FATAL, 0,
                 _("Could not get FileSet resource for verify Job."));
            return false;
         }
      }
      Dmsg1(50, "FileSet = %s\n", jcr->fileset->name());
   }

   /* Pass the current fileset to the client */
   if (jcr->getJobLevel() == L_VERIFY_DISK_TO_CATALOG && jcr->verify_job) {
      jcr->fileset = jcr->verify_job->fileset;
   }
   Dmsg2(100, "ClientId=%u JobLevel=%c\n",
         jcr->previous_jr.ClientId, jcr->getJobLevel());

   if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
      Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
      return false;
   }

   /* Print Job Start message */
   Jmsg(jcr, M_INFO, 0, _("Start Verify JobId=%s Level=%s Job=%s\n"),
      edit_uint64(jcr->JobId, ed1), level_to_str(jcr->getJobLevel()), jcr->Job);

   if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG ||
       jcr->getJobLevel() == L_VERIFY_DATA)
   {
      /*
       * Start conversation with Storage daemon
       */
      jcr->setJobStatus(JS_Blocked);
      if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
         return false;
      }
      /*
       * Now start a job with the Storage daemon
       */
      if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
         return false;
      }
      sd = jcr->store_bsock;
      jcr->sd_calls_client = jcr->client->sd_calls_client;
      /*
       * Send the bootstrap file -- what Volumes/files to restore
       */
      if (!send_bootstrap_file(jcr, sd) ||
          !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
         goto bail_out;
      }
      if (!jcr->sd_calls_client) {
         if (!run_storage_and_start_message_thread(jcr, sd)) {
            return false;
         }
      }
   }
   /*
    * OK, now connect to the File daemon
    *  and ask him for the files.
    */
   jcr->setJobStatus(JS_Blocked);
   if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
      goto bail_out;
   }

   jcr->setJobStatus(JS_Running);
   fd = jcr->file_bsock;


   Dmsg0(30, ">filed: Send include list\n");
   if (!send_include_list(jcr)) {
      goto bail_out;
   }

   Dmsg0(30, ">filed: Send exclude list\n");
   if (!send_exclude_list(jcr)) {
      goto bail_out;
   }

   /*
    * Send Level command to File daemon, as well
    *   as the Storage address if appropriate.
    */
   switch (jcr->getJobLevel()) {
   case L_VERIFY_INIT:
      level = "init";
      break;
   case L_VERIFY_CATALOG:
      level = "catalog";
      break;
   case L_VERIFY_DATA:
   case L_VERIFY_VOLUME_TO_CATALOG:
      if (jcr->sd_calls_client) {
         if (jcr->FDVersion < 10) {
            Jmsg(jcr, M_FATAL, 0, _("The File daemon does not support SDCallsClient.\n"));
            goto bail_out;
         }

         if (!send_client_addr_to_sd(jcr)) {
            goto bail_out;
         }

         if (!run_storage_and_start_message_thread(jcr, jcr->store_bsock)) {
            return false;
         }
         store_address = jcr->rstore->address;  /* dummy */
         store_port = 0;           /* flag that SD calls FD */
      } else {
         /*
          * send Storage daemon address to the File daemon
          */
         if (jcr->rstore->SDDport == 0) {
            jcr->rstore->SDDport = jcr->rstore->SDport;
         }

         store_address = get_storage_address(jcr->client, jcr->rstore);
         store_port = jcr->rstore->SDDport;
      }

      if (!send_store_addr_to_fd(jcr, jcr->rstore, store_address, store_port)) {
         goto bail_out;
      }

      if (!jcr->RestoreBootstrap) {
         Jmsg0(jcr, M_FATAL, 0, _("Deprecated feature ... use bootstrap.\n"));
         goto bail_out;
      }
      if (jcr->getJobLevel() == L_VERIFY_VOLUME_TO_CATALOG) {
         level = "volume";
      } else {
         level = "data";
      }
      break;
   case L_VERIFY_DISK_TO_CATALOG:
      level="disk_to_catalog";
      break;
   default:
      Jmsg2(jcr, M_FATAL, 0, _("Unimplemented Verify level %d(%c)\n"),
            jcr->getJobLevel(),
            jcr->getJobLevel());
      goto bail_out;
   }

   if (!send_runscripts_commands(jcr)) {
      goto bail_out;
   }

   /*
    * Send verify command/level to File daemon
    */
   fd->fsend(verifycmd, level);
   if (!response(jcr, fd, OKverify, "Verify", DISPLAY_ERROR)) {
      goto bail_out;
   }

   /*
    * Now get data back from File daemon and
    *  compare it to the catalog or store it in the
    *  catalog depending on the run type.
    */
   /* Compare to catalog */
   switch (jcr->getJobLevel()) {
   case L_VERIFY_CATALOG:
      Dmsg0(10, "Verify level=catalog\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_VOLUME_TO_CATALOG:
      Dmsg0(10, "Verify level=volume\n");
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_DISK_TO_CATALOG:
      Dmsg0(10, "Verify level=disk_to_catalog\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_compare_to_catalog(jcr, jcr->previous_jr.JobId);
      break;

   case L_VERIFY_INIT:
      /* Build catalog */
      Dmsg0(10, "Verify level=init\n");
      jcr->sd_msg_thread_done = true;   /* no SD msg thread, so it is done */
      jcr->SDJobStatus = JS_Terminated;
      get_attributes_and_put_in_catalog(jcr);
      db_end_transaction(jcr, jcr->db);   /* terminate any open transaction */
      db_write_batch_file_records(jcr);
      break;

   case L_VERIFY_DATA:
      /* Nothing special to do */
      bget_dirmsg(fd);          /* eat EOD */
      break;
   default:
      Jmsg1(jcr, M_FATAL, 0, _("Unimplemented verify level %d\n"), jcr->getJobLevel());
      goto bail_out;
   }

   stat = wait_for_job_termination(jcr);
   verify_cleanup(jcr, stat);
   return true;

bail_out:
   return false;
}