Merge pull request #3690 from tb365/bugfix/tb-bugfix-111502

Bugfix/tb bugfix 111502
This commit is contained in:
yunion-ci-robot
2019-11-18 19:21:21 +08:00
committed by GitHub
9 changed files with 59 additions and 232 deletions
+33 -6
View File
@@ -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")
}
}
+13
View File
@@ -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)
-3
View File
@@ -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"`
+3 -24
View File
@@ -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) {
+1 -24
View File
@@ -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)
-121
View File
@@ -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
}
+1 -2
View File
@@ -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字段对应
-48
View File
@@ -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
})
}
+8 -4
View File
@@ -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感觉很诡异。不能直接知道内部细节