mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-21 06:09:39 +08:00
fix(region): support query public cloud vm modification types (#24653)
This commit is contained in:
@@ -138,6 +138,7 @@ func init() {
|
||||
cmd.Perform("kickstart-complete", &options.ServerKickstartCompleteOptions{})
|
||||
cmd.Get("kickstart", new(options.ServerIdOptions))
|
||||
cmd.Get("vnc", new(options.ServerVncOptions))
|
||||
cmd.Get("modification-types", new(options.ServerIdOptions))
|
||||
cmd.Get("desc", new(options.ServerIdOptions))
|
||||
cmd.Get("status", new(options.ServerIdOptions))
|
||||
cmd.Get("iso", new(options.ServerIdOptions))
|
||||
|
||||
@@ -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.20260409072734-6e765c0846d6
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade
|
||||
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
|
||||
|
||||
@@ -1785,8 +1785,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.20260409072734-6e765c0846d6 h1:1+DtEfMWn4AYP/GJMN3aatH2gyOzry0nb//ASMVS7WQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409072734-6e765c0846d6/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade h1:8DBeLhYpDrOW7oP5s/mGlc458zAN0mZq8ZMbH5b+JTA=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
|
||||
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=
|
||||
|
||||
@@ -1572,3 +1572,11 @@ type ServerPerformStatusInput struct {
|
||||
apis.PerformStatusInput
|
||||
Containers map[string]*ContainerPerformStatusInput `json:"containers"`
|
||||
}
|
||||
|
||||
type ServerModificationType struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ServerModificationTypesOutput struct {
|
||||
ModificationTypes []ServerModificationType `json:"modification_types"`
|
||||
}
|
||||
|
||||
@@ -98,6 +98,29 @@ func (self *SGuest) GetDetailsVnc(ctx context.Context, userCred mcclient.TokenCr
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// 获取公有云可变更配置
|
||||
// 目前支持: 阿里云,腾讯云,华为云
|
||||
func (guest *SGuest) GetDetailsModificationTypes(ctx context.Context, userCred mcclient.TokenCredential, input jsonutils.JSONObject) (*api.ServerModificationTypesOutput, error) {
|
||||
if len(guest.ExternalId) == 0 {
|
||||
return nil, httperrors.NewNotFoundError("guest external id is empty")
|
||||
}
|
||||
vm, err := guest.GetIVM(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetIVM")
|
||||
}
|
||||
|
||||
ret := &api.ServerModificationTypesOutput{}
|
||||
ret.ModificationTypes = make([]api.ServerModificationType, 0)
|
||||
modificationTypes, err := vm.GetModificationTypes()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetModificationTypes")
|
||||
}
|
||||
for _, modificationType := range modificationTypes {
|
||||
ret.ModificationTypes = append(ret.ModificationTypes, api.ServerModificationType{Name: modificationType.InstanceType})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) PreCheckPerformAction(
|
||||
ctx context.Context, userCred mcclient.TokenCredential,
|
||||
action string, query jsonutils.JSONObject, data jsonutils.JSONObject,
|
||||
|
||||
Vendored
+1
-1
@@ -2603,7 +2603,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.20260409072734-6e765c0846d6
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260409123844-2f5e06efeade
|
||||
## explicit; go 1.24
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
+4
@@ -388,3 +388,7 @@ type SInstanceDeployOptions struct {
|
||||
DeleteKeypair bool
|
||||
UserData string
|
||||
}
|
||||
|
||||
type SInstanceModificationType struct {
|
||||
InstanceType string
|
||||
}
|
||||
|
||||
+2
@@ -389,6 +389,8 @@ type ICloudVM interface {
|
||||
DeployVM(ctx context.Context, opts *SInstanceDeployOptions) error
|
||||
|
||||
ChangeConfig(ctx context.Context, config *SManagedVMChangeConfig) error
|
||||
// 获取实例可变更类型
|
||||
GetModificationTypes() ([]SInstanceModificationType, error)
|
||||
|
||||
GetVNCInfo(input *ServerVncInput) (*ServerVncOutput, error)
|
||||
// 若有跟随主机删除的选项,需要设置为True
|
||||
|
||||
+55
@@ -522,6 +522,61 @@ func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.S
|
||||
return fmt.Errorf("Failed to change vm config, specification not supported")
|
||||
}
|
||||
|
||||
func (self *SInstance) GetModificationTypes() ([]cloudprovider.SInstanceModificationType, error) {
|
||||
return self.host.zone.region.GetInstanceModificationTypes(self.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceModificationTypes(instanceId string) ([]cloudprovider.SInstanceModificationType, error) {
|
||||
params := map[string]string{
|
||||
"RegionId": self.RegionId,
|
||||
"ResourceId": instanceId,
|
||||
"DestinationResource": "InstanceType",
|
||||
}
|
||||
body, err := self.ecsRequest("DescribeResourcesModification", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeResourcesModification")
|
||||
}
|
||||
|
||||
parsed := struct {
|
||||
AvailableZones struct {
|
||||
AvailableZone []struct {
|
||||
AvailableResources struct {
|
||||
AvailableResource []struct {
|
||||
SupportedResources struct {
|
||||
SupportedResource []struct {
|
||||
Value string
|
||||
Status string
|
||||
StatusCategory string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}{}
|
||||
if err := body.Unmarshal(&parsed); err != nil {
|
||||
return nil, errors.Wrapf(err, "body.Unmarshal")
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.SInstanceModificationType, 0)
|
||||
seen := map[string]struct{}{}
|
||||
for _, zone := range parsed.AvailableZones.AvailableZone {
|
||||
for _, resource := range zone.AvailableResources.AvailableResource {
|
||||
for _, supportedResource := range resource.SupportedResources.SupportedResource {
|
||||
if len(supportedResource.Value) == 0 || len(supportedResource.Status) == 0 || strings.ToLower(supportedResource.Status) != "available" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[supportedResource.Value]; ok {
|
||||
continue
|
||||
}
|
||||
seen[supportedResource.Value] = struct{}{}
|
||||
ret = append(ret, cloudprovider.SInstanceModificationType{InstanceType: supportedResource.Value})
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
||||
return self.host.zone.region.AttachDisk(self.InstanceId, diskId)
|
||||
}
|
||||
|
||||
+25
@@ -682,6 +682,31 @@ func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.S
|
||||
return fmt.Errorf("Failed to change vm config, specification not supported")
|
||||
}
|
||||
|
||||
func (self *SInstance) GetModificationTypes() ([]cloudprovider.SInstanceModificationType, error) {
|
||||
return self.host.zone.region.GetInstanceModificationTypes(self.GetId())
|
||||
}
|
||||
|
||||
// https://console.huaweicloud.com/apiexplorer/#/openapi/ECS/doc?api=ListResizeFlavors
|
||||
func (self *SRegion) GetInstanceModificationTypes(instanceId string) ([]cloudprovider.SInstanceModificationType, error) {
|
||||
params := url.Values{}
|
||||
params.Set("instance_uuid", instanceId)
|
||||
resp, err := self.list(SERVICE_ECS, "cloudservers/resize_flavors", params)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ListResizeFlavors(%s)", instanceId)
|
||||
}
|
||||
flavors := []SInstanceType{}
|
||||
err = resp.Unmarshal(&flavors, "flavors")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "resp.Unmarshal(flavors)")
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.SInstanceModificationType, 0, len(flavors))
|
||||
for _, flavor := range flavors {
|
||||
ret = append(ret, cloudprovider.SInstanceModificationType{InstanceType: flavor.ID})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
|
||||
return self.host.zone.region.GetInstanceVNCUrl(self.GetId())
|
||||
}
|
||||
|
||||
+4
@@ -106,3 +106,7 @@ func (instance *SInstanceBase) GetIsolateDeviceIds() ([]string, error) {
|
||||
func (instance *SInstanceBase) GetContainers() ([]cloudprovider.ICloudContainer, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetContainers")
|
||||
}
|
||||
|
||||
func (instance *SInstanceBase) GetModificationTypes() ([]cloudprovider.SInstanceModificationType, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetModificationTypes")
|
||||
}
|
||||
|
||||
+44
@@ -496,6 +496,50 @@ func (self *SInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SMa
|
||||
return self.host.zone.region.ChangeVMConfig(self.InstanceId, opts.InstanceType)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetModificationTypes() ([]cloudprovider.SInstanceModificationType, error) {
|
||||
return self.host.zone.region.GetInstanceModificationTypes(self.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceModificationTypes(instanceId string) ([]cloudprovider.SInstanceModificationType, error) {
|
||||
params := map[string]string{
|
||||
"Region": self.Region,
|
||||
"InstanceIds.0": instanceId,
|
||||
}
|
||||
body, err := self.cvmRequest("DescribeInstancesModification", params, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "DescribeInstancesModification")
|
||||
}
|
||||
|
||||
resp := struct {
|
||||
InstanceTypeConfigStatusSet []struct {
|
||||
InstanceTypeConfig struct {
|
||||
InstanceType string
|
||||
Zone string
|
||||
}
|
||||
Status string
|
||||
}
|
||||
}{}
|
||||
|
||||
if err := body.Unmarshal(&resp); err != nil {
|
||||
return nil, errors.Wrapf(err, "body.Unmarshal")
|
||||
}
|
||||
|
||||
ret := make([]cloudprovider.SInstanceModificationType, 0)
|
||||
seen := map[string]struct{}{}
|
||||
for _, cfg := range resp.InstanceTypeConfigStatusSet {
|
||||
if !strings.EqualFold(cfg.Status, "SELL") {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := seen[cfg.InstanceTypeConfig.InstanceType]; ok {
|
||||
continue
|
||||
}
|
||||
seen[cfg.InstanceTypeConfig.InstanceType] = struct{}{}
|
||||
ret = append(ret, cloudprovider.SInstanceModificationType{InstanceType: cfg.InstanceTypeConfig.InstanceType})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
||||
return self.host.zone.region.AttachDisk(self.InstanceId, diskId)
|
||||
}
|
||||
|
||||
+4
@@ -296,3 +296,7 @@ func (self *SInstance) GetIsolateDeviceIds() ([]string, error) {
|
||||
func (self *SInstance) GetContainers() ([]cloudprovider.ICloudContainer, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SInstance) GetModificationTypes() ([]cloudprovider.SInstanceModificationType, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user