Exemple #1
0
    def delete_snapshot(self, snapshot):
        """Delete snapshot of existing volume.

        :param snapshot: snapshot reference
        """
        sname = jcom.sname(snapshot.id)

        LOG.debug('deleating snapshot %s.', sname)

        snapshots = None
        try:
            snapshots = self.ra.get_snapshots(sname)
        except jexc.JDSSResourceNotFoundException:
            LOG.debug('physical volume %s dne, it was already '
                      'deleted.', sname)
            return
        except jexc.JDSSException as jerr:
            raise exception.VolumeBackendAPIException(jerr)

        snapshots = self._clean_garbage_snapshots(sname, snapshots)

        if len(snapshots) > 0:
            self._hide_object(sname)
        else:
            self._gc_delete(sname)
Exemple #2
0
    def test_delete_snapshot_has_clone(self):
        jdssd, ctx = self.get_driver(CONFIG_OK)

        sname = jcom.sname(UUID_2)

        snap = fake_snapshot.fake_snapshot_obj(ctx, id=UUID_2)

        jdssd.ra.get_snapshots.return_value = SNAPSHOTS_EMPTY
        patches = [
            mock.patch.object(jdssd,
                              "_clean_garbage_snapshots",
                              return_value=SNAPSHOTS_CLONE),
            mock.patch.object(jdssd, "_clone_object", return_value=None),
            mock.patch.object(jdssd, "_hide_object", return_value=None),
            mock.patch.object(jdssd, "_gc_delete", return_value=None)
        ]

        self.start_patches(patches)

        jdssd.create_snapshot(snap)

        jdssd.delete_snapshot(snap)
        jdssd._gc_delete.assert_not_called()
        jdssd._hide_object.assert_called_once_with(sname)
        jdssd._clean_garbage_snapshots.assert_called_once_with(
            sname, SNAPSHOTS_EMPTY)
        self.stop_patches(patches)
Exemple #3
0
    def create_volume_from_snapshot(self, volume, snapshot):
        """Create a volume from a snapshot.

        If volume_type extra specs includes 'replication: <is> True'
        the driver needs to create a volume replica (secondary),
        and setup replication between the newly created volume and
        the secondary volume.
        """
        LOG.debug('create volume %(vol)s from snapshot %(snap)s', {
            'vol': volume.id,
            'snap': snapshot.id
        })

        cvname = jcom.vname(volume.id)
        sname = jcom.sname(snapshot.id)

        self._clone_object(sname, cvname)

        clone_size = 0

        try:
            clone_size = int(self.ra.get_lun(cvname)['volsize'])
        except jexc.JDSSException as jerr:

            self._delete_back_recursively(sname, cvname)
            raise exception.VolumeBackendAPIException(
                _("Fail in cloning snapshot %(snap)s to %(clone)s.") % {
                    'snap': snapshot.id,
                    'clone': volume.id
                }) from jerr

        try:
            if clone_size < o_units.Gi * int(volume.size):
                self.extend_volume(volume, int(volume.size))
        except exception.VolumeBackendAPIException:
            # If volume can't be set to a proper size make sure to clean it
            # before failing
            try:
                self._delete_back_recursively(cvname, cvname)
            except exception.VolumeBackendAPIException as err:
                msg = ("Hidden snapshot %s of volume %s "
                       "have to be removed manualy, "
                       "as automatic removal failed: %s")
                LOG.warning(msg, cvname, sname, err)
            raise

        provider_location = self._get_provider_location(volume.id)
        provider_auth = self._get_provider_auth()

        ret = {}
        if provider_auth is not None:
            ret['provider_auth'] = provider_auth

        ret['provider_location'] = provider_location

        return ret
Exemple #4
0
    def test_delete_back_recursively_res_active(self):

        jdssd, ctx = self.get_driver(CONFIG_OK)
        opvname = jcom.vname(UUID_1)
        opsname = jcom.sname(UUID_2)

        jdssd._delete_back_recursively(opvname, opsname)

        jdssd.ra.delete_snapshot.assert_called_once_with(
            opvname,
            opsname,
            recursively_children=True,
            recursively_dependents=True,
            force_umount=True)
Exemple #5
0
    def test_delete_back_recursively_hidden_have_snapshots(self):

        jdssd, ctx = self.get_driver(CONFIG_OK)
        opvname = jcom.hidden(UUID_1)
        opsname = jcom.sname(UUID_2)

        jdssd.ra.get_snapshots.return_value = SNAPSHOTS_RECURSIVE_1.copy()

        jdssd._delete_back_recursively(opvname, opsname)

        jdssd.ra.delete_snapshot.assert_called_once_with(
            opvname,
            opsname,
            recursively_children=True,
            recursively_dependents=True,
            force_umount=True)
Exemple #6
0
    def test_clone_object_dne(self):
        jdssd, ctx = self.get_driver(CONFIG_OK)
        calls = []
        origin = jcom.vname(UUID_1)
        clone = jcom.vname(UUID_2)
        calls.append(mock.call(origin, clone))

        jdssd.ra.create_snapshot.side_effect = (
            jexc.JDSSResourceNotFoundException(res=origin))

        self.assertRaises(exception.VolumeNotFound, jdssd._clone_object,
                          origin, clone)

        origin = jcom.sname(UUID_1)
        calls.append(mock.call(origin, clone))

        self.assertRaises(exception.SnapshotNotFound, jdssd._clone_object,
                          origin, clone)
        jdssd.ra.create_snapshot.assert_has_calls(calls)
Exemple #7
0
    def test_create_snapshot(self):
        jdssd, ctx = self.get_driver(CONFIG_OK)

        vname = jcom.vname(UUID_1)

        sname = jcom.sname(UUID_2)

        snap = fake_snapshot.fake_snapshot_obj(ctx, id=UUID_2)
        snap.volume_id = UUID_1

        patches = [
            mock.patch.object(jdssd, "_clone_object", return_value=None)
        ]

        self.start_patches(patches)

        jdssd.create_snapshot(snap)

        jdssd._clone_object.assert_called_once_with(vname, sname)
        self.stop_patches(patches)
Exemple #8
0
    def create_snapshot(self, snapshot):
        """Create snapshot of existing volume.

        :param snapshot: snapshot reference
        """
        LOG.debug('create snapshot %(snap)s for volume %(vol)s', {
            'snap': snapshot.id,
            'vol': snapshot.volume_id})

        vname = jcom.vname(snapshot.volume_id)
        sname = jcom.sname(snapshot.id)

        self._clone_object(vname, sname)

        try:
            self.ra.make_readonly_lun(sname)
        except jexc.JDSSException as err:
            # Name of snapshot should be the same as a name of volume
            # that is going to be created from it
            self._delete_back_recursively(vname, sname)
            raise exception.VolumeBackendAPIException(err)
Exemple #9
0
    def revert_to_snapshot(self, context, volume, snapshot):
        """Revert volume to snapshot.

        Note: the revert process should not change the volume's
        current size, that means if the driver shrank
        the volume during the process, it should extend the
        volume internally.
        """
        vname = jcom.vname(volume.id)
        sname = jcom.sname(snapshot.id)
        LOG.debug('reverting %(vname)s to %(sname)s', {
            "vname": vname,
            "sname": sname
        })

        vsize = None
        try:
            vsize = self.ra.get_lun(vname).get('volsize')
        except jexc.JDSSResourceNotFoundException as jerr:
            raise exception.VolumeNotFound(volume_id=volume.id) from jerr
        except jexc.JDSSException as jerr:
            raise exception.VolumeBackendAPIException(jerr) from jerr

        if vsize is None:
            raise exception.VolumeDriverException(
                _("unable to identify volume size"))

        try:
            self.ra.rollback_volume_to_snapshot(vname, sname)
        except jexc.JDSSException as jerr:
            raise exception.VolumeBackendAPIException(jerr.message) from jerr

        try:
            rvsize = self.ra.get_lun(vname).get('volsize')
            if rvsize != vsize:
                self.ra.extend_lun(vname, vsize)
        except jexc.JDSSResourceNotFoundException as jerr:
            raise exception.VolumeNotFound(volume_id=volume.id) from jerr
        except jexc.JDSSException as jerr:
            raise exception.VolumeBackendAPIException(jerr) from jerr
Exemple #10
0
    def test_delete_back_recursively_single_snapshot(self):

        jdssd, ctx = self.get_driver(CONFIG_OK)
        opvname = jcom.hidden(UUID_2)
        opsname = jcom.sname(UUID_3)

        jdssd.ra.get_snapshots.side_effect = [
            SNAPSHOTS_RECURSIVE_CHAIN_1.copy(),
            SNAPSHOTS_RECURSIVE_CHAIN_2.copy()
        ]

        origin = "Pool-0/{vorig}@{sorig}".format(vorig=jcom.vname(UUID_1),
                                                 sorig=jcom.vname(UUID_2))
        get_lun_resp = {
            'origin': origin,
            'vscan': None,
            'full_name': 'Pool-0/' + jcom.hidden(UUID_2),
            'userrefs': None,
            'primarycache': 'all',
            'logbias': 'latency',
            'creation': '1591543140',
            'sync': 'always',
            'is_clone': True,
            'dedup': 'off',
            'sharenfs': None,
            'receive_resume_token': None,
            'volsize': '1073741824'
        }
        jdssd.ra.get_lun.return_value = get_lun_resp
        jdssd._delete_back_recursively(opvname, opsname)

        jdssd.ra.delete_snapshot.assert_called_once_with(
            jcom.vname(UUID_1),
            jcom.vname(UUID_2),
            recursively_children=True,
            recursively_dependents=True,
            force_umount=True)

        get_snapshots_expected = [mock.call(opvname)]
        jdssd.ra.get_snapshots.assert_has_calls(get_snapshots_expected)
Exemple #11
0
    def test_create_volume_from_snapshot_extend(self):
        jdssd, ctx = self.get_driver(CONFIG_OK)

        origin_sname = jcom.sname(UUID_1)

        clone_vname = jcom.vname(UUID_2)

        orig_snap = fake_snapshot.fake_snapshot_obj(ctx)
        orig_snap.id = UUID_1

        clone_vol = fake_volume.fake_volume_obj(ctx)
        clone_vol.id = UUID_2
        clone_vol.size = 2

        host = CONFIG_OK["san_hosts"][0]
        port = CONFIG_OK["target_port"]
        target_name = CONFIG_OK["target_prefix"] + UUID_2

        location = '{host}:{port},1 {name} 0'.format(host=host,
                                                     port=port,
                                                     name=target_name)

        cred_format = (r"CHAP [0-9,a-z,A-Z]{{{name_len}}} "
                       "[0-9,a-z,A-Z]{{{pass_len}}}").format(
                           name_len=8, pass_len=CONFIG_OK['chap_password_len'])

        patches = [
            mock.patch.object(jdssd, "_clone_object", return_value=None),
            mock.patch.object(jdssd, "extend_volume", return_value=None),
            mock.patch.object(jdssd,
                              "_get_provider_location",
                              return_value=location),
            mock.patch.object(jdssd,
                              "_get_provider_auth",
                              return_value=cred_format)
        ]

        jdssd.ra.get_lun.return_value = {
            'vscan': None,
            'full_name': 'Pool-0/' + UUID_2,
            'userrefs': None,
            'primarycache': 'all',
            'logbias': 'latency',
            'creation': '1591543140',
            'sync': 'always',
            'is_clone': False,
            'dedup': 'off',
            'sharenfs': None,
            'receive_resume_token': None,
            'volsize': '1073741824'
        }

        self.start_patches(patches)

        ret = jdssd.create_volume_from_snapshot(clone_vol, orig_snap)

        jdssd.extend_volume.assert_called_once_with(clone_vol, clone_vol.size)
        jdssd._clone_object.assert_called_once_with(origin_sname, clone_vname)
        self.stop_patches(patches)

        jdssd.ra.get_lun.assert_called_once_with(jcom.vname(clone_vol.id))
        self.assertEqual(location, ret['provider_location'])
        self.assertEqual(cred_format, ret['provider_auth'])
Exemple #12
0
    'jovian_recovery_delay': 60,
    'jovian_user': '******',
    'jovian_password': '******',
    'jovian_ignore_tpath': [],
    'target_port': 3260,
    'jovian_pool': 'Pool-0',
    'target_prefix': 'iqn.2020-04.com.open-e.cinder:',
    'chap_password_len': 12,
    'san_thin_provision': False,
    'volume_backend_name': 'JovianDSS',
    'reserved_percentage': 10,
    'jovian_block_size': '128K'
}

SNAPSHOTS_CASCADE_1 = [{
    "name": jcom.sname(UUID_1),
    "clones": "Pool-0/" + jcom.sname(UUID_1)
}, {
    "name": jcom.sname(UUID_2),
    "clones": "Pool-0/" + jcom.sname(UUID_2)
}, {
    "name": jcom.sname(UUID_3),
    "clones": "Pool-0/" + jcom.sname(UUID_3)
}]

SNAPSHOTS_CASCADE_2 = [{
    "name": jcom.sname(UUID_1),
    "clones": "Pool-0/" + jcom.sname(UUID_1)
}, {
    "name": jcom.vname(UUID_2),
    "clones": "Pool-0/" + jcom.vname(UUID_2)