/**
  * Given an instance and a snapshot ID, replace the data with that of the snapshot.
  *
  * @param int|string $instanceId
  * @param string     $snapshot A snapshot id or path to a snapshot
  *
  * @return array
  */
 public function restore($instanceId, $snapshot)
 {
     $_filename = null;
     $_instance = $this->_findInstance($instanceId);
     $snapshot = trim($snapshot, DIRECTORY_SEPARATOR . ' ');
     //  Determine source of import
     if (file_exists($snapshot)) {
         //  Absolute path
         $_filename = $snapshot;
     } else {
         if (file_exists($_instance->getSnapshotPath() . DIRECTORY_SEPARATOR . $snapshot)) {
             //  Relative to snapshot path
             $_filename = $_instance->getSnapshotPath() . DIRECTORY_SEPARATOR . $snapshot;
         } else {
             //  A snapshot hash given, find related snapshot
             /** @type Snapshot $_snapshot */
             if (null === ($_snapshot = Snapshot::with('route-hash')->bySnapshotId($snapshot)->first())) {
                 throw new \InvalidArgumentException('The snapshot "' . $snapshot . '" is unrecognized or invalid."');
             }
             return Provision::import(new ImportJob(new PortableServiceRequest($_instance, ['target' => $_snapshot->snapshot_id_text])));
         }
     }
     //  Mount the snapshot
     $_workPath = dirname($_filename);
     $_fsSnapshot = $this->mountSnapshot($instanceId, $_filename, $_workPath);
     //  Reconstitute the manifest and grab the services
     $_manifest = SnapshotManifest::createFromFile(config('snapshot.metadata-file-name'), $_fsSnapshot);
     $_services = Provision::getPortableServices($_manifest->get('guest-location'));
     $_result = [];
     foreach ($_fsSnapshot->listContents() as $_item) {
         //  Find the exports in the snapshot
         if (false !== ($_pos = stripos('-export.', $_item['file']))) {
             if (!PortableTypes::has($_type = substr($_item['file'], 0, $_pos))) {
                 continue;
             }
             if (array_key_exists($_type, $_services)) {
                 $_job = new ImportJob(new PortableServiceRequest($_instance, ['target' => $_workPath . DIRECTORY_SEPARATOR . $_item['file']]));
                 $_result[$_type] = $_services[$_type]->import($_job);
             }
         }
     }
     return $_result;
 }
 /**
  * Returns an array of the portability providers for this provisioner. If
  * no sub-provisioners are portable, an empty array will be returned.
  *
  * @param string $name The provisioner id. If null, the default provisioner is used.
  *
  * @return array|\DreamFactory\Enterprise\Common\Contracts\PortableData[] An array of portability services keyed by PortableTypes
  */
 public function getPortableServices($name = null)
 {
     $name = GuestLocations::resolve($name ?: $this->getDefaultProvisioner());
     $_services = [];
     $_list = config('provisioners.hosts.' . $name . '.provides', []);
     //  Spin through the services
     foreach ($_list as $_key => $_definition) {
         if (PortableTypes::contains($_key)) {
             if (($_service = $this->resolve($name, $_key)) instanceof PortableData) {
                 $_services[$_key] = $_service;
             }
         }
     }
     //  Return the array
     return $_services;
 }