mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-09-24 16:03:43 +08:00
Merge pull request #3690 from tb365/bugfix/tb-bugfix-111502
Bugfix/tb bugfix 111502
This commit is contained in:
@@ -20,10 +20,9 @@ import (
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -352,6 +351,20 @@ func (self *SManagedVirtualizedGuestDriver) RequestDeployGuestOnHost(ctx context
|
||||
|
||||
switch action {
|
||||
case "create":
|
||||
region := host.GetRegion()
|
||||
if len(desc.InstanceType) == 0 && region != nil {
|
||||
sku, err := models.ServerSkuManager.GetMatchedSku(region.GetId(), int64(desc.Cpu), int64(desc.MemoryMB))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ManagedVirtualizedGuestDriver.RequestDeployGuestOnHost.GetMatchedSku")
|
||||
}
|
||||
|
||||
if sku == nil {
|
||||
return errors.Wrap(errors.ErrNotFound, "ManagedVirtualizedGuestDriver.RequestDeployGuestOnHost.GetMatchedSku")
|
||||
}
|
||||
|
||||
desc.InstanceType = sku.Name
|
||||
}
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
return guest.GetDriver().RemoteDeployGuestForCreate(ctx, task.GetUserCred(), guest, host, desc)
|
||||
})
|
||||
@@ -704,7 +717,8 @@ func (self *SManagedVirtualizedGuestDriver) DoGuestCreateDisksTask(ctx context.C
|
||||
}
|
||||
|
||||
func (self *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Context, guest *models.SGuest, task taskman.ITask, instanceType string, vcpuCount, vmemSize int64) error {
|
||||
ihost, err := guest.GetHost().GetIHost()
|
||||
host := guest.GetHost()
|
||||
ihost, err := host.GetIHost()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -714,6 +728,19 @@ func (self *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Co
|
||||
return err
|
||||
}
|
||||
|
||||
if len(instanceType) == 0 {
|
||||
sku, err := models.ServerSkuManager.GetMatchedSku(host.GetRegion().GetId(), vcpuCount, vmemSize)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "ManagedVirtualizedGuestDriver.RequestChangeVmConfig.GetMatchedSku")
|
||||
}
|
||||
|
||||
if sku == nil {
|
||||
return errors.Wrap(errors.ErrNotFound, "ManagedVirtualizedGuestDriver.RequestChangeVmConfig.GetMatchedSku")
|
||||
}
|
||||
|
||||
instanceType = sku.Name
|
||||
}
|
||||
|
||||
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
|
||||
config := &cloudprovider.SManagedVMChangeConfig{
|
||||
Cpu: int(vcpuCount),
|
||||
@@ -722,7 +749,7 @@ func (self *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Co
|
||||
}
|
||||
err := iVM.ChangeConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.ChangeConfig")
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitCreated(time.Second*5, time.Minute*5, func() bool {
|
||||
@@ -745,7 +772,7 @@ func (self *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Co
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.WaitCreated")
|
||||
}
|
||||
|
||||
instanceType = iVM.GetInstanceType()
|
||||
@@ -755,7 +782,7 @@ func (self *SManagedVirtualizedGuestDriver) RequestChangeVmConfig(ctx context.Co
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "GuestDriver.RequestChangeVmConfig.Update")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -806,6 +806,19 @@ func (manager *SServerSkuManager) ListItemFilter(ctx context.Context, q *sqlchem
|
||||
return q, err
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) GetMatchedSku(regionId string, cpu int64, memMB int64) (*SServerSku, error) {
|
||||
ret := &SServerSku{}
|
||||
|
||||
q := manager.Query()
|
||||
q = q.Equals("cpu_core_count", cpu).Equals("memory_size_mb", memMB).Equals("cloudregion_id", regionId).Equals("postpaid_status", api.SkuStatusAvailable)
|
||||
err := q.First(ret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ServerSkuManager.GetMatchedSku")
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (manager *SServerSkuManager) FetchSkuByNameAndProvider(name string, provider string, checkConsistency bool) (*SServerSku, error) {
|
||||
q := manager.Query()
|
||||
q = q.Equals("name", name)
|
||||
|
||||
@@ -86,9 +86,6 @@ type ComputeOptions struct {
|
||||
SyncSkusDay int `default:"1" help:"Days auto sync skus data, default 1 day"`
|
||||
SyncSkusHour int `default:"3" help:"What hour start sync skus, default 03:00"`
|
||||
|
||||
// aws instance type file
|
||||
DefaultAwsInstanceTypeFile string `default:"/etc/yunion/aws_instance_types.json" help:"aws instance type json file"`
|
||||
|
||||
ConvertHypervisorDefaultTemplate string `help:"Kvm baremetal convert option"`
|
||||
ConvertEsxiDefaultTemplate string `help:"ESXI baremetal convert option"`
|
||||
ConvertKubeletDockerVolumeSize string `default:"256g" help:"Docker volume size"`
|
||||
|
||||
@@ -173,7 +173,7 @@ func (self *SHost) GetInstanceById(instanceId string) (*SInstance, error) {
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData)
|
||||
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr
|
||||
return vm, err
|
||||
}
|
||||
|
||||
func (self *SHost) _createVM(name, imgId string, sysDisk cloudprovider.SDiskInfo, cpu, memMB int, instanceType string,
|
||||
func (self *SHost) _createVM(name, imgId string, sysDisk cloudprovider.SDiskInfo, instanceType string,
|
||||
networkId, ipAddr, desc, passwd string,
|
||||
dataDisks []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string) (string, error) {
|
||||
// 网络配置及安全组绑定
|
||||
@@ -268,28 +268,7 @@ func (self *SHost) _createVM(name, imgId string, sysDisk cloudprovider.SDiskInfo
|
||||
}
|
||||
}
|
||||
|
||||
// 匹配实例类型
|
||||
instanceTypes, err := self.zone.region.GetMatchInstanceTypes(cpu, memMB, 0, self.zone.ZoneId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(instanceTypes) == 0 {
|
||||
return "", fmt.Errorf("instance type %dC%dMB not avaiable", cpu, memMB)
|
||||
}
|
||||
|
||||
var vmId string
|
||||
for _, instType := range instanceTypes {
|
||||
instanceTypeId := instType.InstanceTypeId
|
||||
log.Debugf("Try instancetype : %s", instanceTypeId)
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, networkId, secgroupId, self.zone.ZoneId, desc, disks, ipAddr, keypair, userData)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instanceTypeId, err)
|
||||
} else {
|
||||
return vmId, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Failed to create, %s", err.Error())
|
||||
return "", fmt.Errorf("Failed to create, instance type should not be empty")
|
||||
}
|
||||
|
||||
func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
|
||||
|
||||
@@ -467,7 +467,7 @@ func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.S
|
||||
if len(config.InstanceType) > 0 {
|
||||
return self.ChangeConfig2(ctx, config.InstanceType)
|
||||
}
|
||||
return self.host.zone.region.ChangeVMConfig(self.ZoneId, self.InstanceId, config.Cpu, config.MemoryMB, nil)
|
||||
return errors.Wrap(errors.ErrClient, "Instance.ChangeConfig.InstanceTypeIsEmpty")
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error {
|
||||
@@ -1002,29 +1002,6 @@ func (self *SRegion) ReplaceSystemDisk(ctx context.Context, instanceId string, i
|
||||
return tempInstance.Disks[0], nil
|
||||
}
|
||||
|
||||
func (self *SRegion) ChangeVMConfig(zoneId string, instanceId string, ncpu int, vmem int, disks []*SDisk) error {
|
||||
params := &ec2.ModifyInstanceAttributeInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
instanceTypes, err := self.GetMatchInstanceTypes(ncpu, vmem, 0, zoneId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, instancetype := range instanceTypes {
|
||||
t := &ec2.AttributeValue{Value: &instancetype.InstanceTypeId}
|
||||
params.SetInstanceType(t)
|
||||
|
||||
_, err := self.ec2Client.ModifyInstanceAttribute(params)
|
||||
if err != nil {
|
||||
log.Errorf("Failed for %s: %s", instancetype.InstanceTypeId, err)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("Failed to change vm config, specification not supported")
|
||||
}
|
||||
|
||||
func (self *SRegion) ChangeVMConfig2(zoneId string, instanceId string, instanceType string, disks []*SDisk) error {
|
||||
params := &ec2.ModifyInstanceAttributeInput{}
|
||||
params.SetInstanceId(instanceId)
|
||||
|
||||
@@ -1,121 +0,0 @@
|
||||
// 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 aws
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
||||
"yunion.io/x/log"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/compute/options"
|
||||
)
|
||||
|
||||
type Cpu struct {
|
||||
Cores int `json:"cores"`
|
||||
Units string `json:"units"`
|
||||
}
|
||||
|
||||
type CpuCredits struct {
|
||||
OptimizationSupported bool `json:"optimizationSupported"`
|
||||
}
|
||||
|
||||
type ProcessorFeatures struct {
|
||||
AESNI bool `json:"AES-NI"`
|
||||
AVX bool `json:"AVX"`
|
||||
Turbo bool `json:"Turbo"`
|
||||
}
|
||||
|
||||
type SInstanceType struct {
|
||||
Architectures []string `json:"architectures"`
|
||||
Cpu Cpu `json:"cpu"`
|
||||
CpuCredits CpuCredits `json:"cpuCredits"`
|
||||
Description string `json:"description"`
|
||||
EbsEncryptionSupported bool `json:"ebsEncryptionSupported"`
|
||||
EbsOnly bool `json:"ebsOnly"`
|
||||
Family string `json:"family"`
|
||||
FreeTierEligible bool `json:"freeTierEligible"`
|
||||
Ipv6Support bool `json:"ipv6Support"`
|
||||
Memory float32 `json:"memory"`
|
||||
NetworkPerformance string `json:"networkPerformance"`
|
||||
PhysicalProcessor string `json:"physicalProcessor"`
|
||||
ProcessorFeatures ProcessorFeatures `json:"processorFeatures"`
|
||||
ProcessorSpeed float32 `json:"processorSpeed"`
|
||||
SpotSupported bool `json:"spotSupported"`
|
||||
InstanceTypeId string `json:"typeName"`
|
||||
VirtualizationTypes []string `json:"virtualizationTypes"`
|
||||
Vpc bool `json:"vpc"`
|
||||
VpcOnly bool `json:"vpcOnly"`
|
||||
Windows bool `json:"windows"`
|
||||
}
|
||||
|
||||
func (self *SInstanceType) memoryMB() int {
|
||||
return int(self.Memory * 1024)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceTypes() ([]SInstanceType, error) {
|
||||
if self.instanceTypes == nil {
|
||||
var GlobalInstanceTyes []SInstanceType
|
||||
instanceTypes, err := ioutil.ReadFile(options.Options.DefaultAwsInstanceTypeFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(instanceTypes), &GlobalInstanceTyes)
|
||||
if err != nil {
|
||||
log.Errorf("GetInstanceTypes %s", err)
|
||||
return nil, err
|
||||
}
|
||||
return GlobalInstanceTyes, err
|
||||
} else {
|
||||
return self.instanceTypes, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceType(instanceTypeId string) (*SInstanceType, error) {
|
||||
ret, err := self.GetInstanceTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, item := range ret {
|
||||
if item.InstanceTypeId == instanceTypeId {
|
||||
return &item, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("instancetype %s not found", instanceTypeId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetMatchInstanceTypes(cpu int, memMB int, gpu int, zoneId string) ([]SInstanceType, error) {
|
||||
types, err := self.GetInstanceTypes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 实例类型顺序: 微型实例 -> 通用型 -> 计算优化型 ...
|
||||
// todo:部分实例类型 需要启用ena才能正常启动。需要过滤掉。
|
||||
// https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/enhanced-networking-ena.html
|
||||
ret := []SInstanceType{}
|
||||
for _, t := range types {
|
||||
// cpu & mem & disk & ena 都匹配才行
|
||||
if t.Cpu.Cores == cpu && t.memoryMB() == memMB {
|
||||
ret = append(ret, t)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
@@ -89,8 +89,7 @@ type SRegion struct {
|
||||
izones []cloudprovider.ICloudZone
|
||||
ivpcs []cloudprovider.ICloudVpc
|
||||
|
||||
storageCache *SStoragecache
|
||||
instanceTypes []SInstanceType
|
||||
storageCache *SStoragecache
|
||||
|
||||
RegionEndpoint string
|
||||
RegionId string // 这里为保持一致沿用阿里云RegionId的叫法, 与AWS RegionName字段对应
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// 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 shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/aws"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type InstanceTypeListOptions struct {
|
||||
}
|
||||
shellutils.R(&InstanceTypeListOptions{}, "instance-type-list", "List intance types", func(cli *aws.SRegion, args *InstanceTypeListOptions) error {
|
||||
instanceTypes, e := cli.GetInstanceTypes()
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(instanceTypes, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceMatchOptions struct {
|
||||
CPU int `help:"CPU count"`
|
||||
MEM int `help:"Memory in MB"`
|
||||
GPU int `help:"GPU size"`
|
||||
Zone string `help:"Test in zone"`
|
||||
}
|
||||
shellutils.R(&InstanceMatchOptions{}, "instance-type-select", "Select matching instance types", func(cli *aws.SRegion, args *InstanceMatchOptions) error {
|
||||
instanceTypes, e := cli.GetMatchInstanceTypes(args.CPU, args.MEM, args.GPU, args.Zone)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
printList(instanceTypes, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -22,10 +22,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/osprofile"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
@@ -590,10 +589,15 @@ func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.S
|
||||
func (self *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error {
|
||||
err := self.host.zone.region.ChangeVMConfig2(self.OSEXTAZAvailabilityZone, self.GetId(), instanceType, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "Instance.ChangeConfig2.ChangeVMConfig2")
|
||||
}
|
||||
|
||||
return cloudprovider.WaitStatusWithDelay(self, api.VM_READY, 15*time.Second, 15*time.Second, 180*time.Second)
|
||||
err = cloudprovider.WaitStatusWithDelay(self, api.VM_READY, 15*time.Second, 15*time.Second, 180*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Instance.ChangeConfig2.WaitStatusWithDelay")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// todo:// 返回jsonobject感觉很诡异。不能直接知道内部细节
|
||||
|
||||
Reference in New Issue
Block a user