Exemple #1
0
    def _handle_busy_snapshot(self, vserver_client, share_name, snapshot_name,
                              wait_seconds=60):
        """Checks for and handles a busy snapshot.

        If a snapshot is not busy, take no action.  If a snapshot is busy for
        reasons other than a clone dependency, raise immediately.  Otherwise,
        since we always start a clone split operation after cloning a share,
        wait up to a minute for a clone dependency to clear before giving up.
        """
        snapshot = vserver_client.get_snapshot(share_name, snapshot_name)
        if not snapshot['busy']:
            return

        # Fail fast if snapshot is not busy due to a clone dependency
        if snapshot['owners'] != {'volume clone'}:
            raise exception.ShareSnapshotIsBusy(snapshot_name=snapshot_name)

        # Wait for clone dependency to clear.
        retry_interval = 3  # seconds
        for retry in range(int(wait_seconds / retry_interval)):
            LOG.debug('Snapshot %(snap)s for share %(share)s is busy, waiting '
                      'for volume clone dependency to clear.',
                      {'snap': snapshot_name, 'share': share_name})

            time.sleep(retry_interval)
            snapshot = vserver_client.get_snapshot(share_name, snapshot_name)
            if not snapshot['busy']:
                return

        raise exception.ShareSnapshotIsBusy(snapshot_name=snapshot_name)
Exemple #2
0
 def _delete_share(self, share, is_snapshot):
     if is_snapshot:
         dataset_name = self._make_snapshot_name(share)
     else:
         dataset_name = self._make_share_name(share)
     try:
         infinidat_filesystem = (
             self._get_infinidat_filesystem_by_name(dataset_name))
     except exception.ShareResourceNotFound:
         message = ("share %(share)s not found on Infinibox, skipping "
                    "delete")
         LOG.warning(message, {"share": share})
         return  # filesystem not found
     if infinidat_filesystem.has_children():
         # can't delete a filesystem that has a live snapshot
         if is_snapshot:
             raise exception.ShareSnapshotIsBusy(snapshot_name=dataset_name)
         else:
             reason = _("share has snapshots and cannot be deleted")
             raise exception.ShareBusyException(reason=reason)
     try:
         infinidat_export = self._get_export(infinidat_filesystem)
     except exception.ShareBackendException:
         # it's possible that the export has been deleted
         pass
     else:
         infinidat_export.safe_delete()
     infinidat_filesystem.safe_delete()
Exemple #3
0
    def delete_snapshot(self, context, snapshot, share_server=None):
        """Deletes a snapshot of a share."""
        share_name = self._get_valid_share_name(snapshot['share_id'])
        snapshot_name = self._get_valid_snapshot_name(snapshot['id'])

        if self._is_snapshot_busy(share_name, snapshot_name):
            raise exception.ShareSnapshotIsBusy(snapshot_name=snapshot_name)
        args = {'snapshot': snapshot_name, 'volume': share_name}

        LOG.debug('Deleting snapshot %s' % snapshot_name)
        self._client.send_request('snapshot-delete', args)
Exemple #4
0
    def delete_snapshot(self, context, snapshot, share_server=None):
        """Delete a snapshot.

        Snapshots with existing clones cannot be deleted.
        """
        LOG.debug("ZFSSAShareDriver.delete_snapshot: id=%s", snapshot['id'])
        lcfg = self.configuration
        has_clones = self.zfssa.has_clones(lcfg.zfssa_pool, lcfg.zfssa_project,
                                           snapshot['share_id'],
                                           snapshot['id'])
        if has_clones:
            LOG.error(_LE("snapshot %s: has clones"), snapshot['id'])
            raise exception.ShareSnapshotIsBusy(snapshot_name=snapshot['id'])
        self.zfssa.delete_snapshot(lcfg.zfssa_pool, lcfg.zfssa_project,
                                   snapshot['share_id'], snapshot['id'])
Exemple #5
0
    def test_delete_snapshot_busy(self):

        vserver_client = mock.Mock()
        self.mock_object(
            self.library, '_get_vserver',
            mock.Mock(return_value=(fake.VSERVER1, vserver_client)))
        mock_handle_busy_snapshot = self.mock_object(
            self.library, '_handle_busy_snapshot',
            mock.Mock(side_effect=exception.ShareSnapshotIsBusy(
                snapshot_name=fake.SNAPSHOT_NAME)))

        self.assertRaises(exception.ShareSnapshotIsBusy,
                          self.library.delete_snapshot,
                          self.context,
                          fake.SNAPSHOT,
                          share_server=fake.SHARE_SERVER)

        self.assertTrue(mock_handle_busy_snapshot.called)
        self.assertFalse(vserver_client.delete_snapshot.called)
Exemple #6
0
 def _fake_delete_snapshot(self, *args, **kwargs):
     raise exception.ShareSnapshotIsBusy(snapshot_name='fakename')
Exemple #7
0
 def _raise_share_snapshot_is_busy(self, *args, **kwargs):
     raise exception.ShareSnapshotIsBusy(snapshot_name='fakename')