Volume based snapshots for recovery

, A volume recovery of source code analysis based on P version based snapshots

1. Characterization

In pike version, openstack official website added a new feature, Cinder volume revert to snapshot, this feature will restore the volume to support the most recent snapshot. Reduction process overwrites the current state and data volumes. If the volume was extended after the snapshot, then the request will be rejected. The purpose of this characteristic is to allow the user to more easily recovered from instance and volume, and reduce downtime.

2, api interface parameters Sample

POST /v3/{project_id}/volumes/{volume_id}/action

Restore a volume to its own latest snapshot, this interface supports only restore the volume is unmounted, and the volume status is valid

Request Example
{
    "revert": {
        "snapshot_id": "5aa119a8-d25b-45a7-8d1b-88e127885635"
    }
}

3, source tracking

Processing cinder-api service side

api interfaces, http request processing 

Cinder / API / V3 / volumes.py 
    @ wsgi.response (http_client.ACCEPTED) 
    @ wsgi.Controller.api_version ( '3.40') 
    @ wsgi.action ( 'Revert') 
    DEF Revert (Self, REQ, ID, body): 
        "" "A Revert to Snapshot Volume A" "" 

        context = req.environ [ 'cinder.context'] 
        self.assert_valid_body (body, 'Revert') 
        snapshot_id in the body = [ 'Revert'] GET ( 'snapshot_id in the'). - ---------- get a snapshot of the incoming user uuid 
        volume = self.volume_api.get_volume (context, id) id ----------- by volume, to obtain volume object 
        try: 
            l_snap = volume.get_latest_snapshot () ------ read the database to obtain the latest snapshot volume UUID 
        the except exception.VolumeSnapshotNotFound:
            msg = _("Volume %s doesn't have any snapshots.") 
            the raise EXC.HTTPBadRequest(explanation=msg % volume.id)
        Volume Snapshot match of Ensure and #. 
        IF snapshot_id IS None or snapshot_id! = L_snap.id:------- determine whether the user input and the input snapshot snapshot is up to date snapshot 
            msg = _ ( "Specified snapshot% (s_id ) or S IS None Not " 
                    ." The Latest One of Volume% (v_id) S ") 
            The raise exc.HTTPBadRequest (explanation% MSG = { 's_id': snapshot_id in the, 
                                                        'v_id': volume.id}) 
        the try: 
            MSG = '. Reverting Volume% (v_id) Snapshot% to S (s_id) S' 
            log.info (MSG, { 'v_id': volume.id,  
                           's_id': l_snap .id})
            self.volume_api.revert_to_snapshot (context, Volume, l_snap) ------ s1 call volume snapshot restore interface 
        except (exception.InvalidVolume,exception.InvalidSnapshot) as e:
            raise exc.HTTPConflict(explanation=six.text_type(e))
        except exception.VolumeSizeExceedsAvailableQuota as e:
            raise exc.HTTPForbidden(explanation=six.text_type(e))  

cinder volume processing module requests

cinder/volume/api.py
    @wrap_check_policy
    def revert_to_snapshot(self, context, volume, snapshot):
        """revert a volume to a snapshot"""

        v_res = volume.update_single_status_where(-----------------更新卷的状态由 available 变为 reverting,
            'reverting', 'available')
        if not v_res:
            msg = _("Can't revert volume %s to its latest snapshot. "
                    "Volume's status must be 'available'.") % volume.id
            raise exception.InvalidVolume(reason=msg)
        s_res = snapshot.update_single_status_where(------------更新快照的状态由available 变为 restoring 
            fields.SnapshotStatus.RESTORING,
            fields.SnapshotStatus.AVAILABLE)
        if not s_res:
            msg = _("Can't revert volume %s to its latest snapshot. "
                    "Snapshot's status must be 'available'.") % snapshot.id
            raise exception.InvalidSnapshot(reason=msg)

        self.volume_rpcapi.revert_to_snapshot(context, volume, snapshot)--------s2调用cinder volume的rpc接口 

 Rpc call Interface

cinder/volume/rpcapi.py
    @rpc.assert_min_rpc_version('3.15')
    def revert_to_snapshot(self, ctxt, volume, snapshot):
        version = self._compat_ver('3.15')
        cctxt = self._get_cctxt(volume.host, version)
        cctxt.cast(ctxt, 'revert_to_snapshot', volume=volume,snapshot=snapshot)  

 cinder-voume side receives rpc request, the information processing rpc

Cinder / Volume / manager.py 
    DEF revert_to_snapshot (Self, context, Volume, Snapshot): 
        "" "A the Revert to Snapshot Volume A. 

        of The Process of Snapshot Reverting to Consists of Several Steps: 
        1. Create Backup for Snapshot A (in Case of data loss) in order to prevent loss of data to create a snapshot backup 
        2.1. use driver's specific logic to revert volume calls the driver's revert_to_snapshot the interface to restore volumes 
        2.2. try the generic way to revert volume if driver's method is missing if driven revert_to_snapshot method does not , then the normal way to restore volume 
        3. delete the backup snapshot backup delete snapshots 
        "" " 
        backup_snapshot = None 
        the try: 
            log.info (" Start to the perform Revert to snapshot Process. ")
            The Create A Snapshot Which CAN # BE Used to Restore at The Volume 
            # by the Data Process failed The Hand IF Revert. 
            Backup_snapshot = self._create_backup_snapshot (context, Volume) --------- create a snapshot volume backup 
            self._revert_to_snapshot ( context, volume, snapshot) -------------- s1 restore snapshot of 
		the except 
			........... 
        v_res = volume.update_single_status_where ( 'Available', 'Reverting' ) ----------- the volume status is updated by reverting Available 
        IF Not v_res: 
            msg_args = { "ID": volume.id, 
                        "status": 'Available'} 
            MSG = _ ( "the Revert finished, but failed to reset "---------- underlying recovery is over, but the state of the state is not set successfully, you need to manually set
                    "Volume% (ID) to S% Status (Status) S," 
                    "Please Manually RESET IT.")% msg_args 
            The raise exception.BadResetResourceStatus (Message = MSG) 

        s_res = snapshot.update_single_status_where (--------- ------ state and the snapshot is updated by reverting Available 
            fields.SnapshotStatus.AVAILABLE, 
            fields.SnapshotStatus.RESTORING) 
        IF Not s_res: 
            msg_args = { "ID": snapshot.id, 
                        "status": 
                            fields.SnapshotStatus. } AVAILABLE 
            MSG = _ ( "Finished the Revert, but failed to RESET" bottom ----------- complete recovery, but the state is not set successfully snapshot, you need to manually set 
                    "snapshot %(id)s status to %(status)s, "
                    "please manually reset it.") % msg_args
            raise exception.BadResetResourceStatus(message=msg)
        if backup_snapshot:
            self.delete_snapshot(context,----------------------删除备份的快照
                                 backup_snapshot, handle_quota=False)
        msg = ('Volume %(v_id)s reverted to snapshot %(snap_id)s '
               'successfully.')
        msg_args = {'v_id': volume.id, 'snap_id': snapshot.id}
        LOG.info(msg, msg_args)
		
cinder/volume/manager.py	
    def _revert_to_snapshot(self, context, volume, snapshot):
        """Use driver or generic method to rollback volume."""

        self._notify_about_volume_usage (context, Volume, "revert.start") 
        self._notify_about_snapshot_usage (context, Snapshot, "revert.start") 
        the try: 
            . Self driver.revert_to_snapshot (context, Volume, Snapshot) ------ call the relevant snapshot drive to restore 
        the except (NotImplementedError, AttributeError): 
            log.info ( "driver's 'revert_to_snapshot' IS not found." 
                     "to use the Try-to-Copy-snapshot Method, Volume.") 
            Self. _revert_to_snapshot_generic (context, Volume, snapshot) ---------- revert_to_snapshot function not implemented, then take the path ceph general call is this 
        self._notify_about_volume_usage (context, volume, "revert.end ")
        self._notify_about_snapshot_usage(context, snapshot, "revert.end")  

Based driving lvm

Cinder / Volume / the Drivers / lvm.py 
    DEF revert_to_snapshot (Self, context, Volume, Snapshot): 
        "" "A Revert to Snapshot Volume A" "" 
        # NOTE (tommylikehu): We Still CAN Revert at The Volume Because Cinder 
        # the try by Will IF Alternative Approach at The 'NotImplementedError' 
        # IS raised here Wallpaper. 
        IF self.configuration.lvm_type == 'Thin': -------- If lvm configured thin, it does not support snapshots recovery 
            msg = _ ( "Revert volume snapshot for not Implemented the Thin to LVM "). 
            the raise NotImplementedError (msg) 
        the else: 
            self.vg.revert (self._escape_snapshot (snapshot.name)) ----- execution is lvconvert --merge command to merge a snapshot of the original volume, this time the snapshot will be destroyed
            self.vg.deactivate_lv (volume.name) ------ lvchange -an command is executed, the change of volume lv invalid state, the lvchange lv represents a change in the active state, y represents lv active or live, n-represents lv inactive or invalid 
            self.vg.activate_lv (volume.name) -------- execution is lvchange -ay --yes, lv volume represents a change of state to the active state, - yes means no prompt for confirmation interactive, direct regarded, 
            # Recreate at The snapshot that WAS Destroyed by at The Revert 
            self.create_snapshot (snapshot) ----------- create a snapshot  

Since ceph currently not implemented revert_to_snapshot method, so calling _revert_to_snapshot_generic Interface

Cinder / Volume / manager.py 
    DEF _revert_to_snapshot_generic (Self, ctxt, Volume, Snapshot): 
        "" "Way to the Generic A Revert to Snapshot Volume. 
        The use Will Framework The Generic Way to Implement The Revert 
        to Snapshot Feature: 
        1. Create A temporary volume from snapshot ----- create a temporary volume from a snapshot 
        2. mount two volumes to host -------------- mounts two volumes on the host 
        3. copy data from temporary volume to original volume -------- volume copy data from the temporary to the original volume 
        4. detach and destroy temporary volume ---------- unloading and destroying the temporary volume 
        "" " 
        temp_vol = None 

        the try: 
            v_options = { 'DISPLAY_NAME': '[Revert] Temporary Volume Created'
                                         'Snapshot from S%'% snapshot.id} 
            ctxt = context.get_internal_tenant_context () or ctxt 
            temp_vol = self.driver._create_temp_volume_from_snapshot (-------- create a temporary snapshot volume 
                ctxt, volume, snapshot, volume_options = v_options ) 
            self._copy_volume_data (ctxt, temp_vol, volume) ------- volume copy data from the temporary to the original volume, the process will be divided into three smaller steps: Mounting the original volume and the temporary volume; volume copy data from temporary to the original volume; 
unloading temporary volume and the original volume self.driver.delete_volume (temp_vol) ----- delete the temporary volume temp_vol.destroy () the except Exception: with excutils.save_and_reraise_exception (): LOG.exception ( "Failed to use Snapshot% (snapshot) s to create " "a temporary volume and copy data to volume " " %(volume)s.", {'snapshot': snapshot.id, 'volume': volume.id}) if temp_vol and temp_vol.status == 'available': self.driver.delete_volume(temp_vol) temp_vol.destroy()

  

Guess you like

Origin www.cnblogs.com/potato-chip/p/11535166.html