]> source.dussan.org Git - nextcloud-server.git/commitdiff
Mount the old previews in a separate folder for the multi bucket setup and check...
authorMorris Jobke <hey@morrisjobke.de>
Thu, 30 Jul 2020 21:53:54 +0000 (23:53 +0200)
committerMorris Jobke <hey@morrisjobke.de>
Thu, 6 Aug 2020 20:19:21 +0000 (22:19 +0200)
Signed-off-by: Morris Jobke <hey@morrisjobke.de>
lib/private/Files/Mount/ObjectStorePreviewCacheMountProvider.php
lib/private/Preview/Storage/Root.php
tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php [new file with mode: 0644]

index a4acdb6bb0fbfbe7fa214dc5bc405f605097e8b9..9ab0327684b8768a838c7f136f42230f1632c437 100644 (file)
@@ -26,6 +26,8 @@ declare(strict_types=1);
 namespace OC\Files\Mount;
 
 use OC\Files\ObjectStore\AppdataPreviewObjectStoreStorage;
+use OC\Files\ObjectStore\ObjectStoreStorage;
+use OC\Files\Storage\Wrapper\Jail;
 use OCP\Files\Config\IRootMountProvider;
 use OCP\Files\Storage\IStorageFactory;
 use OCP\IConfig;
@@ -45,6 +47,10 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
                $this->config = $config;
        }
 
+       /**
+        * @return MountPoint[]
+        * @throws \Exception
+        */
        public function getRootMounts(IStorageFactory $loader): array {
                if (!is_array($this->config->getSystemValue('objectstore_multibucket'))) {
                        return [];
@@ -65,12 +71,25 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
                                $i++;
                        }
                }
+
+               $rootStorageArguments = $this->getMultiBucketObjectStoreForRoot();
+               $fakeRootStorage = new ObjectStoreStorage($rootStorageArguments);
+               $fakeRootStorageJail = new Jail([
+                       'storage' => $fakeRootStorage,
+                       'root' => '/appdata_' . $instanceId . '/preview',
+               ]);
+
+               // add a fallback location to be able to fetch existing previews from the old bucket
+               $mountPoints[] = new MountPoint(
+                       $fakeRootStorageJail,
+                       '/appdata_' . $instanceId . '/preview/old-multibucket',
+                       null,
+                       $loader
+               );
+
                return $mountPoints;
        }
 
-       /**
-        * @return array
-        */
        protected function getMultiBucketObjectStore(int $number): array {
                $config = $this->config->getSystemValue('objectstore_multibucket');
 
@@ -99,4 +118,30 @@ class ObjectStorePreviewCacheMountProvider implements IRootMountProvider {
 
                return $config['arguments'];
        }
+
+       protected function getMultiBucketObjectStoreForRoot(): array {
+               $config = $this->config->getSystemValue('objectstore_multibucket');
+
+               // sanity checks
+               if (empty($config['class'])) {
+                       $this->logger->error('No class given for objectstore', ['app' => 'files']);
+               }
+               if (!isset($config['arguments'])) {
+                       $config['arguments'] = [];
+               }
+
+               /*
+                * Use any provided bucket argument as prefix
+                * and add the mapping from parent/child => bucket
+                */
+               if (!isset($config['arguments']['bucket'])) {
+                       $config['arguments']['bucket'] = '';
+               }
+               $config['arguments']['bucket'] .= '0';
+
+               // instantiate object store implementation
+               $config['arguments']['objectstore'] = new $config['class']($config['arguments']);
+
+               return $config['arguments'];
+       }
 }
index 107d87c6301f3486e12138c78346220575862fbf..37ae1758121cc04b3fd4188ed6b3f1904b8498b2 100644 (file)
@@ -40,6 +40,17 @@ class Root extends AppData {
        public function getFolder(string $name): ISimpleFolder {
                $internalFolder = $this->getInternalFolder($name);
 
+               try {
+                       return parent::getFolder('old-multibucket/' . $internalFolder);
+               } catch (NotFoundException $e) {
+                       // not in multibucket fallback #1
+               }
+               try {
+                       return parent::getFolder('old-multibucket/' . $name);
+               } catch (NotFoundException $e) {
+                       // not in multibucket fallback #2
+               }
+
                try {
                        return parent::getFolder($internalFolder);
                } catch (NotFoundException $e) {
diff --git a/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php b/tests/lib/Files/Mount/ObjectStorePreviewCacheMountProviderTest.php
new file mode 100644 (file)
index 0000000..2da0739
--- /dev/null
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+/**
+ * @copyright Copyright (c) 2020, Morris Jobke <hey@morrisjobke.de>
+ *
+ * @author Morris Jobke <hey@morrisjobke.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Test\Files\Mount;
+
+use OC\Files\Mount\ObjectStorePreviewCacheMountProvider;
+use OC\Files\ObjectStore\S3;
+use OC\Files\Storage\StorageFactory;
+use OCP\Files\Storage\IStorageFactory;
+use OCP\IConfig;
+use OCP\ILogger;
+use PHPUnit\Framework\MockObject\MockObject;
+
+/**
+ * @group DB
+ *
+ * The DB permission is needed for the fake root storage initialization
+ */
+class ObjectStorePreviewCacheMountProviderTest extends \Test\TestCase {
+
+       /** @var ObjectStorePreviewCacheMountProvider */
+       protected $provider;
+
+       /** @var ILogger|MockObject */
+       protected $logger;
+       /** @var IConfig|MockObject */
+       protected $config;
+       /** @var IStorageFactory|MockObject */
+       protected $loader;
+
+
+       protected function setUp(): void {
+               parent::setUp();
+
+               $this->logger = $this->createMock(ILogger::class);
+               $this->config = $this->createMock(IConfig::class);
+               $this->loader = $this->createMock(StorageFactory::class);
+
+               $this->provider = new ObjectStorePreviewCacheMountProvider($this->logger, $this->config);
+       }
+
+       public function testNoMultibucketObjectStorage() {
+               $this->config->expects($this->once())
+                       ->method('getSystemValue')
+                       ->with('objectstore_multibucket')
+                       ->willReturn(null);
+
+               $this->assertEquals([], $this->provider->getRootMounts($this->loader));
+       }
+
+       public function testMultibucketObjectStorage() {
+               $this->config->expects($this->any())
+                       ->method('getSystemValue')
+                       ->with('objectstore_multibucket')
+                       ->willReturn([
+                               'class' => S3::class,
+                               'arguments' => [
+                                       'bucket' => 'abc',
+                                       'num_buckets' => 64,
+                                       'key' => 'KEY',
+                                       'secret' => 'SECRET',
+                                       'hostname' => 'IP',
+                                       'port' => 'PORT',
+                                       'use_ssl' => false,
+                                       'use_path_style' => true,
+                               ],
+                       ]);
+               $this->config->expects($this->once())
+                       ->method('getSystemValueString')
+                       ->with('instanceid')
+                       ->willReturn('INSTANCEID');
+
+               $mounts = $this->provider->getRootMounts($this->loader);
+
+               // 256 mounts for the subfolders and 1 for the fake root
+               $this->assertCount(257, $mounts);
+
+               // do some sanity checks if they have correct mount point paths
+               $this->assertEquals('/appdata_INSTANCEID/preview/0/0/', $mounts[0]->getMountPoint());
+               $this->assertEquals('/appdata_INSTANCEID/preview/2/5/', $mounts[37]->getMountPoint());
+               // also test the path of the fake bucket
+               $this->assertEquals('/appdata_INSTANCEID/preview/old-multibucket/', $mounts[256]->getMountPoint());
+       }
+}