1<?php 2 3/* 4 Phoronix Test Suite 5 URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ 6 Copyright (C) 2018, Phoronix Media 7 Copyright (C) 2018, Michael Larabel 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program. If not, see <http://www.gnu.org/licenses/>. 21*/ 22 23class backup extends pts_module_interface 24{ 25 const module_name = 'Backup Creation + Restore'; 26 const module_version = '1.0.0'; 27 const module_description = 'This is a module for creating backups of the Phoronix Test Suite / Phoromatic and allows for restoring of created backups. The backup will be in ZIP or TAR format. If only a path is specified, the file-name will be auto-generated with a current time-stamp.'; 28 const module_author = 'Phoronix Media'; 29 30 public static function user_commands() 31 { 32 return array('create' => 'create_backup', 'restore' => 'restore_backup'); 33 } 34 public static function create_backup($r) 35 { 36 if(!isset($r[0]) || empty($r[0])) 37 { 38 echo PHP_EOL . pts_client::cli_just_bold('ERROR: ') . 'You must pass the name of the backup file to create and/or any absolute path for the said file you would like to create.' . PHP_EOL . PHP_EOL; 39 return false; 40 } 41 $backup_location = $r[0]; 42 if(strpos($backup_location, DIRECTORY_SEPARATOR) === false) 43 { 44 $backup_location = getcwd() . DIRECTORY_SEPARATOR . $backup_location; 45 } 46 if(is_dir($backup_location)) 47 { 48 $backup_location .= 'pts-backup-' . date('Y-m-d-H-i-s'); 49 } 50 $file_extension = phodevi::is_windows() ? 'zip' : 'tar'; 51 if(substr($backup_location, -4) != '.' . $file_extension) 52 { 53 $backup_location .= '.' . $file_extension; 54 } 55 echo PHP_EOL . pts_client::cli_just_bold('Proposed Backup File:') . ' ' . $backup_location . PHP_EOL . PHP_EOL; 56 57 if(!is_writable(($dir = dirname($backup_location)))) 58 { 59 echo pts_client::cli_just_bold('ERROR:') . ' This location does not appear writable: ' . $dir . PHP_EOL . PHP_EOL; 60 return false; 61 } 62 63 echo PHP_EOL . 'Making download-cache to cache downloaded test files...' . PHP_EOL; 64 pts_client::execute_command('make_download_cache'); 65 66 $root_backup_temp_dir = pts_client::create_temporary_directory(null, true); 67 pts_file_io::mkdir(($backup_temp_dir = $root_backup_temp_dir . 'pts-backup' . DIRECTORY_SEPARATOR)); 68 $backup_manifest = array(); 69 70 $to_backup = self::backup_map(); 71 72 echo PHP_EOL; 73 foreach($to_backup as $source => $dest) 74 { 75 echo pts_client::cli_just_bold('Backing Up:') . ' ' . $source . PHP_EOL; 76 $success = pts_file_io::copy($source, $backup_temp_dir . $dest); 77 if(!$success) 78 { 79 echo PHP_EOL . 'There may have been problems backing up: ' . $source . PHP_EOL; 80 } 81 } 82 83 84 $manifest = self::dir_checks($backup_temp_dir, $backup_temp_dir); 85 file_put_contents($backup_temp_dir . 'pts-backup-manifest.txt', $manifest); 86 if($file_extension == 'zip') 87 { 88 pts_compression::zip_archive_create($backup_location, $backup_temp_dir); 89 } 90 else 91 { 92 pts_compression::compress_to_archive($backup_temp_dir, $backup_location); 93 } 94 echo pts_client::cli_just_bold('Backup File Written To: ') . $backup_location . PHP_EOL; 95 echo pts_client::cli_just_bold('SHA1: ') . sha1_file($backup_location) . PHP_EOL; 96 echo pts_client::cli_just_bold('File Size: ') . round(filesize($backup_location) / 1000000, 1) . ' MB' . PHP_EOL; 97 pts_file_io::delete($root_backup_temp_dir, null, true); 98 } 99 protected static function backup_map() 100 { 101 return array( 102 // User configuration 103 pts_config::get_config_file_location() => 'phoronix-test-suite.xml', 104 // test results 105 PTS_SAVE_RESULTS_PATH => 'test-results', 106 // test profiles 107 PTS_TEST_PROFILE_PATH => 'test-profiles', 108 // test suites 109 PTS_TEST_SUITE_PATH => 'test-suites', 110 // modules data 111 pts_module::module_data_path() => 'modules-data', 112 // Phoromatic 113 phoromatic_server::phoromatic_path() => 'phoromatic-storage', 114 // Download Cache 115 pts_client::download_cache_path() => 'download-cache', 116 ); 117 } 118 public static function restore_backup($r) 119 { 120 if(!isset($r[0]) || !is_file($r[0])) 121 { 122 echo PHP_EOL . pts_client::cli_just_bold('You must pass the name/path of the backup file to restore.') . PHP_EOL . PHP_EOL; 123 return false; 124 } 125 $backup_archive = $r[0]; 126 echo pts_client::cli_just_bold('Backup File: ') . $backup_archive . PHP_EOL; 127 echo pts_client::cli_just_bold('SHA1: ') . sha1_file($backup_archive) . PHP_EOL; 128 if(substr($backup_archive, -4) == '.zip') 129 { 130 $root_restore_temp_dir = pts_client::create_temporary_directory(null, true); 131 $s = pts_compression::zip_archive_extract($backup_archive, $root_restore_temp_dir); 132 } 133 else if(substr($backup_archive, -4) == '.tar') 134 { 135 $root_restore_temp_dir = dirname($backup_archive); 136 $s = pts_compression::archive_extract($backup_archive); 137 } 138 else 139 { 140 echo PHP_EOL . 'Unknown file type.' . PHP_EOL; 141 return false; 142 } 143 if(!$s) 144 { 145 echo PHP_EOL . 'There was a problem extracting the archive.' . PHP_EOL; 146 return false; 147 } 148 $restore_dir = $root_restore_temp_dir . DIRECTORY_SEPARATOR . 'pts-backup' . DIRECTORY_SEPARATOR; 149 if(!is_dir($restore_dir) || !is_file($restore_dir . 'pts-backup-manifest.txt')) 150 { 151 echo PHP_EOL . 'This does not appear to be a valid PTS backup as no pts-backup found.' . PHP_EOL; 152 return false; 153 } 154 155 $manifest_files = array(); 156 foreach(explode(PHP_EOL, pts_file_io::file_get_contents($restore_dir . 'pts-backup-manifest.txt')) as $line) 157 { 158 $r = explode(': ', $line); 159 $manifest_files[$r[0]] = $r[1]; 160 } 161 // XXX decide how exactly we want to do with manifest_files 162 163 if(is_file($restore_dir . 'phoronix-test-suite.xml')) 164 { 165 $restore_conf = pts_user_io::prompt_bool_input('Do you want to restore the user configuration file specifying paths, etc?', false); 166 if($restore_conf) 167 { 168 pts_file_io::copy($restore_dir . 'phoronix-test-suite.xml', pts_config::get_config_file_location()); 169 } 170 } 171 172 $backup_map = self::backup_map(); 173 foreach($backup_map as $dest => $source) 174 { 175 if($source == 'phoronix-test-suite.xml') 176 continue; 177 178 if(is_dir($restore_dir . $source) || is_file($restore_dir . $source)) 179 { 180 $s = pts_file_io::copy($restore_dir . $source, $dest); 181 if($s) 182 echo PHP_EOL . pts_client::cli_just_bold('Restored: ') . $source . ' to ' . $dest . PHP_EOL; 183 else 184 echo PHP_EOL . 'Failed to restore ' . $source . PHP_EOL; 185 } 186 } 187 188 pts_file_io::delete($root_restore_temp_dir . DIRECTORY_SEPARATOR . 'pts-backup', null, true); 189 } 190 protected static function dir_checks($dir, $remove_base_dir, &$checksums = array()) 191 { 192 $files = scandir($dir); 193 194 foreach($files as $key => $value) 195 { 196 $p = realpath($dir . '/' . $value); 197 if(!is_dir($p)) 198 { 199 $checksums[] = str_replace($remove_base_dir, '', $p) . ': ' . sha1_file($p) . PHP_EOL; 200 } 201 else if($value != '.' && $value != '..') 202 { 203 self::dir_checks($p, $remove_base_dir, $checksums); 204 } 205 } 206 207 return $checksums; 208 } 209 210} 211 212?> 213