Files
cloudpods/pkg/scheduler/cache/candidate/base.go

950 lines
27 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 candidate
import (
"fmt"
"strings"
"sync"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/sets"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/types"
computemodels "yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/scheduler/api"
"yunion.io/x/onecloud/pkg/scheduler/core"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/cloudregion"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/netinterface"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/network"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/network_additional_wire"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/sku"
"yunion.io/x/onecloud/pkg/scheduler/data_manager/zone"
schedmodels "yunion.io/x/onecloud/pkg/scheduler/models"
)
type BaseHostDesc struct {
*computemodels.SHost
Region *computemodels.SCloudregion `json:"region"`
Zone *computemodels.SZone `json:"zone"`
Cloudprovider *computemodels.SCloudprovider `json:"cloudprovider"`
Cloudaccount *computemodels.SCloudaccount `json:"cloudaccount"`
Networks []*api.CandidateNetwork `json:"networks"`
NetInterfaces map[string][]computemodels.SNetInterface `json:"net_interfaces"`
Storages []*api.CandidateStorage `json:"storages"`
IsolatedDevices []*core.IsolatedDeviceDesc `json:"isolated_devices"`
Tenants map[string]int64 `json:"tenants"`
InstanceGroups map[string]*api.CandidateGroup `json:"instance_groups"`
IpmiInfo types.SIPMIInfo `json:"ipmi_info"`
Nics []*types.SNic `json:"nics"`
SharedDomains []string `json:"shared_domains"`
PendingUsage map[string]interface{} `json:"pending_usage"`
ClassMetadata map[string]string `json:"class_metadata"`
}
type baseHostGetter struct {
h *BaseHostDesc
}
func newBaseHostGetter(h *BaseHostDesc) *baseHostGetter {
return &baseHostGetter{h}
}
func (b baseHostGetter) Id() string {
return b.h.GetId()
}
func (b baseHostGetter) Name() string {
return b.h.GetName()
}
func (b baseHostGetter) Zone() *computemodels.SZone {
return b.h.Zone
}
func (b baseHostGetter) Host() *computemodels.SHost {
return b.h.SHost
}
func (b baseHostGetter) IsArmHost() bool {
return b.h.IsArmHost()
}
func (b baseHostGetter) IsRISCVHost() bool {
return b.h.IsRISCVHost()
}
func (b baseHostGetter) CPUArch() string {
return b.h.CpuArchitecture
}
func (b baseHostGetter) KvmCapMaxVcpuCount() int64 {
return int64(b.h.KvmCapMaxVcpu)
}
func (b baseHostGetter) Cloudprovider() *computemodels.SCloudprovider {
return b.h.Cloudprovider
}
func (b baseHostGetter) IsPublic() bool {
return b.h.IsPublic
/*provider := b.Cloudprovider()
if provider == nil {
return false
}
account := provider.GetCloudaccount()
if account == nil {
return false
}
return account.ShareMode == computeapi.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM*/
}
func (b baseHostGetter) KeywordPlural() string {
return b.h.KeywordPlural()
}
func (b baseHostGetter) DomainId() string {
return b.h.DomainId
}
func (b baseHostGetter) PublicScope() string {
return b.h.PublicScope
}
func (b baseHostGetter) SharedDomains() []string {
return b.h.SharedDomains
}
func (b baseHostGetter) Region() *computemodels.SCloudregion {
return b.h.Region
}
func (b baseHostGetter) HostType() string {
return b.h.HostType
}
func (b baseHostGetter) Sku(instanceType string) *sku.ServerSku {
zone := b.Zone()
return sku.GetByZone(instanceType, zone.CloudregionId, zone.GetId())
}
func (b baseHostGetter) Storages() []*api.CandidateStorage {
return b.h.Storages
}
func (b baseHostGetter) InstanceGroups() map[string]*api.CandidateGroup {
return b.h.InstanceGroups
}
func (b baseHostGetter) GetAllClassMetadata() (map[string]string, error) {
return b.h.ClassMetadata, nil
}
func (b baseHostGetter) GetFreeGroupCount(groupId string) (int, error) {
// Must Be
scg, ok := b.h.InstanceGroups[groupId]
if !ok {
return 0, errors.Wrap(core.ErrInstanceGroupNotFound, groupId)
}
free := scg.Granularity - scg.ReferCount
if free < 1 {
return 0, nil
}
pendingScg, ok := b.h.GetPendingUsage().InstanceGroupUsage[groupId]
if ok {
free -= pendingScg.ReferCount
}
return free, nil
}
func (b baseHostGetter) Networks() []*api.CandidateNetwork {
return b.h.Networks
}
func (b baseHostGetter) OvnCapable() bool {
return false
}
func (b baseHostGetter) ResourceType() string {
return reviseResourceType(b.h.ResourceType)
}
func (b baseHostGetter) NetInterfaces() map[string][]computemodels.SNetInterface {
return b.h.NetInterfaces
}
func (b baseHostGetter) Status() string {
return b.h.Status
}
func (b baseHostGetter) HostStatus() string {
return b.h.HostStatus
}
func (b baseHostGetter) Enabled() bool {
return b.h.GetEnabled()
}
func (b baseHostGetter) ProjectGuests() map[string]int64 {
return b.h.Tenants
}
func (b baseHostGetter) CreatingGuestCount() int {
return 0
}
func (b baseHostGetter) RunningCPUCount() int64 {
return 0
}
func (b baseHostGetter) TotalCPUCount(_ bool) int64 {
return int64(b.h.CpuCount)
}
func (b baseHostGetter) RunningMemorySize() int64 {
return 0
}
func (b baseHostGetter) TotalMemorySize(_ bool) int64 {
return int64(b.h.MemSize)
}
func checkStorageSize(s *api.CandidateStorage, reqMaxSize int64, useRsvd bool) error {
storageSize := s.FreeCapacity
if useRsvd {
storageSize += s.GetReserved()
}
minSize := utils.Min(storageSize, s.ActualFreeCapacity)
if minSize >= reqMaxSize {
return nil
}
return errors.Errorf("storage %q free size %d less than max request %d, use reserverd %v, free_capacity(%d), actual_free_capacity(%d)", s.GetName(), minSize, reqMaxSize, useRsvd, storageSize, s.ActualFreeCapacity)
}
func IsStorageBackendMediumMatch(s *api.CandidateStorage, backend string, mediumType string) bool {
if s.StorageType != backend {
return false
}
if mediumType == "" {
return true
}
return s.MediumType == mediumType
}
func (b baseHostGetter) GetFreeStorageSizeOfType(storageType string, mediumType string, useRsvd bool, reqMaxSize int64) (int64, int64, error) {
var size int64
var actualSize int64
foundLEReqStore := false
errs := make([]error, 0)
for _, s := range b.Storages() {
if IsStorageBackendMediumMatch(s, storageType, mediumType) {
size += s.FreeCapacity
actualSize += s.ActualFreeCapacity
if err := checkStorageSize(s, reqMaxSize, false); err != nil {
errs = append(errs, err)
} else {
foundLEReqStore = true
}
}
}
if foundLEReqStore {
return size, actualSize, nil
}
return size, actualSize, errors.NewAggregate(errs)
}
func (b baseHostGetter) GetFreePort(netId string) int {
return b.h.GetFreePort(netId)
}
func (b baseHostGetter) GetIpmiInfo() types.SIPMIInfo {
return b.h.IpmiInfo
}
func (b baseHostGetter) GetNics() []*types.SNic {
return b.h.Nics
}
func (b baseHostGetter) GetQuotaKeys(s *api.SchedInfo) computemodels.SComputeResourceKeys {
return b.h.getQuotaKeys(s)
}
func (b baseHostGetter) GetPendingUsage() *schedmodels.SPendingUsage {
return b.h.GetPendingUsage()
}
func (b baseHostGetter) AvailableIsolatedDevices() []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevices()
}
func (b baseHostGetter) AvailableIsolatedDevicesByTypeSharingMode(devType string, sharingMode string) []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode)
}
func (b baseHostGetter) AvailableIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevicesByVendorModel(vendorModel)
}
func (b baseHostGetter) AvailableIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevicesByDevicePath(devPath)
}
func (b baseHostGetter) AvailableIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevicesByModel(model)
}
func (b baseHostGetter) AvailableIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
return b.h.AvailableIsolatedDevicesByModelAndWire(model, wire)
}
func (b baseHostGetter) GetIsolatedDevice(devID string) *core.IsolatedDeviceDesc {
return b.h.GetIsolatedDevice(devID)
}
func (b baseHostGetter) GetIsolatedDevices() []*core.IsolatedDeviceDesc {
return b.h.GetIsolatedDevices()
}
func reviseResourceType(resType string) string {
if resType == "" {
return computeapi.HostResourceTypeDefault
}
return resType
}
type networkGetter struct {
netFreeMap *sync.Map
}
func newNetworkGetter() *networkGetter {
return &networkGetter{
netFreeMap: new(sync.Map),
}
}
func shouldSkipLoadNetFromCache(host *computemodels.SHost) bool {
if host.IsEmulated || host.HostType == computeapi.HOST_TYPE_ESXI {
return true
}
return false
}
func (g *networkGetter) GetFreePort(host *computemodels.SHost, n *computemodels.SNetwork) (int, error) {
if shouldSkipLoadNetFromCache(host) {
// not calculate emulated host's network free address
return -1, nil
}
if val, ok := g.netFreeMap.Load(n.GetId()); ok {
return val.(int), nil
}
freePort, err := n.GetFreeAddressCount()
if err != nil {
return -1, errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", n.GetName(), n.GetId())
}
g.netFreeMap.Store(n.GetId(), freePort)
return freePort, nil
}
func newBaseHostDesc(b *baseBuilder, host *computemodels.SHost, netGetter *networkGetter) (*BaseHostDesc, error) {
host.ResourceType = reviseResourceType(host.ResourceType)
desc := &BaseHostDesc{
SHost: host,
}
if err := desc.fillCloudProvider(b, host); err != nil {
return nil, fmt.Errorf("Fill cloudprovider info error: %v", err)
}
if err := desc.fillNetworks(host, netGetter); err != nil {
return nil, fmt.Errorf("Fill networks error: %v", err)
}
// only onecloud host should fill onecloud vpc networks
if sets.NewString(computeapi.HOST_TYPE_HYPERVISOR, computeapi.HOST_TYPE_CONTAINER).Has(host.HostType) && len(host.ManagerId) == 0 {
if err := desc.fillOnecloudVpcNetworks(netGetter); err != nil {
return nil, fmt.Errorf("Fill onecloud vpc networks error: %v", err)
}
if err := desc.fillOneCloudHostLocalNetworks(netGetter); err != nil {
return nil, fmt.Errorf("Fill onecloud host local networks error: %v", err)
}
}
if sets.NewString(computeapi.HOST_TYPE_HYPERVISOR, computeapi.HOST_TYPE_BAREMETAL, computeapi.HOST_TYPE_CONTAINER).Has(host.HostType) && len(host.ManagerId) > 0 {
if err := desc.fillCloudpodsVpcNetworks(netGetter); err != nil {
return nil, fmt.Errorf("Fill cloudpods vpc networks error: %v", err)
}
if err := desc.fillCloudpodsHostLocalNetworks(netGetter); err != nil {
return nil, fmt.Errorf("Fill cloudpods host local networks error: %v", err)
}
}
if err := desc.fillZone(host); err != nil {
return nil, fmt.Errorf("Fill zone error: %v", err)
}
if err := desc.fillRegion(host); err != nil {
return nil, fmt.Errorf("Fill region error: %v", err)
}
if err := desc.fillStorages(host); err != nil {
return nil, fmt.Errorf("Fill storage error: %v", err)
}
if err := desc.fillInstanceGroups(host); err != nil {
return nil, fmt.Errorf("Fill instance group error: %v", err)
}
if err := desc.fillClassMetadata(host); err != nil {
return nil, fmt.Errorf("Fill class metadata error: %v", err)
}
if err := desc.fillIpmiInfo(host); err != nil {
return nil, fmt.Errorf("Fill ipmi info error: %v", err)
}
if err := desc.fillNics(host); err != nil {
return nil, fmt.Errorf("Fill nics info error: %v", err)
}
if err := desc.fillIsolatedDevices(b, host); err != nil {
return nil, fmt.Errorf("Fill isolated devices error: %v", err)
}
desc.fillSharedDomains()
desc.PendingUsage = desc.GetPendingUsage().ToMap()
return desc, nil
}
func (b BaseHostDesc) GetSchedDesc() *jsonutils.JSONDict {
desc := jsonutils.Marshal(b.SHost).(*jsonutils.JSONDict)
if b.Cloudprovider != nil {
p := b.Cloudprovider
cloudproviderDesc := jsonutils.NewDict()
cloudproviderDesc.Add(jsonutils.NewString(p.ProjectId), "tenant_id")
cloudproviderDesc.Add(jsonutils.NewString(p.Provider), "provider")
desc.Add(cloudproviderDesc, "cloudprovider")
}
return desc
}
func (b *BaseHostDesc) GetPendingUsage() *schedmodels.SPendingUsage {
usage, err := schedmodels.HostPendingUsageManager.GetPendingUsage(b.GetId())
if err != nil {
return schedmodels.NewPendingUsageBySchedInfo(b.GetId(), nil, nil)
}
return usage
}
func (b *BaseHostDesc) GetFreePort(netId string) int {
var selNet *api.CandidateNetwork = nil
for _, n := range b.Networks {
if n.GetId() == netId {
selNet = n
break
}
}
if selNet == nil {
return 0
}
if shouldSkipLoadNetFromCache(b.SHost) {
freeCount, _ := selNet.GetFreeAddressCount()
return freeCount
}
return selNet.FreePort
}
func (b BaseHostDesc) GetResourceType() string {
return b.ResourceType
}
func (h *BaseHostDesc) AvailableIsolatedDevices() []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
for _, dev := range h.IsolatedDevices {
if !dev.IsUsedUp() {
ret = append(ret, dev)
}
}
return ret
}
func (h *BaseHostDesc) AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode string) []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
for _, dev := range h.AvailableIsolatedDevices() {
if devType != "" && dev.DevType != devType {
continue
}
if sharingMode != "" && dev.SharingMode != sharingMode {
continue
}
ret = append(ret, dev)
}
return ret
}
func (h *BaseHostDesc) AvailableIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
vm := core.NewVendorModelByStr(vendorModel)
for _, dev := range h.AvailableIsolatedDevices() {
if dev.GetVendorModel().IsMatch(vm) {
ret = append(ret, dev)
}
}
return ret
}
func (h *BaseHostDesc) AvailableIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
for _, dev := range h.AvailableIsolatedDevices() {
if strings.Contains(dev.Model, model) {
ret = append(ret, dev)
}
}
return ret
}
func (h *BaseHostDesc) AvailableIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
for _, dev := range h.AvailableIsolatedDevices() {
if devPath == dev.DevicePath {
ret = append(ret, dev)
}
}
return ret
}
func (h *BaseHostDesc) AvailableIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
ret := make([]*core.IsolatedDeviceDesc, 0)
for _, dev := range h.AvailableIsolatedDevices() {
log.Errorf("dev wire is %s, dev model is %s, request model is %s, request wire is %s", dev.Model, dev.WireId, model, wire)
if strings.Contains(dev.Model, model) && dev.WireId == wire {
ret = append(ret, dev)
}
}
return ret
}
func (h *BaseHostDesc) GetIsolatedDevice(devID string) *core.IsolatedDeviceDesc {
for _, dev := range h.IsolatedDevices {
if dev.ID == devID {
return dev
}
}
return nil
}
func (h *BaseHostDesc) GetIsolatedDevices() []*core.IsolatedDeviceDesc {
return h.IsolatedDevices
}
func (h *BaseHostDesc) fillIsolatedDevices(b *baseBuilder, host *computemodels.SHost) error {
allDevs := b.getIsolatedDevices(host.Id)
if len(allDevs) == 0 {
return nil
}
devs := make([]*core.IsolatedDeviceDesc, len(allDevs))
for index, devModel := range allDevs {
dev := &core.IsolatedDeviceDesc{
ID: devModel.Id,
HostID: devModel.HostId,
DevType: devModel.DevType,
SharingMode: devModel.SharingMode,
Model: devModel.Model,
Addr: devModel.Addr,
VendorDeviceID: devModel.VendorDeviceId,
WireId: devModel.WireId,
DevicePath: devModel.DevicePath,
MemorySize: devModel.MemorySize,
MemorySizeAllocated: devModel.MemoryAllocated,
VirtualNum: devModel.VirtualNum,
VirtualNumAllocated: devModel.GuestCount,
}
devs[index] = dev
}
h.IsolatedDevices = devs
return nil
}
func (b *BaseHostDesc) fillCloudProvider(builder *baseBuilder, host *computemodels.SHost) error {
provider, ok := builder.hostCloudproviers[host.GetId()]
if !ok {
return nil
}
b.Cloudprovider = provider
account, ok := builder.hostCloudaccounts[host.GetId()]
if !ok {
return nil
}
b.Cloudaccount = account
return nil
}
func (b *BaseHostDesc) fillRegion(host *computemodels.SHost) error {
regionId := b.Zone.GetCloudRegionId()
obj, ok := cloudregion.Manager.GetResource(regionId)
if !ok {
return errors.Errorf("Not found cloudregion by host %q with id %q", host.GetName(), regionId)
}
b.Region = &obj
return nil
}
func (b *BaseHostDesc) fillZone(host *computemodels.SHost) error {
obj, ok := zone.Manager.GetResource(host.ZoneId)
if !ok {
return errors.Errorf("Not found zone by host %q with id %q", host.GetName(), host.ZoneId)
}
b.Zone = &obj
b.ZoneId = host.ZoneId
return nil
}
// func (b *BaseHostDesc) fillResidentTenants(host *computemodels.SHost) error {
// rets, err := HostResidentTenantCount(host.Id)
// if err != nil {
// return err
// }
//
// b.Tenants = rets
//
// return nil
// }
func (b *BaseHostDesc) fillSharedDomains() error {
b.SharedDomains = b.SHost.GetSharedDomains()
return nil
}
func (b *BaseHostDesc) fillNetworks(host *computemodels.SHost, netGetter *networkGetter) error {
hostId := host.Id
netifs := netinterface.GetByHost(hostId)
wireIds := sets.NewString()
for _, netif := range netifs {
if netif.NicType != computeapi.NIC_TYPE_IPMI && len(netif.WireId) > 0 {
wireIds.Insert(netif.WireId)
}
}
nets := make([]computemodels.SNetwork, 0)
allNets := network.Manager.GetStore().GetAll()
for _, net := range allNets {
netAdditionalWireIds := network_additional_wire.FetchNetworkAdditionalWireIds(net.Id)
if wireIds.Has(net.WireId) || wireIds.HasAny(netAdditionalWireIds...) {
nets = append(nets, net)
}
}
b.Networks = make([]*api.CandidateNetwork, len(nets))
for idx, n := range nets {
freePort, err := netGetter.GetFreePort(host, &n)
if err != nil {
return errors.Wrapf(err, "GetFreePort for network %s(%s)", n.GetName(), n.GetId())
}
b.Networks[idx] = &api.CandidateNetwork{
SNetwork: &nets[idx],
FreePort: freePort,
}
}
// netifs := host.GetNetInterfaces()
// netifs := netinterface.GetByHost(hostId)
netifIndexs := make(map[string][]computemodels.SNetInterface, 0)
for _, netif := range netifs {
if !netif.IsUsableServernic() {
continue
}
wireId := netif.WireId
if _, exist := netifIndexs[wireId]; !exist {
netifIndexs[wireId] = make([]computemodels.SNetInterface, 0)
}
netifIndexs[wireId] = append(netifIndexs[wireId], netif)
}
b.NetInterfaces = netifIndexs
return nil
}
func (b *BaseHostDesc) fillCloudpodsVpcNetworks(netGetter *networkGetter) error {
nets := computemodels.NetworkManager.Query()
wires := computemodels.WireManager.Query().SubQuery()
vpcs := computemodels.VpcManager.Query().SubQuery()
regions := computemodels.CloudregionManager.Query().Equals("provider", computeapi.CLOUD_PROVIDER_CLOUDPODS).SubQuery()
q := nets.AppendField(nets.QueryFields()...)
q = q.AppendField(
vpcs.Field("id", "vpc_id"),
regions.Field("provider"),
)
q = q.Join(wires, sqlchemy.Equals(wires.Field("id"), nets.Field("wire_id")))
q = q.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
q = q.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
q = q.Filter(
sqlchemy.NOT(sqlchemy.Equals(vpcs.Field("external_id"), computeapi.DEFAULT_VPC_ID)),
)
return b.fillNetworksByQuery(netGetter, q)
}
func (b *BaseHostDesc) fillOnecloudVpcNetworks(netGetter *networkGetter) error {
nets := computemodels.NetworkManager.Query()
wires := computemodels.WireManager.Query().SubQuery()
vpcs := computemodels.VpcManager.Query().SubQuery()
regions := computemodels.CloudregionManager.Query().Equals("provider", computeapi.CLOUD_PROVIDER_ONECLOUD).SubQuery()
q := nets.AppendField(nets.QueryFields()...)
q = q.AppendField(
vpcs.Field("id", "vpc_id"),
regions.Field("provider"),
)
q = q.Join(wires, sqlchemy.Equals(wires.Field("id"), nets.Field("wire_id")))
q = q.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
q = q.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
q = q.Filter(
sqlchemy.NOT(sqlchemy.Equals(vpcs.Field("id"), computeapi.DEFAULT_VPC_ID)),
)
return b.fillNetworksByQuery(netGetter, q)
}
func (b *BaseHostDesc) fillOneCloudHostLocalNetworks(netGetter *networkGetter) error {
nets := computemodels.NetworkManager.Query()
wires := computemodels.WireManager.Query().Equals("id", computeapi.DEFAULT_HOST_LOCAL_WIRE_ID).SubQuery()
vpcs := computemodels.VpcManager.Query().Equals("id", computeapi.DEFAULT_VPC_ID).SubQuery()
regions := computemodels.CloudregionManager.Query().Equals("provider", computeapi.CLOUD_PROVIDER_ONECLOUD).SubQuery()
q := nets.AppendField(nets.QueryFields()...)
q = q.AppendField(
vpcs.Field("id", "vpc_id"),
regions.Field("provider"),
)
q = q.Join(wires, sqlchemy.Equals(wires.Field("id"), nets.Field("wire_id")))
q = q.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
q = q.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
return b.fillNetworksByQuery(netGetter, q)
}
func (b *BaseHostDesc) fillCloudpodsHostLocalNetworks(netGetter *networkGetter) error {
nets := computemodels.NetworkManager.Query()
wires := computemodels.WireManager.Query().Equals("external_id", computeapi.DEFAULT_HOST_LOCAL_WIRE_ID).SubQuery()
vpcs := computemodels.VpcManager.Query().Equals("external_id", computeapi.DEFAULT_VPC_ID).SubQuery()
regions := computemodels.CloudregionManager.Query().Equals("provider", computeapi.CLOUD_PROVIDER_CLOUDPODS).SubQuery()
q := nets.AppendField(nets.QueryFields()...)
q = q.AppendField(
vpcs.Field("id", "vpc_id"),
regions.Field("provider"),
)
q = q.Join(wires, sqlchemy.Equals(wires.Field("id"), nets.Field("wire_id")))
q = q.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
q = q.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
return b.fillNetworksByQuery(netGetter, q)
}
func (b *BaseHostDesc) fillNetworksByQuery(netGetter *networkGetter, q *sqlchemy.SQuery) error {
type Row struct {
computemodels.SNetwork
VpcId string
Provider string
}
rows := []Row{}
if err := q.All(&rows); err != nil {
return errors.Wrap(err, "query onecloud vpc networks")
}
for i := range rows {
row := &rows[i]
net := &row.SNetwork
net.SetModelManager(computemodels.NetworkManager, net)
freePort, err := netGetter.GetFreePort(b.SHost, net)
if err != nil {
return errors.Wrapf(err, "GetFreeAddressCount for network %s(%s)", net.GetName(), net.GetId())
}
candidateNet := &api.CandidateNetwork{
SNetwork: net,
FreePort: freePort,
VpcId: row.VpcId,
Provider: row.Provider,
}
b.Networks = append(b.Networks, candidateNet)
}
return nil
}
func (b *BaseHostDesc) GetHypervisorDriver() computemodels.IGuestDriver {
if b.Region == nil {
return nil
}
hostDriver, _ := computemodels.GetHostDriver(b.HostType, b.Region.Provider)
if hostDriver == nil {
return nil
}
driver, _ := computemodels.GetDriver(hostDriver.GetHypervisor(), b.Region.Provider)
return driver
}
func (b *BaseHostDesc) fillStorages(host *computemodels.SHost) error {
ss := make([]*api.CandidateStorage, 0)
storages, err := host.GetStorages()
if err != nil {
return errors.Wrapf(err, "host %s/%s get storages", b.Name, b.Id)
}
for _, tmpS := range storages {
storage := tmpS
cs := &api.CandidateStorage{
SStorage: &storage,
ActualFreeCapacity: storage.Capacity - storage.ActualCapacityUsed,
}
driver := b.GetHypervisorDriver()
if driver == nil || driver.DoScheduleStorageFilter() {
cs.FreeCapacity = storage.GetFreeCapacity()
}
ss = append(ss, cs)
}
b.Storages = ss
return nil
}
func (b *BaseHostDesc) fillInstanceGroups(host *computemodels.SHost) error {
candidateSet := make(map[string]*api.CandidateGroup)
groups, groupSet, err := host.InstanceGroups()
if err != nil {
b.InstanceGroups = candidateSet
return err
}
for i := range groups {
id := groups[i].GetId()
candidateSet[id] = &api.CandidateGroup{
SGroup: &groups[i],
ReferCount: groupSet[id],
}
}
b.InstanceGroups = candidateSet
return nil
}
func (b *BaseHostDesc) fillClassMetadata(host *computemodels.SHost) error {
cm, err := host.GetAllClassMetadata()
if err != nil {
return err
}
b.ClassMetadata = cm
return nil
}
func (b *BaseHostDesc) fillIpmiInfo(host *computemodels.SHost) error {
info, err := host.GetIpmiInfo()
if err != nil {
return err
}
b.IpmiInfo = info
return nil
}
func (b *BaseHostDesc) fillNics(host *computemodels.SHost) error {
b.Nics = host.GetNics()
return nil
}
func (h *BaseHostDesc) GetEnableStatus() string {
if h.GetEnabled() {
return "enable"
}
return "disable"
}
func (h *BaseHostDesc) GetHostType() string {
if h.HostType == api.HostTypeBaremetal && h.IsBaremetal {
return api.HostTypeBaremetal
}
return h.HostType
}
func (h *BaseHostDesc) getQuotaKeys(s *api.SchedInfo) computemodels.SComputeResourceKeys {
computeKeys := computemodels.SComputeResourceKeys{}
computeKeys.DomainId = s.Domain
computeKeys.ProjectId = s.Project
if h.Cloudprovider != nil {
computeKeys.Provider = h.Cloudaccount.Provider
computeKeys.Brand = h.Cloudaccount.Brand
computeKeys.CloudEnv = h.Cloudaccount.GetCloudEnv()
computeKeys.AccountId = h.Cloudaccount.Id
computeKeys.ManagerId = h.Cloudprovider.Id
} else {
computeKeys.Provider = computeapi.CLOUD_PROVIDER_ONECLOUD
computeKeys.Brand = computeapi.ONECLOUD_BRAND_ONECLOUD
computeKeys.CloudEnv = computeapi.CLOUD_ENV_ON_PREMISE
computeKeys.AccountId = ""
computeKeys.ManagerId = ""
}
computeKeys.RegionId = h.Region.Id
computeKeys.ZoneId = h.Zone.Id
driver, _ := computemodels.GetHostDriver(h.HostType, computeKeys.Provider)
if driver != nil {
computeKeys.Hypervisor = driver.GetHypervisor()
}
return computeKeys
}
func HostsResidentTenantStats(hostIDs []string) (map[string]map[string]interface{}, error) {
residentTenantStats, err := FetchHostsResidentTenants(hostIDs)
if err != nil {
return nil, err
}
stat3 := make([]utils.StatItem3, len(residentTenantStats))
for i, item := range residentTenantStats {
stat3[i] = item
}
return utils.ToStatDict3(stat3)
}
func HostResidentTenantCount(id string) (map[string]int64, error) {
residentTenantDict, err := HostsResidentTenantStats([]string{id})
if err != nil {
return nil, err
}
tenantMap, ok := residentTenantDict[id]
if !ok {
log.V(10).Infof("Not found host ID: %s when fill resident tenants, may be no guests on it.", id)
return nil, nil
}
rets := make(map[string]int64, len(tenantMap))
for tenantID, countObj := range tenantMap {
rets[tenantID] = countObj.(int64)
}
return rets, nil
}
type DescBuilder struct {
actor BuildActor
isolatedDevicesDict map[string][]interface{}
}
func NewDescBuilder(act BuildActor) *DescBuilder {
return &DescBuilder{
actor: act,
}
}
func (d *DescBuilder) Build(ids []string) ([]interface{}, error) {
return d.actor.Do(ids)
}