Files
cloudpods/pkg/compute/models/capabilities.go
2020-04-15 17:05:31 +08:00

699 lines
25 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 models
import (
"context"
"database/sql"
"fmt"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/tristate"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/options"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type SCapabilities struct {
Hypervisors []string `json:",allowempty"`
Brands []string `json:",allowempty"`
DisabledBrands []string `json:",allowempty"`
ComputeEngineBrands []string `json:",allowempty"`
DisabledComputeEngineBrands []string `json:",allowempty"`
NetworkManageBrands []string `json:",allowempty"`
DisabledNetworkManageBrands []string `json:",allowempty"`
ObjectStorageBrands []string `json:",allowempty"`
DisabledObjectStorageBrands []string `json:",allowempty"`
ResourceTypes []string `json:",allowempty"`
StorageTypes []string `json:",allowempty"` // going to remove on 2.14
DataStorageTypes []string `json:",allowempty"` // going to remove on 2.14
GPUModels []string `json:",allowempty"`
MinNicCount int
MaxNicCount int
MinDataDiskCount int
MaxDataDiskCount int
SchedPolicySupport bool
Usable bool
PublicNetworkCount int
DBInstance map[string]map[string]map[string][]string //map[engine][engineVersion][category][]{storage_type}
Specs jsonutils.JSONObject
StorageTypes2 map[string][]string `json:",allowempty"`
StorageTypes3 map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
DataStorageTypes2 map[string][]string `json:",allowempty"`
DataStorageTypes3 map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
}
func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, region *SCloudregion, zone *SZone) (SCapabilities, error) {
capa := SCapabilities{}
scopeStr := jsonutils.GetAnyString(query, []string{"scope"})
scope := rbacutils.String2Scope(scopeStr)
var domainId string
domainStr := jsonutils.GetAnyString(query, []string{"domain", "domain_id", "project_domain", "project_domain_id"})
if len(domainStr) > 0 {
domain, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, domainStr)
if err != nil {
if err == sql.ErrNoRows {
return capa, httperrors.NewResourceNotFoundError2("domains", domainStr)
}
return capa, httperrors.NewGeneralError(err)
}
domainId = domain.GetId()
} else {
domainId = userCred.GetProjectDomainId()
}
if scope == rbacutils.ScopeSystem {
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), "capabilities", policy.PolicyActionList)
if result != rbacutils.Allow {
return capa, httperrors.NewForbiddenError("not allow to query system capability")
}
domainId = ""
}
capa.Hypervisors = getHypervisors(region, zone, domainId)
getBrands(region, zone, domainId, &capa)
// capa.Brands, capa.ComputeEngineBrands, capa.NetworkManageBrands, capa.ObjectStorageBrands = a, c, n, o
capa.ResourceTypes = getResourceTypes(region, zone, domainId)
s1, d1, s2, s3, d2, d3 := getStorageTypes(region, zone, domainId)
capa.StorageTypes, capa.DataStorageTypes = s1, d1
capa.StorageTypes2, capa.StorageTypes3 = s2, s3
capa.DataStorageTypes2, capa.DataStorageTypes3 = d2, d3
capa.GPUModels = getGPUs(region, zone, domainId)
capa.SchedPolicySupport = isSchedPolicySupported(region, zone)
capa.MinNicCount = getMinNicCount(region, zone)
capa.MaxNicCount = getMaxNicCount(region, zone)
capa.MinDataDiskCount = getMinDataDiskCount(region, zone)
capa.MaxDataDiskCount = getMaxDataDiskCount(region, zone)
capa.DBInstance = getDBInstanceInfo(region, zone)
capa.Usable = isUsable(region, zone, domainId)
if query == nil {
query = jsonutils.NewDict()
}
if region != nil {
query.(*jsonutils.JSONDict).Add(jsonutils.NewString(region.GetId()), "region")
}
if zone != nil {
query.(*jsonutils.JSONDict).Add(jsonutils.NewString(zone.GetId()), "zone")
}
if len(domainId) > 0 {
query.(*jsonutils.JSONDict).Add(jsonutils.NewString(domainId), "domain_id")
}
var err error
serverType := jsonutils.GetAnyString(query, []string{"host_type", "server_type"})
publicNetworkCount, _ := getNetworkPublicCount(region, zone, domainId, serverType)
capa.PublicNetworkCount = publicNetworkCount
mans := []ISpecModelManager{HostManager, IsolatedDeviceManager}
capa.Specs, err = GetModelsSpecs(ctx, userCred, query.(*jsonutils.JSONDict), mans...)
return capa, err
}
func getRegionZoneSubq(region *SCloudregion) *sqlchemy.SSubQuery {
return ZoneManager.Query("id").Equals("cloudregion_id", region.GetId()).SubQuery()
}
func domainManagerFieldFilter(domainId, field string) *sqlchemy.SSubQuery {
accounts := CloudaccountManager.Query("id")
accounts = CloudaccountManager.filterByDomainId(accounts, domainId)
accounts = accounts.Equals("status", api.CLOUD_PROVIDER_CONNECTED)
accounts = accounts.IsTrue("enabled")
q := CloudproviderManager.Query(field).In("cloudaccount_id", accounts.SubQuery())
/*q := providers.Query(providers.Field(field))
q = q.Join(accounts, sqlchemy.Equals(accounts.Field("id"), providers.Field("cloudaccount_id")))
q = q.Filter(sqlchemy.OR(
sqlchemy.AND(
sqlchemy.Equals(providers.Field("domain_id"), domainId),
sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
),
sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM),
sqlchemy.AND(
sqlchemy.Equals(accounts.Field("domain_id"), domainId),
sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN),
),
))
q = q.Filter(sqlchemy.Equals(accounts.Field("status"), api.CLOUD_PROVIDER_CONNECTED))
q = q.Filter(sqlchemy.IsTrue(accounts.Field("enabled")))*/
return q.SubQuery()
}
/*func getDomainManagerSubq(domainId string) *sqlchemy.SSubQuery {
return domainManagerFieldFilter(domainId, "id")
}*/
func getDomainManagerProviderSubq(domainId string) *sqlchemy.SSubQuery {
return domainManagerFieldFilter(domainId, "provider")
}
func getDBInstanceInfo(region *SCloudregion, zone *SZone) map[string]map[string]map[string][]string {
if zone != nil {
region = zone.GetRegion()
}
if region == nil {
return nil
}
q := DBInstanceSkuManager.Query("engine", "engine_version", "category", "storage_type", "zone1", "zone2", "zone3").Equals("cloudregion_id", region.Id).IsTrue("enabled").Equals("status", api.DBINSTANCE_SKU_AVAILABLE).Distinct()
if zone != nil {
q = q.Filter(sqlchemy.OR(
sqlchemy.Equals(q.Field("zone1"), zone.Id),
sqlchemy.Equals(q.Field("zone2"), zone.Id),
sqlchemy.Equals(q.Field("zone3"), zone.Id),
))
}
rows, err := q.Rows()
if err != nil {
return nil
}
defer rows.Close()
result := map[string]map[string]map[string][]string{}
for rows.Next() {
var engine, engineVersion, category, storageType, zone1, zone2, zone3 string
rows.Scan(&engine, &engineVersion, &category, &storageType, &zone1, &zone2, &zone3)
if _, ok := result[engine]; !ok {
result[engine] = map[string]map[string][]string{}
}
if _, ok := result[engine][engineVersion]; !ok {
result[engine][engineVersion] = map[string][]string{}
}
if _, ok := result[engine][engineVersion][category]; !ok {
result[engine][engineVersion][category] = []string{}
}
if !utils.IsInStringArray(storageType, result[engine][engineVersion][category]) {
result[engine][engineVersion][category] = append(result[engine][engineVersion][category], storageType)
}
}
return result
}
// set all brands, compute engine brands, network manage brands, object storage brands
func getBrands(region *SCloudregion, zone *SZone, domainId string, capa *SCapabilities) {
capa.Brands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, "")
capa.ComputeEngineBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_COMPUTE)
capa.NetworkManageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_NETWORK)
capa.ObjectStorageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.True, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
if utils.IsInStringArray(api.HYPERVISOR_KVM, capa.Hypervisors) || utils.IsInStringArray(api.HYPERVISOR_BAREMETAL, capa.Hypervisors) {
capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)
capa.ComputeEngineBrands = append(capa.ComputeEngineBrands, api.ONECLOUD_BRAND_ONECLOUD)
}
capa.NetworkManageBrands = append(capa.NetworkManageBrands, api.ONECLOUD_BRAND_ONECLOUD)
capa.DisabledBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, "")
capa.DisabledComputeEngineBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_COMPUTE)
capa.DisabledNetworkManageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_NETWORK)
capa.DisabledObjectStorageBrands, _ = CloudaccountManager.getBrandsOfCapability(region, zone, domainId, tristate.False, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE)
return
}
func getHypervisors(region *SCloudregion, zone *SZone, domainId string) []string {
q := HostManager.Query("host_type", "manager_id")
if region != nil {
subq := getRegionZoneSubq(region)
q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
}
if zone != nil {
q = q.Equals("zone_id", zone.Id)
}
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
q = HostManager.FilterByOwner(q, ownerId, rbacutils.ScopeDomain)
/*subq := getDomainManagerSubq(domainId)
q = q.Filter(sqlchemy.OR(
sqlchemy.In(q.Field("manager_id"), subq),
sqlchemy.IsNullOrEmpty(q.Field("manager_id")),
))*/
}
q = q.IsNotEmpty("host_type").IsNotNull("host_type")
// q = q.Equals("host_status", HOST_ONLINE)
q = q.IsTrue("enabled")
q = q.Distinct()
rows, err := q.Rows()
if err != nil {
return nil
}
defer rows.Close()
hypervisors := make([]string, 0)
for rows.Next() {
var hostType string
var managerId string
rows.Scan(&hostType, &managerId)
if len(hostType) > 0 && IsProviderAccountEnabled(managerId) {
hypervisor := api.HOSTTYPE_HYPERVISOR[hostType]
if !utils.IsInStringArray(hypervisor, hypervisors) {
hypervisors = append(hypervisors, hypervisor)
}
}
}
return hypervisors
}
func getResourceTypes(region *SCloudregion, zone *SZone, domainId string) []string {
q := HostManager.Query("resource_type", "manager_id")
if region != nil {
subq := getRegionZoneSubq(region)
q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
}
if zone != nil {
q = q.Equals("zone_id", zone.Id)
}
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
q = HostManager.FilterByOwner(q, ownerId, rbacutils.ScopeDomain)
/*subq := getDomainManagerSubq(domainId)
q = q.Filter(sqlchemy.OR(
sqlchemy.In(q.Field("manager_id"), subq),
sqlchemy.IsNullOrEmpty(q.Field("manager_id")),
))*/
}
q = q.IsNotEmpty("resource_type").IsNotNull("resource_type")
q = q.IsTrue("enabled")
q = q.Distinct()
rows, err := q.Rows()
if err != nil {
return nil
}
defer rows.Close()
resourceTypes := make([]string, 0)
for rows.Next() {
var resType string
var managerId string
rows.Scan(&resType, &managerId)
if len(resType) > 0 && IsProviderAccountEnabled(managerId) {
if !utils.IsInStringArray(resType, resourceTypes) {
resourceTypes = append(resourceTypes, resType)
}
}
}
return resourceTypes
}
type StorageInfo struct {
Id string
Name string
VirtualCapacity int64
Capacity int64
Reserved int64
StorageType string
MediumType string
Cmtbound float32
UsedCapacity sql.NullInt64
WasteCapacity sql.NullInt64
FreeCapacity int64
IsSysDiskStore bool
HostType string
}
type sStorage struct {
Id string
Name string
}
type SimpleStorageInfo struct {
Storages []sStorage
VirtualCapacity int64
Capacity int64
Reserved int64
UsedCapacity int64
WasteCapacity int64
FreeCapacity int64
IsSysDiskStore bool
}
func getStorageTypes(
region *SCloudregion, zone *SZone, domainId string,
) (
[]string, []string,
map[string][]string, map[string]map[string]*SimpleStorageInfo,
map[string][]string, map[string]map[string]*SimpleStorageInfo,
) {
storages := StorageManager.Query().SubQuery()
disks1 := DiskManager.Query().SubQuery()
usedDisk := disks1.Query(
disks1.Field("storage_id"),
sqlchemy.SUM("used_capacity", disks1.Field("disk_size")),
).Equals("status", api.DISK_READY).GroupBy("storage_id").SubQuery()
disks2 := DiskManager.Query().SubQuery()
failedDisk := disks2.Query(
disks2.Field("storage_id"),
sqlchemy.SUM("waste_capacity", disks2.Field("disk_size")),
).NotEquals("status", api.DISK_READY).GroupBy("storage_id").SubQuery()
hostStorages := HoststorageManager.Query().SubQuery()
hostQuery := HostManager.Query()
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
hostQuery = HostManager.FilterByOwner(hostQuery, ownerId, rbacutils.ScopeDomain)
}
hosts := hostQuery.SubQuery()
q := storages.Query(
storages.Field("id"),
storages.Field("name"),
storages.Field("capacity"),
storages.Field("reserved"),
storages.Field("storage_type"),
storages.Field("medium_type"),
storages.Field("cmtbound"),
usedDisk.Field("used_capacity"),
failedDisk.Field("waste_capacity"),
storages.Field("is_sys_disk_store"),
hosts.Field("host_type"),
)
q = q.LeftJoin(usedDisk, sqlchemy.Equals(usedDisk.Field("storage_id"), storages.Field("id")))
q = q.LeftJoin(failedDisk, sqlchemy.Equals(failedDisk.Field("storage_id"), storages.Field("id")))
q = q.Join(hostStorages, sqlchemy.Equals(
hostStorages.Field("storage_id"),
storages.Field("id"),
))
q = q.Join(hosts, sqlchemy.Equals(
hosts.Field("id"),
hostStorages.Field("host_id"),
))
if region != nil {
subq := getRegionZoneSubq(region)
q = q.Filter(sqlchemy.In(storages.Field("zone_id"), subq))
}
if zone != nil {
q = q.Filter(sqlchemy.Equals(storages.Field("zone_id"), zone.Id))
}
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
q = StorageManager.FilterByOwner(q, ownerId, rbacutils.ScopeDomain)
}
q = q.Filter(sqlchemy.Equals(hosts.Field("resource_type"), api.HostResourceTypeShared))
q = q.Filter(sqlchemy.IsNotEmpty(storages.Field("storage_type")))
q = q.Filter(sqlchemy.IsNotNull(storages.Field("storage_type")))
q = q.Filter(sqlchemy.IsNotEmpty(storages.Field("medium_type")))
q = q.Filter(sqlchemy.IsNotNull(storages.Field("medium_type")))
q = q.Filter(sqlchemy.In(storages.Field("status"), []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}))
q = q.Filter(sqlchemy.IsTrue(storages.Field("enabled")))
q = q.Filter(sqlchemy.NotEquals(hosts.Field("host_type"), api.HOST_TYPE_BAREMETAL))
rows, err := q.Rows()
if err != nil {
log.Errorf("get storage types failed %s", err)
return nil, nil, nil, nil, nil, nil
}
defer rows.Close()
var (
sysStorageTypes = make([]string, 0)
allStorageTypes = make([]string, 0)
storageInfos = make(map[string]*SimpleStorageInfo)
sysHypervisorStorageTypes = make(map[string][]string)
allHypervisorStorageTypes = make(map[string][]string)
sysHypervisorStorageInfos = make(map[string]map[string]*SimpleStorageInfo)
allHypervisorStorageInfos = make(map[string]map[string]*SimpleStorageInfo)
setStorageTypes = func(storageHypervisor, storageType string, hypervisorStorageTypes map[string][]string) {
sts, ok := hypervisorStorageTypes[storageHypervisor]
if !ok {
sts = make([]string, 0)
}
sts = append(sts, storageType)
hypervisorStorageTypes[storageHypervisor] = sts
}
addStorageInfo = func(storage *StorageInfo, simpleStorage *SimpleStorageInfo) {
simpleStorage.VirtualCapacity += storage.VirtualCapacity
simpleStorage.FreeCapacity += storage.FreeCapacity
simpleStorage.Reserved += storage.Reserved
simpleStorage.Capacity += storage.Capacity
simpleStorage.WasteCapacity += storage.WasteCapacity.Int64
simpleStorage.UsedCapacity += storage.UsedCapacity.Int64
simpleStorage.Storages = append(simpleStorage.Storages, sStorage{Id: storage.Id, Name: storage.Name})
}
setStorageInfos = func(storageHypervisor, storageType string, storage *StorageInfo,
hypervisorStorageInfos map[string]map[string]*SimpleStorageInfo) bool {
var notFound bool
sfs, ok := hypervisorStorageInfos[storageHypervisor]
if !ok {
sfs = make(map[string]*SimpleStorageInfo)
notFound = true
}
simpleStorage, ok := sfs[storageType]
if !ok {
notFound = true
simpleStorage = &SimpleStorageInfo{Storages: []sStorage{}}
}
if !utils.IsInStringArray(storageHypervisor, api.PUBLIC_CLOUD_HYPERVISORS) {
addStorageInfo(storage, simpleStorage)
sfs[storageType] = simpleStorage
hypervisorStorageInfos[storageHypervisor] = sfs
}
return notFound
}
)
for rows.Next() {
var storage StorageInfo
err := rows.Scan(
&storage.Id, &storage.Name,
&storage.Capacity, &storage.Reserved,
&storage.StorageType, &storage.MediumType,
&storage.Cmtbound, &storage.UsedCapacity,
&storage.WasteCapacity, &storage.IsSysDiskStore,
&storage.HostType,
)
if err != nil {
log.Errorf("Scan storage rows %s", err)
return nil, nil, nil, nil, nil, nil
}
storageHypervisor := api.HOSTTYPE_HYPERVISOR[storage.HostType]
if len(storage.StorageType) > 0 && len(storage.MediumType) > 0 {
storageType := fmt.Sprintf("%s/%s", storage.StorageType, storage.MediumType)
simpleStorage, ok := storageInfos[storageType]
if !ok {
simpleStorage = &SimpleStorageInfo{Storages: []sStorage{}}
if storage.IsSysDiskStore {
sysStorageTypes = append(sysStorageTypes, storageType)
}
allStorageTypes = append(allStorageTypes, storageType)
}
if storage.Cmtbound == 0 {
storage.Cmtbound = options.Options.DefaultStorageOvercommitBound
}
storage.VirtualCapacity = int64(float32((storage.Capacity - storage.Reserved)) * storage.Cmtbound)
storage.FreeCapacity = storage.VirtualCapacity - storage.UsedCapacity.Int64 - storage.WasteCapacity.Int64
addStorageInfo(&storage, simpleStorage)
storageInfos[storageType] = simpleStorage
// set hypervisor storage types and infos
if storage.IsSysDiskStore {
if setStorageInfos(storageHypervisor, storageType, &storage, sysHypervisorStorageInfos) {
setStorageTypes(storageHypervisor, storageType, sysHypervisorStorageTypes)
}
}
if setStorageInfos(storageHypervisor, storageType, &storage, allHypervisorStorageInfos) {
setStorageTypes(storageHypervisor, storageType, allHypervisorStorageTypes)
}
}
}
return sysStorageTypes, allStorageTypes,
sysHypervisorStorageTypes, sysHypervisorStorageInfos,
allHypervisorStorageTypes, allHypervisorStorageInfos
}
func getGPUs(region *SCloudregion, zone *SZone, domainId string) []string {
devices := IsolatedDeviceManager.Query().SubQuery()
hostQuery := HostManager.Query()
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
hostQuery = StorageManager.FilterByOwner(hostQuery, ownerId, rbacutils.ScopeDomain)
}
hosts := hostQuery.SubQuery()
q := devices.Query(devices.Field("model"))
if region != nil {
subq := getRegionZoneSubq(region)
q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
q = q.Filter(sqlchemy.In(hosts.Field("zone_id"), subq))
}
if zone != nil {
q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), zone.Id))
}
/*if len(domainId) > 0 {
subq := getDomainManagerSubq(domainId)
q = q.Filter(sqlchemy.OR(
sqlchemy.In(hosts.Field("manager_id"), subq),
sqlchemy.IsNullOrEmpty(hosts.Field("manager_id")),
))
}*/
q = q.Distinct()
rows, err := q.Rows()
if err != nil {
return nil
}
defer rows.Close()
gpus := make([]string, 0)
for rows.Next() {
var model string
rows.Scan(&model)
if len(model) > 0 {
gpus = append(gpus, model)
}
}
return gpus
}
func getNetworkCount(region *SCloudregion, zone *SZone, domainId string) (int, error) {
return getNetworkCountByFilter(region, zone, domainId, tristate.None, "")
}
func getNetworkPublicCount(region *SCloudregion, zone *SZone, domainId, serverType string) (int, error) {
return getNetworkCountByFilter(region, zone, domainId, tristate.True, serverType)
}
func getNetworkCountByFilter(region *SCloudregion, zone *SZone, domainId string, isPublic tristate.TriState, serverType string) (int, error) {
if zone != nil && region == nil {
region = zone.GetRegion()
}
/*vpcQuery := VpcManager.Query()
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
vpcQuery = VpcManager.FilterByOwner(vpcQuery, ownerId, rbacutils.ScopeDomain)
}
vpcs := vpcQuery.SubQuery()*/
wireQuery := WireManager.Query()
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
wireQuery = WireManager.FilterByOwner(wireQuery, ownerId, rbacutils.ScopeDomain)
}
wires := wireQuery.SubQuery()
networks := NetworkManager.Query().SubQuery()
q := networks.Query()
if !isPublic.IsNone() {
if isPublic.IsTrue() {
q = q.IsTrue("is_public")
} else {
q = q.IsFalse("is_public")
}
}
q = q.Join(wires, sqlchemy.Equals(networks.Field("wire_id"), wires.Field("id")))
if region != nil {
if utils.IsInStringArray(region.Provider, api.REGIONAL_NETWORK_PROVIDERS) {
wires := WireManager.Query().SubQuery()
vpcs := VpcManager.Query().SubQuery()
subq := wires.Query(wires.Field("id")).
Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id"))).
Filter(sqlchemy.Equals(vpcs.Field("cloudregion_id"), region.Id))
q = q.Filter(sqlchemy.In(q.Field("wire_id"), subq))
} else {
subq := getRegionZoneSubq(region)
q = q.Filter(sqlchemy.In(wires.Field("zone_id"), subq))
}
}
if zone != nil && !utils.IsInStringArray(region.Provider, api.REGIONAL_NETWORK_PROVIDERS) {
q = q.Filter(sqlchemy.Equals(wires.Field("zone_id"), zone.Id))
}
if len(domainId) > 0 {
ownerId := &db.SOwnerId{DomainId: domainId}
q = NetworkManager.FilterByOwner(q, ownerId, rbacutils.ScopeDomain)
/*subq := getDomainManagerSubq(domainId)
q = q.Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
q = q.Filter(sqlchemy.OR(
sqlchemy.In(vpcs.Field("manager_id"), subq),
sqlchemy.IsNullOrEmpty(vpcs.Field("manager_id")),
))
if isPublic.Bool() {
q = q.Filter(sqlchemy.OR(
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeSystem),
sqlchemy.AND(
sqlchemy.Equals(q.Field("public_scope"), rbacutils.ScopeDomain),
sqlchemy.Equals(q.Field("domain_id"), domainId))))
}*/
}
if len(serverType) > 0 {
q = q.Filter(sqlchemy.Equals(networks.Field("server_type"), serverType))
}
q = q.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
return q.CountWithError()
}
func isSchedPolicySupported(region *SCloudregion, zone *SZone) bool {
return true
}
func getMinNicCount(region *SCloudregion, zone *SZone) int {
if region != nil {
return region.getMinNicCount()
}
if zone != nil {
return zone.getMinNicCount()
}
return 0
}
func getMaxNicCount(region *SCloudregion, zone *SZone) int {
if region != nil {
return region.getMaxNicCount()
}
if zone != nil {
return zone.getMaxNicCount()
}
return 0
}
func getMinDataDiskCount(region *SCloudregion, zone *SZone) int {
if region != nil {
return region.getMinDataDiskCount()
}
if zone != nil {
return zone.getMinDataDiskCount()
}
return 0
}
func getMaxDataDiskCount(region *SCloudregion, zone *SZone) int {
if region != nil {
return region.getMaxDataDiskCount()
}
if zone != nil {
return zone.getMaxDataDiskCount()
}
return 0
}
func isUsable(region *SCloudregion, zone *SZone, domainId string) bool {
cnt, err := getNetworkCount(region, zone, domainId)
if err != nil {
return false
}
if cnt > 0 {
return true
} else {
return false
}
}