| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407 |
- // 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"
- "regexp"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/netutils"
- "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/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- )
- type SVirtualizedGuestDriver struct {
- SBaseGuestDriver
- }
- func (d *SVirtualizedGuestDriver) DoScheduleSKUFilter() bool {
- return false
- }
- func (self *SVirtualizedGuestDriver) GetMaxVCpuCount() int {
- return 128
- }
- func (self *SVirtualizedGuestDriver) GetMaxVMemSizeGB() int {
- return 512
- }
- func (self *SVirtualizedGuestDriver) PrepareDiskRaidConfig(userCred mcclient.TokenCredential, host *models.SHost, params []*api.BaremetalDiskConfig, disks []*api.DiskConfig) ([]*api.DiskConfig, error) {
- // do nothing
- return nil, nil
- }
- func (self *SVirtualizedGuestDriver) GetNamedNetworkConfiguration(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig) (*models.SNetwork, []models.SNicConfig, api.IPAllocationDirection, bool, error) {
- net, err := host.GetNetworkWithId(netConfig.Network, netConfig.Reserved)
- if err != nil {
- return nil, nil, "", false, errors.Wrapf(err, "get network with id %q, reserverd %v", netConfig.Network, netConfig.Reserved)
- }
- nicConfs := []models.SNicConfig{
- {
- Mac: netConfig.Mac,
- Index: -1,
- Ifname: netConfig.Ifname,
- },
- }
- if netConfig.RequireTeaming || netConfig.TryTeaming {
- nicConfs = append(nicConfs, models.SNicConfig{
- Mac: "",
- Index: -1,
- Ifname: "",
- })
- }
- // reUse := false
- // if len(netConfig.Address) > 0 && !options.Options.EnablePreAllocateIpAddr && !utils.IsInStringArray(host.GetProviderName(), []string{api.CLOUD_PROVIDER_ONECLOUD, api.CLOUD_PROVIDER_VMWARE, api.CLOUD_PROVIDER_CLOUDPODS}) {
- // reUse = true
- // }
- return net, nicConfs, api.IPAllocationStepdown, false, nil
- }
- func (self *SVirtualizedGuestDriver) GetRandomNetworkTypes() []api.TNetworkType {
- return []api.TNetworkType{api.NETWORK_TYPE_GUEST}
- }
- func (self *SVirtualizedGuestDriver) wireAvaiableForGuest(guest *models.SGuest, wire *models.SWire) (bool, error) {
- if guest.BackupHostId == "" {
- return true, nil
- } else {
- backupHost := models.HostManager.FetchHostById(guest.BackupHostId)
- attached := backupHost.IsAttach2Wire(wire.Id)
- return attached, nil
- }
- }
- func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, host *models.SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]models.SGuestnetwork, error) {
- var wirePattern *regexp.Regexp
- if len(netConfig.Wire) > 0 {
- wirePattern = regexp.MustCompile(netConfig.Wire)
- }
- hostNetifs := host.GetHostNetInterfaces()
- netsAvaiable := make([]models.SNetwork, 0)
- driver, err := guest.GetDriver()
- if err != nil {
- return nil, err
- }
- netTypes := driver.GetRandomNetworkTypes()
- if len(netConfig.NetType) > 0 {
- netTypes = []api.TNetworkType{api.TNetworkType(netConfig.NetType)}
- }
- var sriovWires []string
- if netConfig.SriovDevice != nil {
- if netConfig.SriovDevice.Id != "" {
- idev, err := models.IsolatedDeviceManager.FetchById(netConfig.SriovDevice.Id)
- if err != nil {
- return nil, errors.Wrap(err, "fetch isolated device")
- }
- dev, _ := idev.(*models.SIsolatedDevice)
- sriovWires = []string{dev.WireId}
- } else {
- wires, err := models.IsolatedDeviceManager.FindUnusedNicWiresByModel(netConfig.SriovDevice.Model)
- if err != nil {
- return nil, errors.Wrap(err, "FindUnusedNicWiresByModel")
- }
- sriovWires = wires
- }
- }
- for i := 0; i < len(hostNetifs); i += 1 {
- hostNetif := hostNetifs[i]
- wire := hostNetif.GetWire()
- if wire == nil {
- continue
- }
- if ok, err := self.wireAvaiableForGuest(guest, wire); err != nil {
- return nil, err
- } else if !ok {
- continue
- }
- if netConfig.SriovDevice != nil && !utils.IsInStringArray(wire.Id, sriovWires) {
- continue
- }
- // !!
- if wirePattern != nil && !wirePattern.MatchString(wire.Id) && !wirePattern.MatchString(wire.Name) {
- continue
- }
- var net *models.SNetwork
- if netConfig.Private {
- net, _ = wire.GetCandidatePrivateNetwork(ctx, userCred, userCred, models.NetworkManager.AllowScope(userCred), netConfig.Exit, netTypes)
- } else {
- net, _ = wire.GetCandidateAutoAllocNetwork(ctx, userCred, userCred, models.NetworkManager.AllowScope(userCred), netConfig.Exit, netTypes)
- }
- if net != nil {
- netsAvaiable = append(netsAvaiable, *net)
- }
- }
- if len(netsAvaiable) == 0 {
- return nil, fmt.Errorf("No appropriate host virtual network...")
- }
- if len(netConfig.Address) > 0 || len(netConfig.Address6) > 0 {
- addr, _ := netutils.NewIPV4Addr(netConfig.Address)
- addr6, _ := netutils.NewIPV6Addr(netConfig.Address6)
- netsAvaiableForAddr := make([]models.SNetwork, 0)
- for i := range netsAvaiable {
- if (len(netConfig.Address) == 0 || netsAvaiable[i].IsAddressInRange(addr)) && (len(netConfig.Address6) == 0 || netsAvaiable[i].IsAddress6InRange(addr6)) {
- netsAvaiableForAddr = append(netsAvaiableForAddr, netsAvaiable[i])
- }
- }
- if len(netsAvaiableForAddr) == 0 {
- if netConfig.RequireDesignatedIP {
- return nil, fmt.Errorf("No virtual network for IP %s", netConfig.Address)
- }
- } else {
- netsAvaiable = netsAvaiableForAddr
- }
- }
- selNet := models.ChooseCandidateNetworks(netsAvaiable, netConfig.Exit, netTypes)
- if selNet == nil {
- return nil, fmt.Errorf("Not enough address in virtual network")
- }
- nicConfs := make([]models.SNicConfig, 1)
- nicConfs[0] = models.SNicConfig{
- Mac: netConfig.Mac,
- Index: -1,
- Ifname: netConfig.Ifname,
- }
- if netConfig.RequireTeaming || netConfig.TryTeaming {
- nicConf := models.SNicConfig{
- Mac: "",
- Index: -1,
- Ifname: "",
- }
- nicConfs = append(nicConfs, nicConf)
- }
- gn, err := guest.Attach2Network(ctx, userCred, models.Attach2NetworkArgs{
- Network: selNet,
- PendingUsage: pendingUsage,
- IpAddr: netConfig.Address,
- Ip6Addr: netConfig.Address6,
- NicDriver: netConfig.Driver,
- BwLimit: netConfig.BwLimit,
- Virtual: netConfig.Vip,
- TryReserved: netConfig.Reserved,
- AllocDir: api.IPAllocationDefault,
- RequireDesignatedIP: netConfig.RequireDesignatedIP,
- RequireIPv6: netConfig.RequireIPv6,
- StrictIPv6: netConfig.StrictIPv6,
- NicConfs: nicConfs,
- IsDefault: netConfig.IsDefault,
- BillingType: netConfig.BillingType,
- ChargeType: netConfig.ChargeType,
- })
- return gn, err
- }
- func (self *SVirtualizedGuestDriver) GetStorageTypes() []string {
- return nil
- }
- func (self *SVirtualizedGuestDriver) ChooseHostStorage(host *models.SHost, guest *models.SGuest, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
- if len(storageIds) == 0 {
- return host.GetLeastUsedStorage(diskConfig.Backend), nil
- }
- ss, err := models.StorageManager.FetchStorageByIds(storageIds)
- if err != nil {
- return nil, errors.Wrapf(err, "fetch storages by ids: %v", storageIds)
- }
- var candidates []models.SStorage
- if len(diskConfig.Medium) > 0 {
- // try to find mediumType matched storage
- for i := range ss {
- if ss[i].MediumType == diskConfig.Medium {
- candidates = append(candidates, ss[i])
- }
- }
- if len(candidates) == 0 {
- candidates = ss
- }
- } else {
- candidates = ss
- }
- return models.ChooseLeastUsedStorage(candidates, ""), nil
- }
- func (self *SVirtualizedGuestDriver) RequestGuestCreateInsertIso(ctx context.Context, imageId string, bootIndex *int8, task taskman.ITask, guest *models.SGuest) error {
- return guest.StartInsertIsoTask(ctx, 0, imageId, true, bootIndex, 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 {
- taskName := "GuestStopTask"
- if guest.BackupHostId != "" {
- taskName = "HAGuestStopTask"
- }
- task, err := taskman.TaskManager.NewTask(ctx, taskName, guest, userCred, params, parentTaskId, "", nil)
- if err != nil {
- return err
- }
- return task.ScheduleRun(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) 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), false)
- }
- func (self *SVirtualizedGuestDriver) StartGuestSyncstatusTask(guest *models.SGuest, ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
- return models.StartResourceSyncStatusTask(ctx, userCred, guest, "GuestSyncstatusTask", parentTaskId)
- }
- 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.GetEnabled() && host.HostStatus == api.HOST_ONLINE {
- return guest.StartGuestStopTask(ctx, task.GetUserCred(), 0, true, false, 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) ValidateCreateDataOnHost(ctx context.Context, userCred mcclient.TokenCredential, bmName string, host *models.SHost, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
- if host.HostStatus != api.HOST_ONLINE {
- return nil, httperrors.NewInvalidStatusError("Host %s is not online", bmName)
- }
- input.PreferHost = host.Id
- if host.IsPrepaidRecycle() {
- input.VmemSize = host.MemSize
- input.VcpuCount = int(host.CpuCount)
- cnt, err := host.GetGuestCount()
- if err != nil {
- return nil, httperrors.NewInternalServerError("GetGuestCount fail %s", err)
- }
- if cnt >= 1 {
- return nil, httperrors.NewInsufficientResourceError("host has been occupied")
- }
- }
- return input, nil
- }
- func (self *SVirtualizedGuestDriver) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, data *jsonutils.JSONDict, parentTaskId string) error {
- return guest.StartGueststartTask(ctx, userCred, data, parentTaskId)
- }
- func (self *SVirtualizedGuestDriver) CheckDiskTemplateOnStorage(ctx context.Context, userCred mcclient.TokenCredential, imageId string, format 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")
- }
- input := api.CacheImageInput{
- ImageId: imageId,
- Format: format,
- ParentTaskId: task.GetTaskId(),
- }
- return cache.StartImageCacheTask(ctx, userCred, input)
- }
- 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) StartResumeTask(ctx context.Context, userCred mcclient.TokenCredential,
- guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
- task, err := taskman.TaskManager.NewTask(ctx, "GuestResumeTask", 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 {
- guest.SetStatus(ctx, userCred, api.VM_START_SAVE_DISK, "")
- 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) StartGuestSaveGuestImage(ctx context.Context, userCred mcclient.TokenCredential,
- guest *models.SGuest, params *jsonutils.JSONDict, parentTaskId string) error {
- guest.SetStatus(ctx, userCred, api.VM_START_SAVE_DISK, "")
- if task, err := taskman.TaskManager.NewTask(ctx, "GuestSaveGuestImageTask", guest, userCred, params, parentTaskId,
- "", nil); err != nil {
- return err
- } else {
- task.ScheduleRun(nil)
- }
- return nil
- }
|