/// This RPC is called by the CO when a workload using the specified
/// volume is removed (unscheduled) from a node.
/// If the corresponding Controller Plugin has PUBLISH_UNPUBLISH_VOLUME
/// controller capability, the CO MUST guarantee that this RPC is called
/// after ControllerPublishVolume is called for the given volume on the
/// given node and returns a success.
///
/// This operation MUST be idempotent.
This RPC is called by the CO when a workload using the specified
volume is removed (unscheduled) from a node.
If the corresponding Controller Plugin has PUBLISH_UNPUBLISH_VOLUME
controller capability, the CO MUST guarantee that this RPC is called
after ControllerPublishVolume is called for the given volume on the
given node and returns a success.

This operation MUST be idempotent.
This RPC is called by the CO when a workload using the specified volume is removed ( unscheduled ) from a node . If the corresponding Controller Plugin has PUBLISH_UNPUBLISH_VOLUME controller capability the CO MUST guarantee that this RPC is called after ControllerPublishVolume is called for the given volume on the given node and returns a success . This operation MUST be idempotent .
async fn node_unpublish_volume(
        &self,
        request: Request<NodeUnpublishVolumeRequest>,
    ) -> Result<Response<NodeUnpublishVolumeResponse>, Status> {
        let msg = request.into_inner();
        trace!("node_unpublish_volume {:?}", msg);
        let target_path = &msg.target_path;
        let volume_id = &msg.volume_id;
        if volume_id.is_empty() {
            return Err(failure!(
                Code::InvalidArgument,
                "Failed to unpublish volume: missing volume id"
            ));
        }
        if target_path.is_empty() {
            return Err(failure!(
                Code::InvalidArgument,
                "Failed to unpublish volume {}: missing target path",
                volume_id
            ));
        }
        debug!("Unpublishing volume {} from {}", volume_id, target_path);
        if mount::find_mount(None, Some(target_path)).is_none() {
            // No mount found for target_path.
            // The idempotency requirement means this is not an error.
            // Just clean up as best we can and claim success.
            if let Err(error) = fs::remove_dir(PathBuf::from(target_path)) {
                if error.kind() != ErrorKind::NotFound {
                    error!(
                        "Failed to remove directory {}: {}",
                        target_path, error
                    );
                }
            }
            info!(
                "Volume {} is already unpublished from {}",
                volume_id, target_path
            );
            return Ok(Response::new(NodeUnpublishVolumeResponse {}));
        }
        debug!("Unmounting {}", target_path);
        if let Err(error) = mount::bind_unmount(target_path) {
            return Err(failure!(
                Code::Internal,
                "Failed to unpublish volume {}: failed to unmount {}: {}",
                volume_id,
                target_path,
                error
            ));
        }
        debug!("Removing directory {}", target_path);
        if let Err(error) = fs::remove_dir(PathBuf::from(target_path)) {
            if error.kind() != ErrorKind::NotFound {
                error!("Failed to remove directory {}: {}", target_path, error);
            }
        }
        info!("Volume {} unpublished from {}", volume_id, target_path);
        Ok(Response::new(NodeUnpublishVolumeResponse {}))
    }
async fn node_unpublish_volume ( & self , request : Request < NodeUnpublishVolumeRequest > , ) -> Result < Response < NodeUnpublishVolumeResponse > , Status > { let msg = request . into_inner ( ) ; trace ! ( " " msg ) ; let target_path = & msg . target_path ; let volume_id = & msg . volume_id ; if volume_id . is_empty ( ) { return Err ( failure ! ( Code InvalidArgument " " ) ) ; } if target_path . is_empty ( ) { return Err ( failure ! ( Code InvalidArgument " " volume_id ) ) ; } debug ! ( " " volume_id target_path ) ; if mount :: find_mount ( None , Some ( target_path ) ) . is_none ( ) { // No mount found for target_path. // The idempotency requirement means this is not an error. // Just clean up as best we can and claim success. if let Err ( error ) = fs :: remove_dir ( PathBuf :: from ( target_path ) ) { if error . kind ( ) != ErrorKind :: NotFound { error ! ( " " target_path error ) ; } } info ! ( " " volume_id target_path ) ; return Ok ( Response :: new ( NodeUnpublishVolumeResponse { } ) ) ; } debug ! ( " " target_path ) ; if let Err ( error ) = mount :: bind_unmount ( target_path ) { return Err ( failure ! ( Code Internal " " volume_id target_path error ) ) ; } debug ! ( " " target_path ) ; if let Err ( error ) = fs :: remove_dir ( PathBuf :: from ( target_path ) ) { if error . kind ( ) != ErrorKind :: NotFound { error ! ( " " target_path error ) ; } } info ! ( " " volume_id target_path ) ; Ok ( Response :: new ( NodeUnpublishVolumeResponse { } ) ) }
This RPC is called by the CO when a workload using the specified
volume is removed (unscheduled) from a node.
This RPC is called by the CO when a workload using the specified volume is removed ( unscheduled ) from a node .
&self
request
Request<NodeUnpublishVolumeRequest>