Skip to content

Commit

Permalink
csi: node unmount from the client before unpublish RPC
Browse files Browse the repository at this point in the history
When an allocation stops, the `csi_hook` makes an unpublish RPC to the
servers to unpublish via the CSI RPCs: first to the node plugins and
then the controller plugins. The controller RPCs must happen after the
node RPCs so that the node has had a chance to unmount the volume
before the controller tries to detach the associated device.

But the client has local access to the node plugins and can
independently determine if it's safe to send unpublish RPC to those
plugins. This will allow the server to treat the node plugin as
abandoned if a client is disconnected and `stop_on_client_disconnect`
is set. This will let the server try to send unpublish RPCs to the
controller plugins, under the assumption that the client will be
trying to unmount the volume on its end first.
  • Loading branch information
tgross committed Jan 20, 2022
1 parent 1471de4 commit c28c1bd
Showing 1 changed file with 28 additions and 1 deletion.
29 changes: 28 additions & 1 deletion client/allocrunner/csi_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ func (c *csiHook) Postrun() error {

for _, pair := range c.volumeRequests {

err := c.unmount(pair)
if err != nil {
mErr = multierror.Append(mErr, err)
}

mode := structs.CSIVolumeClaimRead
if !pair.request.ReadOnly {
mode = structs.CSIVolumeClaimWrite
Expand All @@ -132,7 +137,7 @@ func (c *csiHook) Postrun() error {
AuthToken: c.nodeSecret,
},
}
err := c.rpcClient.RPC("CSIVolume.Unpublish",
err = c.rpcClient.RPC("CSIVolume.Unpublish",
req, &structs.CSIVolumeUnpublishResponse{})
if err != nil {
mErr = multierror.Append(mErr, err)
Expand Down Expand Up @@ -231,3 +236,25 @@ func (c *csiHook) shouldRun() bool {

return false
}

func (c *csiHook) unmount(pair *volumeAndRequest) error {

mounter, err := c.csimanager.MounterForPlugin(context.TODO(), pair.volume.PluginID)
if err != nil {
return err
}

usageOpts := &csimanager.UsageOptions{
ReadOnly: pair.request.ReadOnly,
AttachmentMode: pair.request.AttachmentMode,
AccessMode: pair.request.AccessMode,
MountOptions: pair.request.MountOptions,
}

err = mounter.UnmountVolume(context.TODO(),
pair.volume.ID, pair.volume.RemoteID(), c.alloc.ID, usageOpts)
if err != nil {
return err
}
return nil
}

0 comments on commit c28c1bd

Please sign in to comment.