[prev in list] [next in list] [prev in thread] [next in thread] 

List:       amanda-hackers
Subject:    Amanda archive-fixes #1
From:       Steve Robbins <steve () cim ! mcgill ! ca>
Date:       1995-07-04 20:35:24
[Download RAW message or body]

Hello,

Here are some hacks I've been making in order to use Amanda for
'archive-type' backup runs.

First, there are two bugfixes for planner.c; one to stop if from
putting skipped disks into the "estimate failed" queue.  This was already
pointed out and fixed by "Bob Haxo" <rshaxo@ucdavis.edu> back on 5 May
(<9505052051.AA01009@toro.ucdavis.edu>).  The second is to stop amanda

Next, I added a configuration parameter called 'promote-limit' which
limits level 0 promotion checking to this many days,
(ex. "promote-limit 5") rather than to "dumpcycle - 2" which remains
as the default if you don't specify it.  I use promote-limit 4, along
with a dumpcycle of 30 to ensure I get full dumps about every month,
and amanda will do nothing on the days in between.  At least, that's
the theory.  I have completed only the first two nights of our first
cycle.

Also, there is a new dumptype option: skip.  This means to skip this disk
entirely.  This option is useful if you want to share disklist files
between configurations, and in one case you want to back up all the disks,
but in the other you only want selected ones.  In the latter
configuration, you give this option in the dumptype definition in
amanda.conf.

Diffs for the above, below.  ;-)


I also have modified amanda so that:

1.  You can specify the port to run on, which lets me run amanda on
each of my two tape drives simultaneously

2.  Amanda will check /etc/fstab and /etc/mtab and warn about added /
missing disks when amcheck is run.

3.  Amanda will check the 'curinfo' file against the disklist file and
warn about obsolete entries in the former when amcheck is run.

Sending clean diffs for these three is a bit problematic, since I have
added in other random hacks and patches from the list.  A sufficient
show of interest would probably motivate me to pull it apart.  (Or I
could make the complete diff of my sources against 2.2.6 available...)

Feedback is appreciated.



--- common-src/conffile.c.orig	Fri Feb 10 14:22:01 1995
+++ common-src/conffile.c	Tue Jul  4 15:57:32 1995
@@ -58,6 +58,7 @@
     /* flag options */
     int compress;
     int record;
+    int skip;
     int skip_incr;
     int skip_full;
     int no_full;
@@ -72,10 +73,11 @@
     BUMPSIZE, BUMPDAYS, BUMPMULT,
     TAPELIST, DISKFILE, INFOFILE, LOGFILE,
     DISKDIR, DISKSIZE, NETUSAGE, INPARALLEL, TIMEOUT, DEFINE,
-    TAPETYPE, TPCHANGER, RUNTAPES, COMMENT, LENGTH, FILEMARK, SPEED,
+    TAPETYPE, TPCHANGER, RUNTAPES, PROMOTELIMIT, COMMENT, LENGTH,
+    FILEMARK, SPEED,
     DUMPTYPE, OPTIONS, PRIORITY, FREQUENCY, PROGRAM,
     NO_COMPRESS, COMPR, COMPR_BEST, COMPR_FAST,
-    SKIP_INCR, SKIP_FULL, NO_FULL, NO_RECORD, NO_HOLD,
+    SKIP, SKIP_INCR, SKIP_FULL, NO_FULL, NO_RECORD, NO_HOLD,
     KRB4_AUTH, BSD_AUTH, KENCRYPT,
     LOW, MEDIUM, HIGH,
     INFINITY,
@@ -114,6 +116,7 @@
 static val_t conf_maxcycle;
 static val_t conf_tapecycle;
 static val_t conf_runtapes;
+static val_t conf_promotelimit;
 static val_t conf_disksize;
 static val_t conf_netusage;
 static val_t conf_inparallel;
@@ -132,7 +135,7 @@
 static struct dumpseen_s dpseen;

 static int seen_org, seen_mailto, seen_dumpuser, seen_tapedev, seen_tpchanger;
-static int seen_labelstr, seen_runtapes;
+static int seen_labelstr, seen_runtapes, seen_promotelimit;
 static int seen_tapelist, seen_infofile, seen_diskfile, seen_diskdir;
 static int seen_logfile, seen_bumpsize, seen_bumpmult, seen_bumpdays;
 static int seen_tapetype, seen_dumpcycle, seen_maxcycle, seen_tapecycle;
@@ -181,6 +184,9 @@
     while(read_confline());
     fclose(conf);

+    /* derived defaults */
+    if (!seen_promotelimit) conf_promotelimit.i = conf_dumpcycle.i - 2;
+
     if(lookup_tapetype(tapetype_id.s) == NULL) {
 	if(!seen_tapetype)
 	    parserror("default tapetype %s not defined", tapetype_id.s);
@@ -239,7 +245,7 @@
     /* defaults for internal variables */

     seen_org = seen_mailto = seen_dumpuser = seen_tapedev = 0;
-    seen_tpchanger = seen_labelstr = seen_runtapes = 0;
+    seen_tpchanger = seen_labelstr = seen_runtapes = seen_promotelimit = 0;
     seen_tapelist = seen_infofile = seen_diskfile = seen_diskdir = 0;
     seen_logfile = seen_bumpsize = seen_bumpmult = seen_bumpdays = 0;
     seen_tapetype = seen_dumpcycle = seen_maxcycle = seen_tapecycle = 0;
@@ -282,6 +288,8 @@
     case MAXCYCLE:  get_simple(&conf_maxcycle,  &seen_maxcycle,  INT);	 break;
     case TAPECYCLE: get_simple(&conf_tapecycle, &seen_tapecycle, INT);	 break;
     case RUNTAPES:  get_simple(&conf_runtapes,  &seen_runtapes,  INT);	 break;
+    case PROMOTELIMIT:
+	get_simple(&conf_promotelimit,  &seen_promotelimit,  INT);	 break;
     case TAPEDEV:   get_simple(&conf_tapedev,   &seen_tapedev,   STRING);break;
     case TPCHANGER: get_simple(&conf_tpchanger, &seen_tpchanger, STRING);break;
     case LABELSTR:  get_simple(&conf_labelstr,  &seen_labelstr,  STRING);break;
@@ -410,8 +418,8 @@
     if((p = lookup_dumptype(dpcur.name)) != NULL) {
 	parserror("dumptype %s already defined on line %d", p->name, p->seen);
     }
-    else if(dpcur.skip_incr + dpcur.skip_full + dpcur.no_full > 1)
-	parserror("only one of SKIP-INCR, SKIP-FULL, NO-FULL allowed");
+    else if(dpcur.skip + dpcur.skip_incr + dpcur.skip_full + dpcur.no_full > 1)
+	parserror("only one of SKIP, SKIP-INCR, SKIP-FULL, NO-FULL allowed");
     else {
 	/* save on list */
 	p = alloc(sizeof(dumptype_t));
@@ -435,7 +443,8 @@
     /* options */
     dpcur.compress_fast = dpcur.record = 1;
     dpcur.compress_best = 0;
-    dpcur.skip_incr = dpcur.skip_full = dpcur.no_full = dpcur.no_hold = 0;
+    dpcur.skip = dpcur.skip_incr = dpcur.skip_full = 0;
+    dpcur.no_full = dpcur.no_hold = 0;
     dpcur.kencrypt = 0;
     memset(&dpseen, 0, sizeof(dpseen));
 }
@@ -549,6 +558,7 @@
     case CNF_DUMPCYCLE: r = conf_dumpcycle.i; break;
     case CNF_TAPECYCLE: r = conf_tapecycle.i; break;
     case CNF_RUNTAPES: r = conf_runtapes.i; break;
+    case CNF_PROMOTELIMIT: r = conf_promotelimit.i; break;
     case CNF_DISKSIZE: r = conf_disksize.i; break;
     case CNF_BUMPSIZE: r = conf_bumpsize.i; break;
     case CNF_BUMPDAYS: r = conf_bumpdays.i; break;
@@ -651,6 +661,7 @@
 	case KRB4_AUTH:  ckseen(&dpseen.auth);  dpcur.auth = AUTH_KRB4;break;
 	case BSD_AUTH:   ckseen(&dpseen.auth);   dpcur.auth = AUTH_BSD;break;
 	case KENCRYPT:   ckseen(&dpseen.kencrypt);  dpcur.kencrypt = 1;break;
+	case SKIP:       ckseen(&dpseen.skip);      dpcur.skip     = 1;break;
 	case SKIP_INCR:  ckseen(&dpseen.skip_incr); dpcur.skip_incr= 1;break;
 	case SKIP_FULL:  ckseen(&dpseen.skip_full); dpcur.skip_full= 1;break;
 	case NO_FULL:    ckseen(&dpseen.no_full);   dpcur.no_full  = 1;break;
@@ -802,10 +813,12 @@
     { "NO-HOLD", NO_HOLD },
     { "NO-RECORD", NO_RECORD },
     { "RUNTAPES", RUNTAPES },
+    { "PROMOTE-LIMIT", PROMOTELIMIT },
     { "OPTIONS", OPTIONS },
     { "ORG", ORG  },
     { "PRIORITY", PRIORITY },
     { "PROGRAM", PROGRAM },
+    { "SKIP", SKIP },
     { "SKIP-FULL", SKIP_FULL },
     { "SKIP-INCR", SKIP_INCR },
     { "SPEED", SPEED },
@@ -975,6 +988,7 @@
     { "DUMPCYCLE", CNF_DUMPCYCLE, INT },
     { "MINCYCLE",  CNF_DUMPCYCLE, INT },
     { "RUNTAPES",   CNF_RUNTAPES, INT },
+    { "PROMOTE-LIMIT", CNF_PROMOTELIMIT, INT },
     { "TAPECYCLE", CNF_TAPECYCLE, INT },
     { "DISKSIZE", CNF_DISKSIZE, INT },
     { "BUMPDAYS", CNF_BUMPDAYS, INT },
@@ -1041,6 +1055,7 @@

     printf("conf_dumpcycle = %d\n", getconf_int(CNF_DUMPCYCLE));
     printf("conf_runtapes = %d\n", getconf_int(CNF_RUNTAPES));
+    printf("conf_promotelimit = %d\n", getconf_int(CNF_PROMOTELIMIT));
     printf("conf_tapecycle = %d\n", getconf_int(CNF_TAPECYCLE));
     printf("conf_bumpsize = %d\n", getconf_int(CNF_BUMPSIZE));
     printf("conf_bumpdays = %d\n", getconf_int(CNF_BUMPDAYS));
@@ -1079,6 +1094,7 @@
 	if(dp->auth == AUTH_BSD) printf(" BSD-AUTH");
 	else if(dp->auth == AUTH_KRB4) printf(" KRB4-AUTH");
 	else printf(" UNKNOWN-AUTH");
+	if(dp->skip) printf(" SKIP");
 	if(dp->skip_incr) printf(" SKIP-INCR");
 	if(dp->skip_full) printf(" SKIP-FULL");
 	if(dp->no_full) printf(" NO-FULL");
--- common-src/conffile.h.orig	Fri Feb 10 14:22:01 1995
+++ common-src/conffile.h	Tue Jul  4 15:54:37 1995
@@ -39,7 +39,8 @@
     CNF_TAPELIST, CNF_DISKFILE, CNF_INFOFILE, CNF_LOGFILE,
     CNF_DISKDIR, CNF_TAPETYPE, CNF_DUMPCYCLE, CNF_TAPECYCLE,
     CNF_DISKSIZE, CNF_NETUSAGE, CNF_INPARALLEL, CNF_TIMEOUT,
-    CNF_BUMPSIZE, CNF_BUMPMULT, CNF_BUMPDAYS, CNF_TPCHANGER, CNF_RUNTAPES
+    CNF_BUMPSIZE, CNF_BUMPMULT, CNF_BUMPDAYS, CNF_TPCHANGER,
+    CNF_RUNTAPES, CNF_PROMOTELIMIT
 } confparm_t;

 typedef enum auth_e {
@@ -73,6 +74,7 @@
     int compress_best:1;
     int compress_fast:1;
     int record:1;
+    int skip:1;
     int skip_incr:1;
     int skip_full:1;
     int no_full:1;
--- server-src/planner.c.orig	Fri Feb 10 14:21:59 1995
+++ server-src/planner.c	Tue Jul  4 15:54:42 1995
@@ -83,7 +83,7 @@
 int total_waiting, max_disks;
 char loginid[80];

-int dumpcycle, runs_per_cycle;
+int dumpcycle, runs_per_cycle, promote_limit;
 int runtapes;
 time_t today;

@@ -184,6 +184,7 @@

     runtapes = getconf_int(CNF_RUNTAPES);
     dumpcycle = getconf_int(CNF_DUMPCYCLE);
+    promote_limit = getconf_int(CNF_PROMOTELIMIT);
     runs_per_cycle = guess_runs_from_tapelist();

     tape = lookup_tapetype(getconf_str(CNF_TAPETYPE));
@@ -405,43 +406,52 @@
     ep->size = -1;
     ep->curr_priority = dp->dtype->priority;

-    /* calculated fields */
+    /* handle "skip" type archives */

-    if(inf.command == PLANNER_FORCE) {
-	/* force a level 0, kind of like a new disk */
-	if(dp->dtype->no_full) {
-	    /*
-	     * XXX - Not sure what it means to force a no-full disk.  The
-	     * purpose of no-full is to just dump changes relative to a
-	     * stable base, for example root partitions that vary only
-	     * slightly from a site-wide prototype.  Only the variations
-	     * are dumped.
-	     *
-	     * If we allow a level 0 onto the Amanda cycle, then we are
-	     * hosed when that tape gets re-used next.  Disallow this for
-	     * now.
-	     */
-	    log(L_ERROR,
-		"Cannot force full dump of %s:%s with no-full option.",
+    if(dp->dtype->skip) {
+	fprintf(stderr,"%s:%s skipped due to skip flag\n",
 		dp->host->hostname, dp->name);
+	/* don't enqueue the disk */
+	ep->level[0] = ep->level[1] = ep->level[2] = -1;

-	    /* clear force command */
-	    if(inf.command == PLANNER_FORCE)
-		inf.command = NO_COMMAND;
-	    if(put_info(dp->host->hostname, dp->name, &inf))
-		error("could not put info record for %s:%s: %s",
-		      dp->host->hostname, dp->name, strerror(errno));
-	    ep->last_level = last_level(dp, &inf);
-	    ep->next_level0 = next_level0(dp, &inf);
-	}
-	else {
-	    ep->last_level = -1;
-	    ep->next_level0 = 0;
-	    log(L_INFO, "Forcing full dump of %s:%s as directed.",
+	fprintf(stderr, "planner: SKIPPED %s %s [skip]\n",
 		dp->host->hostname, dp->name);
-	}
+
+	log(L_SUCCESS, "%s %s [skipped: skip]",
+	    dp->host->hostname, dp->name);
+	return;
     }
-    else {
+
+    /* calculated fields */
+
+    if(inf.command == PLANNER_FORCE && dp->dtype->no_full) {
+	/*
+	 * XXX - Not sure what it means to force a no-full disk.  The
+	 * purpose of no-full is to just dump changes relative to a
+	 * stable base, for example root partitions that vary only
+	 * slightly from a site-wide prototype.  Only the variations
+	 * are dumped.
+	 *
+	 * If we allow a level 0 onto the Amanda cycle, then we are
+	 * hosed when that tape gets re-used next.  Disallow this for
+	 * now.
+	 */
+	log(L_ERROR,
+	    "Cannot force full dump of %s:%s with no-full option.",
+	    dp->host->hostname, dp->name);
+
+	inf.command = NO_COMMAND;
+	if(put_info(dp->host->hostname, dp->name, &inf))
+	    error("could not put info record for %s:%s: %s",
+		  dp->host->hostname, dp->name, strerror(errno));
+    }
+
+    if (inf.command == PLANNER_FORCE) {
+	ep->last_level = -1;
+	ep->next_level0 = 0;
+	log(L_INFO, "Forcing full dump of %s:%s as directed.",
+	    dp->host->hostname, dp->name);
+    } else {
 	ep->last_level = last_level(dp, &inf);
 	ep->next_level0 = next_level0(dp, &inf);
     }
@@ -548,12 +558,12 @@
     i = 0;
     if(!(dp->dtype->skip_full || dp->dtype->no_full))
 	ep->level[i++] = 0;
-    if(ep->last_level == -1) {		/* a new disk */
+    if(ep->last_level == -1 || dp->dtype->skip_incr) {
+	/*non-degradable disk */
 	if(dp->dtype->no_full)
 	    ep->level[i++] = 1;
-	else assert(!dp->dtype->skip_full);	/* should be handled above */
-    }
-    else {				/* not new, pick normally */
+	else assert(!dp->dtype->skip_full);   /* should be handled above */
+    } else {	                              /* degradable, pick normally */
 	curr_level = ep->last_level;
 	if(curr_level == 0)
 	    ep->level[i++] = 1;
@@ -794,8 +804,10 @@
 	destqp = &waitq;
     }

-    for(dp = hostp->disks; dp != NULL; dp = dp->hostnext)
-	    enqueue_disk(destqp, dp);
+    for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
+	if(est(dp)->level[0] == -1) continue;	/* ignore this disk */
+	enqueue_disk(destqp, dp);
+    }
 }

 static disk_t *lookup_hostdisk(hp, str)
@@ -1145,17 +1157,16 @@
 static int promote_highest_priority_incremental()
 {
     disk_t *ptr;
-    int new_size, new_total, check_days, check_limit;
+    int new_size, new_total, check_days;

     /*
      * return 1 if did so; must update total_size correctly; must not
      * cause total_size to exceed tape_length
      */
-    check_limit = dumpcycle-1;
     fprintf(stderr,"   promote: checking up to %d days ahead\n",
-	    check_limit-1);
+	    promote_limit);

-    for(check_days = 1; check_days < check_limit; check_days++) {
+    for(check_days = 1; check_days <= promote_limit; check_days++) {
 	fprintf(stderr,"   promote: checking %d days now\n", check_days);

         for(ptr = schedq.head; ptr != NULL; ptr = ptr->next) {


--
                Steve Robbins -- Consultant in Computerology
                         steve@cim.mcgill.ca

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic