diff --git a/doc/source/devref/share_back_ends_feature_support_mapping.rst b/doc/source/devref/share_back_ends_feature_support_mapping.rst index 2963d49d39..c92f5f0433 100644 --- a/doc/source/devref/share_back_ends_feature_support_mapping.rst +++ b/doc/source/devref/share_back_ends_feature_support_mapping.rst @@ -53,7 +53,7 @@ Mapping of share drivers and share features support +----------------------------------------+-----------------------+-----------------------+--------------+--------------+------------------------+----------------------------+--------------------------+--------------------+ | HDFS | K | \- | M | \- | K | K | \- | \- | +----------------------------------------+-----------------------+-----------------------+--------------+--------------+------------------------+----------------------------+--------------------------+--------------------+ -| Hitachi HNAS | L | L | L | M | L | L | O | \- | +| Hitachi HNAS | L | L | L | M | L | L | O | O | +----------------------------------------+-----------------------+-----------------------+--------------+--------------+------------------------+----------------------------+--------------------------+--------------------+ | Hitachi HSP | N | N | N | N | \- | \- | \- | \- | +----------------------------------------+-----------------------+-----------------------+--------------+--------------+------------------------+----------------------------+--------------------------+--------------------+ @@ -224,7 +224,7 @@ More information: :ref:`capabilities_and_extra_specs` +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+ | HDFS | \- | K | \- | \- | \- | L | \- | K | \- | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+ -| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | \- | +| Hitachi HNAS | \- | L | N | \- | L | \- | \- | L | O | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+ | Hitachi HSP | \- | N | \- | \- | N | \- | \- | \- | \- | +----------------------------------------+-----------+------------+--------+-------------+-------------------+--------------------+-----+----------------------------+--------------------+ diff --git a/manila/share/drivers/hitachi/hnas/driver.py b/manila/share/drivers/hitachi/hnas/driver.py index ff0a2bab98..7c2a19bf3d 100644 --- a/manila/share/drivers/hitachi/hnas/driver.py +++ b/manila/share/drivers/hitachi/hnas/driver.py @@ -552,6 +552,7 @@ class HitachiHNASDriver(driver.ShareDriver): 'qos': False, 'thin_provisioning': True, 'dedupe': dedupe, + 'revert_to_snapshot_support': True, } LOG.info(_LI("HNAS Capabilities: %(data)s."), @@ -703,6 +704,40 @@ class HitachiHNASDriver(driver.ShareDriver): {'shr_id': share['id'], 'shr_size': six.text_type(new_size)}) + def revert_to_snapshot(self, context, snapshot, share_server=None): + """Reverts a share to a given snapshot. + + :param context: The `context.RequestContext` object for the request + :param snapshot: The snapshot to which the share is to be reverted to. + :param share_server: Data structure with share server information. + Not used by this driver. + """ + + self._check_fs_mounted() + + hnas_share_id = self._get_hnas_share_id(snapshot['share_id']) + + hnas_snapshot_id = self._get_hnas_snapshot_id(snapshot) + + dest_path = os.path.join('/shares', hnas_share_id) + src_path = os.path.join('/snapshots', hnas_share_id, hnas_snapshot_id) + + self.hnas.tree_delete(dest_path) + + self.hnas.vvol_create(hnas_share_id) + + self.hnas.quota_add(hnas_share_id, snapshot['size']) + + try: + self.hnas.tree_clone(src_path, dest_path) + except exception.HNASNothingToCloneException: + LOG.warning(_LW("Source directory is empty, creating an empty " + "directory.")) + + LOG.info(_LI("Share %(share)s successfully reverted to snapshot " + "%(snapshot)s."), {'share': snapshot['share_id'], + 'snapshot': snapshot['id']}) + def _get_hnas_share_id(self, share_id): hnas_id = self.private_storage.get(share_id, 'hnas_id') diff --git a/manila/tests/share/drivers/hitachi/hnas/test_driver.py b/manila/tests/share/drivers/hitachi/hnas/test_driver.py index af68dcf875..491bf3863e 100644 --- a/manila/tests/share/drivers/hitachi/hnas/test_driver.py +++ b/manila/tests/share/drivers/hitachi/hnas/test_driver.py @@ -95,6 +95,7 @@ snapshot_nfs = { 'share': share_nfs, 'provider_location': '/snapshots/aa4a7710-f326-41fb-ad18-b4ad587fc87a/' 'abba6d9b-f29c-4bf7-aac1-618cda7aaf0f', + 'size': 2, } snapshot_cifs = { @@ -103,6 +104,7 @@ snapshot_cifs = { 'share': share_cifs, 'provider_location': '/snapshots/f5cadaf2-afbe-4cc4-9021-85491b6b76f7/' '91bc6e1b-1ba5-f29c-abc1-da7618cabf0a', + 'size': 2, } manage_snapshot = { @@ -834,6 +836,7 @@ class HitachiHNASTestCase(test.TestCase): 'qos': False, 'thin_provisioning': True, 'dedupe': True, + 'revert_to_snapshot_support': True, } self.mock_object(ssh.HNASSSHBackend, 'get_stats', mock.Mock( @@ -898,3 +901,35 @@ class HitachiHNASTestCase(test.TestCase): def test_unmanage_snapshot(self): self._driver.unmanage_snapshot(snapshot_nfs) self.assertTrue(self.mock_log.info.called) + + @ddt.data({'snap': snapshot_nfs, 'exc': None}, + {'snap': snapshot_cifs, 'exc': None}, + {'snap': snapshot_nfs, + 'exc': exception.HNASNothingToCloneException('fake')}, + {'snap': snapshot_cifs, + 'exc': exception.HNASNothingToCloneException('fake')}) + @ddt.unpack + def test_revert_to_snapshot(self, exc, snap): + self.mock_object(driver.HitachiHNASDriver, "_check_fs_mounted") + self.mock_object(ssh.HNASSSHBackend, 'tree_delete') + self.mock_object(ssh.HNASSSHBackend, 'vvol_create') + self.mock_object(ssh.HNASSSHBackend, 'quota_add') + self.mock_object(ssh.HNASSSHBackend, 'tree_clone', + mock.Mock(side_effect=exc)) + + self._driver.revert_to_snapshot('context', snap, None) + + driver.HitachiHNASDriver._check_fs_mounted.assert_called_once_with() + ssh.HNASSSHBackend.tree_delete.assert_called_once_with( + '/'.join(('/shares', snap['share_id']))) + ssh.HNASSSHBackend.vvol_create.assert_called_once_with( + snap['share_id']) + ssh.HNASSSHBackend.quota_add.assert_called_once_with( + snap['share_id'], 2) + ssh.HNASSSHBackend.tree_clone.assert_called_once_with( + '/'.join(('/snapshots', snap['share_id'], snap['id'])), + '/'.join(('/shares', snap['share_id']))) + + if exc: + self.assertTrue(self.mock_log.warning.called) + self.assertTrue(self.mock_log.info.called) diff --git a/releasenotes/notes/hnas-revert-to-snapshot-a2405cd6653b1e85.yaml b/releasenotes/notes/hnas-revert-to-snapshot-a2405cd6653b1e85.yaml new file mode 100644 index 0000000000..e018431b88 --- /dev/null +++ b/releasenotes/notes/hnas-revert-to-snapshot-a2405cd6653b1e85.yaml @@ -0,0 +1,9 @@ +--- +features: + - Added Revert-to-snapshot functionality to Hitachi NAS driver. +upgrades: + - If using existing share types with the HNAS back end, + set the 'revert_to_snapshot_support' extra-spec to allow + creating shares that support in-place revert-to-snapshot + functionality. This modification will not affect existing + shares of such types.