function handleSnapshotActions($args) { global $config; if (!isset($args[2])) { // Just output some helpful info and exit echo "Error: Action missing.\n\n"; $this->printSnapshotHelpText($args); return; } switch ($args[2]) { // Handle list case 'list': // If we just get a hostname, check to see if it only has one Scheduled Backup task if (isset($args[3]) && !isset($args[4])) { $hostname = $args[3]; $hostGetter = new hostGetter(); $hostGetter->setLogStream($this->log); if (!($host = $hostGetter->getByName($hostname))) { throw new ProcessingException("Error: Could not find a host with hostname: {$hostname}"); } $scheduledBackups = $host->getScheduledBackups(); // If we dont find scheduled backups - throw exception if (sizeOf($scheduledBackups) == 0) { throw new ProcessingException("Error: Could not find any backups for host: {$hostname}"); } } // If we are dealing with only one specific backup if (isset($args[3]) && isset($args[4])) { $scheduledBackupGetter = new scheduledBackupGetter(); $scheduledBackupGetter->setLogStream($this->log); $hostname = $args[3]; $backupName = $args[4]; $scheduledBackups = array(); if (!($scheduledBackups[0] = $scheduledBackupGetter->getByHostnameAndName($hostname, $backupName))) { throw new ProcessingException("Error: Could not find a backup for host: {$hostname} with name: {$backupName}"); } } if (!isset($args[3]) && !isset($args[4])) { throw new InputException("Error: Not all required parameters for the snapshots to list were given.\n\n" . " Syntax:\n\n\txbm " . $args[1] . " list <hostname> [<backup_name>]\n\n" . " Example:\n\n\txbm " . $args[1] . " list db01.mydomain.com 'Nightly Backup'\n\n"); } echo "-- Listing Backup Snapshots for {$hostname} --\n\n"; // By this point we should have an array scheduledBackups to display info for foreach ($scheduledBackups as $scheduledBackup) { $sbInfo = $scheduledBackup->getInfo(); $groups = $scheduledBackup->getSnapshotGroupsNewestToOldest(); $strategy = $scheduledBackup->getBackupStrategy(); $strategyInfo = $strategy->getInfo(); echo " -- Snapshots for Backup Name: " . $sbInfo['name'] . "\n"; // Display materialized snapshot if enabled $params = $scheduledBackup->getParameters(); if (isset($params['maintain_materialized_copy']) && $params['maintain_materialized_copy'] == 1) { $materialized = $scheduledBackup->getMostRecentCompletedMaterializedSnapshot(); echo "\t-- Latest Materialized Snapshot:\n"; if ($materialized == false) { echo "\t None.\n"; } else { $materializedInfo = $materialized->getInfo(); $mSnap = $materialized->getBackupSnapshot(); $mSnapInfo = $mSnap->getInfo(); echo "\t ID: m" . $materializedInfo['materialized_snapshot_id'] . " Snapshot Time: " . $mSnapInfo['snapshot_time']; // Was going to display path here, but decided users should never know the path // they should always use xbm commands for restores to ensure correct locking //." Path: ".$materialized->getPath()."\n"); } } // Display Snapshots (by group if ROTATING method is used) $groupNum = 0; foreach ($groups as $group) { $groupNum++; if ($strategyInfo['strategy_code'] == 'ROTATING') { echo "\t-- Group: {$groupNum}\n"; } $snapshots = $group->getAllSnapshotsNewestToOldest(); foreach ($snapshots as $snapshot) { $snapInfo = $snapshot->getInfo(); echo "\t ID: " . $snapInfo['backup_snapshot_id'] . " Type: " . $snapInfo['type'] . " Snapshot Time: " . $snapInfo['snapshot_time'] . " Creation Method: " . $snapInfo['creation_method'] . "\n"; } if (sizeOf($snapshots) == 0) { echo "\t None.\n"; } } } echo "\n\n"; break; // Handle restore // Handle restore case 'restore-latest': // If we just got a path and hostname, if (isset($args[3]) && isset($args[4]) && !isset($args[5])) { $hostname = $args[4]; $targetPath = $args[3]; $hostGetter = new hostGetter(); $hostGetter->setLogStream($this->log); if (!($host = $hostGetter->getByName($hostname))) { throw new ProcessingException("Error: Could not find a host with hostname: {$hostname}"); } $scheduledBackups = $host->getScheduledBackups(); // If we dont find scheduled backups - throw exception if (sizeOf($scheduledBackups) == 0) { throw new ProcessingException("Error: Could not find any backups for host: {$hostname}"); } // If we find more than 1 scheduled backup - throw exception if (sizeOf($scheduledBackups) > 1) { throw new ProcessingException("Error: Found multiple Backup Tasks for host: {$hostname} - Please specify which backup name to restore the latest snapshot for."); } $scheduledBackup = $scheduledBackups[0]; } // If we got a host AND backup name if (isset($args[3]) && isset($args[4]) && isset($args[5])) { $targetPath = $args[3]; $hostname = $args[4]; $backupName = $args[5]; $scheduledBackupGetter = new scheduledBackupGetter(); $scheduledBackupGetter->setLogStream($this->log); if (!($scheduledBackup = $scheduledBackupGetter->getByHostnameAndName($hostname, $backupName))) { throw new ProcessingException("Error: Could not find a Scheduled Backup Task for host: {$hostname} with name: {$backupName}"); } } if (!isset($args[3]) || !isset($args[4])) { throw new InputException("Error: Not all required parameters for the Scheduled Backup you wish to restore the latest snapshot for were given.\n\n" . " Syntax:\n\n\txbm " . $args[1] . " restore-latest <target_path> <hostname> [<backup_name>]\n\n" . " Example:\n\n\txbm " . $args[1] . " restore-latest /restores/myrestore db01.mydomain.com 'Nightly Backup'\n\n"); } $sbInfo = $scheduledBackup->getInfo(); // Check if we have any COMPLETED snapshots anyway $snapCount = $scheduledBackup->getCompletedSnapshotCount(); if ($snapCount < 1) { throw new ProcessingException("Error: No snapshots exist for the Scheduled Backup Task with name: " . $sbInfo['name'] . " for host: {$hostname}"); } // We have a scheduledBackup - figure out if we might have a materialized snapshot and work accordingly $params = $scheduledBackup->getParameters(); $snapshot = false; if ($params['maintain_materialized_copy'] == 1) { // Is there a materialized snapshot? $snapshot = $scheduledBackup->getMostRecentCompletedMaterializedSnapshot(); } // If not, lets try finding the most recent snapshot for this scheduledBackup if ($snapshot == false) { $snapshot = $scheduledBackup->getMostRecentCompletedBackupSnapshot(); } // At this point we either have a materialized snapshot or regular snapshot in $snapshot // Lets proceed with restoring... $this->handleRestore($snapshot, $targetPath); break; case 'restore': if (isset($args[3]) && isset($args[4])) { // Handle the valid snapshot id inputs that we know // Numeric - regular snapshot if (is_numeric($args[4])) { $backupSnapshotGetter = new backupSnapshotGetter(); $backupSnapshotGetter->setLogStream($this->log); if (!($snapshot = $backupSnapshotGetter->getById($args[4]))) { throw new ProcessingException("Error: Could not find a Backup Snapshot with ID: " . $args[4]); } // Materialized snapshot } elseif (substr($args[4], 0, 1) == 'm' && is_numeric(substr($args[4], 1))) { $materialId = substr($args[4], 1); $materializedSnapshotGetter = new materializedSnapshotGetter(); $materializedSnapshotGetter->setLogStream($this->log); if (!($snapshot = $materializedSnapshotGetter->getById($materialId))) { throw new ProcessingException("Error: Could not find a materialized Backup Snapshot with ID: " . $args[4]); } // Catch all for when the input snapshot id is not recognized... // it should have been one of the following: // letter m, followed by numeric ID - eg. m12 - m signifies a materialized snapshot // just a numeric id - eg. 12 - no letter m prepended signifies a regular snapshot } else { throw new InputException("Error: The Snapshot ID specified must be of any of these forms: 12, m12 (m denotes a Materialized Snapshot ID)\n\n" . " Syntax:\n\n\txbm " . $args[1] . " restore <snapshot_id> <target_path>\n\n" . " Example:\n\n\txbm " . $args[1] . " restore m21 /restores/myrestore\n\n"); } $snapInfo = $snapshot->getInfo(); if ($snapInfo['status'] != 'COMPLETED') { throw new ProcessingException("Error: The snapshot specified is in " . $snapInfo['status'] . " status. Only COMPLETED snapshots can be restored."); } $this->handleRestore($snapshot, $args[3]); } else { throw new InputException("Error: Not all required parameters for the restore action were given.\n\n" . " Syntax:\n\n\txbm " . $args[1] . " restore <snapshot_idt> <target_path>\n\n" . " Example:\n\n\txbm " . $args[1] . " restore m21 /restores/myrestore\n\n"); } break; // Catch unknown action // Catch unknown action default: echo "Error: Unrecognized action for " . $args[1] . " context: " . $args[2] . "\n\n"; $this->printSnapshotHelpText($args); break; } }
function getMostRecentCompletedMaterializedSnapshot() { global $config; if (!is_numeric($this->id)) { throw new Exception('scheduledBackup->getMostRecentCompletedMaterializedSnapshot: ' . "Error: The ID for this object is not an integer."); } $conn = dbConnection::getInstance($this->log); $sql = "SELECT materialized_snapshot_id FROM materialized_snapshots WHERE status='COMPLETED' AND scheduled_backup_id=" . $this->id . " ORDER BY creation_time DESC LIMIT 1"; if (!($res = $conn->query($sql))) { throw new Exception('scheduledBackup->getMostRecentCompletedMaterializedSnapshot: ' . "Error: Query: {$sql} \nFailed with MySQL Error: {$conn->error}"); } if ($res->num_rows < 1) { return false; } $row = $res->fetch_array(); $snapshotGetter = new materializedSnapshotGetter(); $snapshot = $snapshotGetter->getById($row['materialized_snapshot_id']); return $snapshot; }