capabilities.go 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package models
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "strings"
  20. "yunion.io/x/cloudmux/pkg/cloudprovider"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/tristate"
  25. "yunion.io/x/pkg/util/rbacscope"
  26. "yunion.io/x/pkg/utils"
  27. "yunion.io/x/sqlchemy"
  28. api "yunion.io/x/onecloud/pkg/apis/compute"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/policy"
  32. "yunion.io/x/onecloud/pkg/compute/options"
  33. "yunion.io/x/onecloud/pkg/httperrors"
  34. "yunion.io/x/onecloud/pkg/mcclient"
  35. )
  36. type SCapabilities struct {
  37. Hypervisors []string `json:",allowempty"`
  38. HypervisorInfo map[string][]string `json:",allowempty"`
  39. Brands []string `json:",allowempty"`
  40. EnabledBrands []string `json:",allowempty"`
  41. DisabledBrands []string `json:",allowempty"`
  42. ComputeEngineBrands []string `json:",allowempty"`
  43. DisabledComputeEngineBrands []string `json:",allowempty"`
  44. RdsEngineBrands []string `json:",allowempty"`
  45. DisabledRdsEngineBrands []string `json:",allowempty"`
  46. RedisEngineBrands []string `json:",allowempty"`
  47. DisabledRedisEngineBrands []string `json:",allowempty"`
  48. LoadbalancerEngineBrands []string `json:",allowempty"`
  49. DisabledLoadbalancerEngineBrands []string `json:",allowempty"`
  50. CloudIdBrands []string `json:",allowempty"`
  51. DisabledCloudIdBrands []string `json:",allowempty"`
  52. // 支持SAML 2.0
  53. SamlAuthBrands []string `json:",allowempty"`
  54. DisabledSamlAuthBrands []string `json:",allowempty"`
  55. NatBrands []string `json:",allowempty"`
  56. DisabledNatBrands []string `json:",allowempty"`
  57. NasBrands []string `json:",allowempty"`
  58. DisabledNasBrands []string `json:",allowempty"`
  59. WafBrands []string `json:",allowempty"`
  60. DisabledWafBrands []string `json:",allowempty"`
  61. CdnBrands []string `json:",allowempty"`
  62. DisabledCdnBrands []string `json:",allowempty"`
  63. PublicIpBrands []string `json:",allowempty"`
  64. DisabledPublicIpBrands []string `json:",allowempty"`
  65. NetworkManageBrands []string `json:",allowempty"`
  66. DisabledNetworkManageBrands []string `json:",allowempty"`
  67. ObjectStorageBrands []string `json:",allowempty"`
  68. DisabledObjectStorageBrands []string `json:",allowempty"`
  69. DisabledModelartsPoolsBrands []string `json:",allowempty"`
  70. ModelartsPoolsBrands []string `json:",allowempty"`
  71. MongoDBBrands []string `json:"mongodb_brands,allowempty"`
  72. DisabledMongoDBBrands []string `json:"disabled_mongodb_brands,allowempty"`
  73. KafkaBrands []string `json:"kafka_brands,allowempty"`
  74. DisabledKafkaBrands []string `json:"disabled_kafka_brands,allowempty"`
  75. DisabledDnsBrands []string `json:",allowempty"`
  76. DnsBrands []string `json:",allowempty"`
  77. ContainerBrands []string `json:",allowempty"`
  78. DisabledContainerBrands []string `json:",allowempty"`
  79. VpcPeerBrands []string `json:",allowempty"`
  80. DisabledVpcPeerBrands []string `json:",allowempty"`
  81. SecurityGroupBrands []string `json:",allowempty"`
  82. DisabledSecurityGroupBrands []string `json:",allowempty"`
  83. SnapshotPolicyBrands []string `json:",allowempty"`
  84. DisabledSnapshotPolicyBrands []string `json:",allowempty"`
  85. ReadOnlyBrands []string `json:",allowempty"`
  86. ReadOnlyDisabledBrands []string `json:",allowempty"`
  87. ReadOnlyComputeEngineBrands []string `json:",allowempty"`
  88. ReadOnlyDisabledComputeEngineBrands []string `json:",allowempty"`
  89. ReadOnlyRdsEngineBrands []string `json:",allowempty"`
  90. ReadOnlyDisabledRdsEngineBrands []string `json:",allowempty"`
  91. ReadOnlyRedisEngineBrands []string `json:",allowempty"`
  92. ReadOnlyDisabledRedisEngineBrands []string `json:",allowempty"`
  93. ReadOnlyLoadbalancerEngineBrands []string `json:",allowempty"`
  94. ReadOnlyDisabledLoadbalancerEngineBrands []string `json:",allowempty"`
  95. ReadOnlyCloudIdBrands []string `json:",allowempty"`
  96. ReadOnlyDisabledCloudIdBrands []string `json:",allowempty"`
  97. // 支持SAML 2.0
  98. ReadOnlySamlAuthBrands []string `json:",allowempty"`
  99. ReadOnlyDisabledSamlAuthBrands []string `json:",allowempty"`
  100. ReadOnlyNatBrands []string `json:",allowempty"`
  101. ReadOnlyDisabledNatBrands []string `json:",allowempty"`
  102. ReadOnlyNasBrands []string `json:",allowempty"`
  103. ReadOnlyDisabledNasBrands []string `json:",allowempty"`
  104. ReadOnlyWafBrands []string `json:",allowempty"`
  105. ReadOnlyDisabledWafBrands []string `json:",allowempty"`
  106. ReadOnlyCdnBrands []string `json:",allowempty"`
  107. ReadOnlyDisabledCdnBrands []string `json:",allowempty"`
  108. ReadOnlyPublicIpBrands []string `json:",allowempty"`
  109. ReadOnlyDisabledPublicIpBrands []string `json:",allowempty"`
  110. ReadOnlyNetworkManageBrands []string `json:",allowempty"`
  111. ReadOnlyDisabledNetworkManageBrands []string `json:",allowempty"`
  112. ReadOnlyObjectStorageBrands []string `json:",allowempty"`
  113. ReadOnlyDisabledObjectStorageBrands []string `json:",allowempty"`
  114. ReadOnlyModelartsPoolsBrands []string `json:",allowempty"`
  115. ReadOnlyDisabledModelartsPoolsBrands []string `json:",allowempty"`
  116. ReadOnlyMongoDBBrands []string `json:"readonly_mongodb_brands,allowempty"`
  117. ReadOnlyDisabledMongoDBBrands []string `json:"readonly_disabled_mongodb_brands,allowempty"`
  118. ReadOnlyKafkaBrands []string `json:"readonly_kafka_brands,allowempty"`
  119. ReadOnlyDisabledKafkaBrands []string `json:"readonly_disabled_kafka_brands,allowempty"`
  120. ReadOnlyDnsBrands []string `json:",allowempty"`
  121. ReadOnlyDisabledDnsBrands []string `json:",allowempty"`
  122. ReadOnlyContainerBrands []string `json:",allowempty"`
  123. ReadOnlyDisabledContainerBrands []string `json:",allowempty"`
  124. ReadOnlyVpcPeerBrands []string `json:",allowempty"`
  125. ReadOnlyDisabledVpcPeerBrands []string `json:",allowempty"`
  126. ReadOnlySecurityGroupBrands []string `json:",allowempty"`
  127. ReadOnlyDisabledSecurityGroupBrands []string `json:",allowempty"`
  128. ReadOnlySnapshotPolicyBrands []string `json:",allowempty"`
  129. ReadOnlyDisabledSnapshotPolicyBrands []string `json:",allowempty"`
  130. ResourceTypes []string `json:",allowempty"`
  131. GPUModels []string `json:",allowempty"` // Deprecated by PCIModelTypes
  132. PCIModelTypes []PCIDevModelTypes `json:",allowempty"`
  133. HostCpuArchs []string `json:",allowempty"` // x86_64 aarch64
  134. MinNicCount int
  135. MaxNicCount int
  136. MinDataDiskCount int
  137. MaxDataDiskCount int
  138. SchedPolicySupport bool
  139. Usable bool
  140. // Deprecated
  141. PublicNetworkCount int
  142. AutoAllocNetworkCount int
  143. DBInstance map[string]map[string]map[string][]string //map[engine][engineVersion][category][]{storage_type}
  144. Specs jsonutils.JSONObject
  145. AvailableHostCount int
  146. *StorageInfos
  147. InstanceCapabilities []cloudprovider.SInstanceCapability
  148. }
  149. type StorageInfos struct {
  150. StorageTypes2 map[string][]string `json:",allowempty"`
  151. StorageTypes3 map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
  152. DataStorageTypes2 map[string][]string `json:",allowempty"`
  153. DataStorageTypes3 map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
  154. SystemStorageTypes map[string]map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
  155. DataStorageTypes map[string]map[string]map[string]*SimpleStorageInfo `json:",allowempty"`
  156. }
  157. func GetDiskCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, region *SCloudregion, zone *SZone) (SCapabilities, error) {
  158. capa := SCapabilities{}
  159. var err error
  160. capa.StorageInfos, err = getStorageTypes(ctx, userCred, region, zone, "")
  161. if err != nil {
  162. return capa, errors.Wrapf(err, "getStorageTypes")
  163. }
  164. capa.MinDataDiskCount = getMinDataDiskCount(region, zone)
  165. capa.MaxDataDiskCount = getMaxDataDiskCount(region, zone)
  166. return capa, nil
  167. }
  168. func GetCapabilities(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, region *SCloudregion, zone *SZone) (SCapabilities, error) {
  169. capa := SCapabilities{}
  170. var ownerId mcclient.IIdentityProvider
  171. scopeStr := jsonutils.GetAnyString(query, []string{"scope"})
  172. scope := rbacscope.String2Scope(scopeStr)
  173. var domainId, tenantId string
  174. domainStr := jsonutils.GetAnyString(query, []string{"domain", "domain_id", "project_domain", "project_domain_id"})
  175. tenantStr := jsonutils.GetAnyString(query, []string{"tenant", "tenant_id", "project", "project_id"})
  176. if len(domainStr) > 0 {
  177. domain, err := db.TenantCacheManager.FetchDomainByIdOrName(ctx, domainStr)
  178. if err != nil {
  179. if err == sql.ErrNoRows {
  180. return capa, httperrors.NewResourceNotFoundError2("domains", domainStr)
  181. }
  182. return capa, httperrors.NewGeneralError(err)
  183. }
  184. domainId = domain.GetId()
  185. ownerId = &db.SOwnerId{DomainId: domainId}
  186. scope = rbacscope.ScopeDomain
  187. } else {
  188. domainId = userCred.GetProjectDomainId()
  189. ownerId = userCred
  190. }
  191. if len(tenantStr) > 0 {
  192. project, err := db.TenantCacheManager.FetchTenantById(ctx, tenantStr)
  193. if err != nil {
  194. if err == sql.ErrNoRows {
  195. return capa, httperrors.NewResourceNotFoundError2("projects", tenantStr)
  196. }
  197. return capa, httperrors.NewGeneralError(err)
  198. }
  199. tenantId = project.GetId()
  200. }
  201. if scope == rbacscope.ScopeSystem {
  202. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), "capabilities", policy.PolicyActionList)
  203. if result.Result.IsDeny() {
  204. return capa, httperrors.NewForbiddenError("not allow to query system capability")
  205. }
  206. domainId = ""
  207. }
  208. var err error
  209. capa.HypervisorInfo, err = getHypervisors(ctx, userCred, region, zone, domainId)
  210. if err != nil {
  211. return capa, errors.Wrapf(err, "getHypervisors")
  212. }
  213. capa.Hypervisors = []string{}
  214. for _, hypervisors := range capa.HypervisorInfo {
  215. for _, h := range hypervisors {
  216. if !utils.IsInStringArray(h, capa.Hypervisors) {
  217. capa.Hypervisors = append(capa.Hypervisors, h)
  218. }
  219. }
  220. }
  221. capa.InstanceCapabilities = []cloudprovider.SInstanceCapability{}
  222. for provider, hypervisors := range capa.HypervisorInfo {
  223. for _, hypervisor := range hypervisors {
  224. driver, _ := GetDriver(hypervisor, provider)
  225. if driver != nil {
  226. capa.InstanceCapabilities = append(capa.InstanceCapabilities, driver.GetInstanceCapability())
  227. }
  228. }
  229. }
  230. if zone != nil {
  231. region, err = zone.GetRegion()
  232. if err != nil {
  233. return capa, errors.Wrapf(err, "GetRegion")
  234. }
  235. }
  236. getBrands(region, domainId, &capa)
  237. capa.ResourceTypes = getResourceTypes(ctx, userCred, region, zone, domainId)
  238. capa.StorageInfos, err = getStorageTypes(ctx, userCred, region, zone, domainId)
  239. if err != nil {
  240. return capa, errors.Wrapf(err, "getStorageTypes")
  241. }
  242. capa.GPUModels, capa.PCIModelTypes = getIsolatedDeviceInfo(ctx, userCred, region, zone, domainId, tenantId)
  243. capa.SchedPolicySupport = isSchedPolicySupported(region, zone)
  244. capa.MinNicCount = getMinNicCount(region, zone)
  245. capa.MaxNicCount = getMaxNicCount(region, zone)
  246. capa.MinDataDiskCount = getMinDataDiskCount(region, zone)
  247. capa.MaxDataDiskCount = getMaxDataDiskCount(region, zone)
  248. capa.DBInstance = getDBInstanceInfo(region, zone)
  249. capa.Usable = isUsable(ctx, userCred, ownerId, scope, region, zone)
  250. capa.HostCpuArchs = getHostCpuArchs(ctx, userCred, region, zone, domainId)
  251. if query == nil {
  252. query = jsonutils.NewDict()
  253. }
  254. if region != nil {
  255. query.(*jsonutils.JSONDict).Add(jsonutils.NewString(region.GetId()), "region")
  256. }
  257. if zone != nil {
  258. query.(*jsonutils.JSONDict).Add(jsonutils.NewString(zone.GetId()), "zone")
  259. }
  260. if len(domainId) > 0 {
  261. query.(*jsonutils.JSONDict).Add(jsonutils.NewString(domainId), "domain_id")
  262. }
  263. serverType := jsonutils.GetAnyString(query, []string{"host_type", "server_type"})
  264. autoAllocNetworkCount, _ := getAutoAllocNetworkCount(ctx, userCred, ownerId, scope, region, zone, serverType)
  265. capa.PublicNetworkCount = autoAllocNetworkCount
  266. capa.AutoAllocNetworkCount = autoAllocNetworkCount
  267. mans := []ISpecModelManager{HostManager, IsolatedDeviceManager}
  268. capa.Specs, err = GetModelsSpecs(ctx, userCred, query.(*jsonutils.JSONDict), mans...)
  269. if err != nil {
  270. return capa, err
  271. }
  272. capa.AvailableHostCount, err = GetAvailableHostCount(ctx, userCred, query.(*jsonutils.JSONDict))
  273. return capa, err
  274. }
  275. func GetAvailableHostCount(ctx context.Context, userCred mcclient.TokenCredential, query *jsonutils.JSONDict) (int, error) {
  276. zoneStr, _ := query.GetString("zone")
  277. izone, _ := ZoneManager.FetchByIdOrName(ctx, userCred, zoneStr)
  278. var zoneId string
  279. if izone != nil {
  280. zoneId = izone.GetId()
  281. }
  282. regionStr, _ := query.GetString("region")
  283. iregion, _ := CloudregionManager.FetchByIdOrName(ctx, userCred, regionStr)
  284. var regionId string
  285. if iregion != nil {
  286. regionId = iregion.GetId()
  287. }
  288. domainId, _ := query.GetString("domain_id")
  289. q := HostManager.Query().Equals("enabled", true).
  290. Equals("host_status", "online").Equals("host_type", api.HOST_TYPE_HYPERVISOR)
  291. if len(domainId) > 0 {
  292. ownerId := &db.SOwnerId{DomainId: domainId}
  293. q = HostManager.FilterByOwner(ctx, q, HostManager, userCred, ownerId, rbacscope.ScopeDomain)
  294. }
  295. if len(zoneId) > 0 {
  296. q = q.Equals("zone_id", zoneId)
  297. }
  298. if len(regionId) > 0 {
  299. subq := ZoneManager.Query("id").Equals("cloudregion_id", regionId).SubQuery()
  300. q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
  301. }
  302. return q.CountWithError()
  303. }
  304. func getRegionZoneSubq(region *SCloudregion) *sqlchemy.SSubQuery {
  305. return ZoneManager.Query("id").Equals("cloudregion_id", region.GetId()).SubQuery()
  306. }
  307. func domainManagerFieldFilter(domainId, field string) *sqlchemy.SSubQuery {
  308. accounts := CloudaccountManager.Query("id")
  309. accounts = CloudaccountManager.filterByDomainId(accounts, domainId)
  310. accounts = accounts.Equals("status", api.CLOUD_PROVIDER_CONNECTED)
  311. accounts = accounts.IsTrue("enabled")
  312. q := CloudproviderManager.Query(field).In("cloudaccount_id", accounts.SubQuery())
  313. /*q := providers.Query(providers.Field(field))
  314. q = q.Join(accounts, sqlchemy.Equals(accounts.Field("id"), providers.Field("cloudaccount_id")))
  315. q = q.Filter(sqlchemy.OR(
  316. sqlchemy.AND(
  317. sqlchemy.Equals(providers.Field("domain_id"), domainId),
  318. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_PROVIDER_DOMAIN),
  319. ),
  320. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_SYSTEM),
  321. sqlchemy.AND(
  322. sqlchemy.Equals(accounts.Field("domain_id"), domainId),
  323. sqlchemy.Equals(accounts.Field("share_mode"), api.CLOUD_ACCOUNT_SHARE_MODE_ACCOUNT_DOMAIN),
  324. ),
  325. ))
  326. q = q.Filter(sqlchemy.Equals(accounts.Field("status"), api.CLOUD_PROVIDER_CONNECTED))
  327. q = q.Filter(sqlchemy.IsTrue(accounts.Field("enabled")))*/
  328. return q.SubQuery()
  329. }
  330. /*func getDomainManagerSubq(domainId string) *sqlchemy.SSubQuery {
  331. return domainManagerFieldFilter(domainId, "id")
  332. }*/
  333. func getDomainManagerProviderSubq(domainId string) *sqlchemy.SSubQuery {
  334. return domainManagerFieldFilter(domainId, "provider")
  335. }
  336. func getDBInstanceInfo(region *SCloudregion, zone *SZone) map[string]map[string]map[string][]string {
  337. if zone != nil {
  338. region, _ = zone.GetRegion()
  339. }
  340. if region == nil || !region.GetDriver().IsSupportedDBInstance() {
  341. return nil
  342. }
  343. 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()
  344. if zone != nil {
  345. q = q.Filter(sqlchemy.OR(
  346. sqlchemy.Equals(q.Field("zone1"), zone.Id),
  347. sqlchemy.Equals(q.Field("zone2"), zone.Id),
  348. sqlchemy.Equals(q.Field("zone3"), zone.Id),
  349. ))
  350. }
  351. rows, err := q.Rows()
  352. if err != nil {
  353. return nil
  354. }
  355. defer rows.Close()
  356. result := map[string]map[string]map[string][]string{}
  357. for rows.Next() {
  358. var engine, engineVersion, category, storageType, zone1, zone2, zone3 string
  359. rows.Scan(&engine, &engineVersion, &category, &storageType, &zone1, &zone2, &zone3)
  360. if _, ok := result[engine]; !ok {
  361. result[engine] = map[string]map[string][]string{}
  362. }
  363. if _, ok := result[engine][engineVersion]; !ok {
  364. result[engine][engineVersion] = map[string][]string{}
  365. }
  366. if _, ok := result[engine][engineVersion][category]; !ok {
  367. result[engine][engineVersion][category] = []string{}
  368. }
  369. if !utils.IsInStringArray(storageType, result[engine][engineVersion][category]) {
  370. result[engine][engineVersion][category] = append(result[engine][engineVersion][category], storageType)
  371. }
  372. }
  373. return result
  374. }
  375. // set all brands, compute engine brands, network manage brands, object storage brands
  376. func getBrands(region *SCloudregion, domainId string, capa *SCapabilities) {
  377. brands, err := CloudaccountManager.getBrandsOfCapability(region, domainId)
  378. if err != nil {
  379. log.Errorf("getBrandsOfCapability: %v", err)
  380. }
  381. brandMaps := map[string]map[string]bool{}
  382. for _, brand := range brands {
  383. _, ok := brandMaps[brand.Brand]
  384. if !ok {
  385. brandMaps[brand.Brand] = map[string]bool{}
  386. }
  387. _, ok = brandMaps[brand.Brand][brand.Capability]
  388. if !ok {
  389. brandMaps[brand.Brand][brand.Capability] = brand.Enabled
  390. }
  391. if brand.Enabled {
  392. brandMaps[brand.Brand][brand.Capability] = true
  393. }
  394. }
  395. if region == nil || region.Provider == api.ONECLOUD_BRAND_ONECLOUD {
  396. if utils.IsInStringArray(api.HYPERVISOR_KVM, capa.Hypervisors) || utils.IsInStringArray(api.HYPERVISOR_BAREMETAL, capa.Hypervisors) {
  397. capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)
  398. capa.SecurityGroupBrands = append(capa.SecurityGroupBrands, api.ONECLOUD_BRAND_ONECLOUD)
  399. capa.ComputeEngineBrands = append(capa.ComputeEngineBrands, api.ONECLOUD_BRAND_ONECLOUD)
  400. capa.SnapshotPolicyBrands = append(capa.SnapshotPolicyBrands, api.ONECLOUD_BRAND_ONECLOUD)
  401. capa.DnsBrands = append(capa.DnsBrands, api.ONECLOUD_BRAND_ONECLOUD)
  402. } else if utils.IsInStringArray(api.HYPERVISOR_POD, capa.Hypervisors) {
  403. capa.Brands = append(capa.Brands, api.ONECLOUD_BRAND_ONECLOUD)
  404. capa.ComputeEngineBrands = append(capa.ComputeEngineBrands, api.ONECLOUD_BRAND_ONECLOUD)
  405. }
  406. if count, _ := LoadbalancerClusterManager.Query().Limit(1).CountWithError(); count > 0 {
  407. capa.LoadbalancerEngineBrands = append(capa.LoadbalancerEngineBrands, api.ONECLOUD_BRAND_ONECLOUD)
  408. }
  409. capa.NetworkManageBrands = append(capa.NetworkManageBrands, api.ONECLOUD_BRAND_ONECLOUD)
  410. }
  411. capa.EnabledBrands = []string{}
  412. capa.DisabledBrands = []string{}
  413. var appendBrand = func(enabled *[]string, disabled *[]string, readOnlyEnabled *[]string, readOnlyDisabled *[]string, brand, capability string, isEnable, readOnly bool) {
  414. if !utils.IsInArray(brand, capa.Brands) {
  415. capa.Brands = append(capa.Brands, brand)
  416. }
  417. if readOnly {
  418. if isEnable {
  419. if !utils.IsInArray(brand, *readOnlyEnabled) {
  420. *readOnlyEnabled = append(*readOnlyEnabled, brand)
  421. }
  422. if !utils.IsInArray(brand, capa.ReadOnlyBrands) {
  423. capa.ReadOnlyBrands = append(capa.ReadOnlyBrands, brand)
  424. }
  425. } else {
  426. if !utils.IsInArray(brand, *readOnlyDisabled) {
  427. *readOnlyDisabled = append(*readOnlyDisabled, brand)
  428. }
  429. if !utils.IsInArray(brand, capa.ReadOnlyDisabledBrands) {
  430. capa.ReadOnlyDisabledBrands = append(capa.ReadOnlyDisabledBrands, brand)
  431. }
  432. }
  433. } else {
  434. if isEnable {
  435. if !utils.IsInArray(brand, *enabled) {
  436. *enabled = append(*enabled, brand)
  437. }
  438. if !utils.IsInArray(brand, capa.EnabledBrands) {
  439. capa.EnabledBrands = append(capa.EnabledBrands, brand)
  440. }
  441. } else {
  442. if !utils.IsInArray(brand, *disabled) {
  443. *disabled = append(*disabled, brand)
  444. }
  445. if !utils.IsInArray(brand, capa.DisabledBrands) {
  446. capa.DisabledBrands = append(capa.DisabledBrands, brand)
  447. }
  448. }
  449. }
  450. }
  451. for brand, info := range brandMaps {
  452. for capability, enabled := range info {
  453. readOnly := false
  454. if strings.HasSuffix(capability, cloudprovider.READ_ONLY_SUFFIX) {
  455. readOnly = true
  456. capability = strings.TrimSuffix(capability, cloudprovider.READ_ONLY_SUFFIX)
  457. }
  458. switch capability {
  459. case cloudprovider.CLOUD_CAPABILITY_COMPUTE:
  460. appendBrand(&capa.ComputeEngineBrands, &capa.DisabledComputeEngineBrands, &capa.ReadOnlyComputeEngineBrands, &capa.ReadOnlyDisabledComputeEngineBrands, brand, capability, enabled, readOnly)
  461. case cloudprovider.CLOUD_CAPABILITY_RDS:
  462. appendBrand(&capa.RdsEngineBrands, &capa.DisabledRdsEngineBrands, &capa.ReadOnlyRdsEngineBrands, &capa.ReadOnlyDisabledRdsEngineBrands, brand, capability, enabled, readOnly)
  463. case cloudprovider.CLOUD_CAPABILITY_CACHE:
  464. appendBrand(&capa.RedisEngineBrands, &capa.DisabledRedisEngineBrands, &capa.ReadOnlyRedisEngineBrands, &capa.ReadOnlyDisabledRedisEngineBrands, brand, capability, enabled, readOnly)
  465. case cloudprovider.CLOUD_CAPABILITY_NETWORK:
  466. appendBrand(&capa.NetworkManageBrands, &capa.DisabledNetworkManageBrands, &capa.ReadOnlyNetworkManageBrands, &capa.ReadOnlyDisabledNetworkManageBrands, brand, capability, enabled, readOnly)
  467. case cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE:
  468. appendBrand(&capa.ObjectStorageBrands, &capa.DisabledObjectStorageBrands, &capa.ReadOnlyObjectStorageBrands, &capa.ReadOnlyDisabledObjectStorageBrands, brand, capability, enabled, readOnly)
  469. case cloudprovider.CLOUD_CAPABILITY_CLOUDID:
  470. appendBrand(&capa.CloudIdBrands, &capa.DisabledCloudIdBrands, &capa.ReadOnlyCloudIdBrands, &capa.ReadOnlyDisabledCloudIdBrands, brand, capability, enabled, readOnly)
  471. case cloudprovider.CLOUD_CAPABILITY_PUBLIC_IP:
  472. appendBrand(&capa.PublicIpBrands, &capa.DisabledPublicIpBrands, &capa.ReadOnlyPublicIpBrands, &capa.ReadOnlyDisabledPublicIpBrands, brand, capability, enabled, readOnly)
  473. case cloudprovider.CLOUD_CAPABILITY_LOADBALANCER:
  474. appendBrand(&capa.LoadbalancerEngineBrands, &capa.DisabledLoadbalancerEngineBrands, &capa.ReadOnlyLoadbalancerEngineBrands, &capa.ReadOnlyDisabledLoadbalancerEngineBrands, brand, capability, enabled, readOnly)
  475. case cloudprovider.CLOUD_CAPABILITY_SAML_AUTH:
  476. appendBrand(&capa.SamlAuthBrands, &capa.DisabledSamlAuthBrands, &capa.ReadOnlySamlAuthBrands, &capa.ReadOnlyDisabledSamlAuthBrands, brand, capability, enabled, readOnly)
  477. case cloudprovider.CLOUD_CAPABILITY_NAT:
  478. appendBrand(&capa.NatBrands, &capa.DisabledNatBrands, &capa.ReadOnlyNatBrands, &capa.ReadOnlyDisabledNatBrands, brand, capability, enabled, readOnly)
  479. case cloudprovider.CLOUD_CAPABILITY_NAS:
  480. appendBrand(&capa.NasBrands, &capa.DisabledNasBrands, &capa.ReadOnlyNasBrands, &capa.ReadOnlyDisabledNasBrands, brand, capability, enabled, readOnly)
  481. case cloudprovider.CLOUD_CAPABILITY_WAF:
  482. appendBrand(&capa.WafBrands, &capa.DisabledWafBrands, &capa.ReadOnlyWafBrands, &capa.ReadOnlyDisabledWafBrands, brand, capability, enabled, readOnly)
  483. case cloudprovider.CLOUD_CAPABILITY_CDN:
  484. appendBrand(&capa.CdnBrands, &capa.DisabledCdnBrands, &capa.ReadOnlyCdnBrands, &capa.ReadOnlyDisabledCdnBrands, brand, capability, enabled, readOnly)
  485. case cloudprovider.CLOUD_CAPABILITY_CONTAINER:
  486. appendBrand(&capa.ContainerBrands, &capa.DisabledContainerBrands, &capa.ReadOnlyContainerBrands, &capa.ReadOnlyDisabledContainerBrands, brand, capability, enabled, readOnly)
  487. case cloudprovider.CLOUD_CAPABILITY_VPC_PEER:
  488. appendBrand(&capa.VpcPeerBrands, &capa.DisabledVpcPeerBrands, &capa.ReadOnlyVpcPeerBrands, &capa.ReadOnlyDisabledVpcPeerBrands, brand, capability, enabled, readOnly)
  489. case cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP:
  490. appendBrand(&capa.SecurityGroupBrands, &capa.DisabledSecurityGroupBrands, &capa.ReadOnlySecurityGroupBrands, &capa.ReadOnlyDisabledSecurityGroupBrands, brand, capability, enabled, readOnly)
  491. case cloudprovider.CLOUD_CAPABILITY_SNAPSHOT_POLICY:
  492. appendBrand(&capa.SnapshotPolicyBrands, &capa.DisabledSnapshotPolicyBrands, &capa.ReadOnlySnapshotPolicyBrands, &capa.ReadOnlyDisabledSnapshotPolicyBrands, brand, capability, enabled, readOnly)
  493. case cloudprovider.CLOUD_CAPABILITY_MODELARTES:
  494. appendBrand(&capa.ModelartsPoolsBrands, &capa.DisabledModelartsPoolsBrands, &capa.ReadOnlyModelartsPoolsBrands, &capa.ReadOnlyDisabledModelartsPoolsBrands, brand, capability, enabled, readOnly)
  495. case cloudprovider.CLOUD_CAPABILITY_DNSZONE:
  496. appendBrand(&capa.DnsBrands, &capa.DisabledDnsBrands, &capa.ReadOnlyDnsBrands, &capa.ReadOnlyDisabledDnsBrands, brand, capability, enabled, readOnly)
  497. case cloudprovider.CLOUD_CAPABILITY_MONGO_DB:
  498. appendBrand(&capa.MongoDBBrands, &capa.DisabledMongoDBBrands, &capa.ReadOnlyMongoDBBrands, &capa.ReadOnlyDisabledMongoDBBrands, brand, capability, enabled, readOnly)
  499. case cloudprovider.CLOUD_CAPABILITY_KAFKA:
  500. appendBrand(&capa.KafkaBrands, &capa.DisabledKafkaBrands, &capa.ReadOnlyKafkaBrands, &capa.ReadOnlyDisabledKafkaBrands, brand, capability, enabled, readOnly)
  501. default:
  502. }
  503. }
  504. }
  505. return
  506. }
  507. func getHypervisors(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId string) (map[string][]string, error) {
  508. q := HostManager.Query().IsNotEmpty("host_type").IsTrue("enabled")
  509. if zone != nil {
  510. q = q.Equals("zone_id", zone.Id)
  511. }
  512. zoneQ := ZoneManager.Query()
  513. if region != nil {
  514. zoneQ = zoneQ.Equals("cloudregion_id", region.Id)
  515. }
  516. if len(domainId) > 0 {
  517. ownerId := &db.SOwnerId{DomainId: domainId}
  518. q = HostManager.FilterByOwner(ctx, q, HostManager, userCred, ownerId, rbacscope.ScopeDomain)
  519. }
  520. zones := zoneQ.SubQuery()
  521. regions := CloudregionManager.Query().SubQuery()
  522. sq := q.SubQuery()
  523. hQ := sq.Query(
  524. sq.Field("host_type"),
  525. regions.Field("provider"),
  526. )
  527. hQ = hQ.Join(zones, sqlchemy.Equals(hQ.Field("zone_id"), zones.Field("id")))
  528. hQ = hQ.Join(regions, sqlchemy.Equals(zones.Field("cloudregion_id"), regions.Field("id")))
  529. result := []struct {
  530. HostType string
  531. Provider string
  532. }{}
  533. hQ = hQ.Distinct()
  534. err := hQ.All(&result)
  535. if err != nil {
  536. return nil, err
  537. }
  538. ret := map[string][]string{}
  539. for _, h := range result {
  540. drv, err := GetHostDriver(h.HostType, h.Provider)
  541. if err != nil {
  542. return nil, errors.Wrapf(err, "GetHostDriver")
  543. }
  544. _, ok := ret[h.Provider]
  545. if !ok {
  546. ret[h.Provider] = []string{}
  547. }
  548. if !utils.IsInStringArray(drv.GetHypervisor(), ret[h.Provider]) {
  549. ret[h.Provider] = append(ret[h.Provider], drv.GetHypervisor())
  550. }
  551. }
  552. return ret, nil
  553. }
  554. func getResourceTypes(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId string) []string {
  555. q := HostManager.Query("resource_type", "manager_id")
  556. if region != nil {
  557. subq := getRegionZoneSubq(region)
  558. q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
  559. }
  560. if zone != nil {
  561. q = q.Equals("zone_id", zone.Id)
  562. }
  563. if len(domainId) > 0 {
  564. ownerId := &db.SOwnerId{DomainId: domainId}
  565. q = HostManager.FilterByOwner(ctx, q, HostManager, userCred, ownerId, rbacscope.ScopeDomain)
  566. /*subq := getDomainManagerSubq(domainId)
  567. q = q.Filter(sqlchemy.OR(
  568. sqlchemy.In(q.Field("manager_id"), subq),
  569. sqlchemy.IsNullOrEmpty(q.Field("manager_id")),
  570. ))*/
  571. }
  572. q = q.IsNotEmpty("resource_type").IsNotNull("resource_type")
  573. q = q.IsTrue("enabled")
  574. q = q.Distinct()
  575. rows, err := q.Rows()
  576. if err != nil {
  577. return nil
  578. }
  579. defer rows.Close()
  580. resourceTypes := make([]string, 0)
  581. for rows.Next() {
  582. var resType string
  583. var managerId string
  584. rows.Scan(&resType, &managerId)
  585. if len(resType) > 0 && IsProviderAccountEnabled(managerId) {
  586. if !utils.IsInStringArray(resType, resourceTypes) {
  587. resourceTypes = append(resourceTypes, resType)
  588. }
  589. }
  590. }
  591. return resourceTypes
  592. }
  593. type StorageInfo struct {
  594. Id string
  595. Name string
  596. VirtualCapacity int64
  597. Capacity int64
  598. Reserved sql.NullInt64
  599. StorageType string
  600. MediumType string
  601. Cmtbound sql.NullFloat64
  602. UsedCapacity sql.NullInt64
  603. WasteCapacity sql.NullInt64
  604. FreeCapacity int64
  605. IsSysDiskStore bool
  606. HostType string
  607. Provider string
  608. }
  609. type sStorage struct {
  610. Id string
  611. Name string
  612. }
  613. type SimpleStorageInfo struct {
  614. Storages []sStorage
  615. VirtualCapacity int64
  616. Capacity int64
  617. Reserved int64
  618. UsedCapacity int64
  619. WasteCapacity int64
  620. FreeCapacity int64
  621. IsSysDiskStore bool
  622. }
  623. func getStorageTypes(
  624. ctx context.Context,
  625. userCred mcclient.TokenCredential,
  626. region *SCloudregion, zone *SZone, domainId string,
  627. ) (*StorageInfos, error) {
  628. storageQ := StorageManager.Query()
  629. disks1 := DiskManager.Query().SubQuery()
  630. usedDisk := disks1.Query(
  631. disks1.Field("storage_id"),
  632. sqlchemy.SUM("used_capacity", disks1.Field("disk_size")),
  633. ).Equals("status", api.DISK_READY).GroupBy("storage_id").SubQuery()
  634. disks2 := DiskManager.Query().SubQuery()
  635. failedDisk := disks2.Query(
  636. disks2.Field("storage_id"),
  637. sqlchemy.SUM("waste_capacity", disks2.Field("disk_size")),
  638. ).NotEquals("status", api.DISK_READY).GroupBy("storage_id").SubQuery()
  639. hostStorages := HoststorageManager.Query().SubQuery()
  640. hostQuery := HostManager.Query()
  641. if len(domainId) > 0 {
  642. ownerId := &db.SOwnerId{DomainId: domainId}
  643. hostQuery = HostManager.FilterByOwner(ctx, hostQuery, HostManager, userCred, ownerId, rbacscope.ScopeDomain)
  644. }
  645. hosts := hostQuery.SubQuery()
  646. zoneQ := ZoneManager.Query()
  647. if zone != nil {
  648. zoneQ = zoneQ.Equals("id", zone.Id)
  649. }
  650. if region != nil {
  651. zoneQ = zoneQ.Equals("cloudregion_id", region.Id)
  652. }
  653. zones := zoneQ.SubQuery()
  654. regions := CloudregionManager.Query().SubQuery()
  655. storages := storageQ.SubQuery()
  656. q := storages.Query(
  657. storages.Field("id"),
  658. storages.Field("name"),
  659. storages.Field("capacity"),
  660. storages.Field("reserved"),
  661. storages.Field("storage_type"),
  662. storages.Field("medium_type"),
  663. storages.Field("cmtbound"),
  664. usedDisk.Field("used_capacity"),
  665. failedDisk.Field("waste_capacity"),
  666. storages.Field("is_sys_disk_store"),
  667. hosts.Field("host_type"),
  668. regions.Field("provider"),
  669. )
  670. q = q.LeftJoin(usedDisk, sqlchemy.Equals(usedDisk.Field("storage_id"), storages.Field("id")))
  671. q = q.LeftJoin(failedDisk, sqlchemy.Equals(failedDisk.Field("storage_id"), storages.Field("id")))
  672. q = q.Join(hostStorages, sqlchemy.Equals(
  673. hostStorages.Field("storage_id"),
  674. storages.Field("id"),
  675. ))
  676. q = q.Join(hosts, sqlchemy.Equals(
  677. hosts.Field("id"),
  678. hostStorages.Field("host_id"),
  679. ))
  680. q = q.Join(zones, sqlchemy.Equals(
  681. storages.Field("zone_id"),
  682. zones.Field("id"),
  683. ))
  684. q = q.Join(regions, sqlchemy.Equals(
  685. zones.Field("cloudregion_id"),
  686. regions.Field("id"),
  687. ))
  688. if len(domainId) > 0 {
  689. ownerId := &db.SOwnerId{DomainId: domainId}
  690. q = StorageManager.FilterByOwner(ctx, q, StorageManager, userCred, ownerId, rbacscope.ScopeDomain)
  691. }
  692. q = q.Filter(sqlchemy.Equals(hosts.Field("resource_type"), api.HostResourceTypeShared))
  693. q = q.Filter(sqlchemy.IsNotEmpty(storages.Field("storage_type")))
  694. q = q.Filter(sqlchemy.IsNotNull(storages.Field("storage_type")))
  695. q = q.Filter(sqlchemy.IsNotEmpty(storages.Field("medium_type")))
  696. q = q.Filter(sqlchemy.IsNotNull(storages.Field("medium_type")))
  697. q = q.Filter(sqlchemy.In(storages.Field("status"), []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}))
  698. q = q.Filter(sqlchemy.IsTrue(storages.Field("enabled")))
  699. q = q.Filter(sqlchemy.NotEquals(hosts.Field("host_type"), api.HOST_TYPE_BAREMETAL))
  700. ret := &StorageInfos{
  701. StorageTypes2: map[string][]string{},
  702. StorageTypes3: map[string]map[string]*SimpleStorageInfo{},
  703. DataStorageTypes2: map[string][]string{},
  704. DataStorageTypes3: map[string]map[string]*SimpleStorageInfo{},
  705. SystemStorageTypes: map[string]map[string]map[string]*SimpleStorageInfo{},
  706. DataStorageTypes: map[string]map[string]map[string]*SimpleStorageInfo{},
  707. }
  708. var (
  709. addStorageInfo = func(storage *StorageInfo, simpleStorage *SimpleStorageInfo) {
  710. simpleStorage.VirtualCapacity += storage.VirtualCapacity
  711. simpleStorage.FreeCapacity += storage.FreeCapacity
  712. simpleStorage.Reserved += storage.Reserved.Int64
  713. simpleStorage.Capacity += storage.Capacity
  714. simpleStorage.WasteCapacity += storage.WasteCapacity.Int64
  715. simpleStorage.UsedCapacity += storage.UsedCapacity.Int64
  716. simpleStorage.Storages = append(simpleStorage.Storages, sStorage{Id: storage.Id, Name: storage.Name})
  717. }
  718. setStorageInfos = func(hostDriver IHostDriver, storageType string, storage *StorageInfo,
  719. storageInfos map[string]map[string]*SimpleStorageInfo) {
  720. sfs, ok := storageInfos[hostDriver.GetHypervisor()]
  721. if !ok {
  722. sfs = make(map[string]*SimpleStorageInfo)
  723. }
  724. simpleStorage, ok := sfs[storageType]
  725. if !ok {
  726. simpleStorage = &SimpleStorageInfo{Storages: []sStorage{}}
  727. }
  728. if !utils.IsInStringArray(hostDriver.GetProvider(), api.PUBLIC_CLOUD_PROVIDERS) {
  729. addStorageInfo(storage, simpleStorage)
  730. }
  731. sfs[storageType] = simpleStorage
  732. storageInfos[hostDriver.GetHypervisor()] = sfs
  733. }
  734. setStorageInfos2 = func(hostDriver IHostDriver, storageType string, storage *StorageInfo,
  735. storageInfos2 map[string]map[string]map[string]*SimpleStorageInfo) {
  736. _, ok := storageInfos2[hostDriver.GetProvider()]
  737. if !ok {
  738. storageInfos2[hostDriver.GetProvider()] = make(map[string]map[string]*SimpleStorageInfo)
  739. }
  740. setStorageInfos(hostDriver, storageType, storage, storageInfos2[hostDriver.GetProvider()])
  741. }
  742. )
  743. info := []StorageInfo{}
  744. err := q.All(&info)
  745. if err != nil {
  746. return nil, errors.Wrapf(err, "q.All")
  747. }
  748. for i := range info {
  749. storage := info[i]
  750. if len(storage.Provider) == 0 {
  751. storage.Provider = api.CLOUD_PROVIDER_ONECLOUD
  752. }
  753. hostDriver, err := GetHostDriver(storage.HostType, storage.Provider)
  754. if err != nil {
  755. return nil, errors.Wrapf(err, "GetHostDriver")
  756. }
  757. if len(storage.StorageType) > 0 && len(storage.MediumType) > 0 {
  758. storageType := fmt.Sprintf("%s/%s", storage.StorageType, storage.MediumType)
  759. if storage.IsSysDiskStore {
  760. _, ok := ret.StorageTypes2[hostDriver.GetHypervisor()]
  761. if !ok {
  762. ret.StorageTypes2[hostDriver.GetHypervisor()] = []string{}
  763. }
  764. if !utils.IsInStringArray(storageType, ret.StorageTypes2[hostDriver.GetHypervisor()]) {
  765. ret.StorageTypes2[hostDriver.GetHypervisor()] = append(ret.StorageTypes2[hostDriver.GetHypervisor()], storageType)
  766. }
  767. }
  768. _, ok := ret.DataStorageTypes2[hostDriver.GetHypervisor()]
  769. if !ok {
  770. ret.DataStorageTypes2[hostDriver.GetHypervisor()] = []string{}
  771. }
  772. if !utils.IsInStringArray(storageType, ret.DataStorageTypes2[hostDriver.GetHypervisor()]) {
  773. ret.DataStorageTypes2[hostDriver.GetHypervisor()] = append(ret.DataStorageTypes2[hostDriver.GetHypervisor()], storageType)
  774. }
  775. simpleStorage := &SimpleStorageInfo{Storages: []sStorage{}}
  776. if storage.Cmtbound.Float64 == 0 {
  777. storage.Cmtbound.Float64 = float64(options.Options.DefaultStorageOvercommitBound)
  778. }
  779. storage.VirtualCapacity = int64(float64(storage.Capacity-storage.Reserved.Int64) * storage.Cmtbound.Float64)
  780. storage.FreeCapacity = storage.VirtualCapacity - storage.UsedCapacity.Int64 - storage.WasteCapacity.Int64
  781. addStorageInfo(&storage, simpleStorage)
  782. // set hypervisor storage types and infos
  783. if storage.IsSysDiskStore {
  784. setStorageInfos(hostDriver, storageType, &storage, ret.StorageTypes3)
  785. setStorageInfos2(hostDriver, storageType, &storage, ret.SystemStorageTypes)
  786. }
  787. setStorageInfos(hostDriver, storageType, &storage, ret.DataStorageTypes3)
  788. setStorageInfos2(hostDriver, storageType, &storage, ret.DataStorageTypes)
  789. }
  790. }
  791. return ret, nil
  792. }
  793. type PCIDevModelTypes struct {
  794. Model string
  795. DevType string
  796. SizeMB int
  797. VirtualDev bool
  798. Hypervisor string
  799. }
  800. func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId, tenantId string) ([]string, []PCIDevModelTypes) {
  801. devicesQ := IsolatedDeviceManager.Query()
  802. hostQuery := HostManager.Query()
  803. if len(domainId) > 0 {
  804. ownerId := &db.SOwnerId{DomainId: domainId}
  805. hostQuery = StorageManager.FilterByOwner(ctx, hostQuery, StorageManager, userCred, ownerId, rbacscope.ScopeDomain)
  806. }
  807. if len(tenantId) > 0 {
  808. devicesQ = devicesQ.IsNullOrEmpty("guest_id")
  809. subq := db.SharedResourceManager.Query("resource_id")
  810. subq = subq.Equals("resource_type", IsolatedDeviceManager.Keyword())
  811. subq = subq.Equals("target_project_id", tenantId)
  812. subq = subq.Equals("target_type", db.SharedTargetProject)
  813. conds := []sqlchemy.ICondition{
  814. sqlchemy.AND(
  815. sqlchemy.IsTrue(devicesQ.Field("is_public")),
  816. sqlchemy.Equals(devicesQ.Field("public_scope"), rbacscope.ScopeSystem),
  817. ),
  818. sqlchemy.In(devicesQ.Field("id"), subq.SubQuery()),
  819. }
  820. if len(domainId) > 0 {
  821. subq2 := db.SharedResourceManager.Query("resource_id")
  822. subq2 = subq2.Equals("resource_type", IsolatedDeviceManager.Keyword())
  823. subq2 = subq2.Equals("target_project_id", domainId)
  824. subq2 = subq2.Equals("target_type", db.SharedTargetDomain)
  825. conds = append(conds, sqlchemy.AND(
  826. sqlchemy.IsTrue(devicesQ.Field("is_public")),
  827. sqlchemy.Equals(devicesQ.Field("public_scope"), rbacscope.ScopeDomain),
  828. sqlchemy.OR(
  829. sqlchemy.In(devicesQ.Field("id"), subq2.SubQuery()),
  830. ),
  831. ),
  832. )
  833. }
  834. devicesQ = devicesQ.Filter(sqlchemy.OR(conds...))
  835. }
  836. devices := devicesQ.SubQuery()
  837. hosts := hostQuery.SubQuery()
  838. q := devices.Query(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("nvme_size_mb"))
  839. q = q.Filter(sqlchemy.NotIn(devices.Field("dev_type"), []string{api.USB_TYPE, api.NIC_TYPE}))
  840. if zone != nil {
  841. q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
  842. q = q.Filter(sqlchemy.Equals(hosts.Field("zone_id"), zone.Id))
  843. } else if region != nil {
  844. subq := getRegionZoneSubq(region)
  845. q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
  846. q = q.Filter(sqlchemy.In(hosts.Field("zone_id"), subq))
  847. } else {
  848. q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
  849. }
  850. /*if len(domainId) > 0 {
  851. subq := getDomainManagerSubq(domainId)
  852. q = q.Filter(sqlchemy.OR(
  853. sqlchemy.In(hosts.Field("manager_id"), subq),
  854. sqlchemy.IsNullOrEmpty(hosts.Field("manager_id")),
  855. ))
  856. }*/
  857. q = q.GroupBy(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("nvme_size_mb"))
  858. rows, err := q.Rows()
  859. if err != nil {
  860. log.Errorf("failed get gpu caps: %s", err)
  861. return nil, nil
  862. }
  863. defer rows.Close()
  864. gpus := make([]PCIDevModelTypes, 0)
  865. gpuModels := make([]string, 0)
  866. for rows.Next() {
  867. var m, t string
  868. var sizeMB int
  869. var vdev bool
  870. var hypervisor string
  871. var hostType string
  872. rows.Scan(&hostType, &m, &t, &sizeMB)
  873. if m == "" {
  874. continue
  875. }
  876. if utils.IsInStringArray(t, api.VITRUAL_DEVICE_TYPES) {
  877. vdev = true
  878. }
  879. if utils.IsInStringArray(t, api.VALID_CONTAINER_DEVICE_TYPES) {
  880. hypervisor = api.HYPERVISOR_POD
  881. } else {
  882. hypervisor = api.HYPERVISOR_KVM
  883. }
  884. if hostType == api.HOST_TYPE_ZETTAKIT {
  885. hypervisor = api.HYPERVISOR_ZETTAKIT
  886. }
  887. gpus = append(gpus, PCIDevModelTypes{m, t, sizeMB, vdev, hypervisor})
  888. if !utils.IsInStringArray(m, gpuModels) {
  889. gpuModels = append(gpuModels, m)
  890. }
  891. }
  892. return gpuModels, gpus
  893. }
  894. func getHostCpuArchs(ctx context.Context, userCred mcclient.TokenCredential, region *SCloudregion, zone *SZone, domainId string) []string {
  895. q := HostManager.Query("cpu_architecture").Equals("enabled", true).
  896. Equals("host_status", "online").In("host_type", []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_CONTAINER})
  897. if len(domainId) > 0 {
  898. ownerId := &db.SOwnerId{DomainId: domainId}
  899. q = HostManager.FilterByOwner(ctx, q, HostManager, userCred, ownerId, rbacscope.ScopeDomain)
  900. }
  901. if zone != nil {
  902. q = q.Equals("zone_id", zone.Id)
  903. }
  904. if region != nil {
  905. subq := ZoneManager.Query("id").Equals("cloudregion_id", region.Id).SubQuery()
  906. q = q.Filter(sqlchemy.In(q.Field("zone_id"), subq))
  907. }
  908. q = q.Distinct()
  909. type CpuArch struct {
  910. CpuArchitecture string
  911. }
  912. archs := make([]CpuArch, 0)
  913. if err := q.All(&archs); err != nil && err != sql.ErrNoRows {
  914. log.Errorf("failed fetch host cpu archs %s", err)
  915. return nil
  916. }
  917. if len(archs) == 0 {
  918. return nil
  919. }
  920. res := make([]string, len(archs))
  921. for i := 0; i < len(archs); i++ {
  922. res[i] = archs[i].CpuArchitecture
  923. }
  924. return res
  925. }
  926. func getNetworkCount(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope, region *SCloudregion, zone *SZone) (int, error) {
  927. return getNetworkCountByFilter(ctx, userCred, ownerId, scope, region, zone, tristate.None, "")
  928. }
  929. func getAutoAllocNetworkCount(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope, region *SCloudregion, zone *SZone, serverType string) (int, error) {
  930. return getNetworkCountByFilter(ctx, userCred, ownerId, scope, region, zone, tristate.True, serverType)
  931. }
  932. func getNetworkCountByFilter(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope, region *SCloudregion, zone *SZone, isAutoAlloc tristate.TriState, serverType string) (int, error) {
  933. if zone != nil && region == nil {
  934. var err error
  935. region, err = zone.GetRegion()
  936. if err != nil {
  937. return 0, errors.Wrapf(err, "GetRegion")
  938. }
  939. }
  940. networks := NetworkManager.Query().SubQuery()
  941. q := networks.Query()
  942. if zone != nil || region != nil {
  943. wires := WireManager.Query("id")
  944. var zoneFilter sqlchemy.ICondition
  945. if zone != nil {
  946. zoneFilter = sqlchemy.Equals(wires.Field("zone_id"), zone.Id)
  947. } else {
  948. subq := getRegionZoneSubq(region)
  949. zoneFilter = sqlchemy.In(wires.Field("zone_id"), subq)
  950. }
  951. vpcs := VpcManager.Query().SubQuery()
  952. wires = wires.Join(vpcs, sqlchemy.Equals(wires.Field("vpc_id"), vpcs.Field("id")))
  953. wires = wires.Filter(sqlchemy.OR(
  954. zoneFilter,
  955. sqlchemy.AND(
  956. sqlchemy.IsNullOrEmpty(wires.Field("zone_id")),
  957. sqlchemy.Equals(vpcs.Field("cloudregion_id"), region.Id),
  958. ),
  959. ))
  960. q = q.In("wire_id", wires.SubQuery())
  961. }
  962. q = NetworkManager.FilterByOwner(ctx, q, NetworkManager, userCred, ownerId, scope)
  963. if !isAutoAlloc.IsNone() {
  964. if isAutoAlloc.IsTrue() {
  965. q = q.IsTrue("is_auto_alloc")
  966. } else {
  967. q = q.IsFalse("is_auto_alloc")
  968. }
  969. }
  970. if len(serverType) > 0 {
  971. q = q.Filter(sqlchemy.Equals(networks.Field("server_type"), serverType))
  972. }
  973. q = q.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
  974. return q.CountWithError()
  975. }
  976. func isSchedPolicySupported(region *SCloudregion, zone *SZone) bool {
  977. return true
  978. }
  979. func getMinNicCount(region *SCloudregion, zone *SZone) int {
  980. if region != nil {
  981. return region.getMinNicCount()
  982. }
  983. if zone != nil {
  984. return zone.getMinNicCount()
  985. }
  986. return 0
  987. }
  988. func getMaxNicCount(region *SCloudregion, zone *SZone) int {
  989. if region != nil {
  990. return region.getMaxNicCount()
  991. }
  992. if zone != nil {
  993. return zone.getMaxNicCount()
  994. }
  995. return 0
  996. }
  997. func getMinDataDiskCount(region *SCloudregion, zone *SZone) int {
  998. if region != nil {
  999. return region.getMinDataDiskCount()
  1000. }
  1001. if zone != nil {
  1002. return zone.getMinDataDiskCount()
  1003. }
  1004. return 0
  1005. }
  1006. func getMaxDataDiskCount(region *SCloudregion, zone *SZone) int {
  1007. if region != nil {
  1008. return region.getMaxDataDiskCount()
  1009. }
  1010. if zone != nil {
  1011. return zone.getMaxDataDiskCount()
  1012. }
  1013. return 0
  1014. }
  1015. func isUsable(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, scope rbacscope.TRbacScope, region *SCloudregion, zone *SZone) bool {
  1016. cnt, err := getNetworkCount(ctx, userCred, ownerId, scope, region, zone)
  1017. if err != nil {
  1018. return false
  1019. }
  1020. if cnt > 0 {
  1021. return true
  1022. } else {
  1023. return false
  1024. }
  1025. }