diff --git a/go.mod b/go.mod index 7762b4b9b4..c816fafe01 100644 --- a/go.mod +++ b/go.mod @@ -99,7 +99,7 @@ require ( k8s.io/cri-api v0.28.15 k8s.io/klog/v2 v2.20.0 moul.io/http2curl/v2 v2.3.0 - yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251205085757-3dc9b243b5c2 + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251224112632-f6fa9f38bc63 yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1 yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91 diff --git a/go.sum b/go.sum index 9ccce2737c..e9d536f7c3 100644 --- a/go.sum +++ b/go.sum @@ -1661,8 +1661,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251205085757-3dc9b243b5c2 h1:Im0mZviWDEU5EN1fPoWJwcrGb6u9OxY7oqyYE0PLlHg= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251205085757-3dc9b243b5c2/go.mod h1:aWRX5Phwz3nbHUNnIAm1oVogjguXPYDDgCOy/9Hnnvk= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251224112632-f6fa9f38bc63 h1:hhIEJy8qRWFk/tQ6Fcs1Xjlb4V3a52Pf4Nl0QVz/wig= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251224112632-f6fa9f38bc63/go.mod h1:aWRX5Phwz3nbHUNnIAm1oVogjguXPYDDgCOy/9Hnnvk= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU= yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= diff --git a/pkg/compute/options/options.go b/pkg/compute/options/options.go index 96b82261dd..48351d483e 100644 --- a/pkg/compute/options/options.go +++ b/pkg/compute/options/options.go @@ -240,6 +240,8 @@ type ComputeOptions struct { SkipSyncHostConfigInfoProviders string `help:"Skip sync host cpu and mem config by provider"` SkipSyncStorageConfigInfoProviders string `help:"Skip sync storage capacity and media type config by provider"` + KsyunPostpaidChargeType string `help:"Ksyun server postpaid charge type" choices:"Daily|HourlyInstantSettlement"` + esxi.EsxiOptions NetworkAlwaysManualConfig bool `help:"always manually configure network settings" default:"false"` diff --git a/vendor/modules.txt b/vendor/modules.txt index 12323394c0..983ed72d97 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2243,7 +2243,7 @@ sigs.k8s.io/structured-merge-diff/v4/value # sigs.k8s.io/yaml v1.2.0 ## explicit; go 1.12 sigs.k8s.io/yaml -# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251205085757-3dc9b243b5c2 +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20251224112632-f6fa9f38bc63 ## explicit; go 1.24 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing diff --git a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/instance.go b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/instance.go index a7078cae1e..b59d931e22 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/instance.go +++ b/vendor/yunion.io/x/cloudmux/pkg/cloudprovider/instance.go @@ -161,6 +161,10 @@ type SManagedVMCreateConfig struct { ProjectId string EnableMonitorAgent bool + // 金山云按量付费类型 + // Daily(按量付费(按日月结))、 HourlyInstantSettlement(按量付费(按小时月结)) + KsyunPostpaidChargeType string + SPublicIpInfo Tags map[string]string diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_invoke.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_invoke.go index 8639aaa202..6a9ba2b6c6 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_invoke.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_invoke.go @@ -17,6 +17,7 @@ package aws import ( "io/ioutil" "strings" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -122,15 +123,35 @@ func jsonInvoke(cli *client.Client, apiName, path string, params map[string]inte }, } + isQuery := false + for _, prefix := range []string{"List", "Describe", "Get"} { + if strings.HasPrefix(apiName, prefix) { + isQuery = true + break + } + } + var err error + + retry := 1 + if isQuery { + retry = 3 + } req := cli.NewRequest(op, params, retval) - err := req.Send() - if err != nil { + for i := 0; i < retry; i++ { + err = req.Send() + if err == nil { + return nil + } if e, ok := err.(awserr.RequestFailure); ok && e.StatusCode() == 404 { return cloudprovider.ErrNotFound } + if isHTTPReqErrorRetryable(err) { + time.Sleep(time.Second * 10) + continue + } return err } - return nil + return err } var JsonBuildHandler = request.NamedHandler{ diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_request.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_request.go index 2f9a3f08ab..8a9b9d8fe0 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_request.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws_request.go @@ -21,6 +21,7 @@ import ( "io/ioutil" "net/url" "strings" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/awserr" @@ -268,7 +269,13 @@ func (self *SAwsClient) request(regionId, serviceName, serviceId, apiVersion str } func jsonRequest(cli *client.Client, apiName string, params map[string]string, retval interface{}) error { - method, path := "POST", "/" + method, path, isQuery := "POST", "/", false + for _, prefix := range []string{"List", "Get", "Describe"} { + if strings.HasPrefix(apiName, prefix) { + isQuery = true + break + } + } if cli.ServiceID == CDN_SERVICE_ID { for _, prefix := range []string{"List", "Get"} { if strings.HasPrefix(apiName, prefix) { @@ -343,12 +350,41 @@ func jsonRequest(cli *client.Client, apiName string, params map[string]string, r } req := cli.NewRequest(op, params, retval) - err := req.Send() - if err != nil { + retry := 1 + if isQuery { + retry = 3 + } + var err error + for i := 0; i < retry; i++ { + err = req.Send() + if err == nil { + return nil + } if e, ok := err.(awserr.RequestFailure); ok && e.StatusCode() == 404 { return cloudprovider.ErrNotFound } + if isHTTPReqErrorRetryable(err) { + time.Sleep(time.Second * 10) + continue + } return err } - return nil + return err +} + +func isHTTPReqErrorRetryable(err error) bool { + for _, code := range []string{ + "EOF", + "i/o timeout", + "TLS handshake timeout", + "Client.Timeout exceeded while awaiting headers", + "connection reset by peer", + "context deadline exceeded", + "server misbehaving", + } { + if strings.Contains(err.Error(), code) { + return true + } + } + return false } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/instancetypes.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/instancetypes.go new file mode 100644 index 0000000000..967a9b2c29 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/instancetypes.go @@ -0,0 +1,88 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package baidu + +import ( + "net/url" + "strings" + + "yunion.io/x/pkg/errors" +) + +type SInstanceType struct { + SpecId string + CpuCount int + MemoryCapacityInGb int + EphemeralDiskCount int + CpuModel string + CpuGhz string + EnableJumboFrame bool + NicIpv4Quota int + NicIpv6Quota int + NetworkBandwidth string + NetworkPackage string + NetEthQueueCount string + NetEthMaxQueueCount string + ProductType string + Spec string + ZoneName string + GroupId string + SystemDiskType []string + DataDiskType []string +} + +func (region *SRegion) GetInstanceTypes(zoneName string, specs []string, specIds []string) ([]SInstanceType, error) { + params := url.Values{} + if len(zoneName) > 0 { + params.Set("zoneName", zoneName) + } + if len(specs) > 0 { + params.Set("specs", strings.Join(specs, ",")) + } + if len(specIds) > 0 { + params.Set("specIds", strings.Join(specIds, ",")) + } + + ret := []SInstanceType{} + resp, err := region.bccList("v2/instance/flavorSpec", params) + if err != nil { + return nil, errors.Wrap(err, "list instance") + } + part := struct { + ZoneResources []struct { + ZoneName string + ebsResource struct{} + BccResources struct { + FlavorGroups []struct { + GroupId string + Flavors []SInstanceType + } + } + } + }{} + + err = resp.Unmarshal(&part) + if err != nil { + return nil, err + } + + for _, zoneResource := range part.ZoneResources { + for _, flavorGroup := range zoneResource.BccResources.FlavorGroups { + ret = append(ret, flavorGroup.Flavors...) + } + } + + return ret, nil +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/price.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/price.go new file mode 100644 index 0000000000..d7a9ef2909 --- /dev/null +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/baidu/price.go @@ -0,0 +1,61 @@ +// Copyright 2019 Yunion +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package baidu + +import ( + "yunion.io/x/pkg/errors" +) + +type SInstancePrice struct { + SpecId string + SpecPrices []struct { + Spec string + SpecPrice float64 + Discount float64 + TradePrice float64 + Status string + } +} + +func (region *SRegion) GetInstancePrice(zoneName string, specId, spec string) ([]SInstancePrice, error) { + params := map[string]interface{}{ + "zoneName": zoneName, + "specId": specId, + "spec": spec, + "paymentTiming": "Postpaid", + } + resp, err := region.bccPost("v2/instance/price", nil, params) + if err != nil { + return nil, errors.Wrap(err, "get instance price") + } + ret := []SInstancePrice{} + err = resp.Unmarshal(&ret, "price") + if err != nil { + return nil, errors.Wrap(err, "unmarshal instance price") + } + prepaid := []SInstancePrice{} + params["paymentTiming"] = "Prepaid" + params["purchaseLength"] = 1 + resp, err = region.bccPost("v2/instance/price", nil, params) + if err != nil { + return nil, errors.Wrap(err, "get prepaid instance price") + } + err = resp.Unmarshal(&prepaid, "price") + if err != nil { + return nil, errors.Wrap(err, "unmarshal prepaid price") + } + ret = append(ret, prepaid...) + return ret, nil +} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/host.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/host.go index 65fa9318fc..5c4749cf77 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/host.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/host.go @@ -22,6 +22,7 @@ import ( "yunion.io/x/cloudmux/pkg/cloudprovider" "yunion.io/x/cloudmux/pkg/multicloud" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/utils" "yunion.io/x/jsonutils" ) @@ -92,6 +93,9 @@ func (region *SRegion) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (*SI "SystemDisk.DiskSize": fmt.Sprintf("%d", opts.SysDisk.SizeGB), "SyncTag": "true", } + if utils.IsInStringArray(opts.KsyunPostpaidChargeType, []string{"HourlyInstantSettlement", "Daily"}) { + params["ChargeType"] = opts.KsyunPostpaidChargeType + } if len(opts.Hostname) > 0 { params["HostName"] = opts.Hostname }