Files
cloudpods/pkg/compute/guestdrivers/virtualization.go
T
2018-12-12 23:24:34 +08:00

268 lines
9.7 KiB
Go

package guestdrivers
import (
"context"
"fmt"
"regexp"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"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/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SVirtualizedGuestDriver struct {
SBaseGuestDriver
}
func (self *SVirtualizedGuestDriver) GetMaxVCpuCount() int {
return 128
}
func (self *SVirtualizedGuestDriver) GetMaxVMemSizeGB() int {
return 512
}
func (self *SVirtualizedGuestDriver) PrepareDiskRaidConfig(host *models.SHost, params *jsonutils.JSONDict) error {
// do nothing
return nil
}
func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig) (*models.SNetwork, string, int8, models.IPAddlocationDirection) {
net, _ := host.GetNetworkWithIdAndCredential(netConfig.Network, userCred, netConfig.Reserved)
return net, netConfig.Mac, -1, models.IPAllocationStepdown
}
func (self *SVirtualizedGuestDriver) GetRandomNetworkTypes() []string {
return []string{models.SERVER_TYPE_GUEST}
}
func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *models.SNetworkConfig, pendingUsage quotas.IQuota) error {
var wirePattern *regexp.Regexp
if len(netConfig.Wire) > 0 {
wirePattern = regexp.MustCompile(netConfig.Wire)
}
hostwires := host.GetHostwires()
netsAvaiable := make([]models.SNetwork, 0)
netTypes := guest.GetDriver().GetRandomNetworkTypes()
for i := 0; i < len(hostwires); i += 1 {
hostwire := hostwires[i]
wire := hostwire.GetWire()
if wire == nil {
log.Errorf("host wire is nil?????")
continue
}
log.Debugf("Wire %#v", wire)
// !!
if wirePattern != nil && !wirePattern.MatchString(wire.Id) && !wirePattern.MatchString(wire.Name) {
continue
}
var net *models.SNetwork
if netConfig.Private {
for _, netType := range netTypes {
net, _ = wire.GetCandidatePrivateNetwork(userCred, netConfig.Exit, netType)
if net != nil {
break
}
}
} else {
for _, netType := range netTypes {
net, _ = wire.GetCandidatePublicNetwork(netConfig.Exit, netType)
if net != nil {
break
}
}
}
if net != nil {
netsAvaiable = append(netsAvaiable, *net)
}
}
if len(netsAvaiable) == 0 {
return fmt.Errorf("No appropriate host virtual network...")
}
var selNet *models.SNetwork
for _, netType := range netTypes {
selNet = models.ChooseCandidateNetworks(netsAvaiable, netConfig.Exit, netType)
if selNet != nil {
break
}
}
if selNet == nil {
return fmt.Errorf("Not enough address in virtual network")
}
err := guest.Attach2Network(ctx, userCred, selNet, pendingUsage, netConfig.Address, netConfig.Mac, netConfig.Driver, netConfig.BwLimit, netConfig.Vip, -1, netConfig.Reserved, models.IPAllocationDefault, false)
return err
}
func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, backend string) *models.SStorage {
return host.GetLeastUsedStorage(backend)
}
func (self *SVirtualizedGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, guest *models.SGuest, task taskman.ITask) error {
return guest.StartInsertIsoTask(ctx, imageId, guest.HostId, task.GetUserCred(), task.GetTaskId())
}
func (self *SVirtualizedGuestDriver) StartGuestStopTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, params *jsonutils.JSONDict, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestStopTask", guest, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) StartGuestResetTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, isHard bool, parentTaskId string) error {
var taskName = "GuestSoftResetTask"
if isHard {
taskName = "GuestHardResetTask"
}
task, err := taskman.TaskManager.NewTask(ctx, taskName, guest, userCred, nil, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) StartGuestRestartTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, isForce bool, parentTaskId string) error {
data := jsonutils.NewDict()
data.Set("is_force", jsonutils.NewBool(isForce))
task, err := taskman.TaskManager.NewTask(ctx, "GuestRestartTask", guest, userCred, nil, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) RequestDeleteDetachedDisk(ctx context.Context, disk *models.SDisk, task taskman.ITask, isPurge bool) error {
return disk.StartDiskDeleteTask(ctx, task.GetUserCred(), task.GetTaskId(), isPurge,
jsonutils.QueryBoolean(task.GetParams(), "override_pending_delete", false))
}
func (self *SVirtualizedGuestDriver) OnGuestDeployTaskComplete(ctx context.Context, guest *models.SGuest, task taskman.ITask) error {
if jsonutils.QueryBoolean(task.GetParams(), "restart", false) {
task.SetStage("OnDeployStartGuestComplete", nil)
return guest.StartGueststartTask(ctx, task.GetUserCred(), nil, task.GetTaskId())
}
task.SetStage("OnDeployGuestSyncstatusComplete", nil)
return guest.StartSyncstatus(ctx, task.GetUserCred(), task.GetTaskId())
}
func (self *SVirtualizedGuestDriver) StartGuestSyncstatusTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestSyncstatusTask", guest, userCred, nil, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) RequestStopGuestForDelete(ctx context.Context, guest *models.SGuest,
host *models.SHost, task taskman.ITask) error {
if host == nil {
host = guest.GetHost()
}
if host != nil && host.Enabled && host.HostStatus == models.HOST_ONLINE {
return guest.StartGuestStopTask(ctx, task.GetUserCred(), true, task.GetTaskId())
}
if host != nil && !jsonutils.QueryBoolean(task.GetParams(), "purge", false) {
return fmt.Errorf("fail to contact host")
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return data, nil
}
func (self *SVirtualizedGuestDriver) ValidateCreateHostData(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if host.HostStatus != models.HOST_ONLINE {
return nil, httperrors.NewInvalidStatusError("Host %s is not online", bmName)
}
data.Add(jsonutils.NewString(host.Id), "prefer_host_id")
if host.IsPrepaidRecycle() {
data.Set("vmem_size", jsonutils.NewInt(int64(host.MemSize)))
data.Set("vcpu_count", jsonutils.NewInt(int64(host.CpuCount)))
if host.GetGuestCount() >= 1 {
return nil, httperrors.NewInsufficientResourceError("host has been occupied")
}
}
return data, nil
}
func (self *SVirtualizedGuestDriver) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, data *jsonutils.JSONDict) error {
return guest.StartGueststartTask(ctx, userCred, data, "")
}
func (self *SVirtualizedGuestDriver) CheckDiskTemplateOnStorage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, storageId string, task taskman.ITask) error {
storage := models.StorageManager.FetchStorageById(storageId)
if storage == nil {
return fmt.Errorf("No such storage?? %s", storageId)
}
cache := storage.GetStoragecache()
if cache == nil {
return fmt.Errorf("Cache is missing from storage")
}
return cache.StartImageCacheTask(ctx, userCred, imageId, false, task.GetTaskId())
}
func (self *SVirtualizedGuestDriver) CanKeepDetachDisk() bool {
return true
}
func (self *SVirtualizedGuestDriver) StartGuestDetachdiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestDetachDiskTask", guest, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) StartGuestAttachDiskTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestAttachDiskTask", guest, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) StartSuspendTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestSuspendTask", guest, userCred, params, parentTaskId, "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}
func (self *SVirtualizedGuestDriver) StartGuestSaveImage(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
if task, err := taskman.TaskManager.NewTask(ctx, "GuestSaveImageTask", guest, userCred, params, parentTaskId, "", nil); err != nil {
return err
} else {
task.ScheduleRun(nil)
}
return nil
}
func (self *SVirtualizedGuestDriver) StartGuestDiskSnapshotTask(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, params *jsonutils.JSONDict) error {
task, err := taskman.TaskManager.NewTask(ctx, "GuestDiskSnapshotTask", guest, userCred, params, "", "", nil)
if err != nil {
return err
}
task.ScheduleRun(nil)
return nil
}