Merge pull request #17072 from nextcloud/backport/16836/stable17
[stable17] Fix SMB availability status + higher delay on auth issues
This commit is contained in:
commit
f348b753b1
|
@ -55,6 +55,7 @@ use OCA\Files_External\Lib\Notify\SMBNotifyHandler;
|
||||||
use OCP\Files\Notify\IChange;
|
use OCP\Files\Notify\IChange;
|
||||||
use OCP\Files\Notify\IRenameChange;
|
use OCP\Files\Notify\IRenameChange;
|
||||||
use OCP\Files\Storage\INotifyStorage;
|
use OCP\Files\Storage\INotifyStorage;
|
||||||
|
use OCP\Files\StorageAuthException;
|
||||||
use OCP\Files\StorageNotAvailableException;
|
use OCP\Files\StorageNotAvailableException;
|
||||||
use OCP\ILogger;
|
use OCP\ILogger;
|
||||||
|
|
||||||
|
@ -160,7 +161,7 @@ class SMB extends Common implements INotifyStorage {
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @return \Icewind\SMB\IFileInfo
|
* @return \Icewind\SMB\IFileInfo
|
||||||
* @throws StorageNotAvailableException
|
* @throws StorageAuthException
|
||||||
*/
|
*/
|
||||||
protected function getFileInfo($path) {
|
protected function getFileInfo($path) {
|
||||||
try {
|
try {
|
||||||
|
@ -170,11 +171,26 @@ class SMB extends Common implements INotifyStorage {
|
||||||
}
|
}
|
||||||
return $this->statCache[$path];
|
return $this->statCache[$path];
|
||||||
} catch (ConnectException $e) {
|
} catch (ConnectException $e) {
|
||||||
$this->logger->logException($e, ['message' => 'Error while getting file info']);
|
$this->throwUnavailable($e);
|
||||||
throw new StorageNotAvailableException($e->getMessage(), $e->getCode(), $e);
|
} catch (ForbiddenException $e) {
|
||||||
|
// with php-smbclient, this exceptions is thrown when the provided password is invalid.
|
||||||
|
// Possible is also ForbiddenException with a different error code, so we check it.
|
||||||
|
if($e->getCode() === 1) {
|
||||||
|
$this->throwUnavailable($e);
|
||||||
|
}
|
||||||
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Exception $e
|
||||||
|
* @throws StorageAuthException
|
||||||
|
*/
|
||||||
|
protected function throwUnavailable(\Exception $e) {
|
||||||
|
$this->logger->logException($e, ['message' => 'Error while getting file info']);
|
||||||
|
throw new StorageAuthException($e->getMessage(), $e);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @return \Icewind\SMB\IFileInfo[]
|
* @return \Icewind\SMB\IFileInfo[]
|
||||||
|
|
|
@ -1480,6 +1480,17 @@ $CONFIG = array(
|
||||||
*/
|
*/
|
||||||
'quota_include_external_storage' => false,
|
'quota_include_external_storage' => false,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When an external storage is unavailable for some reasons, it will be flagged
|
||||||
|
* as such for 10 minutes. When the trigger is a failed authentication attempt
|
||||||
|
* the delay is higher and can be controlled with this option. The motivation
|
||||||
|
* is to make account lock outs at Active Directories (and compatible) more
|
||||||
|
* unlikely.
|
||||||
|
*
|
||||||
|
* Defaults to ``1800`` (seconds)
|
||||||
|
*/
|
||||||
|
'external_storage.auth_availability_delay' => 1800,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies how often the local filesystem (the Nextcloud data/ directory, and
|
* Specifies how often the local filesystem (the Nextcloud data/ directory, and
|
||||||
* NFS mounts in data/) is checked for changes made outside Nextcloud. This
|
* NFS mounts in data/) is checked for changes made outside Nextcloud. This
|
||||||
|
|
|
@ -166,11 +166,12 @@ class Storage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $isAvailable
|
* @param bool $isAvailable
|
||||||
|
* @param int $delay amount of seconds to delay reconsidering that storage further
|
||||||
*/
|
*/
|
||||||
public function setAvailability($isAvailable) {
|
public function setAvailability($isAvailable, int $delay = 0) {
|
||||||
$sql = 'UPDATE `*PREFIX*storages` SET `available` = ?, `last_checked` = ? WHERE `id` = ?';
|
$sql = 'UPDATE `*PREFIX*storages` SET `available` = ?, `last_checked` = ? WHERE `id` = ?';
|
||||||
$available = $isAvailable ? 1 : 0;
|
$available = $isAvailable ? 1 : 0;
|
||||||
\OC_DB::executeAudited($sql, array($available, time(), $this->storageId));
|
\OC_DB::executeAudited($sql, [$available, time() + $delay, $this->storageId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,9 @@
|
||||||
namespace OC\Files\Storage\Wrapper;
|
namespace OC\Files\Storage\Wrapper;
|
||||||
|
|
||||||
use OCP\Files\Storage\IStorage;
|
use OCP\Files\Storage\IStorage;
|
||||||
|
use OCP\Files\StorageAuthException;
|
||||||
|
use OCP\Files\StorageNotAvailableException;
|
||||||
|
use OCP\IConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Availability checker for storages
|
* Availability checker for storages
|
||||||
|
@ -33,6 +36,14 @@ use OCP\Files\Storage\IStorage;
|
||||||
class Availability extends Wrapper {
|
class Availability extends Wrapper {
|
||||||
const RECHECK_TTL_SEC = 600; // 10 minutes
|
const RECHECK_TTL_SEC = 600; // 10 minutes
|
||||||
|
|
||||||
|
/** @var IConfig */
|
||||||
|
protected $config;
|
||||||
|
|
||||||
|
public function __construct($parameters) {
|
||||||
|
$this->config = $parameters['config'] ?? \OC::$server->getConfig();
|
||||||
|
parent::__construct($parameters);
|
||||||
|
}
|
||||||
|
|
||||||
public static function shouldRecheck($availability) {
|
public static function shouldRecheck($availability) {
|
||||||
if (!$availability['available']) {
|
if (!$availability['available']) {
|
||||||
// trigger a recheck if TTL reached
|
// trigger a recheck if TTL reached
|
||||||
|
@ -72,11 +83,11 @@ class Availability extends Wrapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \OCP\Files\StorageNotAvailableException
|
* @throws StorageNotAvailableException
|
||||||
*/
|
*/
|
||||||
private function checkAvailability() {
|
private function checkAvailability() {
|
||||||
if (!$this->isAvailable()) {
|
if (!$this->isAvailable()) {
|
||||||
throw new \OCP\Files\StorageNotAvailableException();
|
throw new StorageNotAvailableException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,9 +96,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::mkdir($path);
|
return parent::mkdir($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +106,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::rmdir($path);
|
return parent::rmdir($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,9 +116,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::opendir($path);
|
return parent::opendir($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,9 +126,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::is_dir($path);
|
return parent::is_dir($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,9 +136,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::is_file($path);
|
return parent::is_file($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,9 +146,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::stat($path);
|
return parent::stat($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,9 +156,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::filetype($path);
|
return parent::filetype($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,9 +166,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::filesize($path);
|
return parent::filesize($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,9 +176,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::isCreatable($path);
|
return parent::isCreatable($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,9 +186,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::isReadable($path);
|
return parent::isReadable($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,9 +196,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::isUpdatable($path);
|
return parent::isUpdatable($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,9 +206,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::isDeletable($path);
|
return parent::isDeletable($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,9 +216,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::isSharable($path);
|
return parent::isSharable($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,9 +226,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getPermissions($path);
|
return parent::getPermissions($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,9 +239,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::file_exists($path);
|
return parent::file_exists($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,9 +249,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::filemtime($path);
|
return parent::filemtime($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,9 +259,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::file_get_contents($path);
|
return parent::file_get_contents($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,9 +269,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::file_put_contents($path, $data);
|
return parent::file_put_contents($path, $data);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,9 +279,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::unlink($path);
|
return parent::unlink($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,9 +289,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::rename($path1, $path2);
|
return parent::rename($path1, $path2);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,9 +299,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::copy($path1, $path2);
|
return parent::copy($path1, $path2);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,9 +309,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::fopen($path, $mode);
|
return parent::fopen($path, $mode);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,9 +319,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getMimeType($path);
|
return parent::getMimeType($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,9 +329,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::hash($type, $path, $raw);
|
return parent::hash($type, $path, $raw);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,9 +339,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::free_space($path);
|
return parent::free_space($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,9 +349,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::search($query);
|
return parent::search($query);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,9 +359,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::touch($path, $mtime);
|
return parent::touch($path, $mtime);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,9 +369,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getLocalFile($path);
|
return parent::getLocalFile($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,9 +379,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::hasUpdated($path, $time);
|
return parent::hasUpdated($path, $time);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,9 +388,8 @@ class Availability extends Wrapper {
|
||||||
public function getOwner($path) {
|
public function getOwner($path) {
|
||||||
try {
|
try {
|
||||||
return parent::getOwner($path);
|
return parent::getOwner($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,9 +398,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getETag($path);
|
return parent::getETag($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,9 +408,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getDirectDownload($path);
|
return parent::getDirectDownload($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,9 +418,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
|
return parent::copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,9 +428,8 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
|
return parent::moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -461,9 +438,24 @@ class Availability extends Wrapper {
|
||||||
$this->checkAvailability();
|
$this->checkAvailability();
|
||||||
try {
|
try {
|
||||||
return parent::getMetaData($path);
|
return parent::getMetaData($path);
|
||||||
} catch (\OCP\Files\StorageNotAvailableException $e) {
|
} catch (StorageNotAvailableException $e) {
|
||||||
$this->setAvailability(false);
|
$this->setUnavailable($e);
|
||||||
throw $e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws StorageNotAvailableException
|
||||||
|
*/
|
||||||
|
protected function setUnavailable(StorageNotAvailableException $e) {
|
||||||
|
$delay = self::RECHECK_TTL_SEC;
|
||||||
|
if($e instanceof StorageAuthException) {
|
||||||
|
$delay = max(
|
||||||
|
// 30min
|
||||||
|
$this->config->getSystemValueInt('external_storage.auth_availability_delay', 1800),
|
||||||
|
self::RECHECK_TTL_SEC
|
||||||
|
);
|
||||||
|
}
|
||||||
|
$this->getStorageCache()->setAvailability(false, $delay);
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,29 +21,46 @@
|
||||||
|
|
||||||
namespace Test\Files\Storage\Wrapper;
|
namespace Test\Files\Storage\Wrapper;
|
||||||
|
|
||||||
|
use OC\Files\Cache\Storage as StorageCache;
|
||||||
|
use OC\Files\Storage\Temporary;
|
||||||
|
use OC\Files\Storage\Wrapper\Availability;
|
||||||
|
use OCP\Files\StorageNotAvailableException;
|
||||||
|
|
||||||
class AvailabilityTest extends \Test\TestCase {
|
class AvailabilityTest extends \Test\TestCase {
|
||||||
protected function getWrapperInstance() {
|
|
||||||
$storage = $this->getMockBuilder('\OC\Files\Storage\Temporary')
|
/** @var \PHPUnit\Framework\MockObject\MockObject|StorageCache */
|
||||||
->disableOriginalConstructor()
|
protected $storageCache;
|
||||||
->getMock();
|
/** @var \PHPUnit\Framework\MockObject\MockObject|Temporary */
|
||||||
$wrapper = new \OC\Files\Storage\Wrapper\Availability(['storage' => $storage]);
|
protected $storage;
|
||||||
return [$storage, $wrapper];
|
/** @var Availability */
|
||||||
|
protected $wrapper;
|
||||||
|
|
||||||
|
public function setUp() {
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->storageCache = $this->createMock(StorageCache::class);
|
||||||
|
|
||||||
|
$this->storage = $this->createMock(Temporary::class);
|
||||||
|
$this->storage->expects($this->any())
|
||||||
|
->method('getStorageCache')
|
||||||
|
->willReturn($this->storageCache);
|
||||||
|
|
||||||
|
$this->wrapper = new Availability(['storage' => $this->storage]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage is available
|
* Storage is available
|
||||||
*/
|
*/
|
||||||
public function testAvailable() {
|
public function testAvailable() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => true, 'last_checked' => 0]);
|
->willReturn(['available' => true, 'last_checked' => 0]);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('test');
|
->method('test');
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('mkdir');
|
->method('mkdir');
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,39 +69,37 @@ class AvailabilityTest extends \Test\TestCase {
|
||||||
* @expectedException \OCP\Files\StorageNotAvailableException
|
* @expectedException \OCP\Files\StorageNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function testUnavailable() {
|
public function testUnavailable() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => false, 'last_checked' => time()]);
|
->willReturn(['available' => false, 'last_checked' => time()]);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('test');
|
->method('test');
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('mkdir');
|
->method('mkdir');
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Storage marked unavailable, TTL expired
|
* Storage marked unavailable, TTL expired
|
||||||
*/
|
*/
|
||||||
public function testUnavailableRecheck() {
|
public function testUnavailableRecheck() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => false, 'last_checked' => 0]);
|
->willReturn(['available' => false, 'last_checked' => 0]);
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('test')
|
->method('test')
|
||||||
->willReturn(true);
|
->willReturn(true);
|
||||||
$storage->expects($this->exactly(2))
|
$this->storage->expects($this->exactly(2))
|
||||||
->method('setAvailability')
|
->method('setAvailability')
|
||||||
->withConsecutive(
|
->withConsecutive(
|
||||||
[$this->equalTo(false)], // prevents concurrent rechecks
|
[$this->equalTo(false)], // prevents concurrent rechecks
|
||||||
[$this->equalTo(true)] // sets correct availability
|
[$this->equalTo(true)] // sets correct availability
|
||||||
);
|
);
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('mkdir');
|
->method('mkdir');
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,20 +108,19 @@ class AvailabilityTest extends \Test\TestCase {
|
||||||
* @expectedException \OCP\Files\StorageNotAvailableException
|
* @expectedException \OCP\Files\StorageNotAvailableException
|
||||||
*/
|
*/
|
||||||
public function testAvailableThrowStorageNotAvailable() {
|
public function testAvailableThrowStorageNotAvailable() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => true, 'last_checked' => 0]);
|
->willReturn(['available' => true, 'last_checked' => 0]);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('test');
|
->method('test');
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('mkdir')
|
->method('mkdir')
|
||||||
->will($this->throwException(new \OCP\Files\StorageNotAvailableException()));
|
->will($this->throwException(new StorageNotAvailableException()));
|
||||||
$storage->expects($this->once())
|
$this->storageCache->expects($this->once())
|
||||||
->method('setAvailability')
|
->method('setAvailability')
|
||||||
->with($this->equalTo(false));
|
->with($this->equalTo(false));
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,19 +128,18 @@ class AvailabilityTest extends \Test\TestCase {
|
||||||
* Method failure does not indicate storage unavailability
|
* Method failure does not indicate storage unavailability
|
||||||
*/
|
*/
|
||||||
public function testAvailableFailure() {
|
public function testAvailableFailure() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => true, 'last_checked' => 0]);
|
->willReturn(['available' => true, 'last_checked' => 0]);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('test');
|
->method('test');
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('mkdir')
|
->method('mkdir')
|
||||||
->willReturn(false);
|
->willReturn(false);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('setAvailability');
|
->method('setAvailability');
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,18 +149,17 @@ class AvailabilityTest extends \Test\TestCase {
|
||||||
* @expectedException \Exception
|
* @expectedException \Exception
|
||||||
*/
|
*/
|
||||||
public function testAvailableThrow() {
|
public function testAvailableThrow() {
|
||||||
list($storage, $wrapper) = $this->getWrapperInstance();
|
$this->storage->expects($this->once())
|
||||||
$storage->expects($this->once())
|
|
||||||
->method('getAvailability')
|
->method('getAvailability')
|
||||||
->willReturn(['available' => true, 'last_checked' => 0]);
|
->willReturn(['available' => true, 'last_checked' => 0]);
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('test');
|
->method('test');
|
||||||
$storage->expects($this->once())
|
$this->storage->expects($this->once())
|
||||||
->method('mkdir')
|
->method('mkdir')
|
||||||
->will($this->throwException(new \Exception()));
|
->will($this->throwException(new \Exception()));
|
||||||
$storage->expects($this->never())
|
$this->storage->expects($this->never())
|
||||||
->method('setAvailability');
|
->method('setAvailability');
|
||||||
|
|
||||||
$wrapper->mkdir('foobar');
|
$this->wrapper->mkdir('foobar');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue