def _cascade_volume_delete(self, o_vname, o_snaps): """Delete or hides volume(if it is busy) Go over snapshots and deletes them if possible Calls for recursive volume deletion if volume do not have children """ vsnaps = [] deletable = True for snap in o_snaps: if jcom.is_snapshot(snap['name']): vsnaps += [(snap['name'], jcom.full_name_volume(snap['clones']))] active_vsnaps = [vs for vs in vsnaps if jcom.is_hidden(vs[1]) is False] # If volume have clones or hidden snapshots it should be hidden if len(active_vsnaps) < len(o_snaps): deletable = False for vsnap in active_vsnaps: psnap = [] try: psnap = self.ra.get_snapshots(vsnap[1]) except jexc.JDSSException as jerr: msg = (_('Failure in acquiring snapshot for %s.') % vsnap[1]) raise exception.VolumeBackendAPIException(msg) from jerr try: psnap = self._clean_garbage_snapshots(vsnap[1], psnap) except exception.VolumeBackendAPIException as err: msg = (_('Failure in cleaning garbage snapshots %s' ' for volume %s, %s') % psnap, vsnap[1], err) raise exception.VolumeBackendAPIException(msg) from err if len(psnap) > 0: deletable = False self._hide_object(vsnap[1]) else: try: self.ra.delete_snapshot(o_vname, vsnap[0], recursively_children=True, recursively_dependents=True, force_umount=True) except jexc.JDSSException as jerr: LOG.warning( 'Failure during deletion of physical ' 'snapshot %s, err: %s', vsnap[0], jerr) msg = (_('Failure during deletion of virtual snapshot ' '%s') % vsnap[1]) raise exception.VolumeBackendAPIException(msg) if deletable: self._gc_delete(o_vname) else: self._hide_object(o_vname)
def _delete_back_recursively(self, opvname, opsname): """Deletes snapshot by removing its oldest removable parent Checks if source volume for this snapshot is hidden: If it is hidden and have no other descenents, it calls itself on its source snapshot if such exists, or deletes it If it is not hidden, trigers delete for snapshot :param opvname: origin physical volume name :param opsname: origin physical snapshot name """ if jcom.is_hidden(opvname): # Resource is hidden snaps = [] try: snaps = self.ra.get_snapshots(opvname) except jexc.JDSSResourceNotFoundException: LOG.debug( 'Unable to get physical snapshots related to' ' physical volume %s, volume do not exist', opvname) return except jexc.JDSSException as jerr: raise exception.VolumeBackendAPIException(jerr) snaps = self._clean_garbage_snapshots(opvname, snaps) if len(snaps) > 1: # opvname has active snapshots and cant be deleted # that is why we delete branch related to opsname try: self.ra.delete_snapshot(opvname, opsname, recursively_children=True, recursively_dependents=True, force_umount=True) except jexc.JDSSException as jerr: raise exception.VolumeBackendAPIException(jerr) else: vol = None try: vol = self.ra.get_lun(opvname) except jexc.JDSSResourceNotFoundException: LOG.debug( 'volume %s does not exist, it was already ' 'deleted.', opvname) return except jexc.JDSSException as jerr: raise exception.VolumeBackendAPIException(jerr) if vol['is_clone']: self._delete_back_recursively( jcom.origin_volume(vol['origin']), jcom.origin_snapshot(vol['origin'])) else: try: self.ra.delete_lun(opvname, recursively_children=True, recursively_dependents=True, force_umount=True) except jexc.JDSSResourceNotFoundException: LOG.debug( 'volume %s does not exist, it was already ' 'deleted.', opvname) return except jexc.JDSSException as jerr: raise exception.VolumeBackendAPIException(jerr) else: # Resource is active try: self.ra.delete_snapshot(opvname, opsname, recursively_children=True, recursively_dependents=True, force_umount=True) except jexc.JDSSException as jerr: raise exception.VolumeBackendAPIException(jerr) from jerr