summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Appelman <robin@icewind.nl>2017-03-28 17:51:18 +0200
committerGitHub <noreply@github.com>2017-03-28 17:51:18 +0200
commite26f138fc596492da88b8a0d57749f5703e1d100 (patch)
tree49f4ac330fce3b1d1583ef8678efe9037e54a7b2
parent401a5d896d7b3b6f55d203c647ffae4021ad3343 (diff)
parent8dbca71a77418b3f7ccd8be8a5dc0ab93858513e (diff)
downloadnextcloud-server-e26f138fc596492da88b8a0d57749f5703e1d100.tar.gz
nextcloud-server-e26f138fc596492da88b8a0d57749f5703e1d100.zip
Merge pull request #4112 from nextcloud/swift-config
Better error messages for objectsack swift configuration
-rw-r--r--lib/private/Files/ObjectStore/Swift.php85
1 files changed, 80 insertions, 5 deletions
diff --git a/lib/private/Files/ObjectStore/Swift.php b/lib/private/Files/ObjectStore/Swift.php
index 2ccaad27e88..43ce32af941 100644
--- a/lib/private/Files/ObjectStore/Swift.php
+++ b/lib/private/Files/ObjectStore/Swift.php
@@ -26,6 +26,12 @@ namespace OC\Files\ObjectStore;
use Guzzle\Http\Exception\ClientErrorResponseException;
use OCP\Files\ObjectStore\IObjectStore;
+use OCP\Files\StorageAuthException;
+use OCP\Files\StorageNotAvailableException;
+use OpenCloud\Common\Exceptions\EndpointError;
+use OpenCloud\Common\Service\Catalog;
+use OpenCloud\Common\Service\CatalogItem;
+use OpenCloud\ObjectStore\Service;
use OpenCloud\OpenStack;
use OpenCloud\Rackspace;
@@ -76,17 +82,47 @@ class Swift implements IObjectStore {
return;
}
- // the OpenCloud client library will default to 'cloudFiles' if $serviceName is null
- $serviceName = null;
+ try {
+ $this->client->authenticate();
+ } catch (ClientErrorResponseException $e) {
+ $statusCode = $e->getResponse()->getStatusCode();
+ if ($statusCode == 412) {
+ throw new StorageAuthException('Precondition failed, verify the keystone url', $e);
+ } else if ($statusCode === 401) {
+ throw new StorageAuthException('Authentication failed, verify the username, password and possibly tenant', $e);
+ } else {
+ throw new StorageAuthException('Unknown error', $e);
+ }
+ }
+
+ /** @var Catalog $catalog */
+ $catalog = $this->client->getCatalog();
+
if (isset($this->params['serviceName'])) {
$serviceName = $this->params['serviceName'];
+ } else {
+ $serviceName = Service::DEFAULT_NAME;
}
- // the OpenCloud client library will default to 'publicURL' if $urlType is null
- $urlType = null;
if (isset($this->params['urlType'])) {
$urlType = $this->params['urlType'];
+ if ($urlType !== 'internalURL' && $urlType !== 'publicURL') {
+ throw new StorageNotAvailableException('Invalid url type');
+ }
+ } else {
+ $urlType = Service::DEFAULT_URL_TYPE;
+ }
+
+ $catalogItem = $this->getCatalogForService($catalog, $serviceName);
+ if (!$catalogItem) {
+ $available = implode(', ', $this->getAvailableServiceNames($catalog));
+ throw new StorageNotAvailableException(
+ "Service $serviceName not found in service catalog, available services: $available"
+ );
+ } else if (isset($this->params['region'])) {
+ $this->validateRegion($catalogItem, $this->params['region']);
}
+
$this->objectStoreService = $this->client->objectStoreService($serviceName, $this->params['region'], $urlType);
try {
@@ -102,6 +138,45 @@ class Swift implements IObjectStore {
}
/**
+ * @param Catalog $catalog
+ * @param $name
+ * @return null|CatalogItem
+ */
+ private function getCatalogForService(Catalog $catalog, $name) {
+ foreach ($catalog->getItems() as $item) {
+ /** @var CatalogItem $item */
+ if ($item->hasType(Service::DEFAULT_TYPE) && $item->hasName($name)) {
+ return $item;
+ }
+ }
+
+ return null;
+ }
+
+ private function validateRegion(CatalogItem $item, $region) {
+ $endPoints = $item->getEndpoints();
+ foreach ($endPoints as $endPoint) {
+ if ($endPoint->region === $region) {
+ return;
+ }
+ }
+
+ $availableRegions = implode(', ', array_map(function ($endpoint) {
+ return $endpoint->region;
+ }, $endPoints));
+
+ throw new StorageNotAvailableException("Invalid region '$region', available regions: $availableRegions");
+ }
+
+ private function getAvailableServiceNames(Catalog $catalog) {
+ return array_map(function (CatalogItem $item) {
+ return $item->getName();
+ }, array_filter($catalog->getItems(), function (CatalogItem $item) {
+ return $item->hasType(Service::DEFAULT_TYPE);
+ }));
+ }
+
+ /**
* @return string the container name where objects are stored
*/
public function getStorageId() {
@@ -135,7 +210,7 @@ class Swift implements IObjectStore {
$stream = $objectContent->getStream();
// save the object content in the context of the stream to prevent it being gc'd until the stream is closed
- stream_context_set_option($stream, 'swift','content', $objectContent);
+ stream_context_set_option($stream, 'swift', 'content', $objectContent);
return $stream;
}