Hello!

Here are some notes on how to submit an archive job to BackupPC in the 
same way that the GUI does.  This can be used via cron, etc., yet will 
still be logged and visible from the GUI.

In Googling ways to archive via cron, the only items I've found used 
individual BackuPC_archiveHost commands.  The command you need touse can 
be found when you examine the logs, and is pretty straightforward:  copy 
and paste the command line into a crontab file for your backuppc user, 
make a couple of small changes, and you're done.

However, this does not integrate into the GUI.  This means that you 
either have to mail the cron output to the user, or pipe the output into 
a file and get to it another way, or something similar.  It does not 
allow you to see the history the same way as if they were started from 
the GUI.

According to Craig, the way to get the jobs to show up in the GUI is to 
submit them the same way that the GUI does.  How that is done is left as 
an exercise to the reader...  :)  So, here's what I've found.

If you only want the bottom line, jump to the Summary section at the 
bottom.  If you would like to help me to answer 3 questions I found 
while doing this, jump to the


How the GUI Submits an Archive
==============================

The code responsible for providing the archive GUI is found in 
__INSTALLDIR__/lib/BackupPC/CGI/Archive.pm .  As you go through the 
library, you see the code that builds the pages that make up the archive 
process.  The part that actually generates the request that launches the 
archive job is at the very end:


             my $openPath = "$TopDir/pc/$archivehost/$reqFileName";
             if ( open(REQ, ">", $openPath) ) {
                 binmode(REQ);
                 print(REQ $archive->Dump);
                 close(REQ);
             } else {
 
ErrorExit(eval("qq{$Lang->{Can_t_open_create__openPath}}"));
             }
             $reply = $bpc->ServerMesg("archive $User $archivehost 
$reqFileName");


"$archive" is an array of values that are provided by the user in the 
previous screens:  which hosts to back up, which backup jobs for each 
host, type of compression, parity, etc.  This is written to a file: 
"$TopDir/pc/$archivehost/$reqFileName".

If you make a request and then do an ls on the archive host's directory, 
you will see a file named something like "archiveReq.####.#" where #### 
are digits.  Here's the code that generated that file name.

            for ( my $i = 0 ; ; $i++ ) {
                 $reqFileName = "archiveReq.$$.$i";
                 last if ( !-f "$TopDir/pc/$archivehost/$reqFileName" );
             }

The last digit is generated by loop to the first digit that doesn't 
already exist in a file (in case you have stacked up more than one 
archive job).  Seeing as I don't know perl, I can't figure out what the 
"$$" does, and trying to google for "perl $$" doesn't help...

No matter:  the file name is not very important at all:  from what I can 
tell, the whole file name could be completely random.  So, onward we go.

Here is the contents of a sample file made by selecting localhost, and 
accepting the defaults (at least, as I have them configured):


%ArchiveReq = (
   'archiveloc' => '/var/lib/BackupPC/removable',
   'reqTime' => '1170042557',
   'BackupList' => [
     '12'
   ],
   'host' => 'archive',
   'parfile' => '5',
   'archtype' => '0',
   'compression' => '/bin/cat',
   'compext' => '.raw',
   'HostList' => [
     'localhost'
   ],
   'user' => 'backupuser',
   'splitsize' => '0000000'
);


Once the file is created, there is one more step:  submit a message to 
the server telling it about this request file.  BackupPC will now open 
the archive request file, parse the parameters, and run the archive job 
you've requested.  It then creates a log file in the archive directory 
that can be parsed by the GUI.


How Your Code Can Submit an Archive
===================================

To perform your own archive, all you have to do is have a 
properly-formatted file that contains the details for your archive in 
the archive directory, just like the file created by the GUI, and tell 
BackupPC to start the archive.  A quick and dirty way to get such a file 
would be to use the GUI and copy the archiveReq file it generates for 
you.  You will then have a perfectly-formatted file for your use.

There are two problems with this.  The first is that the specific backup 
number to be archvied (BackupList) is hard-coded.  You probably want the 
latest file, not the specific one that was the latest when you captured 
the file.  Fortunately, that's an easy fix.  If, instead of an actual 
backup number, you use "-1", BackupPC will get the latest version for 
you automatically.  The only thing I find annoying about that is that 
BackupPC will still use "-1" for the filename.  This makes it ugly to 
try to have multiple days' worth of archives in the same directory.  You 
either have to have code somewhere that renames the jobs for you (such 
as a pre- or post-dump command), or change the destination of the 
archive every time to a unique directory.  It would be nicer, though, if 
BackupPC just substituted the right number for you.  But that's how it is.

The second problem is the fact that the time the job was requested 
(reqTime) is also hard-coded.  That means that every job will have the 
exact same request time.  However, this may not be that bad.  When you 
look at a log entry for an archive, you will see that two times are 
recorded:  the request time and the start time.  Only the request time 
will be incorrect:  the start time will show when the job was started by 
BackupPC.  So, you may be able to ignore it.  Or, you can certainly come 
up with code that updates the reqTime field with the current time;  that 
way, the logs will show the correct submission time as well.

Once you have created the request file in the proper directory, you 
simply tell BackupPC to process it.  That can be done easily from the 
command line:

__INSTALLDIR__/bin/BackupPC_serverMesg archive <user> <archiveclient> 
<reqFileName>

This will run your job just as if you had submitted it from the GUI.  It 
can be scripted from wherever you would like, such as from a crontab, 
just as easily as using BackupPC_archiveHost.


Notes about Archive Parameters
==============================

I have not delved extensively into the code to find out exactly how each 
parameter is parsed, and what (if any) error-checking is done.  However, 
I was curious about a couple of parameters.

** First, why is there a user parameter on the command line, when the 
request file also contains this information?  How are they used?

 From what I can tell, the user that is submitted on the command line is 
used for exactly one thing:  it is set as the $user variable that is 
passed via XferArgs to the pre- and post-dump commands.  The user that 
is contained in the request file is used for a different, but similar 
purpose:  it is passed via XferArgs to $xfer.  $xfer is the procedure 
that actually does the archive.  I do not know where it goes or what it 
does with it:  I haven't been able to delve that deeply into BackupPC's 
internals yet.

Why are there two parameters for assigning the user name?  And why is 
one used in one place and the other somewhere else?  Only Craig knows... 
  :)  Would you mind telling us?

** Second, how is reqTime used?

AFAICT, reqTime is only used by the GUI:  it is not actually used during 
an archive.  At least, BackupPC_archive does not use it, and it is not 
passed to xfer$, so I don't think anyone else could use it either.  My 
guess is the only time that this parameter is parsed is when rendering 
the archive job's log details in the GUI.  In fact, I altered the date 
by putting a z before the numbers.  When you do this, the job runs fine. 
  However, in the GUI, the request time is always the current time, not 
the request time.

** Third:  how does BackupPC_archive know which number is the latest 
backup?  Is there an easy way to do this outside of BackupPC, preferably 
without having to duplicate code?

Here is the relevant code (with unrelated code removed) for how the GUI 
determines the latest backup:


         foreach my $host ( sort(keys(%Status)) ) {
             my @Backups = $bpc->BackupInfoRead($host);
             for ( my $i = 0 ; $i < @Backups ; $i++ ) {
                 $backupnumber = $Backups[$i]{num};
             }
         }


The GUI code that determines the latest backup uses 
$bpc->BackupInfoRead($host) to get that information.  That's how the 
latest backup is determined by the GUI.

I would like to know what the code that parses the archive request 
file's backup number parameter does, but it's parsed by $xfer, and I'm 
not sure where that code is.  I think that this is merely passed to 
BackupPC_archiveHost, but I am not sure.

I also looked at BackupPC_archiveHost:  it too can handle the "-1" 
parameter.  It passes the "-1" to BackupPC_tarCreate. 
BackupPC_tarCreate reads the files and generates a tar datastream for 
archiveHost.  It also converts the "-1" into the latest backup for that 
host.  (NOTE:  That may present a problem for getting archiveHost to 
create files with the proper backup number, mentioned in my previous 
e-mail:  how can I get the data from tarCreate back to archiveHost? 
Might it be possible to do the "-1" to backup number conversion in a 
library function available to both of them, as well as the GUI?  I will 
have to do some more digging.)  Here is the code it uses (with some 
unrelated lines removed) (NOTE:  $Num is the backup number, such as "-1"):


my @Backups = $bpc->BackupInfoRead($Host);
$Num = [EMAIL PROTECTED] + $Num]{num} if ( [EMAIL PROTECTED] <= $Num && $Num < 
0 );
for ( $i = 0 ; $i < @Backups ; $i++ ) {
     last if ( $Backups[$i]{num} == $Num );
}


It is similar to the GUI code.  In both cases, it loops through the data 
returned by BackupInfoRead($Host) and finds either the latest backup 
only (in the case of the GUI) or the requested backup (in the case of 
BackupPC_tarCreate).

So, what does BackupInfoRead() do?  The code is in 
__INSTALLDIR__/lib/BackupPC/Storage/text.pm:


sub BackupInfoRead
{
     my($s, $host) = @_;
     local(*BK_INFO, *LOCK);
     my(@Backups);

     flock(LOCK, LOCK_EX) if open(LOCK, "$s->{TopDir}/pc/$host/LOCK");
     if ( open(BK_INFO, "$s->{TopDir}/pc/$host/backups") ) {
         binmode(BK_INFO);
         while ( <BK_INFO> ) {
             s/[\n\r]+//;
             next if ( !/^(\d+\t(incr|full|partial).*)/ );
             $_ = $1;
             @[EMAIL PROTECTED]@{$s->{BackupFields}}} = split(/\t/);
         }
         close(BK_INFO);
     }
     close(LOCK);
     return @Backups;
}


It parses __TOPDIR__/pc/$host/backups and gets the info from there. 
Others have suggested parsing the filesystem to get this information, 
but I am not confident of its robustness.  It *should* work reasonably 
well, but obviously the above way is safer.

However, it does not seem like there is an easy way to get this 
information from outside of BackupPC.  Other than the fact that the 
names of the files are "-1", and the fact that you can't create a new 
archive (with parity, anyway) on top of an existing archive without an 
error, there isn't much of a reason for getting this information anyway. 
  So, I would like to figure out a way to do one of these two things: 
either get the latest backup number or save archive files with the 
proper number in the filename even when using "-1" as the backup number.


Summary
=======

To submit an archive job like the GUI, you must:

1) Create a properly-formatted archive request file in the archive 
host's directory.

This can be done by using the GUI to create the file, saving it 
somewhere else and copying it into place when needed, or by generating 
the file from scratch using some other method.  If you use a 
pre-generated file, you may need to make a couple of small changes: 
change BackupList to the proper value (likely "-1"), and update reqTime.

2) use the BackupPC_serverMesg command to notify BackupPC of the pending 
archive.  it uses the following syntax:

        __INSTALLDIR__/bin/BackupPC_serverMesg archive <user> <archiveclient> 
<reqFileName>

where <user> is the user passed to the pre- and post-dump commands, 
<archiveclient> is the host name for your archive host, and 
<reqFileName> is the file you created in step 1.


I hope this information will be useful to others:  hopefully it can save 
you a few hours.  If you have any thoughts, I would appreciate any info 
you might have particularly regarding suggestions for updating 
BackupPC_archiveHost to save files with the proper backup number in the 
filename.


Thank you,

Timothy J. Massey

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
BackupPC-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/backuppc-users
http://backuppc.sourceforge.net/

Reply via email to