From 22fce22a7e255725d97ad84cf6b4437a72a567f7 Mon Sep 17 00:00:00 2001 From: andrewsykim Date: Mon, 21 Jan 2019 16:20:15 -0500 Subject: [PATCH] add support for Cinder volumes in PersistentVolumeLabel admission controller --- .../persistentvolume/label/admission.go | 63 ++++++++++++++++++- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/plugin/pkg/admission/storage/persistentvolume/label/admission.go b/plugin/pkg/admission/storage/persistentvolume/label/admission.go index 9352df782a..fb28017adb 100644 --- a/plugin/pkg/admission/storage/persistentvolume/label/admission.go +++ b/plugin/pkg/admission/storage/persistentvolume/label/admission.go @@ -70,9 +70,9 @@ var _ kubeapiserveradmission.WantsCloudConfig = &persistentVolumeLabel{} // // As a side effect, the cloud provider may block invalid or non-existent volumes. func newPersistentVolumeLabel() *persistentVolumeLabel { - // DEPRECATED: cloud-controller-manager will now start NewPersistentVolumeLabelController - // which does exactly what this admission controller used to do. So once GCE, AWS and AZURE can - // run externally, we can remove this admission controller. + // DEPRECATED: in a future release, we will use mutating admission webhooks to apply PV labels. + // Once the mutating admission webhook is used for AWS, Azure, GCE, and OpenStack, + // this admission controller will be removed. klog.Warning("PersistentVolumeLabel admission controller is deprecated. " + "Please remove this controller from your configuration files and scripts.") return &persistentVolumeLabel{ @@ -132,6 +132,13 @@ func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) { } volumeLabels = labels } + if volume.Spec.Cinder != nil { + labels, err := l.findCinderDiskLabels(volume) + if err != nil { + return admission.NewForbidden(a, fmt.Errorf("error querying Cinder volume %s: %v", volume.Spec.Cinder.VolumeID, err)) + } + volumeLabels = labels + } requirements := make([]api.NodeSelectorRequirement, 0) if len(volumeLabels) != 0 { @@ -327,3 +334,53 @@ func (l *persistentVolumeLabel) findAzureDiskLabels(volume *api.PersistentVolume } return pvlabler.GetLabelsForVolume(context.TODO(), pv) } + +func (l *persistentVolumeLabel) getOpenStackPVLabeler() (cloudprovider.PVLabeler, error) { + l.mutex.Lock() + defer l.mutex.Unlock() + + if l.openStackPVLabeler == nil { + var cloudConfigReader io.Reader + if len(l.cloudConfig) > 0 { + cloudConfigReader = bytes.NewReader(l.cloudConfig) + } + + cloudProvider, err := cloudprovider.GetCloudProvider("openstack", cloudConfigReader) + if err != nil || cloudProvider == nil { + return nil, err + } + + openStackPVLabeler, ok := cloudProvider.(cloudprovider.PVLabeler) + if !ok { + return nil, errors.New("OpenStack cloud provider does not implement PV labeling") + } + + l.openStackPVLabeler = openStackPVLabeler + } + + return l.openStackPVLabeler, nil + +} + +func (l *persistentVolumeLabel) findCinderDiskLabels(volume *api.PersistentVolume) (map[string]string, error) { + // Ignore any volumes that are being provisioned + if volume.Spec.Cinder.VolumeID == vol.ProvisionedVolumeName { + return nil, nil + } + + pvlabler, err := l.getOpenStackPVLabeler() + if err != nil { + return nil, err + } + if pvlabler == nil { + return nil, fmt.Errorf("unable to build OpenStack cloud provider for Cinder disk") + } + + pv := &v1.PersistentVolume{} + err = k8s_api_v1.Convert_core_PersistentVolume_To_v1_PersistentVolume(volume, pv, nil) + if err != nil { + return nil, fmt.Errorf("failed to convert PersistentVolume to core/v1: %q", err) + } + return pvlabler.GetLabelsForVolume(context.TODO(), pv) + +}