Merge pull request #90907 from gnufied/fix-overflow-issue

When casting resource.Quantity to int64 it may overflow
This commit is contained in:
Kubernetes Prow Robot 2020-05-15 02:47:39 -07:00 committed by GitHub
commit f3a8eccd32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 319 additions and 135 deletions

View File

@ -183,7 +183,13 @@ func (plugin *azureFilePlugin) ExpandVolumeDevice(
return oldSize, err
}
if err := azure.ResizeFileShare(resourceGroup, accountName, shareName, int(volumehelpers.RoundUpToGiB(newSize))); err != nil {
requestGiB, err := volumehelpers.RoundUpToGiBInt(newSize)
if err != nil {
return oldSize, err
}
if err := azure.ResizeFileShare(resourceGroup, accountName, shareName, requestGiB); err != nil {
return oldSize, err
}

View File

@ -158,7 +158,11 @@ func (a *azureFileProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
var sku, resourceGroup, location, account, shareName string
capacity := a.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
requestGiB := int(volumehelpers.RoundUpToGiB(capacity))
requestGiB, err := volumehelpers.RoundUpToGiBInt(capacity)
if err != nil {
return nil, err
}
secretNamespace := a.options.PVC.Namespace
// Apply ProvisionerParameters (case-insensitive). We leave validation of
// the values to the cloud provider.

View File

@ -101,7 +101,10 @@ func (util *GCEDiskUtil) CreateVolume(c *gcePersistentDiskProvisioner, node *v1.
name := volumeutil.GenerateVolumeName(c.options.ClusterName, c.options.PVName, 63) // GCE PD name can have up to 63 characters
capacity := c.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
// GCE PDs are allocated in chunks of GiBs
requestGB := volumehelpers.RoundUpToGiB(capacity)
requestGB, err := volumehelpers.RoundUpToGiB(capacity)
if err != nil {
return "", 0, nil, "", err
}
// Apply Parameters.
// Values for parameter "replication-type" are canonicalized to lower case.
@ -159,7 +162,7 @@ func (util *GCEDiskUtil) CreateVolume(c *gcePersistentDiskProvisioner, node *v1.
name,
diskType,
selectedZones,
int64(requestGB),
requestGB,
*c.options.CloudTags)
if err != nil {
klog.V(2).Infof("Error creating regional GCE PD volume: %v", err)
@ -176,7 +179,7 @@ func (util *GCEDiskUtil) CreateVolume(c *gcePersistentDiskProvisioner, node *v1.
name,
diskType,
selectedZone,
int64(requestGB),
requestGB,
*c.options.CloudTags)
if err != nil {
klog.V(2).Infof("Error creating single-zone GCE PD volume: %v", err)

View File

@ -1212,11 +1212,18 @@ func (plugin *glusterfsPlugin) ExpandVolumeDevice(spec *volume.Spec, newSize res
}
// Find out delta size
expansionSize := resource.NewScaledQuantity((newSize.Value() - oldSize.Value()), 0)
expansionSizeGiB := int(volumehelpers.RoundUpToGiB(*expansionSize))
expansionSize := newSize
expansionSize.Sub(oldSize)
expansionSizeGiB, err := volumehelpers.RoundUpToGiBInt(expansionSize)
if err != nil {
return oldSize, err
}
// Find out requested Size
requestGiB := volumehelpers.RoundUpToGiB(newSize)
requestGiB, err := volumehelpers.RoundUpToGiB(newSize)
if err != nil {
return oldSize, err
}
//Check the existing volume size
currentVolumeInfo, err := cli.VolumeInfo(volumeID)

View File

@ -25,7 +25,7 @@ import (
volumeclient "github.com/libopenstorage/openstorage/api/client/volume"
osdspec "github.com/libopenstorage/openstorage/api/spec"
volumeapi "github.com/libopenstorage/openstorage/volume"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
volumehelpers "k8s.io/cloud-provider/volume/helpers"
@ -60,7 +60,10 @@ func (util *portworxVolumeUtil) CreateVolume(p *portworxVolumeProvisioner) (stri
capacity := p.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
// Portworx Volumes are specified in GiB
requestGiB := volumehelpers.RoundUpToGiB(capacity)
requestGiB, err := volumehelpers.RoundUpToGiB(capacity)
if err != nil {
return "", 0, nil, err
}
// Perform a best-effort parsing of parameters. Portworx 1.2.9 and later parses volume parameters from
// spec.VolumeLabels. So even if below SpecFromOpts() fails to parse certain parameters or
@ -211,7 +214,11 @@ func (util *portworxVolumeUtil) ResizeVolume(spec *volume.Spec, newSize resource
}
vol := vols[0]
newSizeInBytes := uint64(volumehelpers.RoundUpToGiB(newSize) * volumehelpers.GiB)
tBytes, ok := newSize.AsInt64()
if !ok {
return fmt.Errorf("quantity %v is too great, overflows int64", newSize)
}
newSizeInBytes := uint64(tBytes)
if vol.Spec.Size >= newSizeInBytes {
klog.Infof("Portworx volume: %s already at size: %d greater than or equal to new "+
"requested size: %d. Skipping resize.", spec.Name(), vol.Spec.Size, newSizeInBytes)

View File

@ -649,7 +649,11 @@ func (util *rbdUtil) ExpandImage(rbdExpander *rbdVolumeExpander, oldSize resourc
var err error
// Convert to MB that rbd defaults on.
sz := int(volumehelpers.RoundUpToMiB(newSize))
sz, err := volumehelpers.RoundUpToMiBInt(newSize)
if err != nil {
return oldSize, err
}
newVolSz := fmt.Sprintf("%d", sz)
newSizeQuant := resource.MustParse(fmt.Sprintf("%dMi", sz))

View File

@ -23,6 +23,7 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//vendor/github.com/thecodeteam/goscaleio/types/v1:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",

View File

@ -55,6 +55,10 @@ type sioVolume struct {
volume.MetricsNil
}
const (
minimumVolumeSizeGiB = 8
)
// *******************
// volume.Volume Impl
var _ volume.Volume = &sioVolume{}
@ -272,21 +276,17 @@ func (v *sioVolume) Provision(selectedNode *api.Node, allowedTopologies []api.To
// setup volume attrributes
genName := v.generateName("k8svol", 11)
eightGig := int64(8 * volumehelpers.GiB)
capacity := v.options.PVC.Spec.Resources.Requests[api.ResourceName(api.ResourceStorage)]
volSizeBytes := capacity.Value()
volSizeGB := int64(volumehelpers.RoundUpToGiB(capacity))
if volSizeBytes == 0 {
return nil, fmt.Errorf("invalid volume size of 0 specified")
volSizeGiB, err := volumehelpers.RoundUpToGiB(capacity)
if err != nil {
return nil, err
}
if volSizeBytes < eightGig {
eightGiBCapacity := resource.NewQuantity(eightGig, resource.BinarySI)
volSizeGB = int64(volumehelpers.RoundUpToGiB(*eightGiBCapacity))
klog.V(4).Info(log("capacity less than 8Gi found, adjusted to %dGi", volSizeGB))
if volSizeGiB < minimumVolumeSizeGiB {
volSizeGiB = minimumVolumeSizeGiB
klog.V(4).Info(log("capacity less than 8Gi found, adjusted to %dGi", volSizeGiB))
}
@ -298,7 +298,7 @@ func (v *sioVolume) Provision(selectedNode *api.Node, allowedTopologies []api.To
// create volume
volName := genName
vol, err := v.sioMgr.CreateVolume(volName, volSizeGB)
vol, err := v.sioMgr.CreateVolume(volName, volSizeGiB)
if err != nil {
klog.Error(log("provision failed while creating volume: %v", err))
return nil, err
@ -333,7 +333,7 @@ func (v *sioVolume) Provision(selectedNode *api.Node, allowedTopologies []api.To
AccessModes: v.options.PVC.Spec.AccessModes,
Capacity: api.ResourceList{
api.ResourceName(api.ResourceStorage): resource.MustParse(
fmt.Sprintf("%dGi", volSizeGB),
fmt.Sprintf("%dGi", volSizeGiB),
),
},
PersistentVolumeSource: api.PersistentVolumeSource{

View File

@ -23,6 +23,7 @@ import (
"strings"
"testing"
volumehelpers "k8s.io/cloud-provider/volume/helpers"
"k8s.io/klog"
api "k8s.io/api/core/v1"
@ -425,7 +426,7 @@ func TestVolumeProvisionerWithIncompleteConfig(t *testing.T) {
}
}
func TestVolumeProvisionerWithZeroCapacity(t *testing.T) {
func TestVolumeProvisionerWithMinimumCapacity(t *testing.T) {
plugMgr, tmpDir := newPluginMgr(t, makeScaleIOSecret(testSecret, testns))
defer os.RemoveAll(tmpDir)
@ -441,7 +442,7 @@ func TestVolumeProvisionerWithZeroCapacity(t *testing.T) {
options := volume.VolumeOptions{
ClusterName: "testcluster",
PVName: "pvc-sio-dynamic-vol",
PVC: volumetest.CreateTestPVC("0Mi", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}),
PVC: volumetest.CreateTestPVC("100Mi", []api.PersistentVolumeAccessMode{api.ReadWriteOnce}),
PersistentVolumeReclaimPolicy: api.PersistentVolumeReclaimDelete,
}
options.PVC.Namespace = testns
@ -466,11 +467,25 @@ func TestVolumeProvisionerWithZeroCapacity(t *testing.T) {
}
sioVol.sioMgr.client = sio
_, err = provisioner.Provision(nil, nil)
if err == nil {
t.Fatalf("call to Provision() should fail with invalid capacity")
pv, err :=
provisioner.Provision(nil, nil)
if err != nil {
t.Fatalf("call to Provision() failed %v", err)
}
pvSize := pv.Spec.Capacity.Storage()
if pvSize == nil {
t.Fatalf("unexpected pv size: nil")
}
gibSize, err := volumehelpers.RoundUpToGiB(*pvSize)
if err != nil {
t.Fatalf("unexpected error while converting size to GiB: %v", err)
}
if gibSize != minimumVolumeSizeGiB {
t.Fatalf("expected GiB size to be %v got %v", minimumVolumeSizeGiB, gibSize)
}
}
func TestVolumeProvisionerWithSecretNamespace(t *testing.T) {

View File

@ -39,74 +39,88 @@ const (
KiB = 1024
)
// RoundUpToGB rounds up given quantity to chunks of GB
func RoundUpToGB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, GB)
}
// RoundUpToGiB rounds up given quantity upto chunks of GiB
func RoundUpToGiB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, GiB)
func RoundUpToGiB(size resource.Quantity) (int64, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSize(requestBytes, GiB), nil
}
// RoundUpToMB rounds up given quantity to chunks of MB
func RoundUpToMB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, MB)
func RoundUpToMB(size resource.Quantity) (int64, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSize(requestBytes, MB), nil
}
// RoundUpToMiB rounds up given quantity upto chunks of MiB
func RoundUpToMiB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, MiB)
func RoundUpToMiB(size resource.Quantity) (int64, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSize(requestBytes, MiB), nil
}
// RoundUpToKB rounds up given quantity to chunks of KB
func RoundUpToKB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, KB)
func RoundUpToKB(size resource.Quantity) (int64, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSize(requestBytes, KB), nil
}
// RoundUpToKiB rounds up given quantity upto chunks of KiB
func RoundUpToKiB(size resource.Quantity) int64 {
requestBytes := size.Value()
return roundUpSize(requestBytes, KiB)
}
// RoundUpToGBInt rounds up given quantity to chunks of GB. It returns an
// int instead of an int64 and an error if there's overflow
func RoundUpToGBInt(size resource.Quantity) (int, error) {
requestBytes := size.Value()
return roundUpSizeInt(requestBytes, GB)
func RoundUpToKiB(size resource.Quantity) (int64, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSize(requestBytes, KiB), nil
}
// RoundUpToGiBInt rounds up given quantity upto chunks of GiB. It returns an
// int instead of an int64 and an error if there's overflow
func RoundUpToGiBInt(size resource.Quantity) (int, error) {
requestBytes := size.Value()
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSizeInt(requestBytes, GiB)
}
// RoundUpToMBInt rounds up given quantity to chunks of MB. It returns an
// int instead of an int64 and an error if there's overflow
func RoundUpToMBInt(size resource.Quantity) (int, error) {
requestBytes := size.Value()
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSizeInt(requestBytes, MB)
}
// RoundUpToMiBInt rounds up given quantity upto chunks of MiB. It returns an
// int instead of an int64 and an error if there's overflow
func RoundUpToMiBInt(size resource.Quantity) (int, error) {
requestBytes := size.Value()
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSizeInt(requestBytes, MiB)
}
// RoundUpToKBInt rounds up given quantity to chunks of KB. It returns an
// int instead of an int64 and an error if there's overflow
func RoundUpToKBInt(size resource.Quantity) (int, error) {
requestBytes := size.Value()
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSizeInt(requestBytes, KB)
}
@ -117,6 +131,16 @@ func RoundUpToKiBInt(size resource.Quantity) (int, error) {
return roundUpSizeInt(requestBytes, KiB)
}
// RoundUpToGiBInt32 rounds up given quantity up to chunks of GiB. It returns an
// int32 instead of an int64 and an error if there's overflow
func RoundUpToGiBInt32(size resource.Quantity) (int32, error) {
requestBytes, ok := size.AsInt64()
if !ok {
return 0, fmt.Errorf("quantity %v is too great, overflows int64", size)
}
return roundUpSizeInt32(requestBytes, GiB)
}
// roundUpSizeInt calculates how many allocation units are needed to accommodate
// a volume of given size. It returns an int instead of an int64 and an error if
// there's overflow
@ -129,6 +153,18 @@ func roundUpSizeInt(volumeSizeBytes int64, allocationUnitBytes int64) (int, erro
return roundedUpInt, nil
}
// roundUpSizeInt32 calculates how many allocation units are needed to accommodate
// a volume of given size. It returns an int32 instead of an int64 and an error if
// there's overflow
func roundUpSizeInt32(volumeSizeBytes int64, allocationUnitBytes int64) (int32, error) {
roundedUp := roundUpSize(volumeSizeBytes, allocationUnitBytes)
roundedUpInt32 := int32(roundedUp)
if int64(roundedUpInt32) != roundedUp {
return 0, fmt.Errorf("quantity %v is too great, overflows int32", roundedUp)
}
return roundedUpInt32, nil
}
// roundUpSize calculates how many allocation units are needed to accommodate
// a volume of given size. E.g. when user wants 1500MiB volume, while AWS EBS
// allocates volumes in gibibyte-sized chunks,

View File

@ -22,61 +22,12 @@ import (
"k8s.io/apimachinery/pkg/api/resource"
)
func Test_RoundUpToGB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
}{
{
name: "round Ki to GB",
resource: resource.MustParse("1000Ki"),
roundedVal: int64(1),
},
{
name: "round k to GB",
resource: resource.MustParse("1000k"),
roundedVal: int64(1),
},
{
name: "round Mi to GB",
resource: resource.MustParse("1000Mi"),
roundedVal: int64(2),
},
{
name: "round M to GB",
resource: resource.MustParse("1000M"),
roundedVal: int64(1),
},
{
name: "round G to GB",
resource: resource.MustParse("1000G"),
roundedVal: int64(1000),
},
{
name: "round Gi to GB",
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1074),
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToGB(test.resource)
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
t.Error("unexpected rounded value")
}
})
}
}
func Test_RoundUpToGiB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
name string
resource resource.Quantity
roundedVal int64
expectError bool
}{
{
name: "round Ki to GiB",
@ -108,11 +59,25 @@ func Test_RoundUpToGiB(t *testing.T) {
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1000),
},
{
name: "round overflowed quantity to int64",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int64(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToGiB(test.resource)
val, err := RoundUpToGiB(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
@ -124,9 +89,10 @@ func Test_RoundUpToGiB(t *testing.T) {
func Test_RoundUpToMB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
name string
resource resource.Quantity
roundedVal int64
expectError bool
}{
{
name: "round Ki to MB",
@ -158,11 +124,25 @@ func Test_RoundUpToMB(t *testing.T) {
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1073742),
},
{
name: "round overflowed quantity to int64",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int64(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToMB(test.resource)
val, err := RoundUpToMB(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
@ -174,9 +154,10 @@ func Test_RoundUpToMB(t *testing.T) {
func Test_RoundUpToMiB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
name string
resource resource.Quantity
roundedVal int64
expectError bool
}{
{
name: "round Ki to MiB",
@ -208,11 +189,25 @@ func Test_RoundUpToMiB(t *testing.T) {
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1024000),
},
{
name: "round overflowed quantity to int64",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int64(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToMiB(test.resource)
val, err := RoundUpToMiB(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
@ -224,9 +219,10 @@ func Test_RoundUpToMiB(t *testing.T) {
func Test_RoundUpToKB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
name string
resource resource.Quantity
roundedVal int64
expectError bool
}{
{
name: "round Ki to KB",
@ -258,11 +254,25 @@ func Test_RoundUpToKB(t *testing.T) {
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1073741824),
},
{
name: "round overflowed quantity to int64",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int64(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToKB(test.resource)
val, err := RoundUpToKB(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
@ -274,9 +284,10 @@ func Test_RoundUpToKB(t *testing.T) {
func Test_RoundUpToKiB(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int64
name string
resource resource.Quantity
roundedVal int64
expectError bool
}{
{
name: "round Ki to KiB",
@ -308,11 +319,90 @@ func Test_RoundUpToKiB(t *testing.T) {
resource: resource.MustParse("1000Gi"),
roundedVal: int64(1048576000),
},
{
name: "round overflowed quantity to int64",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int64(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val := RoundUpToKiB(test.resource)
val, err := RoundUpToKiB(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)
t.Error("unexpected rounded value")
}
})
}
}
func Test_RoundUpToGiBInt32(t *testing.T) {
testcases := []struct {
name string
resource resource.Quantity
roundedVal int32
expectError bool
}{
{
name: "round Ki to GiB",
resource: resource.MustParse("1000Ki"),
roundedVal: int32(1),
},
{
name: "round k to GiB",
resource: resource.MustParse("1000k"),
roundedVal: int32(1),
},
{
name: "round Mi to GiB",
resource: resource.MustParse("1000Mi"),
roundedVal: int32(1),
},
{
name: "round M to GiB",
resource: resource.MustParse("1000M"),
roundedVal: int32(1),
},
{
name: "round G to GiB",
resource: resource.MustParse("1000G"),
roundedVal: int32(932),
},
{
name: "round Gi to GiB",
resource: resource.MustParse("1000Gi"),
roundedVal: int32(1000),
},
{
name: "round overflowed quantity to int32",
resource: resource.MustParse("73786976299133170k"),
roundedVal: int32(0),
expectError: true,
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
val, err := RoundUpToGiBInt32(test.resource)
if !test.expectError && err != nil {
t.Errorf("expected no error got: %v", err)
}
if test.expectError && err == nil {
t.Errorf("expected error but got nothing")
}
if val != test.roundedVal {
t.Logf("actual rounded value: %d", val)
t.Logf("expected rounded value: %d", test.roundedVal)

View File

@ -2815,7 +2815,10 @@ func (c *Cloud) ResizeDisk(
return oldSize, descErr
}
// AWS resizes in chunks of GiB (not GB)
requestGiB := volumehelpers.RoundUpToGiB(newSize)
requestGiB, err := volumehelpers.RoundUpToGiB(newSize)
if err != nil {
return oldSize, err
}
newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGiB))
// If disk already if of greater or equal size than requested we return

View File

@ -284,7 +284,11 @@ func (c *ManagedDiskController) ResizeDisk(diskURI string, oldSize resource.Quan
}
// Azure resizes in chunks of GiB (not GB)
requestGiB := int32(volumehelpers.RoundUpToGiB(newSize))
requestGiB, err := volumehelpers.RoundUpToGiBInt32(newSize)
if err != nil {
return oldSize, err
}
newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGiB))
klog.V(2).Infof("azureDisk - begin to resize disk(%s) with new size(%d), old size(%v)", diskName, requestGiB, oldSize)

View File

@ -25,7 +25,7 @@ import (
"net/http"
"strings"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/types"
@ -809,7 +809,11 @@ func (g *Cloud) ResizeDisk(diskToResize string, oldSize resource.Quantity, newSi
}
// GCE resizes in chunks of GiBs
requestGIB := volumehelpers.RoundUpToGiB(newSize)
requestGIB, err := volumehelpers.RoundUpToGiB(newSize)
if err != nil {
return oldSize, err
}
newSizeQuant := resource.MustParse(fmt.Sprintf("%dGi", requestGIB))
// If disk is already of size equal or greater than requested size, we simply return