Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
57
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/BUILD
generated
vendored
Normal file
57
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"actual_state_of_world.go",
|
||||
"desired_state_of_world.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util/operationexecutor:go_default_library",
|
||||
"//pkg/volume/util/types:go_default_library",
|
||||
"//pkg/volume/util/volumehelper:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"actual_state_of_world_test.go",
|
||||
"desired_state_of_world_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api/v1:go_default_library",
|
||||
"//pkg/controller/volume/attachdetach/testing:go_default_library",
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//pkg/volume/util/types:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/types",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
615
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/actual_state_of_world.go
generated
vendored
Normal file
615
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/actual_state_of_world.go
generated
vendored
Normal file
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package cache implements data structures used by the attach/detach controller
|
||||
to keep track of volumes, the nodes they are attached to, and the pods that
|
||||
reference them.
|
||||
*/
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
)
|
||||
|
||||
// ActualStateOfWorld defines a set of thread-safe operations supported on
|
||||
// the attach/detach controller's actual state of the world cache.
|
||||
// This cache contains volumes->nodes i.e. a set of all volumes and the nodes
|
||||
// the attach/detach controller believes are successfully attached.
|
||||
// Note: This is distinct from the ActualStateOfWorld implemented by the kubelet
|
||||
// volume manager. They both keep track of different objects. This contains
|
||||
// attach/detach controller specific state.
|
||||
type ActualStateOfWorld interface {
|
||||
// ActualStateOfWorld must implement the methods required to allow
|
||||
// operationexecutor to interact with it.
|
||||
operationexecutor.ActualStateOfWorldAttacherUpdater
|
||||
|
||||
// AddVolumeNode adds the given volume and node to the underlying store
|
||||
// indicating the specified volume is attached to the specified node.
|
||||
// A unique volume name is generated from the volumeSpec and returned on
|
||||
// success.
|
||||
// If volumeSpec is not an attachable volume plugin, an error is returned.
|
||||
// If no volume with the name volumeName exists in the store, the volume is
|
||||
// added.
|
||||
// If no node with the name nodeName exists in list of attached nodes for
|
||||
// the specified volume, the node is added.
|
||||
AddVolumeNode(volumeSpec *volume.Spec, nodeName types.NodeName, devicePath string) (v1.UniqueVolumeName, error)
|
||||
|
||||
// SetVolumeMountedByNode sets the MountedByNode value for the given volume
|
||||
// and node. When set to true this value indicates the volume is mounted by
|
||||
// the given node, indicating it may not be safe to detach.
|
||||
// If no volume with the name volumeName exists in the store, an error is
|
||||
// returned.
|
||||
// If no node with the name nodeName exists in list of attached nodes for
|
||||
// the specified volume, an error is returned.
|
||||
SetVolumeMountedByNode(volumeName v1.UniqueVolumeName, nodeName types.NodeName, mounted bool) error
|
||||
|
||||
// SetNodeStatusUpdateNeeded sets statusUpdateNeeded for the specified
|
||||
// node to true indicating the AttachedVolume field in the Node's Status
|
||||
// object needs to be updated by the node updater again.
|
||||
// If the specifed node does not exist in the nodesToUpdateStatusFor list,
|
||||
// log the error and return
|
||||
SetNodeStatusUpdateNeeded(nodeName types.NodeName)
|
||||
|
||||
// ResetDetachRequestTime resets the detachRequestTime to 0 which indicates there is no detach
|
||||
// request any more for the volume
|
||||
ResetDetachRequestTime(volumeName v1.UniqueVolumeName, nodeName types.NodeName)
|
||||
|
||||
// SetDetachRequestTime sets the detachRequestedTime to current time if this is no
|
||||
// previous request (the previous detachRequestedTime is zero) and return the time elapsed
|
||||
// since last request
|
||||
SetDetachRequestTime(volumeName v1.UniqueVolumeName, nodeName types.NodeName) (time.Duration, error)
|
||||
|
||||
// DeleteVolumeNode removes the given volume and node from the underlying
|
||||
// store indicating the specified volume is no longer attached to the
|
||||
// specified node.
|
||||
// If the volume/node combo does not exist, this is a no-op.
|
||||
// If after deleting the node, the specified volume contains no other child
|
||||
// nodes, the volume is also deleted.
|
||||
DeleteVolumeNode(volumeName v1.UniqueVolumeName, nodeName types.NodeName)
|
||||
|
||||
// VolumeNodeExists returns true if the specified volume/node combo exists
|
||||
// in the underlying store indicating the specified volume is attached to
|
||||
// the specified node.
|
||||
VolumeNodeExists(volumeName v1.UniqueVolumeName, nodeName types.NodeName) bool
|
||||
|
||||
// GetAttachedVolumes generates and returns a list of volumes/node pairs
|
||||
// reflecting which volumes are attached to which nodes based on the
|
||||
// current actual state of the world.
|
||||
GetAttachedVolumes() []AttachedVolume
|
||||
|
||||
// GetAttachedVolumes generates and returns a list of volumes attached to
|
||||
// the specified node reflecting which volumes are attached to that node
|
||||
// based on the current actual state of the world.
|
||||
GetAttachedVolumesForNode(nodeName types.NodeName) []AttachedVolume
|
||||
|
||||
GetAttachedVolumesPerNode() map[types.NodeName][]operationexecutor.AttachedVolume
|
||||
|
||||
// GetVolumesToReportAttached returns a map containing the set of nodes for
|
||||
// which the VolumesAttached Status field in the Node API object should be
|
||||
// updated. The key in this map is the name of the node to update and the
|
||||
// value is list of volumes that should be reported as attached (note that
|
||||
// this may differ from the actual list of attached volumes for the node
|
||||
// since volumes should be removed from this list as soon a detach operation
|
||||
// is considered, before the detach operation is triggered).
|
||||
GetVolumesToReportAttached() map[types.NodeName][]v1.AttachedVolume
|
||||
|
||||
// GetNodesToUpdateStatusFor returns the map of nodeNames to nodeToUpdateStatusFor
|
||||
GetNodesToUpdateStatusFor() map[types.NodeName]nodeToUpdateStatusFor
|
||||
}
|
||||
|
||||
// AttachedVolume represents a volume that is attached to a node.
|
||||
type AttachedVolume struct {
|
||||
operationexecutor.AttachedVolume
|
||||
|
||||
// MountedByNode indicates that this volume has been been mounted by the
|
||||
// node and is unsafe to detach.
|
||||
// The value is set and unset by SetVolumeMountedByNode(...).
|
||||
MountedByNode bool
|
||||
|
||||
// DetachRequestedTime is used to capture the desire to detach this volume.
|
||||
// When the volume is newly created this value is set to time zero.
|
||||
// It is set to current time, when SetDetachRequestTime(...) is called, if it
|
||||
// was previously set to zero (other wise its value remains the same).
|
||||
// It is reset to zero on ResetDetachRequestTime(...) calls.
|
||||
DetachRequestedTime time.Time
|
||||
}
|
||||
|
||||
// NewActualStateOfWorld returns a new instance of ActualStateOfWorld.
|
||||
func NewActualStateOfWorld(volumePluginMgr *volume.VolumePluginMgr) ActualStateOfWorld {
|
||||
return &actualStateOfWorld{
|
||||
attachedVolumes: make(map[v1.UniqueVolumeName]attachedVolume),
|
||||
nodesToUpdateStatusFor: make(map[types.NodeName]nodeToUpdateStatusFor),
|
||||
volumePluginMgr: volumePluginMgr,
|
||||
}
|
||||
}
|
||||
|
||||
type actualStateOfWorld struct {
|
||||
// attachedVolumes is a map containing the set of volumes the attach/detach
|
||||
// controller believes to be successfully attached to the nodes it is
|
||||
// managing. The key in this map is the name of the volume and the value is
|
||||
// an object containing more information about the attached volume.
|
||||
attachedVolumes map[v1.UniqueVolumeName]attachedVolume
|
||||
|
||||
// nodesToUpdateStatusFor is a map containing the set of nodes for which to
|
||||
// update the VolumesAttached Status field. The key in this map is the name
|
||||
// of the node and the value is an object containing more information about
|
||||
// the node (including the list of volumes to report attached).
|
||||
nodesToUpdateStatusFor map[types.NodeName]nodeToUpdateStatusFor
|
||||
|
||||
// volumePluginMgr is the volume plugin manager used to create volume
|
||||
// plugin objects.
|
||||
volumePluginMgr *volume.VolumePluginMgr
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// The volume object represents a volume the the attach/detach controller
|
||||
// believes to be successfully attached to a node it is managing.
|
||||
type attachedVolume struct {
|
||||
// volumeName contains the unique identifier for this volume.
|
||||
volumeName v1.UniqueVolumeName
|
||||
|
||||
// spec is the volume spec containing the specification for this volume.
|
||||
// Used to generate the volume plugin object, and passed to attach/detach
|
||||
// methods.
|
||||
spec *volume.Spec
|
||||
|
||||
// nodesAttachedTo is a map containing the set of nodes this volume has
|
||||
// successfully been attached to. The key in this map is the name of the
|
||||
// node and the value is a node object containing more information about
|
||||
// the node.
|
||||
nodesAttachedTo map[types.NodeName]nodeAttachedTo
|
||||
|
||||
// devicePath contains the path on the node where the volume is attached
|
||||
devicePath string
|
||||
}
|
||||
|
||||
// The nodeAttachedTo object represents a node that has volumes attached to it.
|
||||
type nodeAttachedTo struct {
|
||||
// nodeName contains the name of this node.
|
||||
nodeName types.NodeName
|
||||
|
||||
// mountedByNode indicates that this node/volume combo is mounted by the
|
||||
// node and is unsafe to detach
|
||||
mountedByNode bool
|
||||
|
||||
// number of times SetVolumeMountedByNode has been called to set the value
|
||||
// of mountedByNode to true. This is used to prevent mountedByNode from
|
||||
// being reset during the period between attach and mount when volumesInUse
|
||||
// status for the node may not be set.
|
||||
mountedByNodeSetCount uint
|
||||
|
||||
// detachRequestedTime used to capture the desire to detach this volume
|
||||
detachRequestedTime time.Time
|
||||
}
|
||||
|
||||
// nodeToUpdateStatusFor is an object that reflects a node that has one or more
|
||||
// volume attached. It keeps track of the volumes that should be reported as
|
||||
// attached in the Node's Status API object.
|
||||
type nodeToUpdateStatusFor struct {
|
||||
// nodeName contains the name of this node.
|
||||
nodeName types.NodeName
|
||||
|
||||
// statusUpdateNeeded indicates that the value of the VolumesAttached field
|
||||
// in the Node's Status API object should be updated. This should be set to
|
||||
// true whenever a volume is added or deleted from
|
||||
// volumesToReportAsAttached. It should be reset whenever the status is
|
||||
// updated.
|
||||
statusUpdateNeeded bool
|
||||
|
||||
// volumesToReportAsAttached is the list of volumes that should be reported
|
||||
// as attached in the Node's status (note that this may differ from the
|
||||
// actual list of attached volumes since volumes should be removed from this
|
||||
// list as soon a detach operation is considered, before the detach
|
||||
// operation is triggered).
|
||||
volumesToReportAsAttached map[v1.UniqueVolumeName]v1.UniqueVolumeName
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) MarkVolumeAsAttached(
|
||||
_ v1.UniqueVolumeName, volumeSpec *volume.Spec, nodeName types.NodeName, devicePath string) error {
|
||||
_, err := asw.AddVolumeNode(volumeSpec, nodeName, devicePath)
|
||||
return err
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) MarkVolumeAsDetached(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
|
||||
asw.DeleteVolumeNode(volumeName, nodeName)
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) RemoveVolumeFromReportAsAttached(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) error {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
return asw.removeVolumeFromReportAsAttached(volumeName, nodeName)
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) AddVolumeToReportAsAttached(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
asw.addVolumeToReportAsAttached(volumeName, nodeName)
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) AddVolumeNode(
|
||||
volumeSpec *volume.Spec, nodeName types.NodeName, devicePath string) (v1.UniqueVolumeName, error) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
|
||||
attachableVolumePlugin, err := asw.volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return "", fmt.Errorf(
|
||||
"failed to get AttachablePlugin from volumeSpec for volume %q err=%v",
|
||||
volumeSpec.Name(),
|
||||
err)
|
||||
}
|
||||
|
||||
volumeName, err := volumehelper.GetUniqueVolumeNameFromSpec(
|
||||
attachableVolumePlugin, volumeSpec)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(
|
||||
"failed to GetUniqueVolumeNameFromSpec for volumeSpec %q err=%v",
|
||||
volumeSpec.Name(),
|
||||
err)
|
||||
}
|
||||
|
||||
volumeObj, volumeExists := asw.attachedVolumes[volumeName]
|
||||
if !volumeExists {
|
||||
volumeObj = attachedVolume{
|
||||
volumeName: volumeName,
|
||||
spec: volumeSpec,
|
||||
nodesAttachedTo: make(map[types.NodeName]nodeAttachedTo),
|
||||
devicePath: devicePath,
|
||||
}
|
||||
} else {
|
||||
// If volume object already exists, it indicates that the information would be out of date.
|
||||
// Update the fields for volume object except the nodes attached to the volumes.
|
||||
volumeObj.devicePath = devicePath
|
||||
volumeObj.spec = volumeSpec
|
||||
glog.V(2).Infof("Volume %q is already added to attachedVolume list to node %q, update device path %q",
|
||||
volumeName,
|
||||
nodeName,
|
||||
devicePath)
|
||||
}
|
||||
asw.attachedVolumes[volumeName] = volumeObj
|
||||
|
||||
_, nodeExists := volumeObj.nodesAttachedTo[nodeName]
|
||||
if !nodeExists {
|
||||
// Create object if it doesn't exist.
|
||||
volumeObj.nodesAttachedTo[nodeName] = nodeAttachedTo{
|
||||
nodeName: nodeName,
|
||||
mountedByNode: true, // Assume mounted, until proven otherwise
|
||||
mountedByNodeSetCount: 0,
|
||||
detachRequestedTime: time.Time{},
|
||||
}
|
||||
} else {
|
||||
glog.V(5).Infof("Volume %q is already added to attachedVolume list to the node %q",
|
||||
volumeName,
|
||||
nodeName)
|
||||
}
|
||||
|
||||
asw.addVolumeToReportAsAttached(volumeName, nodeName)
|
||||
return volumeName, nil
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) SetVolumeMountedByNode(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName, mounted bool) error {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
|
||||
volumeObj, nodeObj, err := asw.getNodeAndVolume(volumeName, nodeName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to SetVolumeMountedByNode with error: %v", err)
|
||||
}
|
||||
|
||||
if mounted {
|
||||
// Increment set count
|
||||
nodeObj.mountedByNodeSetCount = nodeObj.mountedByNodeSetCount + 1
|
||||
} else {
|
||||
// Do not allow value to be reset unless it has been set at least once
|
||||
if nodeObj.mountedByNodeSetCount == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
nodeObj.mountedByNode = mounted
|
||||
volumeObj.nodesAttachedTo[nodeName] = nodeObj
|
||||
glog.V(4).Infof("SetVolumeMountedByNode volume %v to the node %q mounted %t",
|
||||
volumeName,
|
||||
nodeName,
|
||||
mounted)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) ResetDetachRequestTime(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
|
||||
volumeObj, nodeObj, err := asw.getNodeAndVolume(volumeName, nodeName)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to ResetDetachRequestTime with error: %v", err)
|
||||
return
|
||||
}
|
||||
nodeObj.detachRequestedTime = time.Time{}
|
||||
volumeObj.nodesAttachedTo[nodeName] = nodeObj
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) SetDetachRequestTime(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) (time.Duration, error) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
|
||||
volumeObj, nodeObj, err := asw.getNodeAndVolume(volumeName, nodeName)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("Failed to set detach request time with error: %v", err)
|
||||
}
|
||||
// If there is no previous detach request, set it to the current time
|
||||
if nodeObj.detachRequestedTime.IsZero() {
|
||||
nodeObj.detachRequestedTime = time.Now()
|
||||
volumeObj.nodesAttachedTo[nodeName] = nodeObj
|
||||
glog.V(4).Infof("Set detach request time to current time for volume %v on node %q",
|
||||
volumeName,
|
||||
nodeName)
|
||||
}
|
||||
return time.Since(nodeObj.detachRequestedTime), nil
|
||||
}
|
||||
|
||||
// Get the volume and node object from actual state of world
|
||||
// This is an internal function and caller should acquire and release the lock
|
||||
func (asw *actualStateOfWorld) getNodeAndVolume(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) (attachedVolume, nodeAttachedTo, error) {
|
||||
|
||||
volumeObj, volumeExists := asw.attachedVolumes[volumeName]
|
||||
if volumeExists {
|
||||
nodeObj, nodeExists := volumeObj.nodesAttachedTo[nodeName]
|
||||
if nodeExists {
|
||||
return volumeObj, nodeObj, nil
|
||||
}
|
||||
}
|
||||
|
||||
return attachedVolume{}, nodeAttachedTo{}, fmt.Errorf("volume %v is no longer attached to the node %q",
|
||||
volumeName,
|
||||
nodeName)
|
||||
}
|
||||
|
||||
// Remove the volumeName from the node's volumesToReportAsAttached list
|
||||
// This is an internal function and caller should acquire and release the lock
|
||||
func (asw *actualStateOfWorld) removeVolumeFromReportAsAttached(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) error {
|
||||
|
||||
nodeToUpdate, nodeToUpdateExists := asw.nodesToUpdateStatusFor[nodeName]
|
||||
if nodeToUpdateExists {
|
||||
_, nodeToUpdateVolumeExists :=
|
||||
nodeToUpdate.volumesToReportAsAttached[volumeName]
|
||||
if nodeToUpdateVolumeExists {
|
||||
nodeToUpdate.statusUpdateNeeded = true
|
||||
delete(nodeToUpdate.volumesToReportAsAttached, volumeName)
|
||||
asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("volume %q or node %q does not exist in volumesToReportAsAttached list",
|
||||
volumeName,
|
||||
nodeName)
|
||||
|
||||
}
|
||||
|
||||
// Add the volumeName to the node's volumesToReportAsAttached list
|
||||
// This is an internal function and caller should acquire and release the lock
|
||||
func (asw *actualStateOfWorld) addVolumeToReportAsAttached(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
|
||||
// In case the volume/node entry is no longer in attachedVolume list, skip the rest
|
||||
if _, _, err := asw.getNodeAndVolume(volumeName, nodeName); err != nil {
|
||||
glog.V(4).Infof("Volume %q is no longer attached to node %q", volumeName, nodeName)
|
||||
return
|
||||
}
|
||||
nodeToUpdate, nodeToUpdateExists := asw.nodesToUpdateStatusFor[nodeName]
|
||||
if !nodeToUpdateExists {
|
||||
// Create object if it doesn't exist
|
||||
nodeToUpdate = nodeToUpdateStatusFor{
|
||||
nodeName: nodeName,
|
||||
statusUpdateNeeded: true,
|
||||
volumesToReportAsAttached: make(map[v1.UniqueVolumeName]v1.UniqueVolumeName),
|
||||
}
|
||||
asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate
|
||||
glog.V(4).Infof("Add new node %q to nodesToUpdateStatusFor", nodeName)
|
||||
}
|
||||
_, nodeToUpdateVolumeExists :=
|
||||
nodeToUpdate.volumesToReportAsAttached[volumeName]
|
||||
if !nodeToUpdateVolumeExists {
|
||||
nodeToUpdate.statusUpdateNeeded = true
|
||||
nodeToUpdate.volumesToReportAsAttached[volumeName] = volumeName
|
||||
asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate
|
||||
glog.V(4).Infof("Report volume %q as attached to node %q", volumeName, nodeName)
|
||||
}
|
||||
}
|
||||
|
||||
// Update the flag statusUpdateNeeded to indicate whether node status is already updated or
|
||||
// needs to be updated again by the node status updater.
|
||||
// If the specifed node does not exist in the nodesToUpdateStatusFor list, log the error and return
|
||||
// This is an internal function and caller should acquire and release the lock
|
||||
func (asw *actualStateOfWorld) updateNodeStatusUpdateNeeded(nodeName types.NodeName, needed bool) {
|
||||
nodeToUpdate, nodeToUpdateExists := asw.nodesToUpdateStatusFor[nodeName]
|
||||
if !nodeToUpdateExists {
|
||||
// should not happen
|
||||
glog.Errorf(
|
||||
"Failed to set statusUpdateNeeded to needed %t because nodeName=%q does not exist",
|
||||
needed,
|
||||
nodeName)
|
||||
return
|
||||
}
|
||||
|
||||
nodeToUpdate.statusUpdateNeeded = needed
|
||||
asw.nodesToUpdateStatusFor[nodeName] = nodeToUpdate
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) SetNodeStatusUpdateNeeded(nodeName types.NodeName) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
asw.updateNodeStatusUpdateNeeded(nodeName, true)
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) DeleteVolumeNode(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) {
|
||||
asw.Lock()
|
||||
defer asw.Unlock()
|
||||
|
||||
volumeObj, volumeExists := asw.attachedVolumes[volumeName]
|
||||
if !volumeExists {
|
||||
return
|
||||
}
|
||||
|
||||
_, nodeExists := volumeObj.nodesAttachedTo[nodeName]
|
||||
if nodeExists {
|
||||
delete(asw.attachedVolumes[volumeName].nodesAttachedTo, nodeName)
|
||||
}
|
||||
|
||||
if len(volumeObj.nodesAttachedTo) == 0 {
|
||||
delete(asw.attachedVolumes, volumeName)
|
||||
}
|
||||
|
||||
// Remove volume from volumes to report as attached
|
||||
asw.removeVolumeFromReportAsAttached(volumeName, nodeName)
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) VolumeNodeExists(
|
||||
volumeName v1.UniqueVolumeName, nodeName types.NodeName) bool {
|
||||
asw.RLock()
|
||||
defer asw.RUnlock()
|
||||
|
||||
volumeObj, volumeExists := asw.attachedVolumes[volumeName]
|
||||
if volumeExists {
|
||||
if _, nodeExists := volumeObj.nodesAttachedTo[nodeName]; nodeExists {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) GetAttachedVolumes() []AttachedVolume {
|
||||
asw.RLock()
|
||||
defer asw.RUnlock()
|
||||
|
||||
attachedVolumes := make([]AttachedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
|
||||
for _, volumeObj := range asw.attachedVolumes {
|
||||
for _, nodeObj := range volumeObj.nodesAttachedTo {
|
||||
attachedVolumes = append(
|
||||
attachedVolumes,
|
||||
getAttachedVolume(&volumeObj, &nodeObj))
|
||||
}
|
||||
}
|
||||
|
||||
return attachedVolumes
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) GetAttachedVolumesForNode(
|
||||
nodeName types.NodeName) []AttachedVolume {
|
||||
asw.RLock()
|
||||
defer asw.RUnlock()
|
||||
|
||||
attachedVolumes := make(
|
||||
[]AttachedVolume, 0 /* len */, len(asw.attachedVolumes) /* cap */)
|
||||
for _, volumeObj := range asw.attachedVolumes {
|
||||
for actualNodeName, nodeObj := range volumeObj.nodesAttachedTo {
|
||||
if actualNodeName == nodeName {
|
||||
attachedVolumes = append(
|
||||
attachedVolumes,
|
||||
getAttachedVolume(&volumeObj, &nodeObj))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return attachedVolumes
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) GetAttachedVolumesPerNode() map[types.NodeName][]operationexecutor.AttachedVolume {
|
||||
asw.RLock()
|
||||
defer asw.RUnlock()
|
||||
|
||||
attachedVolumesPerNode := make(map[types.NodeName][]operationexecutor.AttachedVolume)
|
||||
for _, volumeObj := range asw.attachedVolumes {
|
||||
for nodeName, nodeObj := range volumeObj.nodesAttachedTo {
|
||||
volumes, exists := attachedVolumesPerNode[nodeName]
|
||||
if !exists {
|
||||
volumes = []operationexecutor.AttachedVolume{}
|
||||
}
|
||||
volumes = append(volumes, getAttachedVolume(&volumeObj, &nodeObj).AttachedVolume)
|
||||
attachedVolumesPerNode[nodeName] = volumes
|
||||
}
|
||||
}
|
||||
|
||||
return attachedVolumesPerNode
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) GetVolumesToReportAttached() map[types.NodeName][]v1.AttachedVolume {
|
||||
asw.RLock()
|
||||
defer asw.RUnlock()
|
||||
|
||||
volumesToReportAttached := make(map[types.NodeName][]v1.AttachedVolume)
|
||||
for nodeName, nodeToUpdateObj := range asw.nodesToUpdateStatusFor {
|
||||
if nodeToUpdateObj.statusUpdateNeeded {
|
||||
attachedVolumes := make(
|
||||
[]v1.AttachedVolume,
|
||||
len(nodeToUpdateObj.volumesToReportAsAttached) /* len */)
|
||||
i := 0
|
||||
for _, volume := range nodeToUpdateObj.volumesToReportAsAttached {
|
||||
attachedVolumes[i] = v1.AttachedVolume{
|
||||
Name: volume,
|
||||
DevicePath: asw.attachedVolumes[volume].devicePath,
|
||||
}
|
||||
i++
|
||||
}
|
||||
volumesToReportAttached[nodeToUpdateObj.nodeName] = attachedVolumes
|
||||
}
|
||||
// When GetVolumesToReportAttached is called by node status updater, the current status
|
||||
// of this node will be updated, so set the flag statusUpdateNeeded to false indicating
|
||||
// the current status is already updated.
|
||||
asw.updateNodeStatusUpdateNeeded(nodeName, false)
|
||||
}
|
||||
|
||||
return volumesToReportAttached
|
||||
}
|
||||
|
||||
func (asw *actualStateOfWorld) GetNodesToUpdateStatusFor() map[types.NodeName]nodeToUpdateStatusFor {
|
||||
return asw.nodesToUpdateStatusFor
|
||||
}
|
||||
|
||||
func getAttachedVolume(
|
||||
attachedVolume *attachedVolume,
|
||||
nodeAttachedTo *nodeAttachedTo) AttachedVolume {
|
||||
return AttachedVolume{
|
||||
AttachedVolume: operationexecutor.AttachedVolume{
|
||||
VolumeName: attachedVolume.volumeName,
|
||||
VolumeSpec: attachedVolume.spec,
|
||||
NodeName: nodeAttachedTo.nodeName,
|
||||
DevicePath: attachedVolume.devicePath,
|
||||
PluginIsAttachable: true,
|
||||
},
|
||||
MountedByNode: nodeAttachedTo.mountedByNode,
|
||||
DetachRequestedTime: nodeAttachedTo.detachRequestedTime}
|
||||
}
|
1144
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/actual_state_of_world_test.go
generated
vendored
Normal file
1144
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/actual_state_of_world_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
363
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/desired_state_of_world.go
generated
vendored
Normal file
363
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/desired_state_of_world.go
generated
vendored
Normal file
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Package cache implements data structures used by the attach/detach controller
|
||||
to keep track of volumes, the nodes they are attached to, and the pods that
|
||||
reference them.
|
||||
*/
|
||||
package cache
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util/operationexecutor"
|
||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumehelper"
|
||||
)
|
||||
|
||||
// DesiredStateOfWorld defines a set of thread-safe operations supported on
|
||||
// the attach/detach controller's desired state of the world cache.
|
||||
// This cache contains nodes->volumes->pods where nodes are all the nodes
|
||||
// managed by the attach/detach controller, volumes are all the volumes that
|
||||
// should be attached to the specified node, and pods are the pods that
|
||||
// reference the volume and are scheduled to that node.
|
||||
// Note: This is distinct from the DesiredStateOfWorld implemented by the
|
||||
// kubelet volume manager. The both keep track of different objects. This
|
||||
// contains attach/detach controller specific state.
|
||||
type DesiredStateOfWorld interface {
|
||||
// AddNode adds the given node to the list of nodes managed by the attach/
|
||||
// detach controller.
|
||||
// If the node already exists this is a no-op.
|
||||
AddNode(nodeName k8stypes.NodeName)
|
||||
|
||||
// AddPod adds the given pod to the list of pods that reference the
|
||||
// specified volume and is scheduled to the specified node.
|
||||
// A unique volumeName is generated from the volumeSpec and returned on
|
||||
// success.
|
||||
// If the pod already exists under the specified volume, this is a no-op.
|
||||
// If volumeSpec is not an attachable volume plugin, an error is returned.
|
||||
// If no volume with the name volumeName exists in the list of volumes that
|
||||
// should be attached to the specified node, the volume is implicitly added.
|
||||
// If no node with the name nodeName exists in list of nodes managed by the
|
||||
// attach/detach attached controller, an error is returned.
|
||||
AddPod(podName types.UniquePodName, pod *v1.Pod, volumeSpec *volume.Spec, nodeName k8stypes.NodeName) (v1.UniqueVolumeName, error)
|
||||
|
||||
// DeleteNode removes the given node from the list of nodes managed by the
|
||||
// attach/detach controller.
|
||||
// If the node does not exist this is a no-op.
|
||||
// If the node exists but has 1 or more child volumes, an error is returned.
|
||||
DeleteNode(nodeName k8stypes.NodeName) error
|
||||
|
||||
// DeletePod removes the given pod from the list of pods that reference the
|
||||
// specified volume and are scheduled to the specified node.
|
||||
// If no pod exists in the list of pods that reference the specified volume
|
||||
// and are scheduled to the specified node, this is a no-op.
|
||||
// If a node with the name nodeName does not exist in the list of nodes
|
||||
// managed by the attach/detach attached controller, this is a no-op.
|
||||
// If no volume with the name volumeName exists in the list of managed
|
||||
// volumes under the specified node, this is a no-op.
|
||||
// If after deleting the pod, the specified volume contains no other child
|
||||
// pods, the volume is also deleted.
|
||||
DeletePod(podName types.UniquePodName, volumeName v1.UniqueVolumeName, nodeName k8stypes.NodeName)
|
||||
|
||||
// NodeExists returns true if the node with the specified name exists in
|
||||
// the list of nodes managed by the attach/detach controller.
|
||||
NodeExists(nodeName k8stypes.NodeName) bool
|
||||
|
||||
// VolumeExists returns true if the volume with the specified name exists
|
||||
// in the list of volumes that should be attached to the specified node by
|
||||
// the attach detach controller.
|
||||
VolumeExists(volumeName v1.UniqueVolumeName, nodeName k8stypes.NodeName) bool
|
||||
|
||||
// GetVolumesToAttach generates and returns a list of volumes to attach
|
||||
// and the nodes they should be attached to based on the current desired
|
||||
// state of the world.
|
||||
GetVolumesToAttach() []VolumeToAttach
|
||||
|
||||
// GetPodToAdd generates and returns a map of pods based on the current desired
|
||||
// state of world
|
||||
GetPodToAdd() map[types.UniquePodName]PodToAdd
|
||||
}
|
||||
|
||||
// VolumeToAttach represents a volume that should be attached to a node.
|
||||
type VolumeToAttach struct {
|
||||
operationexecutor.VolumeToAttach
|
||||
}
|
||||
|
||||
// PodToAdd represents a pod that references the underlying volume and is
|
||||
// scheduled to the underlying node.
|
||||
type PodToAdd struct {
|
||||
// pod contains the api object of pod
|
||||
Pod *v1.Pod
|
||||
|
||||
// volumeName contains the unique identifier for this volume.
|
||||
VolumeName v1.UniqueVolumeName
|
||||
|
||||
// nodeName contains the name of this node.
|
||||
NodeName k8stypes.NodeName
|
||||
}
|
||||
|
||||
// NewDesiredStateOfWorld returns a new instance of DesiredStateOfWorld.
|
||||
func NewDesiredStateOfWorld(volumePluginMgr *volume.VolumePluginMgr) DesiredStateOfWorld {
|
||||
return &desiredStateOfWorld{
|
||||
nodesManaged: make(map[k8stypes.NodeName]nodeManaged),
|
||||
volumePluginMgr: volumePluginMgr,
|
||||
}
|
||||
}
|
||||
|
||||
type desiredStateOfWorld struct {
|
||||
// nodesManaged is a map containing the set of nodes managed by the attach/
|
||||
// detach controller. The key in this map is the name of the node and the
|
||||
// value is a node object containing more information about the node.
|
||||
nodesManaged map[k8stypes.NodeName]nodeManaged
|
||||
// volumePluginMgr is the volume plugin manager used to create volume
|
||||
// plugin objects.
|
||||
volumePluginMgr *volume.VolumePluginMgr
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// nodeManaged represents a node that is being managed by the attach/detach
|
||||
// controller.
|
||||
type nodeManaged struct {
|
||||
// nodeName contains the name of this node.
|
||||
nodeName k8stypes.NodeName
|
||||
|
||||
// volumesToAttach is a map containing the set of volumes that should be
|
||||
// attached to this node. The key in the map is the name of the volume and
|
||||
// the value is a pod object containing more information about the volume.
|
||||
volumesToAttach map[v1.UniqueVolumeName]volumeToAttach
|
||||
}
|
||||
|
||||
// The volume object represents a volume that should be attached to a node.
|
||||
type volumeToAttach struct {
|
||||
// volumeName contains the unique identifier for this volume.
|
||||
volumeName v1.UniqueVolumeName
|
||||
|
||||
// spec is the volume spec containing the specification for this volume.
|
||||
// Used to generate the volume plugin object, and passed to attach/detach
|
||||
// methods.
|
||||
spec *volume.Spec
|
||||
|
||||
// scheduledPods is a map containing the set of pods that reference this
|
||||
// volume and are scheduled to the underlying node. The key in the map is
|
||||
// the name of the pod and the value is a pod object containing more
|
||||
// information about the pod.
|
||||
scheduledPods map[types.UniquePodName]pod
|
||||
}
|
||||
|
||||
// The pod represents a pod that references the underlying volume and is
|
||||
// scheduled to the underlying node.
|
||||
type pod struct {
|
||||
// podName contains the unique identifier for this pod
|
||||
podName types.UniquePodName
|
||||
|
||||
// pod object contains the api object of pod
|
||||
podObj *v1.Pod
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) AddNode(nodeName k8stypes.NodeName) {
|
||||
dsw.Lock()
|
||||
defer dsw.Unlock()
|
||||
|
||||
if _, nodeExists := dsw.nodesManaged[nodeName]; !nodeExists {
|
||||
dsw.nodesManaged[nodeName] = nodeManaged{
|
||||
nodeName: nodeName,
|
||||
volumesToAttach: make(map[v1.UniqueVolumeName]volumeToAttach),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) AddPod(
|
||||
podName types.UniquePodName,
|
||||
podToAdd *v1.Pod,
|
||||
volumeSpec *volume.Spec,
|
||||
nodeName k8stypes.NodeName) (v1.UniqueVolumeName, error) {
|
||||
dsw.Lock()
|
||||
defer dsw.Unlock()
|
||||
|
||||
nodeObj, nodeExists := dsw.nodesManaged[nodeName]
|
||||
if !nodeExists {
|
||||
return "", fmt.Errorf(
|
||||
"no node with the name %q exists in the list of managed nodes",
|
||||
nodeName)
|
||||
}
|
||||
|
||||
attachableVolumePlugin, err := dsw.volumePluginMgr.FindAttachablePluginBySpec(volumeSpec)
|
||||
if err != nil || attachableVolumePlugin == nil {
|
||||
return "", fmt.Errorf(
|
||||
"failed to get AttachablePlugin from volumeSpec for volume %q err=%v",
|
||||
volumeSpec.Name(),
|
||||
err)
|
||||
}
|
||||
|
||||
volumeName, err := volumehelper.GetUniqueVolumeNameFromSpec(
|
||||
attachableVolumePlugin, volumeSpec)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(
|
||||
"failed to GetUniqueVolumeNameFromSpec for volumeSpec %q err=%v",
|
||||
volumeSpec.Name(),
|
||||
err)
|
||||
}
|
||||
|
||||
volumeObj, volumeExists := nodeObj.volumesToAttach[volumeName]
|
||||
if !volumeExists {
|
||||
volumeObj = volumeToAttach{
|
||||
volumeName: volumeName,
|
||||
spec: volumeSpec,
|
||||
scheduledPods: make(map[types.UniquePodName]pod),
|
||||
}
|
||||
dsw.nodesManaged[nodeName].volumesToAttach[volumeName] = volumeObj
|
||||
}
|
||||
if _, podExists := volumeObj.scheduledPods[podName]; !podExists {
|
||||
dsw.nodesManaged[nodeName].volumesToAttach[volumeName].scheduledPods[podName] =
|
||||
pod{
|
||||
podName: podName,
|
||||
podObj: podToAdd,
|
||||
}
|
||||
}
|
||||
|
||||
return volumeName, nil
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) DeleteNode(nodeName k8stypes.NodeName) error {
|
||||
dsw.Lock()
|
||||
defer dsw.Unlock()
|
||||
|
||||
nodeObj, nodeExists := dsw.nodesManaged[nodeName]
|
||||
if !nodeExists {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(nodeObj.volumesToAttach) > 0 {
|
||||
return fmt.Errorf(
|
||||
"failed to delete node %q from list of nodes managed by attach/detach controller--the node still contains %v volumes in its list of volumes to attach",
|
||||
nodeName,
|
||||
len(nodeObj.volumesToAttach))
|
||||
}
|
||||
|
||||
delete(
|
||||
dsw.nodesManaged,
|
||||
nodeName)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) DeletePod(
|
||||
podName types.UniquePodName,
|
||||
volumeName v1.UniqueVolumeName,
|
||||
nodeName k8stypes.NodeName) {
|
||||
dsw.Lock()
|
||||
defer dsw.Unlock()
|
||||
|
||||
nodeObj, nodeExists := dsw.nodesManaged[nodeName]
|
||||
if !nodeExists {
|
||||
return
|
||||
}
|
||||
|
||||
volumeObj, volumeExists := nodeObj.volumesToAttach[volumeName]
|
||||
if !volumeExists {
|
||||
return
|
||||
}
|
||||
if _, podExists := volumeObj.scheduledPods[podName]; !podExists {
|
||||
return
|
||||
}
|
||||
|
||||
delete(
|
||||
dsw.nodesManaged[nodeName].volumesToAttach[volumeName].scheduledPods,
|
||||
podName)
|
||||
|
||||
if len(volumeObj.scheduledPods) == 0 {
|
||||
delete(
|
||||
dsw.nodesManaged[nodeName].volumesToAttach,
|
||||
volumeName)
|
||||
}
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) NodeExists(nodeName k8stypes.NodeName) bool {
|
||||
dsw.RLock()
|
||||
defer dsw.RUnlock()
|
||||
|
||||
_, nodeExists := dsw.nodesManaged[nodeName]
|
||||
return nodeExists
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) VolumeExists(
|
||||
volumeName v1.UniqueVolumeName, nodeName k8stypes.NodeName) bool {
|
||||
dsw.RLock()
|
||||
defer dsw.RUnlock()
|
||||
|
||||
nodeObj, nodeExists := dsw.nodesManaged[nodeName]
|
||||
if nodeExists {
|
||||
if _, volumeExists := nodeObj.volumesToAttach[volumeName]; volumeExists {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) GetVolumesToAttach() []VolumeToAttach {
|
||||
dsw.RLock()
|
||||
defer dsw.RUnlock()
|
||||
|
||||
volumesToAttach := make([]VolumeToAttach, 0 /* len */, len(dsw.nodesManaged) /* cap */)
|
||||
for nodeName, nodeObj := range dsw.nodesManaged {
|
||||
for volumeName, volumeObj := range nodeObj.volumesToAttach {
|
||||
volumesToAttach = append(volumesToAttach,
|
||||
VolumeToAttach{
|
||||
VolumeToAttach: operationexecutor.VolumeToAttach{
|
||||
VolumeName: volumeName,
|
||||
VolumeSpec: volumeObj.spec,
|
||||
NodeName: nodeName,
|
||||
ScheduledPods: getPodsFromMap(volumeObj.scheduledPods),
|
||||
}})
|
||||
}
|
||||
}
|
||||
|
||||
return volumesToAttach
|
||||
}
|
||||
|
||||
// Construct a list of v1.Pod objects from the given pod map
|
||||
func getPodsFromMap(podMap map[types.UniquePodName]pod) []*v1.Pod {
|
||||
pods := make([]*v1.Pod, 0, len(podMap))
|
||||
for _, pod := range podMap {
|
||||
pods = append(pods, pod.podObj)
|
||||
}
|
||||
return pods
|
||||
}
|
||||
|
||||
func (dsw *desiredStateOfWorld) GetPodToAdd() map[types.UniquePodName]PodToAdd {
|
||||
dsw.RLock()
|
||||
defer dsw.RUnlock()
|
||||
|
||||
pods := make(map[types.UniquePodName]PodToAdd)
|
||||
for nodeName, nodeObj := range dsw.nodesManaged {
|
||||
for volumeName, volumeObj := range nodeObj.volumesToAttach {
|
||||
for podUID, pod := range volumeObj.scheduledPods {
|
||||
pods[podUID] = PodToAdd{
|
||||
Pod: pod.podObj,
|
||||
VolumeName: volumeName,
|
||||
NodeName: nodeName,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return pods
|
||||
}
|
1034
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/desired_state_of_world_test.go
generated
vendored
Normal file
1034
vendor/k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache/desired_state_of_world_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue