Files
cloudpods/pkg/compute/guestdrivers/esxi.go
2019-12-12 11:31:41 +08:00

299 lines
9.2 KiB
Go

// 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"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"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"
"yunion.io/x/onecloud/pkg/multicloud/esxi"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SESXiGuestDriver struct {
SManagedVirtualizedGuestDriver
}
func init() {
driver := SESXiGuestDriver{}
models.RegisterGuestDriver(&driver)
}
func (self *SESXiGuestDriver) DoScheduleCPUFilter() bool { return true }
func (self *SESXiGuestDriver) DoScheduleMemoryFilter() bool { return true }
func (self *SESXiGuestDriver) DoScheduleSKUFilter() bool { return false }
func (self *SESXiGuestDriver) GetHypervisor() string {
return api.HYPERVISOR_ESXI
}
func (self *SESXiGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_VMWARE
}
func (self *SESXiGuestDriver) GetComputeQuotaKeys(scope rbacutils.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseQuotaKeys = quotas.OwnerIdQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_ON_PREMISE
keys.Provider = api.CLOUD_PROVIDER_VMWARE
// ignore brand
// ignore hypervisor keys.Hypervisor = api.HYPERVISOR_ESXI
return keys
}
func (self *SESXiGuestDriver) GetDefaultSysDiskBackend() string {
return api.STORAGE_LOCAL
}
func (self *SESXiGuestDriver) GetMinimalSysDiskSizeGb() int {
return options.Options.DefaultDiskSizeMB / 1024
}
func (self *SESXiGuestDriver) RequestSyncSecgroupsOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
return nil // do nothing, not support securitygroup
}
func (self *SESXiGuestDriver) GetMaxSecurityGroupCount() int {
//暂不支持绑定安全组
return 0
}
func (self *SESXiGuestDriver) GetDetachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SESXiGuestDriver) GetAttachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SESXiGuestDriver) GetChangeConfigStatus() ([]string, error) {
return []string{api.VM_READY}, nil
}
func (self *SESXiGuestDriver) CanKeepDetachDisk() bool {
return false
}
// func (self *SESXiGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
// err := disk.RealDelete(ctx, task.GetUserCred())
// if err != nil {
// return err
// }
// task.ScheduleRun(nil)
// return nil
// }
func (self *SESXiGuestDriver) RequestGuestHotAddIso(ctx context.Context, guest *models.SGuest, path string, boot bool, task taskman.ITask) error {
task.ScheduleRun(nil)
return nil
}
func (self *SESXiGuestDriver) GetRebuildRootStatus() ([]string, error) {
return []string{api.VM_READY}, nil
}
func (self *SESXiGuestDriver) GetDeployStatus() ([]string, error) {
return []string{api.VM_READY}, nil
}
func (self *SESXiGuestDriver) ValidateCreateEip(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) error {
return httperrors.NewInputParameterError("%s not support create eip", self.GetHypervisor())
}
func (self *SESXiGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY}) {
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
}
if disk.DiskType == api.DISK_TYPE_SYS {
return fmt.Errorf("Cannot resize system disk")
}
/*if !utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_PUBLIC_CLOUD, models.STORAGE_CLOUD_SSD, models.STORAGE_CLOUD_EFFICIENCY}) {
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
}*/
return nil
}
func (self *SESXiGuestDriver) GetJsonDescAtHost(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost) jsonutils.JSONObject {
return guest.GetJsonDescAtHypervisor(ctx, host)
}
func (self *SESXiGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error {
config, err := guest.GetDeployConfigOnHost(ctx, task.GetUserCred(), host, task.GetParams())
if err != nil {
log.Errorf("GetDeployConfigOnHost error: %v", err)
return err
}
log.Debugf("RequestDeployGuestOnHost: %s", config)
if !host.IsEsxiAgentReady() {
return fmt.Errorf("No ESXi agent host")
}
diskCat := guest.CategorizeDisks()
if diskCat.Root == nil {
return fmt.Errorf("no root disk???")
}
storage := diskCat.Root.GetStorage()
if storage == nil {
return fmt.Errorf("root disk has no storage???")
}
config.Add(jsonutils.NewString(host.AccessIp), "host_ip")
config.Add(jsonutils.NewString(guest.Id), "guest_id")
extId := guest.Id
if len(guest.ExternalId) > 0 {
extId = guest.ExternalId
}
config.Add(jsonutils.NewString(extId), "guest_ext_id")
accessInfo, err := host.GetCloudaccount().GetVCenterAccessInfo(storage.ExternalId)
if err != nil {
return err
}
config.Add(jsonutils.Marshal(accessInfo), "datastore")
url := "/disks/agent/deploy"
body := jsonutils.NewDict()
body.Add(config, "disk")
header := task.GetTaskRequestHeader()
_, err = host.EsxiRequest(ctx, httputils.POST, url, header, body)
return err
}
func (self *SESXiGuestDriver) RqeuestSuspendOnHost(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
host := guest.GetHost()
if host == nil {
return nil, errors.Error("fail to get host of guest")
}
ihost, err := host.GetIHost()
if err != nil {
return nil, err
}
ivm, err := ihost.GetIVMById(guest.GetExternalId())
if err != nil {
return nil, err
}
vm := ivm.(*esxi.SVirtualMachine)
err = vm.SuspendVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "VM.SuspendVM for vmware")
}
return nil, nil
})
return nil
}
func (self *SESXiGuestDriver) RqeuestResumeOnHost(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
host := guest.GetHost()
if host == nil {
return nil, errors.Error("fail to get host of guest")
}
ihost, err := host.GetIHost()
if err != nil {
return nil, err
}
ivm, err := ihost.GetIVMById(guest.GetExternalId())
if err != nil {
return nil, err
}
vm := ivm.(*esxi.SVirtualMachine)
err = vm.ResumeVM(ctx)
if err != nil {
return nil, errors.Wrap(err, "VM.Resume for VMware")
}
return nil, nil
})
return nil
}
func (self *SESXiGuestDriver) OnGuestDeployTaskDataReceived(ctx context.Context, guest *models.SGuest, task taskman.ITask, data jsonutils.JSONObject) error {
if data.Contains("host_ip") {
hostIp, _ := data.GetString("host_ip")
host, err := models.HostManager.GetHostByIp(hostIp)
if err != nil {
log.Errorf("fail to find host with IP %s: %s", hostIp, err)
return err
}
if host.Id != guest.HostId {
models.HostManager.ClearSchedDescCache(host.Id)
models.HostManager.ClearSchedDescCache(guest.HostId)
guest.OnScheduleToHost(ctx, task.GetUserCred(), host.Id)
}
}
return self.SManagedVirtualizedGuestDriver.OnGuestDeployTaskDataReceived(ctx, guest, task, data)
}
func (self *SESXiGuestDriver) AllowReconfigGuest() bool {
return true
}
func (self *SESXiGuestDriver) DoGuestCreateDisksTask(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
subtask, err := taskman.TaskManager.NewTask(ctx, "ESXiGuestCreateDiskTask", guest, task.GetUserCred(), task.GetParams(), task.GetTaskId(), "", nil)
if err != nil {
return err
}
subtask.ScheduleRun(nil)
return nil
}
func (self *SESXiGuestDriver) RequestRenewInstance(guest *models.SGuest, bc billing.SBillingCycle) (time.Time, error) {
return time.Time{}, nil
}
func (self *SESXiGuestDriver) IsSupportEip() bool {
return false
}
func (self *SESXiGuestDriver) RequestAssociateEip(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, eip *models.SElasticip, task taskman.ITask) error {
return fmt.Errorf("ESXiGuestDriver not support associate eip")
}
func (self *SESXiGuestDriver) CancelExpireTime(
ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest) error {
return guest.CancelExpireTime(ctx, userCred)
}
func (self *SESXiGuestDriver) IsSupportPostpaidExpire() bool {
return true
}
func (self *SESXiGuestDriver) IsSupportCdrom(guest *models.SGuest) (bool, error) {
return false, nil
}