Version1015Date20211104103506.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-License-Identifier: AGPL-3.0-or-later
  6. */
  7. namespace OCA\Files_External\Migration;
  8. use Closure;
  9. use OC\Files\Cache\Storage;
  10. use OCP\DB\Exception;
  11. use OCP\DB\IResult;
  12. use OCP\DB\ISchemaWrapper;
  13. use OCP\IDBConnection;
  14. use OCP\Migration\IOutput;
  15. use OCP\Migration\SimpleMigrationStep;
  16. use Psr\Log\LoggerInterface;
  17. class Version1015Date20211104103506 extends SimpleMigrationStep {
  18. public function __construct(
  19. private IDBConnection $connection,
  20. private LoggerInterface $logger,
  21. ) {
  22. }
  23. public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
  24. $qb = $this->connection->getQueryBuilder();
  25. $qb->update('storages')
  26. ->set('id', $qb->createParameter('newId'))
  27. ->where($qb->expr()->eq('id', $qb->createParameter('oldId')));
  28. $mounts = $this->getS3Mounts();
  29. if (!$mounts instanceof IResult) {
  30. throw new \Exception('Could not fetch existing mounts for migration');
  31. }
  32. while ($mount = $mounts->fetch()) {
  33. $config = $this->getStorageConfig((int)$mount['mount_id']);
  34. $hostname = $config['hostname'];
  35. $bucket = $config['bucket'];
  36. $key = $config['key'];
  37. $oldId = Storage::adjustStorageId('amazon::' . $bucket);
  38. $newId = Storage::adjustStorageId('amazon::external::' . md5($hostname . ':' . $bucket . ':' . $key));
  39. try {
  40. $qb->setParameter('oldId', $oldId);
  41. $qb->setParameter('newId', $newId);
  42. $qb->execute();
  43. $this->logger->info('Migrated s3 storage id for mount with id ' . $mount['mount_id'] . ' to ' . $newId);
  44. } catch (Exception $e) {
  45. $this->logger->error('Failed to migrate external s3 storage id for mount with id ' . $mount['mount_id'], [
  46. 'exception' => $e
  47. ]);
  48. }
  49. }
  50. return null;
  51. }
  52. /**
  53. * @throws Exception
  54. * @return IResult|int
  55. */
  56. private function getS3Mounts() {
  57. $qb = $this->connection->getQueryBuilder();
  58. $qb->select('m.mount_id')
  59. ->selectAlias('c.value', 'bucket')
  60. ->from('external_mounts', 'm')
  61. ->innerJoin('m', 'external_config', 'c', 'c.mount_id = m.mount_id')
  62. ->where($qb->expr()->eq('m.storage_backend', $qb->createPositionalParameter('amazons3')))
  63. ->andWhere($qb->expr()->eq('c.key', $qb->createPositionalParameter('bucket')));
  64. return $qb->execute();
  65. }
  66. /**
  67. * @throws Exception
  68. */
  69. private function getStorageConfig(int $mountId): array {
  70. $qb = $this->connection->getQueryBuilder();
  71. $qb->select('key', 'value')
  72. ->from('external_config')
  73. ->where($qb->expr()->eq('mount_id', $qb->createPositionalParameter($mountId)));
  74. $config = [];
  75. foreach ($qb->execute()->fetchAll() as $row) {
  76. $config[$row['key']] = $row['value'];
  77. }
  78. return $config;
  79. }
  80. }