/** * Request a download of a snapshot by id/hash * * @param string $snapshotId The snapshot-id */ public function download($snapshotId) { try { /** @type RouteHash $_hash */ $_hash = RouteHash::with(['snapshot'])->byHash($snapshotId)->firstOrFail(); /** @type Filesystem $_fs */ $_fs = $_hash->snapshot->instance->getSnapshotMount(); $_fs->readStream($_hash->actual_path_text); } catch (\Exception $_ex) { abort(Response::HTTP_NOT_FOUND); } }
/** * @param Filesystem $fsToCheck The file system to check * * @return int Returns the number of files that were trashed. * @throws \Exception */ public function expireFiles($fsToCheck) { $_count = 0; try { /** @type Collection $_hashes */ $_hashes = RouteHash::where('expire_date', '<', Carbon::createFromTimestamp(time() - config('snapshot.days-to-keep') * DateTimeIntervals::SECONDS_PER_DAY))->get(); if (!empty($_hashes)) { foreach ($_hashes as $_hash) { if ($fsToCheck->has($_hash->actual_path_text)) { if ($this->moveToTrash($fsToCheck, $_hash->actual_path_text)) { // ONLY delete route_hash row if file was MOVED/DELETED $_hash->delete(); } } unset($_hash); } unset($_hashes); } } catch (\Exception $_ex) { $this->error($_ex->getMessage()); throw $_ex; } return $_count; }
/** * Creates an export of a instance * * @param Instance $instance The instance of the exports * @param array $exports Array of files to include in the snapshot * @param Filesystem $destination The destination upon which to place the export. Currently unused * If null, the instance's snapshot storage area is used. * @param int $keepDays The number of days to keep the snapshot * * @return array|boolean The snapshot metadata array or false on failure. */ public function createFromExports(Instance $instance, array $exports, Filesystem $destination = null, $keepDays = EnterpriseDefaults::SNAPSHOT_DAYS_TO_KEEP) { // Build our "mise en place", as it were... $_success = false; $_stamp = date('YmdHis'); // Create the snapshot ID $_snapshotId = $_stamp . '.' . Inflector::neutralize($instance->instance_name_text); $_snapshotName = str_replace('{id}', $_snapshotId, config('snapshot.templates.snapshot-file-name')); // Set up the temp dir $this->setWorkPath($instance->getSnapshotPath()); // Create the snapshot archive and stuff it full of goodies /** @var SnapshotManifest $_manifest */ list($_fsSnapshot, $_manifest, $_routeHash, $_routeLink) = $this->createExportArchive($_snapshotId, $_snapshotName, ['timestamp' => $_stamp, 'guest-location' => $instance->guest_location_nbr, 'instance-id' => $instance->instance_id_text, 'cluster-id' => (int) $instance->cluster_id, 'db-server-id' => (int) $instance->db_server_id, 'web-server-id' => (int) $instance->web_server_id, 'app-server-id' => (int) $instance->app_server_id, 'owner-id' => (int) $instance->user->id, 'owner-email-address' => $instance->user->email_addr_text, 'owner-storage-key' => $instance->user->storage_id_text, 'storage-key' => $instance->storage_id_text], $keepDays); try { $this->addFilesToArchive($exports, $_fsSnapshot); try { // Write our snapshot manifesto $_manifest->write(); // Close up the files /** @noinspection PhpUndefinedMethodInspection */ $this->flushZipArchive($_fsSnapshot); // Look up the hash entry if (null === ($_routeHash = RouteHash::byHash($_routeHash)->first())) { throw new \LogicException('Previously created route hash not found.'); } // Create our snapshot record Snapshot::create(['user_id' => $instance->user_id, 'instance_id' => $instance->id, 'route_hash_id' => $_routeHash->id, 'snapshot_id_text' => $_snapshotId, 'public_ind' => true, 'public_url_text' => $_routeLink, 'expire_date' => $_routeHash->expire_date]); // Copy to $destination if requested if ($destination) { if (false === ($_fd = fopen($this->workPath . $_snapshotName, 'r'))) { throw new FileSystemException('Unable to open export file "' . $this->workPath . $_snapshotName . '".'); } $destination->putStream($_snapshotName, $_fd); fclose($_fd); } // Let the user know... $this->notifyInstanceOwner($instance, 'Export successful', ['firstName' => $instance->user->first_name_text, 'headTitle' => 'Export Complete', 'contentHeader' => 'Your export has completed', 'emailBody' => <<<HTML <p>Your export is complete. It may be downloaded it for up to {$keepDays} days, from the following link:<br/> <br/> <strong><a href="{$_routeLink}" target="_blank">{$_routeLink}</a></strong> </p> HTML ]); $_success = true; } catch (\Exception $_ex) { $this->error('exception building snapshot archive: ' . $_ex->getMessage()); throw $_ex; } } catch (\Exception $_ex) { $this->error('exception during sub-provisioner export call: ' . $_ex->getMessage()); $this->notifyInstanceOwner($instance, 'Export failure', ['firstName' => $instance->user->first_name_text, 'headTitle' => 'Export Failure', 'contentHeader' => 'Your export was not created', 'emailBody' => <<<HTML <p>The export requested did not complete properly. Please make sure your instance is up and running, then try again. If the issue persists, please contact support.</p> HTML ]); $_success = false; } finally { // Cleanup $_fsSnapshot = null; } return $_success ? $_manifest->toArray() : false; }
/** * Hijacks the request and resumes as a file download of a snapshot * * @param string $hash * * @return bool|false|string * @throws ModelNotFoundException */ public static function downloadFromHash($hash) { /** * @type Filesystem $_fs * @type RouteHash $_routeHash */ try { if (null !== ($_routeHash = RouteHash::byHash($hash)->with(['snapshot'])->firstOrFail())) { // Look up the snapshot and get an instance of the file system $_snapshot = $_routeHash->snapshot ?: static::fromHash($hash)->with(['instance'])->firstOrFail(); try { $_instance = static::_locateInstance($_snapshot->instance_id); } catch (ModelNotFoundException $_ex) { throw new ModelNotFoundException('Instance not found for snapshot "' . $_snapshot->snapshot_id_text . '"'); } if (null === ($_fs = $_instance->getSnapshotMount())) { throw new ModelNotFoundException('Snapshot storage area is not available.'); } // Get some work space to download the snapshot $_workPath = static::getWorkPath('snapshot-download', true); $_fsWork = new Filesystem(new Local($_workPath)); $_tempFile = $_routeHash->actual_path_text; // Delete any file with the same name... file_exists($_workPath . DIRECTORY_SEPARATOR . $_tempFile) && @unlink($_workPath . DIRECTORY_SEPARATOR . $_tempFile); // Download the snapshot to local temp static::writeStream($_fsWork, $_fs->readStream($_tempFile), $_tempFile); // Download the local file to client /** @noinspection PhpUndefinedMethodInspection */ return response()->download($_workPath . DIRECTORY_SEPARATOR . $_tempFile, $_tempFile); } throw new ModelNotFoundException(); } catch (\Exception $_ex) { Log::error('route hash "' . $hash . '" not found: ' . $_ex->getMessage()); abort(Response::HTTP_NOT_FOUND); } // Death to all ye who enter here... return false; }