3 $BASE_LIB=$_SERVER["BASE_LIB"];
4 $BASE_DIR=$_SERVER["BASE_DIR"];
5 $BASE_DATA=$_SERVER["BASE_DATA"];
6 $BACULA_USER=$_SERVER["BACULA_USER"];
8 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $BASE_DIR;
10 require_once "$BASE_LIB/lib.php";
12 if(!isset($argv[2])) {
13 echo "Usage: ".$argv[0]." changer_name command\n";
14 echo "\tbacula-config - outputs bacula config\n";
15 echo "\tinit - inits the bacula php changer stuff\n";
16 echo "\tadd-disk - adds a disk\n";
17 echo "\tdisks - lists currently (known) disks\n";
18 echo "\tstatus - prints status (whats where in which slot, drive, etc)\n";
41 echo "invalid command\n";
44 function bacula_config()
46 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv, $BASE_DIR;
48 check_init_and_fail($argv[1]);
51 $db = db_getDB($argv[1]);
53 $ntapes = conf_getVal($changer, "ndrives");
54 $tapeloc = conf_getVal($changer, "drivelocation");
55 $tapesz = conf_getVal($changer, "tapesize");
60 -------------------------------- bacula-sd.conf -----------------------------
62 Name = <?php echo "$changer\n"?>
64 for($i=0; $i<$ntapes; $i++) {
65 echo " Device = \"$changer-drive$i\"\n";
68 Changer Command = "<?php echo $BASE_DIR."/bin/pbdc-bacula"?> %c %o %S %a %d"
69 Changer Device = "<?php echo $changer ?>"
73 for($i=0; $i < $ntapes; $i++) {
76 Name = <?php echo "\"$changer-drive$i\"\n" ?>
77 DriveIndex = <?php echo "$i\n" ?>
81 ArchiveDevice = <?php echo "\"$tapeloc/$changer-drive$i\"\n" ?>
92 -------------------------------- bacula-dir.conf -----------------------------
94 Name = <INSERT STORAGE NAME>
95 Address = <ADDRESS OF WHERE SD IS RUNNING>
97 Password = "<SD PASSWORD>"
98 Device = <?php echo "\"$changer-drive$i\"\n" ?>
103 # a pool for our storage
105 Name = <POOL NAME GOES HERE>
107 Recycle = yes # Bacula can automatically recycle Volumes
108 AutoPrune = yes # Prune expired volumes
109 Volume Retention = 50 days # I set this to 50 days, dont ask me why
110 Maximum Volume Bytes = <?php echo "$tapesz"."G"?> # Limit Volume size to something reasonable
111 Maximum Volumes = 1000 # Limit number of Volumes in Pool SET THIS
114 # add a default job job defs for our pool - modify where necessary
115 # i.e. look at the normal jobdefs, or modify that with your backup defs.
120 Storage = <INSERT STORAGE NAME>
122 Pool = <POOL NAME GOES HERE>
124 Write Bootstrap = "/var/lib/bacula/%c.bsr"
132 function pbdc_status()
134 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
136 check_init_and_fail($argv[1]);
139 $db = db_getDB($argv[1]);
141 $res = $db->query("select * from disk_list");
143 $tapeloc = conf_getVal($changer, "drivelocation");
144 $amloc = conf_getVal($changer, "automountdir");
147 foreach($res as $row) {
148 echo "Listing tapes for disk ".$row["disk_id"].", ".$row["disk_name"]."\n";
149 //echo "dir: $amloc/".$row["disk_name"]."/pbdc/".$argv[1]."/tapes/\n";
151 $dh = opendir("$amloc/".$row["disk_name"]."/pbdc/".$argv[1]."/tapes/");
152 while(($file = readdir($dh)) !== false) {
153 if(ereg("d[0-9]+_vol[0-9]+", $file)!=false) {
154 $sql = "select slot_no from slots where tape_name=='$file'";
155 $res2 = $db->query($sql);
157 foreach($res2 as $row2)
158 $slot = $row2["slot_no"];
159 } else $slot = "none";
160 echo "Tape: $file (slot $sln)\n";
162 //echo "didnt match: $file\n";
169 $nt = (int)(conf_getVal($changer, "ndrives"));
170 for($i = 0; $i < $nt; $i++) {
171 if(file_exists("$tapeloc/$changer-drive$i")) {
172 $rl = basename(readlink("$tapeloc/$changer-drive$i"));
173 echo "drive $i points has tape $rl loaded\n";
175 echo "drive $i is unloaded\n";
180 function list_disks()
182 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
184 check_init_and_fail($argv[1]);
186 $db = db_getDB($argv[1]);
188 $res = $db->query("select * from disk_list");
191 foreach($res as $row) {
192 echo "Disk ".$row["disk_id"].": ".$row["disk_name"]."\n";
197 echo "No disks defined yet for this changer\n";
206 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
208 // check if we are the bacula user
209 $user = posix_getlogin();
210 $user = $_SERVER["USER"];
211 if($user != $BACULA_USER) {
212 echo "This command must be run as the bacula user ($BACULA_USER not $user)\n";
216 $changer_name = $argv[1];
218 echo "This command will init the data for $changer_name\n";
220 if(file_exists("$BASE_DATA/$changer_name.db")&&check_init($changer_name)) {
221 //echo "Daemon is already init'd, are you sure you wish to do this, it will loose all config [y/n]:";
222 $r = readline("Daemon is already init'd, are you sure you wish to do this, it will loose all config [y/n]:");
224 echo "Ok, but its your disaster, waiting 5 seconds prior to init'ing the database (hit ctrl-c to exit)\n";
226 unlink("$BASE_DATA/$changer_name.db");
228 echo "Ok, not doing it, so long chum\n";
233 echo "Creating database\n";
234 $ra = readline("Directory where automount occurs [/changer/]:");
235 $rb = readline("Number of drives [2]:");
236 $rc = readline("Size of tapes [20] (in gb):");
237 $rd = readline("Where to store drive pointers [/var/run/bacula/]:");
239 if($ra == "") $ra = "/changer/";
240 if($rb == "") $rb = 2;
241 if($rc == "") $rc = 20;
242 if($rd == "") $rd = "/var/run/bacula/";
244 conf_setVal($changer_name, "automountdir", "$ra");
245 conf_setVal($changer_name, "ndrives", "$rb");
246 conf_setVal($changer_name, "tapesize", "$rc");
247 conf_setVal($changer_name, "drivelocation", "$rd");
249 // check if they were set
250 echo "got: ".conf_getVal($changer_name, "automountdir").", and ".conf_getVal($changer_name, "tapesize").", and ".conf_getVal($changer_name, "ndrives")."\n";
253 function check_init_and_fail($changer)
255 $lk = conf_getVal($changer, "automountdir");
257 echo "DB not init'd yet, please run init first\n";
262 function check_init($changer)
264 $lk = conf_getVal($changer, "automountdir");
272 function disk_get_size($file, $realname="")
274 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
276 check_init_and_fail($argv[1]);
280 error_reporting(E_ALL);
282 $dh = opendir("/dev/disk/by-uuid");
283 $amdir = conf_getVal($changer, "automountdir");
288 if(file_exists("/$amdir/$file/.")) {
289 $cmd = "/bin/df -k /$amdir/$file/. |/usr/bin/tail -1 |/usr/bin/awk '{ print $4 }'";
290 $pl = popen($cmd, "r");
292 $f = fread($pl, 1024);
293 echo "cmd: $cmd\nf: $f\n";
295 if($ts > 1) $parsed = true;
300 if(!$parsed && $realname != "") {
301 $fh = fopen("/sys/class/block/$realname/size", "r");
302 $lk = ((int)(fgets($fh)));
303 $ts = ($lk/1024)*512;
308 $realsize = (int)(($ts/1024)/1024);
315 // disks get inited by going to /changer_dir/disk_uuid/ then:
316 // creating pbdc/changer_name/stuff.
317 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
319 check_init_and_fail($argv[1]);
323 $dh = opendir("/dev/disk/by-uuid");
324 $amdir = conf_getVal($changer, "automountdir");
329 while(($file = readdir($dh)) !== false) {
330 if($file != "." && $file != "..") {
331 $st = stat("/dev/disk/by-uuid/".$file);
332 $realname = basename(readlink("/dev/disk/by-uuid/".$file));
333 $realsize = disk_get_size($file, $realname);
335 // now get the size, first lets try and parse df output
336 echo "disk $i: /dev/$realname or /dev/disk/by-uuid/$file of size ".$realsize."gb\n";
337 $disk[$i]["real"] = "/dev/$realname";
338 $disk[$i]["syml"] = "/dev/disk/by-uuid/".$file;
339 $disk[$i]["size"] = $realsize;
347 $i = readline("Choose a disk from the list above:");
348 if(isset($disk[$i]["real"])) {
349 echo "you have chosen, ".$disk[$i]["syml"]." (".$disk[$i]["real"].") of size ".$disk[$i]["size"]."gb\n";
350 $ans = readline("is this correct? [y/n]:");
352 echo "you said no, i bail\n";
356 echo "invalid selection\n";
360 // now we try and init the disk
361 // we have to get automount directory config
362 $dir = conf_getVal($argv[1], "automountdir");
364 echo "cant find automount directory, $dir\n";
366 $mkd = "$dir/".basename($disk[$i]["syml"])."/pbdc/".$argv[1]."/tapes/";
367 $k = mkdir($mkd, 0700, true);
370 echo "Error, couldn't create directory, check permissions on $mkd?\n";
373 $ts = conf_getVal($argv[1], "tapesize");
374 $max = (int)($disk[$i]["size"]/$ts);
376 $kt = (int)(readline("No of tapes to create [max:$max] @ ".$ts."gb each:"));
378 echo "Sorry, max number of tapes is $max, creating $max instead\n";
382 $did = add_diskToDB($argv[1], basename($disk[$i]["syml"]));
385 echo "Disk already exists, doing nothing\n";
389 // disk names are d.$did_vol0000x
390 //echo "did: $did\n";
391 for($ii=0; $ii < $kt; $ii++) {
392 $tid = sprintf("d%d_vol%04d", $did, $ii);
393 //echo "would create $tid\n";
394 $tp = "$dir/".basename($disk[$i]["syml"])."/pbdc/".$argv[1]."/tapes/$tid";
395 if(!file_exists($tp)) {
397 echo "created tape $tid\n";
399 echo "tape $tid already existed\n";
401 add_to_slot($argv[1], $tid, $did);
405 function add_to_slot($changer, $tapename, $disk_id)
407 global $BASE_DATA, $BASE_LIB, $BACULA_USER, $argv;
409 $db = db_getDB($changer);
415 $res = $db->query("select * from slots");
416 foreach($res as $row) {
417 $slot[$row["slot_no"]]["diskid"] = $row["disk_id"];
418 $slot[$row["slot_no"]]["tapename"] = $row["tape_name"];
420 if($row["slot_no"] > $max_slot) $max_slot = $row["slot_no"];
423 // first tape, straight in with you
425 $db->query("insert into slots values (NULL, 1, $disk_id, '$tapename')");
429 // next hunt thru the slots and see if its filled yet.
430 foreach($slot as $lk) {
431 if($lk["tapename"] == $tapename) {
432 // tape was already there, move along
437 // now we go from 0 to the end looking for a free slot
438 for($i=1; $i < $max_slot; $i++) {
439 if(!isset($slot[$i])) {
440 // we have a free slot, but it shouldnt appear that way like that.. oh well.
441 $db->query("insert into slots values (NULL, $i, $disk_id, '$tapename')");
444 if($slot[$i]["tapename"] == "") {
446 $db->query("delete from slots where slot_no='$i'");
447 $db->query("insert into slots values (NULL, $i, $disk_id, '$tapename')");
452 // So much error checking to do.
453 // if we made it here, we need more slots.
455 $db->query("insert into slots values (NULL, $ns, $disk_id, '$tapename')");