mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-30 17:13:08 +08:00
fix(region): update gp3 disk size (#24812)
This commit is contained in:
@@ -108,7 +108,7 @@ require (
|
||||
k8s.io/cri-api v0.28.15
|
||||
k8s.io/klog/v2 v2.90.1
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260422030642-84e9ebcd4edc
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084604-0d6b96958d7b
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005
|
||||
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
@@ -1783,8 +1783,8 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260422030642-84e9ebcd4edc h1:WEwV9QBvFzOZhvJbpcRYzgA1jAHnzq3IB2qhs+eECIc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260422030642-84e9ebcd4edc/go.mod h1:rCz5Nds6Zi/5uaj51oRDYdj5fZ5uULmKbuBAgNLuI+w=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084604-0d6b96958d7b h1:G1f0+6msw1sX1d9D/91tdZ++b8qpXuHktau3vPh4X8I=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084604-0d6b96958d7b/go.mod h1:rCz5Nds6Zi/5uaj51oRDYdj5fZ5uULmKbuBAgNLuI+w=
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005 h1:3sWwcjGXGjG9mLBWa7AyLq+QSi0udTAx21pfVQRFMBE=
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
@@ -198,7 +198,7 @@ var (
|
||||
STORAGE_PUBLIC_CLOUD, STORAGE_CLOUD_SSD, STORAGE_CLOUD_ESSD_PL0, STORAGE_CLOUD_ESSD, STORAGE_CLOUD_ESSD_PL2, STORAGE_CLOUD_ESSD_PL3,
|
||||
STORAGE_EPHEMERAL_SSD, STORAGE_CLOUD_EFFICIENCY,
|
||||
STORAGE_STANDARD_LRS, STORAGE_STANDARDSSD_LRS, STORAGE_PREMIUM_LRS,
|
||||
STORAGE_GP2_SSD, STORAGE_GP3_SSD, STORAGE_IO1_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,
|
||||
STORAGE_GP2_SSD, STORAGE_GP3_SSD, STORAGE_IO1_SSD, STORAGE_IO2_SSD, STORAGE_ST1_HDD, STORAGE_SC1_HDD, STORAGE_STANDARD_HDD,
|
||||
STORAGE_LOCAL_BASIC, STORAGE_LOCAL_SSD, STORAGE_CLOUD_BASIC, STORAGE_CLOUD_PREMIUM,
|
||||
STORAGE_HUAWEI_SSD, STORAGE_HUAWEI_SAS, STORAGE_HUAWEI_SATA,
|
||||
STORAGE_OPENSTACK_ISCSI, STORAGE_UCLOUD_CLOUD_NORMAL, STORAGE_UCLOUD_CLOUD_SSD,
|
||||
|
||||
@@ -84,6 +84,15 @@ func (self *SAwsGuestDriver) GetWindowsUserDataType() string {
|
||||
return cloudprovider.CLOUD_EC2
|
||||
}
|
||||
|
||||
// AWS EBS 单卷容量:参见 https://docs.aws.amazon.com/ebs/latest/userguide/ebs-volume-types.html
|
||||
const (
|
||||
awsEbsGp2MaxSizeGiB = 16384 // gp2 最大 16 TiB
|
||||
awsEbsGp3MaxSizeGiB = 65536 // gp3 最大 64 TiB
|
||||
awsEbsIoMaxSizeGiB = 16384 // io1/io2 常规卷最大 16 TiB(io2 Block Express 另受实例等约束)
|
||||
awsEbsHddMaxSizeGiB = 16384 // st1/sc1 最大 16 TiB
|
||||
awsEbsSt1Sc1MinSizeGiB = 125 // st1/sc1 最小 125 GiB
|
||||
)
|
||||
|
||||
func (self *SAwsGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCapability {
|
||||
return cloudprovider.SInstanceCapability{
|
||||
Hypervisor: self.GetHypervisor(),
|
||||
@@ -100,18 +109,21 @@ func (self *SAwsGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCapa
|
||||
},
|
||||
Storages: cloudprovider.Storage{
|
||||
DataDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP2_SSD, MaxSizeGb: 16384, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP3_SSD, MaxSizeGb: 16384, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO1_SSD, MaxSizeGb: 16384, MinSizeGb: 4, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_ST1_HDD, MaxSizeGb: 16384, MinSizeGb: 500, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_SC1_HDD, MaxSizeGb: 16384, MinSizeGb: 500, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP2_SSD, MaxSizeGb: awsEbsGp2MaxSizeGiB, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP3_SSD, MaxSizeGb: awsEbsGp3MaxSizeGiB, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO1_SSD, MaxSizeGb: awsEbsIoMaxSizeGiB, MinSizeGb: 4, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO2_SSD, MaxSizeGb: awsEbsIoMaxSizeGiB, MinSizeGb: 4, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_ST1_HDD, MaxSizeGb: awsEbsHddMaxSizeGiB, MinSizeGb: awsEbsSt1Sc1MinSizeGiB, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_SC1_HDD, MaxSizeGb: awsEbsHddMaxSizeGiB, MinSizeGb: awsEbsSt1Sc1MinSizeGiB, StepSizeGb: 1, Resizable: true},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_STANDARD_HDD, MaxSizeGb: 1024, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
|
||||
},
|
||||
SysDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP2_SSD, MaxSizeGb: 16384, MinSizeGb: 1, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO1_SSD, MaxSizeGb: 16384, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_ST1_HDD, MaxSizeGb: 16384, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_SC1_HDD, MaxSizeGb: 16384, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP2_SSD, MaxSizeGb: awsEbsGp2MaxSizeGiB, MinSizeGb: 1, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GP3_SSD, MaxSizeGb: awsEbsGp3MaxSizeGiB, MinSizeGb: 1, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO1_SSD, MaxSizeGb: awsEbsIoMaxSizeGiB, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_IO2_SSD, MaxSizeGb: awsEbsIoMaxSizeGiB, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_ST1_HDD, MaxSizeGb: awsEbsHddMaxSizeGiB, MinSizeGb: awsEbsSt1Sc1MinSizeGiB, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_SC1_HDD, MaxSizeGb: awsEbsHddMaxSizeGiB, MinSizeGb: awsEbsSt1Sc1MinSizeGiB, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_STANDARD_HDD, MaxSizeGb: 1024, MinSizeGb: 1, StepSizeGb: 1, Resizable: false},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -48,17 +48,21 @@ func (self *SAwsHostDriver) GetProvider() string {
|
||||
}
|
||||
|
||||
func (self *SAwsHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if storage.StorageType == api.STORAGE_GP2_SSD || storage.StorageType == api.STORAGE_GP3_SSD {
|
||||
if storage.StorageType == api.STORAGE_GP2_SSD {
|
||||
if sizeGb < 1 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 1G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == api.STORAGE_GP3_SSD {
|
||||
if sizeGb < 1 || sizeGb > 65536 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 1G ~ 65536GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == api.STORAGE_IO1_SSD || storage.StorageType == api.STORAGE_IO2_SSD {
|
||||
if sizeGb < 4 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 4G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_ST1_HDD, api.STORAGE_SC1_HDD}) {
|
||||
if sizeGb < 500 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 500G ~ 16384GB", storage.StorageType)
|
||||
if sizeGb < 125 || sizeGb > 16384 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 125G ~ 16384GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == api.STORAGE_STANDARD_HDD {
|
||||
if sizeGb < 1 || sizeGb > 1024 {
|
||||
|
||||
Vendored
+1
-1
@@ -2598,7 +2598,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.3.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260422030642-84e9ebcd4edc
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084604-0d6b96958d7b
|
||||
## explicit; go 1.24
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
+229
-1
@@ -155,8 +155,236 @@ func (b *SBucket) GetWebsiteUrl() string {
|
||||
return fmt.Sprintf("http://%s.%s", b.Name, b.region.getS3WebsiteEndpoint())
|
||||
}
|
||||
|
||||
// S3 daily storage metrics (BucketSizeBytes / NumberOfObjects) are published to CloudWatch once per day
|
||||
// with Period 86400. See https://docs.aws.amazon.com/AmazonS3/latest/userguide/metrics-dimensions.html
|
||||
const (
|
||||
s3BucketMetricsNamespace = "AWS/S3"
|
||||
s3BucketMetricsPeriod = "86400"
|
||||
)
|
||||
|
||||
type s3CwMetricDimension struct {
|
||||
Name string `xml:"Name"`
|
||||
Value string `xml:"Value"`
|
||||
}
|
||||
|
||||
type s3CwListedMetric struct {
|
||||
Namespace string `xml:"Namespace"`
|
||||
MetricName string `xml:"MetricName"`
|
||||
Dimensions []s3CwMetricDimension `xml:"Dimensions>member"`
|
||||
}
|
||||
|
||||
// s3CwListMetricsOutput decodes the ListMetricsResult element only: cloudmux Unmarshal
|
||||
// uses DecodeElement(..., StartElement{Name: Operation+"Result"}) so fields must match
|
||||
// direct children of ListMetricsResult (Metrics, NextToken), not wrap ListMetricsResult again.
|
||||
type s3CwListMetricsOutput struct {
|
||||
Metrics []s3CwListedMetric `xml:"Metrics>member"`
|
||||
NextToken string `xml:"NextToken"`
|
||||
}
|
||||
|
||||
func s3CwMetricHasFilterId(dimensions []s3CwMetricDimension) bool {
|
||||
for i := range dimensions {
|
||||
if dimensions[i].Name == "FilterId" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func s3CwFindDimensionValue(dimensions []s3CwMetricDimension, name string) string {
|
||||
for i := range dimensions {
|
||||
if dimensions[i].Name == name {
|
||||
return dimensions[i].Value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// s3CwKnownStorageTypes probes GetMetricStatistics when ListMetrics omits metrics
|
||||
// (e.g. no data reported in past two weeks per AWS ListMetrics behavior).
|
||||
var s3CwKnownStorageTypes = []string{
|
||||
"StandardStorage",
|
||||
"StandardIAStorage",
|
||||
"OneZoneIAStorage",
|
||||
"ReducedRedundancyStorage",
|
||||
"IntelligentTieringFAStorage",
|
||||
"IntelligentTieringAIAStorage",
|
||||
"IntelligentTieringArchiveStorage",
|
||||
"IntelligentTieringDeepArchiveStorage",
|
||||
"GlacierStorage",
|
||||
"GlacierInstantRetrievalStorage",
|
||||
"DeepArchiveStorage",
|
||||
"OutpostsStandardStorage",
|
||||
"OutpostsOneZoneIAStorage",
|
||||
"ExpressOneZoneStorage",
|
||||
"ExpressOneZoneIAStorage",
|
||||
}
|
||||
|
||||
func (b *SBucket) listS3BucketStorageTypes() (map[string]struct{}, error) {
|
||||
storageTypes := map[string]struct{}{}
|
||||
var nextToken string
|
||||
for {
|
||||
params := map[string]string{
|
||||
"Namespace": s3BucketMetricsNamespace,
|
||||
"Dimensions.member.1.Name": "BucketName",
|
||||
"Dimensions.member.1.Value": b.Name,
|
||||
}
|
||||
if len(nextToken) > 0 {
|
||||
params["NextToken"] = nextToken
|
||||
}
|
||||
out := s3CwListMetricsOutput{}
|
||||
err := b.region.client.monitorRequest(b.region.RegionId, "ListMetrics", params, &out)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, m := range out.Metrics {
|
||||
if m.MetricName != "BucketSizeBytes" && m.MetricName != "NumberOfObjects" {
|
||||
continue
|
||||
}
|
||||
if s3CwMetricHasFilterId(m.Dimensions) {
|
||||
continue
|
||||
}
|
||||
st := s3CwFindDimensionValue(m.Dimensions, "StorageType")
|
||||
if len(st) == 0 {
|
||||
continue
|
||||
}
|
||||
storageTypes[st] = struct{}{}
|
||||
}
|
||||
nextToken = out.NextToken
|
||||
if len(nextToken) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return storageTypes, nil
|
||||
}
|
||||
|
||||
// s3CwLatestPointValue picks the latest datapoint; S3 daily storage metrics document
|
||||
// Average as the valid statistic, while some samples use Maximum — take whichever is set.
|
||||
func s3CwLatestPointValue(dps Datapoints) float64 {
|
||||
var bestTs time.Time
|
||||
var bestVal float64
|
||||
found := false
|
||||
for i := range dps.Datapoints {
|
||||
d := dps.Datapoints[i]
|
||||
if !found || d.Timestamp.After(bestTs) {
|
||||
bestTs = d.Timestamp
|
||||
// S3 daily storage metrics publish Average; Maximum may be unset in the XML response.
|
||||
bestVal = d.Average
|
||||
if bestVal == 0 {
|
||||
bestVal = d.Maximum
|
||||
}
|
||||
if bestVal == 0 {
|
||||
bestVal = d.Sum
|
||||
}
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return 0
|
||||
}
|
||||
return bestVal
|
||||
}
|
||||
|
||||
func (b *SBucket) getS3BucketMetricDatapoints(metricName, storageType string, start, end time.Time) (Datapoints, error) {
|
||||
params := map[string]string{
|
||||
"Namespace": s3BucketMetricsNamespace,
|
||||
"MetricName": metricName,
|
||||
"Dimensions.member.1.Name": "BucketName",
|
||||
"Dimensions.member.1.Value": b.Name,
|
||||
"Dimensions.member.2.Name": "StorageType",
|
||||
"Dimensions.member.2.Value": storageType,
|
||||
"StartTime": start.UTC().Format(time.RFC3339),
|
||||
"EndTime": end.UTC().Format(time.RFC3339),
|
||||
"Period": s3BucketMetricsPeriod,
|
||||
"Statistics.member.1": "Average",
|
||||
"Statistics.member.2": "Maximum",
|
||||
}
|
||||
ret := Datapoints{}
|
||||
err := b.region.client.monitorRequest(b.region.RegionId, "GetMetricStatistics", params, &ret)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func s3CwHasDatapoints(dps Datapoints) bool {
|
||||
return len(dps.Datapoints) > 0
|
||||
}
|
||||
|
||||
func (b *SBucket) discoverS3BucketStorageTypesByProbe(start, end time.Time) (map[string]struct{}, error) {
|
||||
storageTypes := map[string]struct{}{}
|
||||
for _, st := range s3CwKnownStorageTypes {
|
||||
dps, err := b.getS3BucketMetricDatapoints("BucketSizeBytes", st, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s3CwHasDatapoints(dps) {
|
||||
storageTypes[st] = struct{}{}
|
||||
continue
|
||||
}
|
||||
dps2, err := b.getS3BucketMetricDatapoints("NumberOfObjects", st, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s3CwHasDatapoints(dps2) {
|
||||
storageTypes[st] = struct{}{}
|
||||
}
|
||||
}
|
||||
return storageTypes, nil
|
||||
}
|
||||
|
||||
func (b *SBucket) getS3BucketMetricValue(metricName, storageType string, start, end time.Time) (float64, error) {
|
||||
ret, err := b.getS3BucketMetricDatapoints(metricName, storageType, start, end)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return s3CwLatestPointValue(ret), nil
|
||||
}
|
||||
|
||||
func (b *SBucket) getStatsFromCloudWatch() (cloudprovider.SBucketStats, error) {
|
||||
stats := cloudprovider.SBucketStats{}
|
||||
if b.region == nil || b.region.client == nil {
|
||||
return stats, errors.Error("bucket region or client is nil")
|
||||
}
|
||||
end := time.Now().UTC()
|
||||
start := end.Add(-8 * 24 * time.Hour)
|
||||
storageTypes, err := b.listS3BucketStorageTypes()
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
if len(storageTypes) == 0 {
|
||||
storageTypes, err = b.discoverS3BucketStorageTypesByProbe(start, end)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
}
|
||||
if len(storageTypes) == 0 {
|
||||
return stats, nil
|
||||
}
|
||||
var sizeSum int64
|
||||
var countSum int64
|
||||
for st := range storageTypes {
|
||||
sz, err := b.getS3BucketMetricValue("BucketSizeBytes", st, start, end)
|
||||
if err != nil {
|
||||
return stats, errors.Wrapf(err, "BucketSizeBytes %s", st)
|
||||
}
|
||||
sizeSum += int64(sz)
|
||||
cnt, err := b.getS3BucketMetricValue("NumberOfObjects", st, start, end)
|
||||
if err != nil {
|
||||
return stats, errors.Wrapf(err, "NumberOfObjects %s", st)
|
||||
}
|
||||
countSum += int64(cnt)
|
||||
}
|
||||
stats.SizeBytes = sizeSum
|
||||
stats.ObjectCount = int(countSum)
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStats() cloudprovider.SBucketStats {
|
||||
stats, _ := cloudprovider.GetIBucketStats(b)
|
||||
stats, err := b.getStatsFromCloudWatch()
|
||||
if err != nil {
|
||||
log.Errorf("getStatsFromCloudWatch %s: %v", b.Name, err)
|
||||
return cloudprovider.SBucketStats{SizeBytes: -1, ObjectCount: -1}
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
|
||||
+21
-8
@@ -351,17 +351,29 @@ func (self *SRegion) ResizeDisk(diskId string, sizeGb int64) error {
|
||||
return self.ec2Request("ModifyVolume", params, &ret)
|
||||
}
|
||||
|
||||
// io1类型的卷需要指定IOPS参数,最大不超过32000。这里根据aws网站的建议值进行设置
|
||||
// io2类型的卷需要指定IOPS参数,最大不超过64000。
|
||||
// GenDiskIops Base 100, 卷每增加2G。IOPS增加1。最多到3000 iops
|
||||
// io1 卷 IOPS 默认按容量估算,上限 32000(参见 AWS Provisioned IOPS 文档)
|
||||
// io2 卷 IOPS 上限 64000
|
||||
// GenDiskIops: Base 100, 卷每增加 2GiB IOPS 增加 1
|
||||
func GenDiskIops(diskType string, sizeGB int) int64 {
|
||||
switch diskType {
|
||||
case api.STORAGE_IO1_SSD, api.STORAGE_IO2_SSD:
|
||||
case api.STORAGE_IO1_SSD:
|
||||
iops := int64(100 + sizeGB/2)
|
||||
if iops < 32000 {
|
||||
return iops
|
||||
if iops < 100 {
|
||||
return 100
|
||||
}
|
||||
return 100
|
||||
if iops > 32000 {
|
||||
return 32000
|
||||
}
|
||||
return iops
|
||||
case api.STORAGE_IO2_SSD:
|
||||
iops := int64(100 + sizeGB/2)
|
||||
if iops < 100 {
|
||||
return 100
|
||||
}
|
||||
if iops > 64000 {
|
||||
return 64000
|
||||
}
|
||||
return iops
|
||||
case api.STORAGE_GP3_SSD:
|
||||
return 3000
|
||||
}
|
||||
@@ -395,7 +407,8 @@ func (self *SRegion) CreateDisk(zoneId string, volumeType string, opts *cloudpro
|
||||
if len(opts.SnapshotId) > 0 {
|
||||
params["SnapshotId"] = opts.SnapshotId
|
||||
}
|
||||
if opts.Throughput >= 125 && opts.Throughput <= 1000 && volumeType == api.STORAGE_GP3_SSD {
|
||||
// gp3 吞吐:125–2000 MiB/s(参见 AWS gp3 文档)
|
||||
if opts.Throughput >= 125 && opts.Throughput <= 2000 && volumeType == api.STORAGE_GP3_SSD {
|
||||
params["Throughput"] = fmt.Sprintf("%d", opts.Throughput)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -798,7 +798,7 @@ func (self *SRegion) CreateInstance(name string, image *SImage, instanceType str
|
||||
}) {
|
||||
params[fmt.Sprintf("BlockDeviceMapping.%d.Ebs.Iops", i+1)] = fmt.Sprintf("%d", iops)
|
||||
}
|
||||
if disk.Throughput >= 125 && disk.Throughput <= 1000 && disk.StorageType == api.STORAGE_GP3_SSD {
|
||||
if disk.Throughput >= 125 && disk.Throughput <= 2000 && disk.StorageType == api.STORAGE_GP3_SSD {
|
||||
params[fmt.Sprintf("BlockDeviceMapping.%d.Ebs.Throughput", i+1)] = fmt.Sprintf("%d", disk.Throughput)
|
||||
}
|
||||
}
|
||||
|
||||
+12
-8
@@ -579,17 +579,21 @@ func (self *SAzureClient) getUniqName(resourceGroup, resourceType, name string)
|
||||
newName := name
|
||||
for i := 0; i < 20; i++ {
|
||||
err := self._get(prefix+newName, nil, url.Values{}, false)
|
||||
if err == nil {
|
||||
info := strings.Split(newName, "-")
|
||||
num, err := strconv.Atoi(info[len(info)-1])
|
||||
if err != nil {
|
||||
info = append(info, "1")
|
||||
} else {
|
||||
info[len(info)-1] = fmt.Sprintf("%d", num+1)
|
||||
}
|
||||
newName = strings.Join(info, "-")
|
||||
continue
|
||||
}
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
return newName, nil
|
||||
}
|
||||
info := strings.Split(newName, "-")
|
||||
num, err := strconv.Atoi(info[len(info)-1])
|
||||
if err != nil {
|
||||
info = append(info, "1")
|
||||
} else {
|
||||
info[len(info)-1] = fmt.Sprintf("%d", num+1)
|
||||
}
|
||||
newName = strings.Join(info, "-")
|
||||
return "", err
|
||||
}
|
||||
return "", fmt.Errorf("not find uniq name for %s[%s]", resourceType, name)
|
||||
}
|
||||
|
||||
+3
@@ -69,6 +69,9 @@ func (self *SRegion) AllocateEIP(name, projectId string) (*SEipAddress, error) {
|
||||
params := map[string]interface{}{
|
||||
"Location": self.Name,
|
||||
"Name": name,
|
||||
"Sku": map[string]string{
|
||||
"Name": "Standard",
|
||||
},
|
||||
"Properties": map[string]string{
|
||||
"PublicIPAddressVersion": "IPv4",
|
||||
"PublicIPAllocationMethod": "Static",
|
||||
|
||||
Reference in New Issue
Block a user