Location: PHPKode > projects > Browseable Online Backup System > bobs-0.6.4/systemcheck.php
<?php

// systemcheck.php - Verify bobs is configured properly and working

//if (isset($_GET['menu_bobs'])){                 // BOBS menu button pushed
//    $bobsdir = dirname($_SERVER['PHP_SELF']);
//    header("Location: $bobsdir");               // Redirect browser to BOBS main index
//    exit;                                       // Make sure that code below does not get executed
//}

require_once ('inc/class_rfasttemplate.php');   // Template class
require_once("inc/class_config.php");           // configuration class
require_once("inc/class_admin.php");            // Administration interface class
include_once("inc/header.pinc");                // Main menu

$config = new config();                         // Create instance of configuration class
$admin = new admin();                           // Create instance of admin class

// some global variables
$backup='';
$srvtmpl='';

$t = new rFastTemplate ('inc/templates');
$t->define (array('content' => 'systemcheck.thtml'));
$t->define_dynamic (array ('item' => 'content', 'help' => 'content'));

// Heading

$t->assign ('TITLE', 'System check');
$t->parse ('CONTENT', 'content');
echo ($t->fetch());


// --------------------------------
// Site root
// --------------------------------

$siteroot = $config->get_siteroot();
$t->assign ('ITEM', "Bobs site root directory is $siteroot");
if (strlen($siteroot) <= 0){
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "Siteroot is not set in config.php.<br>
                Reinstall bobs or manually edit the config.php
                file in bobs web directory.");
    putfail();
} else {
    $t->assign ('STATUS', 'PASS');
    putpass();
}

$t->assign ('ITEM', "Checking if $siteroot exists");
if (is_dir($siteroot)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "siteroot directory $siteroot does not exist.<br>
                Bobs is not properly installed. Reinstall bobs.");
    putfail();
}

$t->assign ('ITEM', "Checking if $siteroot is readable");
if (is_readable($siteroot)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "Siteroot directory $siteroot is not readable.<br>
                Check the directory permissions or reinstall bobs.");
    putfail();
}

// --------------------------------
// Server directory
// --------------------------------

$serverdir = $siteroot . '/inc/servers';
$t->assign ('ITEM', "Checking if $serverdir exists");
if (is_dir($serverdir)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "Servers directory $serverdir does not exist.<br>
                Bobs is not properly installed. Reinstall bobs.");
    putfail();
}

$httpduser = rtrim(`whoami`);
$t->assign ('ITEM', "Web server is running as user id $httpduser");
$t->assign ('STATUS', 'INFO');
putpass();

$serverdir = $siteroot . '/inc/servers';
$t->assign ('ITEM', "Checking if $serverdir is writeable by $httpduser");
if (is_writeable($serverdir)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "$httpduser can't write to $serverdir.<br>
                Run these commands as root:<br>
                chown $httpduser.root $serverdir<br>
                chmod 755 $serverdir");
    putfail();
}

// --------------------------------
// Default password
// --------------------------------

$t->assign ('ITEM', "Checking if default administrator password has been changed");
if ($admin->check_admin('admin') != "yes"){
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'WARN');
    $t->assign ('HELP', "The default administrator password has not been changed.<br>
                See the bobs INSTALL document.");
    putfail();
}

// --------------------------------
// Data directory
// --------------------------------

$datadir = $config->get_datadir();
$t->assign ('ITEM', "Bobs data directory is $datadir");
if (strlen($datadir) <= 0){
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "datadir is not set in config.php.<br>
                Reinstall bobs or manually edit the config.php
                file in bobs web directory.");
    putfail();
} else {
    $t->assign ('STATUS', 'PASS');
    putpass();
}

$t->assign ('ITEM', "Checking if $datadir exists");
if (is_dir($datadir)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "Bobs data directory $datadir does not exist.<br>
                Bobs is not properly installed. Reinstall bobs.");
    putfail();
}

$backupdir = $config->get_backupdir();
$t->assign ('ITEM', "Checking if $backupdir is writeable by $httpduser");
if (is_writeable($backupdir)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "$httpduser can't write to $backupdir.<br>
                Run these commands as root:<br>
                chown $httpduser.root $backupdir<br>
                chmod 755 $backupdir");
    putfail();
}

$freespace = disk_free_space($backupdir);
$meg = round($freespace / 1024 / 1024);
$t->assign ('ITEM', "Free space in $backupdir is $meg M");
if ($meg >= 100) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "You only have $meg megabytes of free space on $backupdir.");
    putfail();
}

// --------------------------------
// Check cron daily and backup.php
// --------------------------------

$crondir = $config->get_crondir();
$t->assign ('ITEM', "Bobs cron daily directory is $crondir");
if (strlen($crondir) <= 0){
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "The location of the daily cron files has not been set.<br>
                This is usually /etc/cron.daily/.<br>
                Reinstall bobs and manually specify --with-crondir=DIR<br>
                if it is not set automatically.");
    putfail();
} else {
    $t->assign ('STATUS', 'PASS');
    putpass();
}

$cronbackup = $crondir . '/backup.php';
$t->assign ('ITEM', "Checking if $cronbackup exists and is executable");
if (is_executable($cronbackup)) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "$cronbackup either doesn't exist or is not executable.<br>
                Run ./configure from the install directory and<br>
                see if 'cron directory = /etc/cron.daily'");
    putfail();
}

// --------------------------------
// Check cmdloop
// --------------------------------

$pid = rtrim(`/sbin/pidof -x cmdloop`);
if (strlen($pid) > 0) {
    $t->assign ('ITEM', "Checking for running cmdloop process<br>
            cmdloop process id is $pid");
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('ITEM', "Checking for running cmdloop process");
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "cmdloop doesn't seem to be running.<br>
                Try running this command as root:<br>
                /etc/init.d/cmdloopd start");
    putfail();
}

// --------------------------------
// database support
// --------------------------------

$t->assign ('ITEM', "Checking for dba database support");
if (extension_loaded("dba")) {
    $t->assign ('STATUS', 'PASS');
    putpass();
} else {
    $t->assign ('STATUS', 'FAIL');
    $t->assign ('HELP', "dba database support is not loaded.<br>
                You need to check your php configuration and include dba support.");
    putfail();
}

$t->assign ('ITEM', "Checking for dba (db3 or db4) database support");
$tempfile = '/tmp/bobstest' . posix_getpid();
$handle = @dba_open("$tempfile", "n", "db3");          // open a temporary database
if (!$handle) {
    $handle = @dba_open("$tempfile", "n", "db4");      // open a temporary database
    if (!$handle) {
        $t->assign ('STATUS', 'FAIL');
        $t->assign ('HELP', "dba database support is not working.<br>
                             You need to check your php configuration and<br>
                             include dba database support.");
        putfail();
    }
}
if ($handle) {
    dba_close($handle);                               // close it
    unlink($tempfile);                                // and delete it.
    $t->assign ('STATUS', 'PASS');
    putpass();
}

// ----------------------------
// Server specific checks
// ----------------------------

if (isset($_GET['server']) && $_GET['server'] != "" ) {
    $server = $_GET['server'];
    $share = $_GET['share'];
    $t->assign ('ITEM', "<b>Performing tests on $server / $share<b>");
    $t->assign ('STATUS', 'INFO');
    putpass();
    server_tests($server, $share);
}



// ----------------------------
// End the table and html page
// ----------------------------

$t->parse ('ROW', 'endtable');                  // end the table
echo ($t->fetch());
echo "</body></html>\n";

// ----------------------------
// End of program
// ----------------------------
return;

// ========================================================
// Functions start here
// ========================================================

// ----------------------------
// Server specific tests
// ----------------------------
function server_tests($server, $share){
    global $t, $backup, $srvtmpl;
    
    // Need 'add_queue_command' function from class_backup.php

    $t->assign ('ITEM', "Including file class_backup.php");
    $return = include_once('inc/class_backup.php');
    if ($return){
        $t->assign ('STATUS', 'PASS');
        putpass();
    } else {
        $t->assign ('STATUS', 'FAIL');
        $t->assign ('HELP', "Unable to include file class_backup.php<br>
                Cannot perform server tests. Reinstall bobs.");
        putfail();
    }

    $t->assign ('ITEM', "Including file class_server.php");
    $return = include_once('inc/class_server.php');
    if ($return){
        $t->assign ('STATUS', 'PASS');
        putpass();
    } else {
        $t->assign ('STATUS', 'FAIL');
        $t->assign ('HELP', "Unable to include file class_server.php<br>
                Cannot perform server tests. Reinstall bobs.");
        putfail();
    }

    // Instantiate the backup class so I can use add_queue_command()

    $srvcfg = new server();
    $srvcfg->set_config($server . '.' . $share);
    $backup = new backup($srvcfg->sys_conf, $srvcfg->config);

    // Test communication with cmdloop process

    $srvtmpl = new rFastTemplate ('inc/templates');
    $srvtmpl->define (array('srvchk' => 'servercheck2.sh'));

    $srvtmpl->parse ('ROW', 'basictest');
    $rtnval = submit();
    $srvtmpl->clear_dynamic ('basictest');
    if ($rtnval[0] != -1){
        $t->assign ('ITEM', "Testing communication with cmdloop process.<br>
            Process said: \"$rtnval[0]\"");
        $t->assign ('STATUS', 'PASS');
        putpass();
    } else {
        $t->assign ('ITEM', "Testing communication with cmdloop process");
        $t->assign ('STATUS', 'FAIL');
        $t->assign ('HELP', "Didn't get a valid response from cmdloop.");
        putfail();
    }

    // If backup has not been run on this server,
    // the mount directory will not exist.
    // Create it now so I can test if the mounts and stuff work.
    // Don't need it if backup method is rsync or rcync_ssh so don't create it.

    $config = $srvcfg->get_config();
    $method = $config['backup_method'];
    $mountdir=$srvcfg->get_mount_dir();
    if (! is_dir($mountdir) && ($method != "rsync") && ($method != "rsync_ssh")){
        $t->assign ('ITEM', "It appears $server/$share hasn't been backed up.<br>
                I will attempt to create the mount directories needed to
                continue these tests.");
        $srvtmpl->assign ('MOUNTDIR', "$mountdir"); 
        $srvtmpl->parse ('ROW', 'crtmntdir');
        $rtnval = submit();                         
        $srvtmpl->clear_dynamic ('crtmntdir');
        $cmdoutput = getcmdout($rtnval);            
        if ($rtnval[0] == 0){
            $t->assign ('STATUS', 'PASS');
            putpass();
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Unable to create mount directories. Message was:<br>
                $cmdoutput");
            putfail();
            return(FALSE);                  // don't continue testing
        }
    }

    // Try to mount the selected share.

    $config = $srvcfg->get_config();
    $method = $config['backup_method'];
    if (($method != "rsync") && ($method != "rsync_ssh")){
        $mntcmd = $srvcfg->get_mount_cmd('backup');
        $t->assign ('ITEM', "Attempting to mount for backup method type \"$method\" using this command:<br>
            $mntcmd");
        $srvtmpl->assign ('COMMAND', "$mntcmd");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
            $mounted=TRUE;
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Mount failed with this message:<br>$cmdoutput");
            putfail();
            $mounted=FALSE;
        }

        // Test writing a file to the mounted directory
        
        if ($mounted == TRUE){
            $mountdir=$srvcfg->get_mount_dir();
            $t->assign ('ITEM', "Attempting to write, read and delete a file on<br>
                $mountdir");
            $srvtmpl->assign ('MOUNTDIR', "$mountdir");        // the mount command
            $srvtmpl->parse ('ROW', 'writetest');
            $rtnval = submit();                             // submit the mount cmd
            $srvtmpl->clear_dynamic ('writetest');
            $cmdoutput = getcmdout($rtnval);                // Get the command's output
            if ($rtnval[0] == 0) {
                $t->assign ('STATUS', 'PASS');
                putpass();
            } else {
                $t->assign ('STATUS', 'FAIL');
                $t->assign ('HELP', "Write file test failed with these messages:<br>
                $cmdoutput");
                putfail();
            }
        }

        // Now unmount the share

        sleep(5);                                   // Allow time for last operation to finish
        $umntcmd = $srvcfg->get_umount_cmd('backup');
        $t->assign ('ITEM', "Attempting to unmount for backup method type \"$method\" using this command:<br>
            $umntcmd");
        $srvtmpl->assign ('COMMAND', "$umntcmd");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Unmount failed with this message:<br>$cmdoutput");
            putfail();
        }

    }

    // See if rsync works

    if ($method == "rsync"){
        $rsync_share = $config['rsync_share'];
	$rsync = "rsync -n " . $server . '::' . $rsync_share;
        $t->assign ('ITEM', "Using rsync to list files for backup method \"$method\" using this command:<br>
            $rsync");
        $srvtmpl->assign ('COMMAND', "$rsync");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Rsync failed with this message:<br>$cmdoutput");
            putfail();
        }
    }

    // Test rsync over ssh

    if ($method == "rsync_ssh"){
    	$server_ip = $config['server_ip'];
	if ($server_ip != ''){
		$server_or_ip = $server_ip;
	} else {
		$server_or_ip = $server;
	}
        $rsync_ssh_path = $config['rsync_ssh_path'];
        $rsync = "rsync -n -e ssh " . $server_or_ip . ':' . $rsync_ssh_path;
        $t->assign ('ITEM', "Testing rsync over ssh for backup method \"$method\" using this command:<br>
            $rsync");
        $srvtmpl->assign ('COMMAND', "$rsync");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Rsync over ssh failed with this message:<br>$cmdoutput");
            putfail();
        }
    }

    // Test mounting and unmounting the 'restore' method
    // and reading and writing a file.

    sleep(5);                                   // Allow time for last operation to finish
    $method = $config['restore_method'];
    if (($method != "rsync") && ($method != "rsync_ssh") && ($method != "none")){
        $mntcmd = $srvcfg->get_mount_cmd('restore');
        $t->assign ('ITEM', "Attempting to mount for restore method type \"$method\" using this command:<br>
            $mntcmd");
        $srvtmpl->assign ('COMMAND', "$mntcmd");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
            $mounted=TRUE;
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Mount failed with this message:<br>$cmdoutput");
            putfail();
            $mounted=FALSE;
        }

        // Test writing a file to the mounted directory
        
        if ($mounted == TRUE){
            $mountdir=$srvcfg->get_mount_dir();
            $t->assign ('ITEM', "Attempting to write, read and delete a file on<br>
                $mountdir");
            $srvtmpl->assign ('MOUNTDIR', "$mountdir");        // the mount command
            $srvtmpl->parse ('ROW', 'writetest');
            $rtnval = submit();                             // submit the mount cmd
            $srvtmpl->clear_dynamic ('writetest');
            $cmdoutput = getcmdout($rtnval);                // Get the command's output
            if ($rtnval[0] == 0) {
                $t->assign ('STATUS', 'PASS');
                putpass();
            } else {
                $t->assign ('STATUS', 'FAIL');
                $t->assign ('HELP', "Write file test failed with these messages:<br>
                $cmdoutput");
                putfail();
            }
        }

        // Now unmount the share

        sleep(5);                                   // Allow time for last operation to finish
        $umntcmd = $srvcfg->get_umount_cmd('restore');
        $t->assign ('ITEM', "Attempting to unmount for restore method type \"$method\" using this command:<br>
            $umntcmd.");
        $srvtmpl->assign ('COMMAND', "$umntcmd");        // the mount command
        $srvtmpl->parse ('ROW', 'cmdwoutput');
        $rtnval = submit();                             // submit the mount cmd
        $srvtmpl->clear_dynamic ('cmdwoutput');
        $cmdoutput = getcmdout($rtnval);                // Get the command's output
        if ($rtnval[0] == 0) {
            $t->assign ('STATUS', 'PASS');
            putpass();
        } else {
            $t->assign ('STATUS', 'FAIL');
            $t->assign ('HELP', "Unmount failed with this message:<br>$cmdoutput");
            putfail();
        }

    }

    // See if any backups have completed

    $backups_exist = FALSE;
    $backupdir = $srvcfg->get_backupdir();
    $srvbakdir = $backupdir . '/' . $server . '/' . $share;
    $t->assign ('ITEM', "Checking for completed backups in $srvbakdir.");
    if (is_dir($srvbakdir) && ($dir = opendir($srvbakdir))) {
        while (($file = readdir($dir)) && ($backups_exist == FALSE)) {
            if (($file != ".") && ($file != "..")){
                $backups_exist = TRUE;
            }
        }
        closedir($dir);
    }

    if ($backups_exist == TRUE) {
        $t->assign ('STATUS', 'PASS');
        putpass();
    } else {
        $t->assign ('STATUS', 'WARN');
        $t->assign ('HELP', "I didn't find any backup files.<br>
            This is normal for a new installation.<br>
            You won't be able to use the bobs 'restore' menu
            until a backup has successfully completed.");
        putfail();
    }
}

// ----------------------------
// Output a passed template row
// ----------------------------
function putpass(){
    global $t;
    
    $t->parse ('ROW', 'itempass');
    echo ($t->fetch());
    $t->clear_dynamic ('itempass');
}

// ----------------------------
// Output a failed template row
// ----------------------------
function putfail(){
    global $t;
    
    $t->parse ('ROW', 'itemfail');
    echo ($t->fetch());
    $t->clear_dynamic ('itemfail');
    $t->parse ('HELP', 'help');
    echo ($t->fetch());
    $t->clear_dynamic ('help');
}

// ----------------------------
// Submit a script to be processed by cmdloop
// ----------------------------
function submit(){
    global $backup, $srvtmpl;

    // Generate a temporary file name for return status
    //$pid = posix_getpid();                        // Current process id
    $id = uniqid(bobssrvchk);
    $tempfile = "/tmp/" . "$id";
    `umask 077; touch $tempfile`;                   // I need to create it so I can delete it

    $srvtmpl->assign ('TEMPFILE', $tempfile);
    $srvtmpl->parse ('SRVCHK', 'srvchk');
    $script = $srvtmpl->fetch();
    $backup->add_queue_command($script, 'bash');    // submit the script to run under cmdloop

    // Read the response from the fifo
    $maxsec = 20;                                   // max seconds to wait for script
    $count = 0;
    $filesize = 0;
    while ($filesize == 0 && $count < $maxsec) {
        $count += 1;
        sleep(1);
        clearstatcache();
        $stats = stat("$tempfile");
        $filesize = $stats[7];                      // element 8 is file size
    }
    
    // Read the script output
    if ($filesize > 0) {
        $fout = file($tempfile);
        unlink($tempfile);                          // cleanup: delete the temp file
        return($fout);                              // return the script output
    }
    unlink($tempfile);                              // cleanup: delete the temp file
    return(array(-1, 'Operation timed out.'));
}

// ----------------------------
// Get just the output portion of the submit() return value
// ----------------------------
function getcmdout($rtnval){
    $cmdoutput = "";
    
    foreach (array_slice($rtnval, 1) as $key => $value){
        $cmdoutput .= nl2br("$value");
    }
    $cmdoutput = '<div class="cmdoutput">' . $cmdoutput . '</div>';
    return $cmdoutput;
}

// THE END
?>
Return current item: Browseable Online Backup System