From 2f7b966a94a5d612768f755d07fc3279dbb259c1 Mon Sep 17 00:00:00 2001 From: Daishan Peng Date: Wed, 31 Jan 2018 14:35:05 -0700 Subject: [PATCH] add capability endpoint to decide flex volume --- core/compute/compute_common.go | 8 ++++++-- core/compute/compute_unix.go | 8 ++++++-- core/storage/volume.go | 26 +++++++++++++++++++++++--- handlers/storage.go | 8 ++++++-- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/core/compute/compute_common.go b/core/compute/compute_common.go index 0ebbd5ea..1c341e4f 100755 --- a/core/compute/compute_common.go +++ b/core/compute/compute_common.go @@ -144,7 +144,9 @@ func setupVolumes(config *container.Config, instance model.Instance, hostConfig rancherManagedVolumeNames := map[string]struct{}{} if vMounts := instance.VolumesFromDataVolumeMounts; len(vMounts) > 0 { for _, volume := range vMounts { - if storage.IsRancherVolume(volume) { + if ok, err := storage.IsRancherVolume(volume); err != nil { + return err + } else if ok { rancherManagedVolumeNames[volume.Name] = struct{}{} } } @@ -208,7 +210,9 @@ func setupVolumes(config *container.Config, instance model.Instance, hostConfig for _, vMount := range vMounts { storagePool := model.StoragePool{} // volume active == exists, possibly not attached to this host - if !storage.IsRancherVolume(vMount) { + if ok, err := storage.IsRancherVolume(vMount); err != nil { + return err + } else if !ok { if ok, err := storage.IsVolumeActive(vMount, storagePool, client); !ok && err == nil { if err := storage.DoVolumeActivate(vMount, storagePool, progress, client); err != nil { return errors.Wrap(err, constants.SetupVolumesError+"failed to activate volume") diff --git a/core/compute/compute_unix.go b/core/compute/compute_unix.go index b08b0a00..d44f41c8 100755 --- a/core/compute/compute_unix.go +++ b/core/compute/compute_unix.go @@ -487,7 +487,9 @@ func configureDNS(dockerClient *client.Client, containerID string) error { func setupRancherFlexVolume(instance model.Instance, hostConfig *container.HostConfig) error { for _, volume := range instance.VolumesFromDataVolumeMounts { - if storage.IsRancherVolume(volume) { + if ok, err := storage.IsRancherVolume(volume); err != nil { + return err + } else if ok { payload := struct { Name string Options map[string]string `json:"Opts,omitempty"` @@ -527,7 +529,9 @@ func setupRancherFlexVolume(instance model.Instance, hostConfig *container.HostC func unmountRancherFlexVolume(instance model.Instance) error { for _, volume := range instance.VolumesFromDataVolumeMounts { - if storage.IsRancherVolume(volume) { + if ok, err := storage.IsRancherVolume(volume); err != nil { + return err + } else if ok { payload := struct{ Name string }{Name: volume.Name} _, err := storage.CallRancherStorageVolumePlugin(volume, storage.Unmount, payload) if err != nil { diff --git a/core/storage/volume.go b/core/storage/volume.go index f8c0e23b..9e382f3a 100755 --- a/core/storage/volume.go +++ b/core/storage/volume.go @@ -252,11 +252,31 @@ func rancherStorageSockPath(volume model.Volume) string { return filepath.Join(rancherSockDir, volume.Data.Fields.Driver+".sock") } -func IsRancherVolume(volume model.Volume) bool { +// a volume will be considered a flex volume if it is in rancherDrivers and the capability is flex +// raise an error if its rancher-managed driver but the socket file is not available +func IsRancherVolume(volume model.Volume) (bool, error) { if _, ok := rancherDrivers[volume.Data.Fields.Driver]; ok { - return true + if _, err := os.Stat(rancherStorageSockPath(volume)); err == nil { + // check if Capabilities is flex + payload := struct { + Name string + Options map[string]string `json:"Opts,omitempty"` + }{ + Name: volume.Name, + Options: volume.Data.Fields.DriverOpts, + } + response, err := CallRancherStorageVolumePlugin(volume, Capabilities, payload) + if err != nil { + return false, err + } + if response.Capabilities.Scope == "flex" { + return true, nil + } + return false, nil + } + return false, errors.Errorf("socket file not found at %s", rancherStorageSockPath(volume)) } - return false + return false, nil } func IsVolumeRemoved(volume model.Volume, storagePool model.StoragePool, client *engineCli.Client) (bool, error) { diff --git a/handlers/storage.go b/handlers/storage.go index 0d676fd2..a94a0b20 100644 --- a/handlers/storage.go +++ b/handlers/storage.go @@ -68,7 +68,9 @@ func (h *StorageHandler) VolumeActivate(event *revents.Event, cli *client.Ranche progress := utils.GetProgress(event, cli) // if its rancher volume, use flexVolume and bypass docker volume plugin - if storage.IsRancherVolume(volume) { + if ok, err := storage.IsRancherVolume(volume); err != nil { + return err + } else if ok { err := storage.VolumeActivateFlex(volume) if err != nil { return err @@ -93,7 +95,9 @@ func (h *StorageHandler) VolumeRemove(event *revents.Event, cli *client.RancherC storagePool := volumeStoragePoolMap.StoragePool progress := utils.GetProgress(event, cli) - if storage.IsRancherVolume(volume) { + if ok, err := storage.IsRancherVolume(volume); err != nil { + return err + } else if ok { // we need to make sure the reference is cleaned up in docker, so if it exists in docker then clean up in docker first if inspect, err := h.dockerClient.VolumeInspect(context.Background(), volume.Name); err != nil && !engineCli.IsErrVolumeNotFound(err) { return errors.Wrapf(err, constants.VolumeRemoveError+"failed to inspect volume %v", volume.Name)