mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +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",
|
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
|
||||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
|
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions",
|
||||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
|
"ImportPath": "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes",
|
||||||
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
"Rev": "54086d6c81b90e91e1d52b866ee726baf5cbe2b1"
|
||||||
|
@ -29,6 +29,7 @@ go_library(
|
|||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud: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: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/v1/volumes:go_default_library",
|
||||||
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v2/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",
|
"//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/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||||
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/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/types:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
|
@ -24,9 +24,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
k8s_volume "k8s.io/kubernetes/pkg/volume"
|
k8s_volume "k8s.io/kubernetes/pkg/volume"
|
||||||
|
|
||||||
"github.com/gophercloud/gophercloud"
|
"github.com/gophercloud/gophercloud"
|
||||||
|
volumeexpand "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
|
||||||
volumes_v1 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
|
volumes_v1 "github.com/gophercloud/gophercloud/openstack/blockstorage/v1/volumes"
|
||||||
volumes_v2 "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
|
volumes_v2 "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
|
||||||
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/volumeattach"
|
||||||
@ -39,6 +41,7 @@ type volumeService interface {
|
|||||||
createVolume(opts VolumeCreateOpts) (string, string, error)
|
createVolume(opts VolumeCreateOpts) (string, string, error)
|
||||||
getVolume(volumeID string) (Volume, error)
|
getVolume(volumeID string) (Volume, error)
|
||||||
deleteVolume(volumeName string) error
|
deleteVolume(volumeName string) error
|
||||||
|
expandVolume(volumeID string, newSize int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Volumes implementation for v1
|
// Volumes implementation for v1
|
||||||
@ -64,6 +67,8 @@ type Volume struct {
|
|||||||
Name string
|
Name string
|
||||||
// Current status of the volume.
|
// Current status of the volume.
|
||||||
Status string
|
Status string
|
||||||
|
// Volume size in GB
|
||||||
|
Size int
|
||||||
}
|
}
|
||||||
|
|
||||||
type VolumeCreateOpts struct {
|
type VolumeCreateOpts struct {
|
||||||
@ -139,6 +144,7 @@ func (volumes *VolumesV1) getVolume(volumeID string) (Volume, error) {
|
|||||||
ID: volumeV1.ID,
|
ID: volumeV1.ID,
|
||||||
Name: volumeV1.Name,
|
Name: volumeV1.Name,
|
||||||
Status: volumeV1.Status,
|
Status: volumeV1.Status,
|
||||||
|
Size: volumeV1.Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(volumeV1.Attachments) > 0 && volumeV1.Attachments[0]["server_id"] != nil {
|
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,
|
ID: volumeV2.ID,
|
||||||
Name: volumeV2.Name,
|
Name: volumeV2.Name,
|
||||||
Status: volumeV2.Status,
|
Status: volumeV2.Status,
|
||||||
|
Size: volumeV2.Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(volumeV2.Attachments) > 0 {
|
if len(volumeV2.Attachments) > 0 {
|
||||||
@ -188,6 +195,30 @@ func (volumes *VolumesV2) deleteVolume(volumeID string) error {
|
|||||||
return err
|
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) {
|
func (os *OpenStack) OperationPending(diskName string) (bool, string, error) {
|
||||||
volume, err := os.getVolume(diskName)
|
volume, err := os.getVolume(diskName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -274,6 +305,39 @@ func (os *OpenStack) DetachDisk(instanceID, volumeID string) error {
|
|||||||
return nil
|
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.
|
// getVolume retrieves Volume by its ID.
|
||||||
func (os *OpenStack) getVolume(volumeID string) (Volume, error) {
|
func (os *OpenStack) getVolume(volumeID string) (Volume, error) {
|
||||||
volumes, err := os.volumeService("")
|
volumes, err := os.volumeService("")
|
||||||
|
@ -52,6 +52,7 @@ go_test(
|
|||||||
"//pkg/volume/testing:go_default_library",
|
"//pkg/volume/testing:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/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/types:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
"//vendor/k8s.io/client-go/util/testing:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
@ -583,6 +584,10 @@ func (testcase *testcase) InstanceID() (string, error) {
|
|||||||
return testcase.instanceID, nil
|
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 {
|
func (testcase *testcase) DeleteVolume(volumeID string) error {
|
||||||
return errors.New("Not implemented")
|
return errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ type CinderProvider interface {
|
|||||||
DisksAreAttached(instanceID string, volumeIDs []string) (map[string]bool, error)
|
DisksAreAttached(instanceID string, volumeIDs []string) (map[string]bool, error)
|
||||||
ShouldTrustDevicePath() bool
|
ShouldTrustDevicePath() bool
|
||||||
Instances() (cloudprovider.Instances, bool)
|
Instances() (cloudprovider.Instances, bool)
|
||||||
|
ExpandVolume(volumeID string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type cinderPlugin struct {
|
type cinderPlugin struct {
|
||||||
@ -227,6 +228,31 @@ func (plugin *cinderPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*
|
|||||||
return volume.NewSpecFromVolume(cinderVolume), nil
|
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.
|
// Abstract interface to PD operations.
|
||||||
type cdManager interface {
|
type cdManager interface {
|
||||||
// Attaches the disk to the kubelet's host machine.
|
// 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 {
|
if pv.Spec.Glusterfs != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if pv.Spec.Cinder != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user