mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
implement cinder resize
This commit is contained in:
parent
0c7d7becf8
commit
af108fb938
8
Godeps/Godeps.json
generated
8
Godeps/Godeps.json
generated
@ -1567,10 +1567,10 @@
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
|
||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
|
||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
|
||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
|
||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||
|
@ -29,6 +29,7 @@ go_library(
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes:go_default_library",
|
||||
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/attachinterfaces:go_default_library",
|
||||
@ -51,6 +52,7 @@ go_library(
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
@ -24,9 +24,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
k8s_volume "k8s.io/kubernetes/pkg/volume"
|
||||
|
||||
"github.com/gophercloud/gophercloud"
|
||||
volumeexpand "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
|
||||
volumes_v1 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
|
||||
volumes_v2 "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
|
||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
||||
@ -39,6 +41,7 @@ type volumeService interface {
|
||||
createVolume(opts VolumeCreateOpts) (string, string, error)
|
||||
getVolume(volumeID string) (Volume, error)
|
||||
deleteVolume(volumeName string) error
|
||||
expandVolume(volumeID string, newSize int) error
|
||||
}
|
||||
|
||||
// Volumes implementation for v1
|
||||
@ -64,6 +67,8 @@ type Volume struct {
|
||||
Name string
|
||||
// Current status of the volume.
|
||||
Status string
|
||||
// Volume size in GB
|
||||
Size int
|
||||
}
|
||||
|
||||
type VolumeCreateOpts struct {
|
||||
@ -139,6 +144,7 @@ func (volumes *VolumesV1) getVolume(volumeID string) (Volume, error) {
|
||||
ID: volumeV1.ID,
|
||||
Name: volumeV1.Name,
|
||||
Status: volumeV1.Status,
|
||||
Size: volumeV1.Size,
|
||||
}
|
||||
|
||||
if len(volumeV1.Attachments) > 0 && volumeV1.Attachments[0]["server_id"] != nil {
|
||||
@ -162,6 +168,7 @@ func (volumes *VolumesV2) getVolume(volumeID string) (Volume, error) {
|
||||
ID: volumeV2.ID,
|
||||
Name: volumeV2.Name,
|
||||
Status: volumeV2.Status,
|
||||
Size: volumeV2.Size,
|
||||
}
|
||||
|
||||
if len(volumeV2.Attachments) > 0 {
|
||||
@ -188,6 +195,30 @@ func (volumes *VolumesV2) deleteVolume(volumeID string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (volumes *VolumesV1) expandVolume(volumeID string, newSize int) error {
|
||||
startTime := time.Now()
|
||||
create_opts := volumeexpand.ExtendSizeOpts{
|
||||
NewSize: newSize,
|
||||
}
|
||||
err := volumeexpand.ExtendSize(volumes.blockstorage, volumeID, create_opts).ExtractErr()
|
||||
timeTaken := time.Since(startTime).Seconds()
|
||||
recordOpenstackOperationMetric("expand_volume", timeTaken, err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (volumes *VolumesV2) expandVolume(volumeID string, newSize int) error {
|
||||
startTime := time.Now()
|
||||
create_opts := volumeexpand.ExtendSizeOpts{
|
||||
NewSize: newSize,
|
||||
}
|
||||
err := volumeexpand.ExtendSize(volumes.blockstorage, volumeID, create_opts).ExtractErr()
|
||||
timeTaken := time.Since(startTime).Seconds()
|
||||
recordOpenstackOperationMetric("expand_volume", timeTaken, err)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (os *OpenStack) OperationPending(diskName string) (bool, string, error) {
|
||||
volume, err := os.getVolume(diskName)
|
||||
if err != nil {
|
||||
@ -274,6 +305,39 @@ func (os *OpenStack) DetachDisk(instanceID, volumeID string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExpandVolume expands the size of specific cinder volume (in GiB)
|
||||
func (os *OpenStack) ExpandVolume(volumeID string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) {
|
||||
volume, err := os.getVolume(volumeID)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
if volume.Status != VolumeAvailableStatus {
|
||||
// cinder volume can not be expanded if its status is not available
|
||||
return oldSize, fmt.Errorf("volume status is not available")
|
||||
}
|
||||
|
||||
volSizeBytes := newSize.Value()
|
||||
// Cinder works with gigabytes, convert to GiB with rounding up
|
||||
volSizeGB := int(k8s_volume.RoundUpSize(volSizeBytes, 1024*1024*1024))
|
||||
newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", volSizeGB))
|
||||
|
||||
// if volume size equals to or greater than the newSize, return nil
|
||||
if volume.Size >= volSizeGB {
|
||||
return newSizeQuant, nil
|
||||
}
|
||||
|
||||
volumes, err := os.volumeService("")
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
err = volumes.expandVolume(volumeID, volSizeGB)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
return newSizeQuant, nil
|
||||
}
|
||||
|
||||
// getVolume retrieves Volume by its ID.
|
||||
func (os *OpenStack) getVolume(volumeID string) (Volume, error) {
|
||||
volumes, err := os.volumeService("")
|
||||
|
@ -52,6 +52,7 @@ go_test(
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||
],
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
@ -583,6 +584,10 @@ func (testcase *testcase) InstanceID() (string, error) {
|
||||
return testcase.instanceID, nil
|
||||
}
|
||||
|
||||
func (testcase *testcase) ExpandVolume(volumeID string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) {
|
||||
return resource.Quantity{}, nil
|
||||
}
|
||||
|
||||
func (testcase *testcase) DeleteVolume(volumeID string) error {
|
||||
return errors.New("Not implemented")
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ type CinderProvider interface {
|
||||
DisksAreAttached(instanceID string, volumeIDs []string) (map[string]bool, error)
|
||||
ShouldTrustDevicePath() bool
|
||||
Instances() (cloudprovider.Instances, bool)
|
||||
ExpandVolume(volumeID string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error)
|
||||
}
|
||||
|
||||
type cinderPlugin struct {
|
||||
@ -227,6 +228,31 @@ func (plugin *cinderPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*
|
||||
return volume.NewSpecFromVolume(cinderVolume), nil
|
||||
}
|
||||
|
||||
var _ volume.ExpandableVolumePlugin = &cinderPlugin{}
|
||||
|
||||
func (plugin *cinderPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize resource.Quantity, oldSize resource.Quantity) (resource.Quantity, error) {
|
||||
cinder, _, err := getVolumeSource(spec)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
cloud, err := plugin.getCloudProvider()
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
expandedSize, err := cloud.ExpandVolume(cinder.VolumeID, oldSize, newSize)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
glog.V(2).Infof("volume %s expanded to new size %d successfully", cinder.VolumeID, int(newSize.Value()))
|
||||
return expandedSize, nil
|
||||
}
|
||||
|
||||
func (plugin *cinderPlugin) RequiresFSResize() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Abstract interface to PD operations.
|
||||
type cdManager interface {
|
||||
// Attaches the disk to the kubelet's host machine.
|
||||
|
@ -152,6 +152,9 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
|
||||
if pv.Spec.Glusterfs != nil {
|
||||
return true
|
||||
}
|
||||
if pv.Spec.Cinder != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user