function getInfo()
 {
     global $config;
     if (!is_numeric($this->id)) {
         throw new Exception('backupStrategy->getInfo: ' . "Error: The ID for this object is not an integer.");
     }
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT * FROM backup_strategies WHERE backup_strategy_id=" . $this->id;
     if (!($res = $conn->query($sql))) {
         throw new Exception('backupStrategy->getInfo: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     $info = $res->fetch_array();
     return $info;
 }
 function setKilled($bool = true)
 {
     if (!is_numeric($this->id)) {
         throw new Exception('backupJob->setKilled: ' . "Error: The ID for this object is not an integer.");
     }
     $conn = dbConnection::getInstance($this->log);
     if ($bool) {
         $killed = 1;
     } else {
         $killed = 0;
     }
     $sql = "UPDATE backup_jobs SET killed = " . $killed . " WHERE backup_job_id=" . $this->id;
     if (!$conn->query($sql)) {
         throw new DBException('backupJob->setKilled: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     return;
 }
 function getChild()
 {
     global $config;
     if (!is_numeric($this->id)) {
         throw new Exception('backupSnapshot->getChild: ' . "Error: The ID for this object is not an integer.");
     }
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT backup_snapshot_id FROM backup_snapshots WHERE status='COMPLETED' AND parent_snapshot_id=" . $this->id;
     if (!($res = $conn->query($sql))) {
         throw new Exception('backupSnapshot->getChild: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     if ($res->num_rows != 1) {
         throw new Exception('backupSnapshot->getChild: ' . "Error: Could not identify a single child of this backupSnapshot.");
     }
     $row = $res->fetch_array();
     $backupGetter = new backupSnapshotGetter();
     return $backupGetter->getById($row['backup_snapshot_id']);
 }
 function destroy()
 {
     global $config;
     // Validate
     $this->__validate();
     $this->setStatus('DELETING');
     $this->deleteFiles();
     // Remove the row from the DB.
     $conn = dbConnection::getInstance($this->log);
     $sql = "DELETE FROM materialized_snapshots WHERE materialized_snapshot_id=" . $this->id;
     if (!$conn->query($sql)) {
         throw new Exception('materializedSnapshot->destroy: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     if ($conn->affected_rows != 1) {
         throw new Exception('materializedSnapshot->destroy: ' . "Error: Failed to delete the Materialized Snapshot with ID " . $this->id . ".");
     }
     return true;
 }
 /**
  * QueryBuilder::getCount()
  * 
  * @return
  */
 function getCount()
 {
     $where = sizeof($this->wheres) > 0 ? ' WHERE ' . implode(" \n AND \n\t", $this->wheres) : '';
     $order = sizeof($this->orders) > 0 ? ' ORDER BY ' . implode(", ", $this->orders) : '';
     $group = sizeof($this->groups) > 0 ? ' GROUP BY ' . implode(", ", $this->groups) : '';
     $query = "SELECT count(*) FROM \n\t" . $this->class->databaseInfo->table . "\n " . implode("\n ", $this->joins) . $where . ' ' . $group . ' ' . $order . ' ';
     return dbConnection::getInstance($this->class->databaseInfo->connection)->fetchOne($query);
 }
示例#6
0
 function setParam($param, $value)
 {
     // Validate this...
     if (!is_numeric($this->id)) {
         throw new Exception('host->getScheduledBackupDisplay: ' . "Error: The ID for this object is not an integer.");
     }
     $conn = dbConnection::getInstance($this->log);
     switch (strtolower($param)) {
         case 'hostname':
             self::validateHostname($value);
             $backups = $this->getScheduledBackups();
             if (sizeOf($backups) > 0) {
                 // We have backups linked to this volume
                 // Collect and print the information ...
                 $info = $this->getInfo();
                 $errMsg = 'Error: Unable to edit the hostname for host with hostname: ' . $info['hostname'] . "\n\n" . $this->getScheduledBackupDisplay();
                 throw new ProcessingException($errMsg);
             }
             $sql = "UPDATE hosts SET hostname='" . $conn->real_escape_string($value) . "' WHERE host_id=" . $this->id;
             break;
         case 'description':
             self::validateHostDescription($value);
             $sql = "UPDATE hosts SET description='" . $conn->real_escape_string($value) . "' WHERE host_id=" . $this->id;
             break;
         case 'ssh_port':
             self::validateSSHPort($value);
             $sql = "UPDATE hosts SET ssh_port=" . $value . " WHERE host_id=" . $this->id;
             break;
         case 'active':
             self::validateActive($value);
             $sql = "UPDATE hosts SET active='" . $conn->real_escape_string(strtoupper($value)) . "' WHERE host_id=" . $this->id;
             break;
         case 'staging_path':
             self::validateStagingPath($value);
             $sql = "UPDATE hosts SET staging_path='" . $conn->real_escape_string($value) . "' WHERE host_id=" . $this->id;
             break;
         default:
             throw new InputException("Error: Unknown Host parameter: " . $param);
             break;
     }
     if (!$conn->query($sql)) {
         throw new DBException('host->setParam: ' . "Error: Query {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     return;
 }
 function destroy()
 {
     // Validate this...
     if (!is_numeric($this->id)) {
         throw new Exception('scheduledBackup->destroy: ' . "Error: The ID for this object is not an integer.");
     }
     $queueManager = new queueManager();
     $queueManager->setLogStream($this->log);
     // We need to take over all queues for this backup and make sure nothing is running.
     $queues = array('scheduledBackup:' . $this->id, 'retentionApply:' . $this->id, 'postProcess:' . $this->id);
     foreach ($queues as $queue) {
         $ticket = $queueManager->getTicketNumber($queue);
         if (!$queueManager->checkFrontOfQueue($queue, $ticket)) {
             throw new ProcessingException("Error: Cannot remove the Scheduled Backup Task as it is currently running.");
         }
     }
     // Check to see if anything is running for this scheduledBackup
     $runningBackupGetter = new runningBackupGetter();
     $runningBackupGetter->setLogStream($this->log);
     $runningBackups = $runningBackupGetter->getByScheduledBackup($this);
     if (sizeOf($runningBackups) > 0) {
         throw new ProcessingException("Error: Cannot remove the Scheduled Backup Task as it is currently running.");
     }
     // Get all snapshots and destroy them..
     $groups = $this->getSnapshotGroupsNewestToOldest();
     foreach ($groups as $group) {
         $snapshots = $group->getAllSnapshotsNewestToOldest();
         foreach ($snapshots as $snapshot) {
             $snapshot->destroy();
         }
     }
     // If we have a materialized snapshot - destroy that too
     if ($latestMaterialized = $this->getMostRecentCompletedMaterializedSnapshot()) {
         $latestMaterialized->destroy();
     }
     $conn = dbConnection::getInstance($this->log);
     // Remove DB the entries for this scheduledBackup
     $sql = "DELETE sb.*, sbp.* FROM scheduled_backups sb JOIN scheduled_backup_params sbp USING (scheduled_backup_id) WHERE scheduled_backup_id = " . $this->id;
     if (!$conn->query($sql)) {
         throw new DBException('scheduledBackup->setParam: ' . "Error: Query {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     return;
 }
 function getStagingTmpdir()
 {
     global $config;
     if (!is_numeric($this->id)) {
         throw new Exception('runningBackup->getStagingTmpdir: ' . "Error: The ID for this object is not an integer.");
     }
     $conn = dbConnection::getInstance($this->log);
     $info = $this->getInfo();
     // Collect the info we need to connect to the remote host
     $backupGetter = new scheduledBackupGetter();
     $scheduledBackup = $backupGetter->getById($info['scheduled_backup_id']);
     $sbInfo = $scheduledBackup->getInfo();
     $host = $scheduledBackup->getHost();
     $hostInfo = $host->getInfo();
     $this->remoteTempDir = new remoteTempDir();
     $tempDir = $this->remoteTempDir->init($hostInfo['hostname'], $hostInfo['ssh_port'], $sbInfo['backup_user'], $hostInfo['staging_path'], 'xbm-');
     // Put the path into the DB
     $sql = "UPDATE running_backups SET staging_tmpdir='" . $conn->real_escape_string($tempDir) . "' WHERE running_backup_id=" . $this->id;
     if (!$conn->query($sql)) {
         throw new Exception('runningBackup->getStagingTmpdir: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     return $tempDir;
 }
 function upgrade()
 {
     // Look for running backups without checking schema version
     $runningBackupGetter = new runningBackupGetter();
     $runningBackupGetter->setSchemaVersionChecks(false);
     // Get the runningbackups - this getter automatically removes stale entries, so it should only return truly running pids...
     $runningBackups = $runningBackupGetter->getAll();
     $backupCount = sizeOf($runningBackups);
     // If we find running backups, abort with error
     if ($backupCount > 0) {
         throw new ProcessingException('schemaUpgrader->upgrade: ' . "Error: Detected " . $backupCount . " backup(s) currently running. Please retry upgrading the schema later.");
     }
     // Create a new DB connection getter that does not check the schema version...
     $conn = dbConnection::getInstance($this->log, false);
     $schemaVersion = $conn->getSchemaVersion();
     switch (true) {
         // If the schema versions match - all is good  - nothing to do
         case $schemaVersion == XBM_SCHEMA_VERSION:
             $this->resultMsg = "The schema version of the XtraBackup Manager database is already at the expected version number (" . XBM_SCHEMA_VERSION . ").";
             return true;
             break;
             // If the schema version of the DB is higher than what we need - throw an error!
         // If the schema version of the DB is higher than what we need - throw an error!
         case $schemaVersion > XBM_SCHEMA_VERSION:
             $this->resultMsg = "The schema version of the XtraBackup Manager database (" . $schemaVersion . ") is higher than the expected version number (" . XBM_SCHEMA_VERSION . ").";
             return false;
             break;
             // Schema version is < expected version - we need to upgrade!
         // Schema version is < expected version - we need to upgrade!
         case $schemaVersion < XBM_SCHEMA_VERSION:
             // Find all the files in the $XBM_AUTO_INSTALLDIR/sql/changes/ directory
             global $XBM_AUTO_INSTALLDIR;
             $files = glob($XBM_AUTO_INSTALLDIR . '/sql/changes/*');
             // Sort them just in case the OS gives them back in a strange order
             asort($files);
             // Walk the array and build a list of scripts to run of files that are numeric and > $schemaVersion
             $toRun = array();
             foreach ($files as $filename) {
                 $basename = basename($filename);
                 if (is_numeric($basename) && $basename > $schemaVersion && $basename <= XBM_SCHEMA_VERSION) {
                     $toRun[] = $filename;
                 }
             }
             // Walk over the array applying each schema update
             foreach ($toRun as $scriptName) {
                 $version = basename($scriptName);
                 // Run the script
                 $sql = file_get_contents($scriptName);
                 if (!($res = $conn->query($sql))) {
                     throw new Exception('schemaUpgrader->upgrade: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
                 }
                 // Update the schemaVersion in the DB
                 $sql = "UPDATE schema_version SET version=" . $version;
                 if (!($res = $conn->query($sql))) {
                     throw new Exception('schemaUpgrader->upgrade: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
                 }
             }
             $this->resultMsg = "The XtraBackup Manager database schema was successfully upgraded to schema version " . XBM_SCHEMA_VERSION . ".";
             return true;
             break;
             // Catch all - should never get here
         // Catch all - should never get here
         default:
             $this->resultMsg = "An issue occurred when comparing schema versions. This probably indicated a bug in XtraBackup Manager.";
             return false;
             break;
     }
     // Catch all - should never get here
     $this->resultMsg = "An issue occurred when comparing schema versions. This probably indicated a bug in XtraBackup Manager.";
     return false;
     // Get the schema version
 }
 /**
  * Logger::dbCheck()
  * Checks if the current database exists, and creates it if it's not there.
  */
 public function dbCheck()
 {
     if (!$this->checked) {
         $this->log[] = "checking if db exists";
         $this->checked = dbConnection::getInstance('Logger')->tableExists(Settings::Load()->Get('Logger', 'logtable'));
         if (!$this->checked) {
             $createquery = $this->createqueries[strtolower(Settings::Load()->Get('Logger', 'dbtype'))];
             $createquery = str_replace('@logtable@', Settings::Load()->Get('Logger', 'logtable'), $createquery);
             $this->checked = dbConnection::getInstance('Logger')->query($createquery);
             if (!$this->checked) {
                 die("Error creating logdatabase");
             }
             Logger::Log("Log database created.");
         }
     }
 }
 function getById($id)
 {
     global $config;
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT backup_strategy_id FROM backup_strategies WHERE backup_strategy_id=" . $id;
     if (!($res = $conn->query($sql))) {
         throw new DBException('backupStrategyGetter->getById: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     if ($res->num_rows != 1) {
         return false;
     }
     $strategy = new backupStrategy($id);
     $strategy->setLogStream($this->log);
     return $strategy;
 }
 function getAllSnapshotsNewestToOldest()
 {
     $this->__validate();
     global $config;
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT backup_snapshot_id FROM backup_snapshots WHERE status='COMPLETED' AND scheduled_backup_id=" . $this->scheduledBackupId . " \n\t\t\t\t\tAND snapshot_group_num=" . $this->snapshotGroupNum . " ORDER BY snapshot_time DESC";
     if (!($res = $conn->query($sql))) {
         throw new Exception('backupSnapshotGroup->getAllSnapshotsNewestToOldest: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     $snapshots = array();
     while ($row = $res->fetch_array()) {
         $snapshotGetter = new backupSnapshotGetter();
         $snapshots[] = $snapshotGetter->getById($row['backup_snapshot_id']);
     }
     return $snapshots;
 }
 function getScheduledBackups()
 {
     // Validate this...
     if (!is_numeric($this->id)) {
         throw new Exception('backupVolume->getScheduledBackups: ' . "Error: The ID for this object is not an integer.");
     }
     global $config;
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT scheduled_backup_id FROM scheduled_backups WHERE backup_volume_id=" . $this->id;
     if (!($res = $conn->query($sql))) {
         throw new DBException('backupVolume->getScheduledBackups: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     $backupGetter = new scheduledBackupGetter();
     $backupGetter->setLogStream($this->log);
     $backups = array();
     while ($row = $res->fetch_array()) {
         $backups[] = $backupGetter->getById($row['scheduled_backup_id']);
     }
     return $backups;
 }
 function applyRetentionPolicy(backupJob $job)
 {
     global $config;
     $scheduledBackup = $job->getScheduledBackup();
     $this->infolog->write("Checking to see if any snapshots need to be merged into the seed backup.", XBM_LOG_INFO);
     if (!is_object($scheduledBackup)) {
         throw new Exception('continuousIncrementalBackupTaker->applyRetentionPolicy: ' . "Error: This function requires a scheduledBackup object as a parameter.");
     }
     $conn = dbConnection::getInstance($this->log);
     $sql = "SELECT backup_snapshot_id FROM backup_snapshots WHERE status='COMPLETED' AND scheduled_backup_id=" . $scheduledBackup->id . " AND snapshot_time IS NOT NULL ORDER BY snapshot_time ASC";
     if (!($res = $conn->query($sql))) {
         throw new Exception('continuousIncrementalBackupTaker->applyRetentionPolicy: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
     }
     // Get info for this scheduledBackup
     $info = $scheduledBackup->getInfo();
     // Get the params/options for this scheduledBackup
     $params = $scheduledBackup->getParameters();
     // Validate them
     $this->validateParams($params);
     // Build service objects for later use
     $snapshotGetter = new backupSnapshotGetter();
     $snapshotMerger = new backupSnapshotMerger();
     // Check to see if the number of rows we have is more than the number of snapshots we should have at a max
     while ($res->num_rows > $params['max_snapshots']) {
         // Grab the first row - it is the SEED
         if (!($row = $res->fetch_array())) {
             throw new Exception('continuousIncrementalBackupTaker->applyRetentionPolicy: ' . "Error: Could not retrieve the object ID for the seed of Scheduled Backup ID " . $scheduledBackup->id);
         }
         $seedSnapshot = $snapshotGetter->getById($row['backup_snapshot_id']);
         // Grab the second row - it is the DELTA to be collapsed.
         if (!($row = $res->fetch_array())) {
             throw new Exception('continuousIncrementalBackupTaker->applyRetentionPolicy: ' . "Error: Could not retrieve the object ID for the seed of Scheduled Backup ID " . $scheduledBackup->id);
         }
         $deltaSnapshot = $snapshotGetter->getById($row['backup_snapshot_id']);
         $this->infolog->write("Merging deltas in Backup Snapshot ID #" . $deltaSnapshot->id . " with Backup Snapshot ID #" . $seedSnapshot->id . ".", XBM_LOG_INFO);
         // Merge them together
         $snapshotMerger->mergeSnapshots($seedSnapshot, $deltaSnapshot);
         // Check to see what merge work is needed now.
         $sql = "SELECT backup_snapshot_id FROM backup_snapshots WHERE status='COMPLETED' AND scheduled_backup_id=" . $scheduledBackup->id . " AND snapshot_time IS NOT NULL ORDER BY snapshot_time ASC";
         if (!($res = $conn->query($sql))) {
             throw new Exception('continuousIncrementalBackupTaker->applyRetentionPolicy: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}");
         }
     }
     return true;
 }