*: initial update to kube 1.8

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-09-26 16:23:09 +02:00
parent 2453222695
commit d6e819133d
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
1237 changed files with 84117 additions and 564982 deletions

View file

@ -23,17 +23,26 @@ import (
"sync"
"github.com/golang/glog"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/cloudprovider"
"k8s.io/kubernetes/pkg/util/io"
"k8s.io/kubernetes/pkg/util/mount"
)
const (
// Common parameter which can be specified in StorageClass to specify the desired FSType
// Provisioners SHOULD implement support for this if they are block device based
// Must be a filesystem type supported by the host operating system.
// Ex. "ext4", "xfs", "ntfs". Default value depends on the provisioner
VolumeParameterFSType = "fstype"
)
// VolumeOptions contains option information about a volume.
type VolumeOptions struct {
// The attributes below are required by volume.Provisioner
@ -42,6 +51,8 @@ type VolumeOptions struct {
// Reclamation policy for a persistent volume
PersistentVolumeReclaimPolicy v1.PersistentVolumeReclaimPolicy
// Mount options for a persistent volume
MountOptions []string
// Suggested PV.Name of the PersistentVolume to provision.
// This is a generated name guaranteed to be unique in Kubernetes cluster.
// If you choose not to use it as volume name, ensure uniqueness by either
@ -58,6 +69,19 @@ type VolumeOptions struct {
CloudTags *map[string]string
// Volume provisioning parameters from StorageClass
Parameters map[string]string
// This flag helps identify whether kubelet is running in a container
Containerized bool
}
type DynamicPluginProber interface {
Init() error
// If an update has occurred since the last probe, updated = true
// and the list of probed plugins is returned.
// Otherwise, update = false and probedPlugins = nil.
//
// If an error occurs, updated and probedPlugins are undefined.
Probe() (updated bool, probedPlugins []VolumePlugin, err error)
}
// VolumePlugin is an interface to volume plugins that can be used on a
@ -178,6 +202,14 @@ type AttachableVolumePlugin interface {
GetDeviceMountRefs(deviceMountPath string) ([]string, error)
}
// ExpandableVolumePlugin is an extended interface of VolumePlugin and is used for volumes that can be
// expanded
type ExpandableVolumePlugin interface {
VolumePlugin
ExpandVolumeDevice(spec *Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error)
RequiresFSResize() bool
}
// VolumeHost is an interface that plugins can use to access the kubelet.
type VolumeHost interface {
// GetPluginDir returns the absolute path to a directory under which
@ -216,7 +248,7 @@ type VolumeHost interface {
GetCloudProvider() cloudprovider.Interface
// Get mounter interface.
GetMounter() mount.Interface
GetMounter(pluginName string) mount.Interface
// Get writer interface for writing data to disk.
GetWriter() io.Writer
@ -236,15 +268,20 @@ type VolumeHost interface {
// Returns a function that returns a configmap.
GetConfigMapFunc() func(namespace, name string) (*v1.ConfigMap, error)
// Returns an interface that should be used to execute any utilities in volume plugins
GetExec(pluginName string) mount.Exec
// Returns the labels on the node
GetNodeLabels() (map[string]string, error)
}
// VolumePluginMgr tracks registered plugins.
type VolumePluginMgr struct {
mutex sync.Mutex
plugins map[string]VolumePlugin
Host VolumeHost
mutex sync.Mutex
plugins map[string]VolumePlugin
prober DynamicPluginProber
probedPlugins []VolumePlugin
Host VolumeHost
}
// Spec is an internal representation of a volume. All API volume types translate to Spec.
@ -339,11 +376,24 @@ func NewSpecFromPersistentVolume(pv *v1.PersistentVolume, readOnly bool) *Spec {
// InitPlugins initializes each plugin. All plugins must have unique names.
// This must be called exactly once before any New* methods are called on any
// plugins.
func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost) error {
func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, prober DynamicPluginProber, host VolumeHost) error {
pm.mutex.Lock()
defer pm.mutex.Unlock()
pm.Host = host
if prober == nil {
// Use a dummy prober to prevent nil deference.
pm.prober = &dummyPluginProber{}
} else {
pm.prober = prober
}
if err := pm.prober.Init(); err != nil {
// Prober init failure should not affect the initialization of other plugins.
glog.Errorf("Error initializing dynamic plugin prober: %s", err)
pm.prober = &dummyPluginProber{}
}
if pm.plugins == nil {
pm.plugins = map[string]VolumePlugin{}
}
@ -362,7 +412,7 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost)
}
err := plugin.Init(host)
if err != nil {
glog.Errorf("Failed to load volume plugin %s, error: %s", plugin, err.Error())
glog.Errorf("Failed to load volume plugin %s, error: %s", name, err.Error())
allErrs = append(allErrs, err)
continue
}
@ -372,6 +422,21 @@ func (pm *VolumePluginMgr) InitPlugins(plugins []VolumePlugin, host VolumeHost)
return utilerrors.NewAggregate(allErrs)
}
func (pm *VolumePluginMgr) initProbedPlugin(probedPlugin VolumePlugin) error {
name := probedPlugin.GetPluginName()
if errs := validation.IsQualifiedName(name); len(errs) != 0 {
return fmt.Errorf("volume plugin has invalid name: %q: %s", name, strings.Join(errs, ";"))
}
err := probedPlugin.Init(pm.Host)
if err != nil {
return fmt.Errorf("Failed to load volume plugin %s, error: %s", name, err.Error())
}
glog.V(1).Infof("Loaded volume plugin %q", name)
return nil
}
// FindPluginBySpec looks for a plugin that can support a given volume
// specification. If no plugins can support or more than one plugin can
// support it, return error.
@ -379,19 +444,34 @@ func (pm *VolumePluginMgr) FindPluginBySpec(spec *Spec) (VolumePlugin, error) {
pm.mutex.Lock()
defer pm.mutex.Unlock()
matches := []string{}
if spec == nil {
return nil, fmt.Errorf("Could not find plugin because volume spec is nil")
}
matchedPluginNames := []string{}
matches := []VolumePlugin{}
for k, v := range pm.plugins {
if v.CanSupport(spec) {
matches = append(matches, k)
matchedPluginNames = append(matchedPluginNames, k)
matches = append(matches, v)
}
}
pm.refreshProbedPlugins()
for _, plugin := range pm.probedPlugins {
if plugin.CanSupport(spec) {
matchedPluginNames = append(matchedPluginNames, plugin.GetPluginName())
matches = append(matches, plugin)
}
}
if len(matches) == 0 {
return nil, fmt.Errorf("no volume plugin matched")
}
if len(matches) > 1 {
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matches, ","))
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
}
return pm.plugins[matches[0]], nil
return matches[0], nil
}
// FindPluginByName fetches a plugin by name or by legacy name. If no plugin
@ -401,19 +481,52 @@ func (pm *VolumePluginMgr) FindPluginByName(name string) (VolumePlugin, error) {
defer pm.mutex.Unlock()
// Once we can get rid of legacy names we can reduce this to a map lookup.
matches := []string{}
matchedPluginNames := []string{}
matches := []VolumePlugin{}
for k, v := range pm.plugins {
if v.GetPluginName() == name {
matches = append(matches, k)
matchedPluginNames = append(matchedPluginNames, k)
matches = append(matches, v)
}
}
pm.refreshProbedPlugins()
for _, plugin := range pm.probedPlugins {
if plugin.GetPluginName() == name {
matchedPluginNames = append(matchedPluginNames, plugin.GetPluginName())
matches = append(matches, plugin)
}
}
if len(matches) == 0 {
return nil, fmt.Errorf("no volume plugin matched")
}
if len(matches) > 1 {
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matches, ","))
return nil, fmt.Errorf("multiple volume plugins matched: %s", strings.Join(matchedPluginNames, ","))
}
return matches[0], nil
}
// Check if probedPlugin cache update is required.
// If it is, initialize all probed plugins and replace the cache with them.
func (pm *VolumePluginMgr) refreshProbedPlugins() {
updated, plugins, err := pm.prober.Probe()
if err != nil {
glog.Errorf("Error dynamically probing plugins: %s", err)
return // Use cached plugins upon failure.
}
if updated {
pm.probedPlugins = []VolumePlugin{}
for _, plugin := range plugins {
if err := pm.initProbedPlugin(plugin); err != nil {
glog.Errorf("Error initializing dynamically probed plugin %s; error: %s",
plugin.GetPluginName(), err)
continue
}
pm.probedPlugins = append(pm.probedPlugins, plugin)
}
}
return pm.plugins[matches[0]], nil
}
// FindPersistentPluginBySpec looks for a persistent volume plugin that can
@ -538,6 +651,32 @@ func (pm *VolumePluginMgr) FindAttachablePluginByName(name string) (AttachableVo
return nil, nil
}
// FindExpandablePluginBySpec fetches a persistent volume plugin by spec.
func (pm *VolumePluginMgr) FindExpandablePluginBySpec(spec *Spec) (ExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginBySpec(spec)
if err != nil {
return nil, err
}
if expandableVolumePlugin, ok := volumePlugin.(ExpandableVolumePlugin); ok {
return expandableVolumePlugin, nil
}
return nil, nil
}
// FindExpandablePluginBySpec fetches a persistent volume plugin by name.
func (pm *VolumePluginMgr) FindExpandablePluginByName(name string) (ExpandableVolumePlugin, error) {
volumePlugin, err := pm.FindPluginByName(name)
if err != nil {
return nil, err
}
if expandableVolumePlugin, ok := volumePlugin.(ExpandableVolumePlugin); ok {
return expandableVolumePlugin, nil
}
return nil, nil
}
// NewPersistentVolumeRecyclerPodTemplate creates a template for a recycler
// pod. By default, a recycler pod simply runs "rm -rf" on a volume and tests
// for emptiness. Most attributes of the template will be correct for most
@ -601,3 +740,8 @@ func ValidateRecyclerPodTemplate(pod *v1.Pod) error {
}
return nil
}
type dummyPluginProber struct{}
func (*dummyPluginProber) Init() error { return nil }
func (*dummyPluginProber) Probe() (bool, []VolumePlugin, error) { return false, nil, nil }