| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- // 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 guestdrivers
- import (
- "context"
- "fmt"
- "sort"
- "yunion.io/x/cloudmux/pkg/cloudprovider"
- "yunion.io/x/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/utils"
- api "yunion.io/x/onecloud/pkg/apis/compute"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
- "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
- "yunion.io/x/onecloud/pkg/compute/models"
- "yunion.io/x/onecloud/pkg/compute/options"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- )
- type SCNwareGuestDriver struct {
- SManagedVirtualizedGuestDriver
- }
- func init() {
- driver := SCNwareGuestDriver{}
- models.RegisterGuestDriver(&driver)
- }
- func (self *SCNwareGuestDriver) DoScheduleCPUFilter() bool { return true }
- func (self *SCNwareGuestDriver) DoScheduleMemoryFilter() bool { return true }
- func (self *SCNwareGuestDriver) DoScheduleSKUFilter() bool { return false }
- func (self *SCNwareGuestDriver) DoScheduleStorageFilter() bool { return true }
- func (self *SCNwareGuestDriver) GetHypervisor() string {
- return api.HYPERVISOR_CNWARE
- }
- func (self *SCNwareGuestDriver) GetProvider() string {
- return api.CLOUD_PROVIDER_CNWARE
- }
- func (self *SCNwareGuestDriver) GetComputeQuotaKeys(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
- keys := models.SComputeResourceKeys{}
- keys.SBaseProjectQuotaKeys = quotas.OwnerIdProjectQuotaKeys(scope, ownerId)
- keys.CloudEnv = api.CLOUD_ENV_PRIVATE_CLOUD
- keys.Provider = api.CLOUD_PROVIDER_CNWARE
- keys.Brand = brand
- keys.Hypervisor = api.HYPERVISOR_CNWARE
- return keys
- }
- func (self *SCNwareGuestDriver) GetDefaultSysDiskBackend() string {
- return api.STORAGE_CNWARE_LOCAL
- }
- func (self *SCNwareGuestDriver) GetMinimalSysDiskSizeGb() int {
- return 10
- }
- func (self *SCNwareGuestDriver) GetStorageTypes() []string {
- return []string{
- api.STORAGE_CNWARE_FCSAN,
- api.STORAGE_CNWARE_IPSAN,
- api.STORAGE_CNWARE_NAS,
- api.STORAGE_CNWARE_CEPH,
- api.STORAGE_CNWARE_LOCAL,
- api.STORAGE_CNWARE_NVME,
- }
- }
- func (self *SCNwareGuestDriver) GetMaxSecurityGroupCount() int {
- return 0
- }
- func (self *SCNwareGuestDriver) ChooseHostStorage(host *models.SHost, guest *models.SGuest, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
- switch {
- case !options.Options.LockStorageFromCachedimage:
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- case len(diskConfig.ImageId) > 0:
- var (
- image *cloudprovider.SImage
- err error
- )
- obj, err := models.CachedimageManager.FetchById(diskConfig.ImageId)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to fetch cachedimage %s", diskConfig.ImageId)
- }
- cachedimage := obj.(*models.SCachedimage)
- if len(cachedimage.ExternalId) > 0 || cloudprovider.TImageType(cachedimage.ImageType) != cloudprovider.ImageTypeSystem {
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- }
- storages, err := cachedimage.GetStorages()
- if err != nil {
- return nil, errors.Wrapf(err, "unable to GetStorages of cachedimage %s", diskConfig.ImageId)
- }
- if len(storages) == 0 {
- log.Warningf("there no storage associated with cachedimage %q", image.Id)
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- }
- if len(storages) > 1 {
- log.Warningf("there are multiple storageCache associated with caheimage %q", image.Id)
- }
- wantStorageIds := make([]string, len(storages))
- for i := range wantStorageIds {
- wantStorageIds[i] = storages[i].GetId()
- }
- for i := range wantStorageIds {
- if utils.IsInStringArray(wantStorageIds[i], storageIds) {
- log.Infof("use storage %q in where cachedimage %q", wantStorageIds[i], image.Id)
- return &storages[i], nil
- }
- }
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- default:
- ispId := guest.GetMetadata(context.Background(), "__base_instance_snapshot_id", nil)
- if len(ispId) == 0 {
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- }
- obj, err := models.InstanceSnapshotManager.FetchById(ispId)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to fetch InstanceSnapshot %q", ispId)
- }
- isp := obj.(*models.SInstanceSnapshot)
- ispGuest, err := isp.GetGuest()
- if err != nil {
- return nil, errors.Wrapf(err, "unable to fetch Guest of InstanceSnapshot %q", ispId)
- }
- storages, err := ispGuest.GetStorages()
- if err != nil {
- return nil, errors.Wrapf(err, "GetStorages")
- }
- if len(storages) == 0 {
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- }
- if utils.IsInStringArray(storages[0].GetId(), storageIds) {
- return &storages[0], nil
- }
- return self.SVirtualizedGuestDriver.ChooseHostStorage(host, guest, diskConfig, storageIds)
- }
- }
- func (self *SCNwareGuestDriver) GetDetachDiskStatus() ([]string, error) {
- return []string{api.VM_READY, api.VM_RUNNING}, nil
- }
- func (self *SCNwareGuestDriver) GetAttachDiskStatus() ([]string, error) {
- return []string{api.VM_READY, api.VM_RUNNING}, nil
- }
- func (self *SCNwareGuestDriver) GetRebuildRootStatus() ([]string, error) {
- return []string{api.VM_READY}, nil
- }
- func (self *SCNwareGuestDriver) GetChangeConfigStatus(guest *models.SGuest) ([]string, error) {
- return []string{api.VM_READY}, nil
- }
- func (self *SCNwareGuestDriver) GetDeployStatus() ([]string, error) {
- return []string{api.VM_RUNNING}, nil
- }
- func (self *SCNwareGuestDriver) IsNeedRestartForResetLoginInfo() bool {
- return false
- }
- func (self *SCNwareGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
- if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
- return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
- }
- return nil
- }
- func (self *SCNwareGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, input api.ServerCreateEipInput) error {
- return httperrors.NewInputParameterError("%s not support create eip, it only support bind eip", self.GetHypervisor())
- }
- func (self *SCNwareGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *api.ServerCreateInput) (*api.ServerCreateInput, error) {
- if data.CpuSockets > data.VcpuCount {
- return nil, httperrors.NewInputParameterError("The number of cpu sockets cannot be greater than the number of cpus")
- }
- // check disk config
- if len(data.Disks) == 0 {
- return data, nil
- }
- rootDisk := data.Disks[0]
- if len(rootDisk.ImageId) == 0 {
- return data, nil
- }
- image, err := models.CachedimageManager.GetImageInfo(ctx, userCred, rootDisk.ImageId, false)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to GetImageInfo of image %q", rootDisk.ImageId)
- }
- if len(image.SubImages) <= 1 {
- return data, nil
- }
- sort.Slice(image.SubImages, func(i, j int) bool {
- return image.SubImages[i].Index < image.SubImages[j].Index
- })
- newDataDisks := make([]*api.DiskConfig, 0, len(image.SubImages)+len(data.Disks)-1)
- for i, subImage := range image.SubImages {
- nDataDisk := *rootDisk
- nDataDisk.SizeMb = subImage.MinDiskMB
- nDataDisk.Format = "vmdk"
- nDataDisk.Index = i
- if i > 0 {
- nDataDisk.ImageId = ""
- }
- newDataDisks = append(newDataDisks, &nDataDisk)
- }
- for i := 1; i < len(data.Disks); i++ {
- data.Disks[i].Index += len(image.SubImages) - 1
- newDataDisks = append(newDataDisks, data.Disks[i])
- }
- data.Disks = newDataDisks
- return data, nil
- }
- func (self *SCNwareGuestDriver) GetGuestInitialStateAfterCreate() string {
- return api.VM_RUNNING
- }
- func (self *SCNwareGuestDriver) GetGuestInitialStateAfterRebuild() string {
- return api.VM_READY
- }
- func (self *SCNwareGuestDriver) IsNeedInjectPasswordByCloudInit() bool {
- return true
- }
- func (self *SCNwareGuestDriver) GetUserDataType() string {
- return cloudprovider.CLOUD_SHELL
- }
- func (self *SCNwareGuestDriver) IsWindowsUserDataTypeNeedEncode() bool {
- return true
- }
- func (self *SCNwareGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCapability {
- return cloudprovider.SInstanceCapability{
- Hypervisor: self.GetHypervisor(),
- Provider: self.GetProvider(),
- DefaultAccount: cloudprovider.SDefaultAccount{
- Linux: cloudprovider.SOsDefaultAccount{
- DefaultAccount: api.VM_DEFAULT_LINUX_LOGIN_USER,
- },
- Windows: cloudprovider.SOsDefaultAccount{
- DefaultAccount: api.VM_DEFAULT_WINDOWS_LOGIN_USER,
- },
- },
- }
- }
- func (self *SCNwareGuestDriver) AllowReconfigGuest() bool {
- return true
- }
- func (self *SCNwareGuestDriver) IsSupportEip() bool {
- return false
- }
- func (self *SCNwareGuestDriver) RequestSyncSecgroupsOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
- return nil // do nothing, not support securitygroup
- }
- func (self *SCNwareGuestDriver) DoGuestCreateDisksTask(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
- return nil
- }
- func (self *SCNwareGuestDriver) GetChangeInstanceTypeStatus() ([]string, error) {
- return []string{api.VM_READY}, nil
- }
- func (self *SCNwareGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context, guest *models.SGuest, input api.ServerChangeConfigInput) (*api.ServerChangeConfigSettings, error) {
- confs, err := self.SBaseGuestDriver.ValidateGuestChangeConfigInput(ctx, guest, input)
- if err != nil {
- return nil, errors.Wrap(err, "SBaseGuestDriver.ValidateGuestChangeConfigInput")
- }
- sku, err := models.ServerSkuManager.FetchSkuByNameAndProvider(input.Sku, "OneCloud", true)
- if err != nil {
- return nil, errors.Wrap(err, "FetchSkuByNameAndProvider")
- }
- confs.InstanceTypeFamily = ""
- confs.InstanceType = ""
- confs.VcpuCount = sku.CpuCoreCount
- confs.VmemSize = sku.MemorySizeMB
- confs.CpuSockets = 1
- log.Infof("ValidateGuestChangeConfigInput: %+v", confs)
- if input.CpuSockets != nil && *input.CpuSockets > 0 {
- confs.CpuSockets = *input.CpuSockets
- }
- defaultStorageId := ""
- if root, _ := guest.GetSystemDisk(); root != nil {
- defaultStorageId = root.StorageId
- }
- storages, err := guest.GetStorages()
- if err != nil {
- return nil, errors.Wrapf(err, "GetStorages")
- }
- storageMap := map[string]string{}
- for _, storage := range storages {
- storageMap[storage.StorageType] = storage.Id
- if len(defaultStorageId) == 0 {
- defaultStorageId = storage.Id
- }
- }
- for i := range confs.Create {
- confs.Create[i].Format = "vmdk"
- if len(confs.Create[i].Storage) == 0 {
- // 若不指定存储类型,默认和系统盘一致
- if len(confs.Create[i].Backend) == 0 {
- confs.Create[i].Storage = defaultStorageId
- } else if storageId, ok := storageMap[confs.Create[i].Backend]; ok { // 否则和已有磁盘存储保持一致
- confs.Create[i].Storage = storageId
- }
- }
- }
- return confs, nil
- }
|