guest_queries.go 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  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. "strings"
  19. "time"
  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/compare"
  26. "yunion.io/x/sqlchemy"
  27. "yunion.io/x/onecloud/pkg/apis"
  28. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  29. api "yunion.io/x/onecloud/pkg/apis/compute"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  31. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  32. "yunion.io/x/onecloud/pkg/compute/options"
  33. "yunion.io/x/onecloud/pkg/mcclient"
  34. "yunion.io/x/onecloud/pkg/util/stringutils2"
  35. )
  36. func (manager *SGuestManager) FetchCustomizeColumns(
  37. ctx context.Context,
  38. userCred mcclient.TokenCredential,
  39. query jsonutils.JSONObject,
  40. objs []interface{},
  41. fields stringutils2.SSortedStrings,
  42. isList bool,
  43. ) []api.ServerDetails {
  44. rows := make([]api.ServerDetails, len(objs))
  45. virtRows := manager.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  46. hostRows := manager.SHostResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  47. encRows := manager.SEncryptedResourceManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  48. guestIds := make([]string, len(objs))
  49. guests := make([]SGuest, len(objs))
  50. backupHostIds := make([]string, len(objs))
  51. for i := range objs {
  52. rows[i] = api.ServerDetails{
  53. VirtualResourceDetails: virtRows[i],
  54. HostResourceInfo: hostRows[i],
  55. EncryptedResourceDetails: encRows[i],
  56. }
  57. guest := objs[i].(*SGuest)
  58. guestIds[i] = guest.GetId()
  59. backupHostIds[i] = guest.BackupHostId
  60. guests[i] = *guest
  61. }
  62. if len(fields) == 0 || fields.Contains("disk") {
  63. gds := fetchGuestDisksInfo(guestIds)
  64. if gds != nil {
  65. for i := range rows {
  66. rows[i].DisksInfo = []api.GuestDiskInfo{}
  67. if disks, ok := gds[guestIds[i]]; ok {
  68. for j := range disks {
  69. if len(rows[i].ManagerId) > 0 {
  70. disks[j].Iops = disks[j].DiskIops
  71. }
  72. rows[i].DisksInfo = append(rows[i].DisksInfo, disks[j].GuestDiskInfo)
  73. }
  74. }
  75. rows[i].DiskCount = len(rows[i].DisksInfo)
  76. shortDescs := []string{}
  77. for _, info := range rows[i].DisksInfo {
  78. rows[i].DiskSizeMb += int64(info.SizeMb)
  79. shortDescs = append(shortDescs, info.ShortDesc())
  80. }
  81. rows[i].Disks = strings.Join(shortDescs, "\n")
  82. }
  83. }
  84. }
  85. if len(fields) == 0 || fields.Contains("snapshotpolicy") {
  86. counts := fetchGuestSnapshotpolicyInfo(guestIds)
  87. for i := range rows {
  88. rows[i].SnapshotpolicyCount = counts[guestIds[i]]
  89. for j := range rows[i].DisksInfo {
  90. rows[i].DisksSnapshotpolicyCount += counts[rows[i].DisksInfo[j].Id]
  91. }
  92. }
  93. }
  94. /*if len(fields) == 0 || fields.Contains("ips") {
  95. gips := fetchGuestIPs(guestIds, tristate.False)
  96. if gips != nil {
  97. for i := range rows {
  98. if gip, ok := gips[guestIds[i]]; ok {
  99. rows[i].IPs = strings.Join(gip, ",")
  100. }
  101. }
  102. }
  103. }*/
  104. if len(fields) == 0 || fields.Contains("vip") {
  105. gvips := fetchGuestVips(guestIds)
  106. if gvips != nil {
  107. for i := range rows {
  108. if vips, ok := gvips[guestIds[i]]; ok {
  109. rows[i].Vip = strings.Join(vips, ",")
  110. }
  111. }
  112. }
  113. }
  114. if len(fields) == 0 || fields.Contains("vip_eip") {
  115. gvips := fetchGuestVipEips(guestIds)
  116. if gvips != nil {
  117. for i := range rows {
  118. if vips, ok := gvips[guestIds[i]]; ok {
  119. rows[i].VipEip = strings.Join(vips, ",")
  120. }
  121. }
  122. }
  123. }
  124. if len(fields) == 0 || fields.Contains("ips") || fields.Contains("macs") || fields.Contains("nics") || fields.Contains("subips") {
  125. nicsMap := fetchGuestNICs(ctx, guestIds, tristate.False)
  126. if nicsMap != nil {
  127. for i := range rows {
  128. if nics, ok := nicsMap[guestIds[i]]; ok {
  129. if len(fields) == 0 || fields.Contains("nics") {
  130. rows[i].Nics = nics
  131. }
  132. if len(fields) == 0 || fields.Contains("macs") {
  133. macs := make([]string, 0, len(nics))
  134. for _, nic := range nics {
  135. macs = append(macs, nic.Mac)
  136. }
  137. rows[i].Macs = strings.Join(macs, ",")
  138. }
  139. if len(fields) == 0 || fields.Contains("ips") {
  140. ips := make([]string, 0, len(nics))
  141. for _, nic := range nics {
  142. if len(nic.IpAddr) > 0 {
  143. ips = append(ips, nic.IpAddr)
  144. }
  145. if len(nic.Ip6Addr) > 0 {
  146. ips = append(ips, nic.Ip6Addr)
  147. }
  148. }
  149. rows[i].IPs = strings.Join(ips, ",")
  150. }
  151. if len(fields) == 0 || fields.Contains("subips") {
  152. subips := make([]string, 0)
  153. for _, nic := range nics {
  154. if len(nic.SubIps) > 0 {
  155. ips := strings.Split(nic.SubIps, ",")
  156. subips = append(subips, ips...)
  157. }
  158. }
  159. rows[i].SubIPs = subips
  160. }
  161. }
  162. }
  163. }
  164. }
  165. if len(fields) == 0 || fields.Contains("vpc") || fields.Contains("vpc_id") {
  166. gvpcs := fetchGuestVpcs(guestIds)
  167. if gvpcs != nil {
  168. for i := range rows {
  169. if gvpc, ok := gvpcs[guestIds[i]]; ok {
  170. if len(fields) == 0 || fields.Contains("vpc") {
  171. rows[i].Vpc = strings.Join(gvpc.Vpc, ",")
  172. }
  173. if len(fields) == 0 || fields.Contains("vpc_id") {
  174. rows[i].VpcId = strings.Join(gvpc.VpcId, ",")
  175. }
  176. if len(fields) == 0 || fields.Contains("external_access_mode") {
  177. rows[i].VpcExternalAccessMode = strings.Join(gvpc.ExternalAccessMode, ",")
  178. }
  179. }
  180. }
  181. }
  182. }
  183. if len(fields) == 0 || fields.Contains("secgroups") || fields.Contains("secgroup") {
  184. gsgs := fetchSecgroups(guestIds)
  185. if gsgs != nil {
  186. for i := range rows {
  187. if gsg, ok := gsgs[guestIds[i]]; ok {
  188. if len(fields) == 0 || fields.Contains("secgroups") {
  189. rows[i].Secgroups = gsg
  190. }
  191. if len(fields) == 0 || fields.Contains("secgroup") {
  192. rows[i].Secgroup = gsg[0].Name
  193. }
  194. }
  195. }
  196. }
  197. }
  198. if len(fields) == 0 || fields.Contains("network_secgroups") {
  199. gnss := fetchGuestNetworkSecgroups(guestIds)
  200. if gnss != nil {
  201. for i := range rows {
  202. if gns, ok := gnss[guestIds[i]]; ok {
  203. rows[i].NetworkSecgroups = gns
  204. }
  205. }
  206. }
  207. }
  208. if len(fields) == 0 || fields.Contains("eip") || fields.Contains("eip_mode") {
  209. geips := fetchGuestEips(guestIds)
  210. if geips != nil {
  211. for i := range rows {
  212. if eip, ok := geips[guestIds[i]]; ok {
  213. if len(fields) == 0 || fields.Contains("eip") {
  214. rows[i].Eip = eip.IpAddr
  215. }
  216. if len(fields) == 0 || fields.Contains("eip_mode") {
  217. rows[i].EipMode = eip.Mode
  218. }
  219. }
  220. }
  221. }
  222. }
  223. if len(fields) == 0 || fields.Contains("keypair") {
  224. gkps := fetchGuestKeypairs(guestIds)
  225. if gkps != nil {
  226. for i := range rows {
  227. if kps, ok := gkps[guestIds[i]]; ok {
  228. rows[i].Keypair = kps.Keypair
  229. }
  230. }
  231. }
  232. }
  233. if len(fields) == 0 || fields.Contains("isolated_devices") || fields.Contains("is_gpu") {
  234. gdevs := fetchGuestIsolatedDevices(guestIds)
  235. if gdevs != nil {
  236. for i := range rows {
  237. if gdev, ok := gdevs[guestIds[i]]; ok {
  238. if len(fields) == 0 || fields.Contains("isolated_devices") {
  239. rows[i].IsolatedDevices = gdev
  240. }
  241. if len(fields) == 0 || fields.Contains("is_gpu") {
  242. if len(gdev) > 0 {
  243. rows[i].IsGpu = true
  244. } else {
  245. rows[i].IsGpu = false
  246. }
  247. }
  248. } else {
  249. if len(fields) == 0 || fields.Contains("is_gpu") {
  250. rows[i].IsGpu = false
  251. }
  252. }
  253. }
  254. }
  255. info, _ := fetchGuestGpuInstanceTypes(guestIds)
  256. if len(info) > 0 {
  257. for i := range rows {
  258. gpu, ok := info[guests[i].InstanceType]
  259. if ok {
  260. rows[i].IsGpu = true
  261. rows[i].GpuModel = gpu.Model
  262. rows[i].GpuCount = gpu.Amount
  263. }
  264. }
  265. }
  266. }
  267. if len(fields) == 0 || fields.Contains("cdrom") {
  268. gcds := fetchGuestCdroms(guestIds)
  269. if gcds != nil {
  270. for i := range rows {
  271. for _, gcd := range gcds[guestIds[i]] {
  272. if details := gcd.GetDetails(); len(details) > 0 {
  273. t := api.Cdrom{Ordinal: gcd.Ordinal, Detail: details, BootIndex: gcd.BootIndex, Name: gcd.Name}
  274. rows[i].Cdrom = append(rows[i].Cdrom, t)
  275. }
  276. }
  277. }
  278. }
  279. }
  280. if len(fields) == 0 || fields.Contains("floppy") {
  281. gfloppys := fetchGuestFloppys(guestIds)
  282. if gfloppys != nil {
  283. for i := range rows {
  284. for _, gfl := range gfloppys[guestIds[i]] {
  285. if details := gfl.GetDetails(); len(details) > 0 {
  286. t := api.Floppy{Ordinal: gfl.Ordinal, Detail: details}
  287. rows[i].Floppy = append(rows[i].Floppy, t)
  288. }
  289. }
  290. }
  291. }
  292. }
  293. if len(fields) == 0 || fields.Contains("scaling_group") {
  294. sggs := fetchScalingGroupGuest(guestIds...)
  295. if sggs != nil && len(sggs) != 0 {
  296. for i := range rows {
  297. if sgg, ok := sggs[guestIds[i]]; ok {
  298. rows[i].ScalingStatus = sgg.GuestStatus
  299. rows[i].ScalingGroupId = sgg.ScalingGroupId
  300. }
  301. }
  302. }
  303. }
  304. if len(fields) == 0 || fields.Contains("backup_host_name") || fields.Contains("backup_host_status") && len(backupHostIds) > 0 {
  305. backups, _ := fetchGuestBackupInfo(backupHostIds)
  306. meta := []db.SMetadata{}
  307. db.Metadata.Query().In("obj_id", guestIds).Equals("obj_type", manager.Keyword()).Equals("key", api.MIRROR_JOB).All(&meta)
  308. syncStatus := map[string]string{}
  309. for i := range meta {
  310. v := meta[i]
  311. syncStatus[v.ObjId] = v.Value
  312. }
  313. if len(backups) > 0 || len(syncStatus) > 0 {
  314. for i := range rows {
  315. rows[i].BackupInfo, _ = backups[backupHostIds[i]]
  316. rows[i].BackupGuestSyncStatus, _ = syncStatus[guestIds[i]]
  317. }
  318. }
  319. }
  320. if len(fields) == 0 || fields.Contains("container") {
  321. containers, _ := fetchContainers(guestIds)
  322. if len(containers) > 0 {
  323. for i := range rows {
  324. rows[i].Containers, _ = containers[guestIds[i]]
  325. }
  326. }
  327. }
  328. for i := range rows {
  329. if len(fields) == 0 || fields.Contains("auto_delete_at") {
  330. if guests[i].PendingDeleted {
  331. pendingDeletedAt := guests[i].PendingDeletedAt.Add(time.Second * time.Duration(options.Options.PendingDeleteExpireSeconds))
  332. rows[i].AutoDeleteAt = pendingDeletedAt
  333. }
  334. }
  335. if len(fields) == 0 || fields.Contains("can_recycle") {
  336. if guests[i].BillingType == billing_api.BILLING_TYPE_PREPAID && !guests[i].ExpiredAt.Before(time.Now()) && len(rows[i].ManagerId) > 0 {
  337. rows[i].CanRecycle = true
  338. }
  339. }
  340. rows[i].IsPrepaidRecycle = (rows[i].HostResourceType == api.HostResourceTypePrepaidRecycle && rows[i].HostBillingType == billing_api.BILLING_TYPE_PREPAID)
  341. drv, _ := GetDriver(guests[i].Hypervisor, rows[i].Provider)
  342. if drv != nil {
  343. rows[i].CdromSupport, _ = drv.IsSupportCdrom(&guests[i])
  344. rows[i].FloppySupport, _ = drv.IsSupportFloppy(&guests[i])
  345. rows[i].MonitorUrl = drv.FetchMonitorUrl(ctx, &guests[i])
  346. }
  347. if len(guests[i].HostId) == 0 && guests[i].Status == api.VM_SCHEDULE_FAILED {
  348. rows[i].Brand = "Unknown"
  349. rows[i].Provider = "Unknown"
  350. }
  351. if !isList {
  352. rows[i].Networks = guests[i].getNetworksDetails()
  353. rows[i].VirtualIps = strings.Join(guests[i].getVirtualIPs(), ",")
  354. rows[i].SecurityRules = guests[i].getSecurityGroupsRules()
  355. osName := guests[i].GetOS()
  356. if len(osName) > 0 {
  357. rows[i].OsName = osName
  358. if len(guests[i].OsType) == 0 {
  359. rows[i].OsType = osName
  360. }
  361. }
  362. if userCred.HasSystemAdminPrivilege() {
  363. rows[i].AdminSecurityRules = guests[i].getAdminSecurityRules()
  364. }
  365. }
  366. }
  367. return rows
  368. }
  369. type sGustDiskSize struct {
  370. GuestId string
  371. DiskSizeMb int64
  372. DiskCount int
  373. }
  374. type GuestDiskInfo struct {
  375. DiskIops int
  376. api.GuestDiskInfo
  377. }
  378. type sGuestDiskInfo struct {
  379. GuestDiskInfo
  380. GuestId string
  381. }
  382. func fetchGuestDisksInfo(guestIds []string) map[string][]GuestDiskInfo {
  383. disks := DiskManager.Query().SubQuery()
  384. guestdisks := GuestdiskManager.Query().SubQuery()
  385. storages := StorageManager.Query().SubQuery()
  386. q := disks.Query(
  387. disks.Field("id"),
  388. disks.Field("name"),
  389. disks.Field("fs_format"),
  390. disks.Field("disk_type"),
  391. guestdisks.Field("index"),
  392. disks.Field("disk_size").Label("size"),
  393. disks.Field("disk_format"),
  394. guestdisks.Field("driver"),
  395. guestdisks.Field("cache_mode"),
  396. guestdisks.Field("aio_mode"),
  397. disks.Field("auto_reset"),
  398. storages.Field("medium_type"),
  399. storages.Field("storage_type"),
  400. guestdisks.Field("iops"),
  401. disks.Field("iops").Label("disk_iops"),
  402. disks.Field("throughput"),
  403. guestdisks.Field("bps"),
  404. disks.Field("template_id").Label("image_id"),
  405. guestdisks.Field("guest_id"),
  406. guestdisks.Field("boot_index"),
  407. disks.Field("storage_id"),
  408. disks.Field("preallocation"),
  409. )
  410. q = q.Join(guestdisks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")))
  411. q = q.Join(storages, sqlchemy.Equals(disks.Field("storage_id"), storages.Field("id")))
  412. q = q.Filter(sqlchemy.In(guestdisks.Field("guest_id"), guestIds)).Asc(guestdisks.Field("index"))
  413. gds := []sGuestDiskInfo{}
  414. err := q.All(&gds)
  415. if err != nil {
  416. log.Errorf("fetchGuestDisksInfo: %v", err)
  417. return nil
  418. }
  419. imageIds := []string{}
  420. ret := map[string][]GuestDiskInfo{}
  421. for i := range gds {
  422. if len(gds[i].ImageId) > 0 {
  423. imageIds = append(imageIds, gds[i].ImageId)
  424. }
  425. _, ok := ret[gds[i].GuestId]
  426. if !ok {
  427. ret[gds[i].GuestId] = []GuestDiskInfo{}
  428. }
  429. ret[gds[i].GuestId] = append(ret[gds[i].GuestId], gds[i].GuestDiskInfo)
  430. }
  431. imageNames, err := db.FetchIdNameMap2(CachedimageManager, imageIds)
  432. if err != nil {
  433. return ret
  434. }
  435. for guestId, infos := range ret {
  436. for i := range infos {
  437. if len(infos[i].ImageId) > 0 {
  438. ret[guestId][i].Image, _ = imageNames[infos[i].ImageId]
  439. }
  440. }
  441. }
  442. return ret
  443. }
  444. func fetchGuestSnapshotpolicyInfo(guestIds []string) map[string]int {
  445. ret := map[string]int{}
  446. disks := GuestdiskManager.Query("disk_id").In("guest_id", guestIds).SubQuery()
  447. spq := SnapshotPolicyResourceManager.Query()
  448. spq = spq.Filter(sqlchemy.OR(
  449. sqlchemy.In(spq.Field("resource_id"), guestIds),
  450. sqlchemy.In(spq.Field("resource_id"), disks),
  451. ))
  452. sq := spq.SubQuery()
  453. q := sq.Query(
  454. sq.Field("resource_id"),
  455. sqlchemy.COUNT("count", sq.Field("snapshotpolicy_id")),
  456. ).GroupBy(sq.Field("resource_id"))
  457. counts := []struct {
  458. ResourceId string
  459. Count int
  460. }{}
  461. err := q.All(&counts)
  462. if err != nil {
  463. return nil
  464. }
  465. for _, count := range counts {
  466. ret[count.ResourceId] = count.Count
  467. }
  468. return ret
  469. }
  470. func (guest *SGuest) GetDisksSize() int {
  471. return guest.getDiskSize()
  472. }
  473. func (guest *SGuest) getDiskSize() int {
  474. result := fetchGuestDisksInfo([]string{guest.Id})
  475. if result == nil {
  476. return -1
  477. }
  478. gds, ok := result[guest.Id]
  479. if !ok {
  480. return -1
  481. }
  482. size := 0
  483. for _, gd := range gds {
  484. size += gd.SizeMb
  485. }
  486. return size
  487. }
  488. func fetchGuestIPs(guestIds []string, virtual tristate.TriState) map[string][]string {
  489. guestnetworks := GuestnetworkManager.Query().SubQuery()
  490. q := guestnetworks.Query(guestnetworks.Field("guest_id"), guestnetworks.Field("ip_addr"))
  491. q = q.In("guest_id", guestIds)
  492. if virtual.IsTrue() {
  493. q = q.IsTrue("virtual")
  494. } else if virtual.IsFalse() {
  495. q = q.IsFalse("virtual")
  496. }
  497. q = q.IsNotEmpty("ip_addr")
  498. q = q.Asc("ip_addr")
  499. type sGuestIdIpAddr struct {
  500. GuestId string
  501. IpAddr string
  502. }
  503. gias := make([]sGuestIdIpAddr, 0)
  504. err := q.All(&gias)
  505. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  506. return nil
  507. }
  508. ret := make(map[string][]string)
  509. for i := range gias {
  510. if _, ok := ret[gias[i].GuestId]; !ok {
  511. ret[gias[i].GuestId] = make([]string, 0)
  512. }
  513. ret[gias[i].GuestId] = append(ret[gias[i].GuestId], gias[i].IpAddr)
  514. }
  515. return ret
  516. }
  517. func fetchGuestVips(guestIds []string) map[string][]string {
  518. groupguests := GroupguestManager.Query().SubQuery()
  519. groupnetworks := GroupnetworkManager.Query().SubQuery()
  520. q := groupnetworks.Query(groupnetworks.Field("ip_addr"), groupnetworks.Field("ip6_addr"), groupguests.Field("guest_id"))
  521. q = q.Join(groupguests, sqlchemy.Equals(q.Field("group_id"), groupguests.Field("group_id")))
  522. q = q.In("guest_id", guestIds)
  523. type sGuestVip struct {
  524. IpAddr string
  525. Ip6Addr string
  526. GuestId string
  527. }
  528. gvips := make([]sGuestVip, 0)
  529. err := q.All(&gvips)
  530. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  531. return nil
  532. }
  533. ret := make(map[string][]string)
  534. for i := range gvips {
  535. if _, ok := ret[gvips[i].GuestId]; !ok {
  536. ret[gvips[i].GuestId] = make([]string, 0)
  537. }
  538. if len(gvips[i].IpAddr) > 0 {
  539. ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
  540. }
  541. if len(gvips[i].Ip6Addr) > 0 {
  542. ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].Ip6Addr)
  543. }
  544. }
  545. return ret
  546. }
  547. func fetchGuestVipEips(guestIds []string) map[string][]string {
  548. groupguests := GroupguestManager.Query().SubQuery()
  549. eips := ElasticipManager.Query().Equals("associate_type", api.EIP_ASSOCIATE_TYPE_INSTANCE_GROUP).SubQuery()
  550. q := eips.Query(eips.Field("ip_addr"), groupguests.Field("guest_id"))
  551. q = q.Join(groupguests, sqlchemy.Equals(eips.Field("associate_id"), groupguests.Field("group_id")))
  552. q = q.In("guest_id", guestIds)
  553. type sGuestVip struct {
  554. IpAddr string
  555. GuestId string
  556. }
  557. gvips := make([]sGuestVip, 0)
  558. err := q.All(&gvips)
  559. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  560. return nil
  561. }
  562. ret := make(map[string][]string)
  563. for i := range gvips {
  564. if _, ok := ret[gvips[i].GuestId]; !ok {
  565. ret[gvips[i].GuestId] = make([]string, 0)
  566. }
  567. ret[gvips[i].GuestId] = append(ret[gvips[i].GuestId], gvips[i].IpAddr)
  568. }
  569. return ret
  570. }
  571. func fetchGuestNICs(ctx context.Context, guestIds []string, virtual tristate.TriState) map[string][]api.GuestnetworkShortDesc {
  572. netq := NetworkManager.Query().SubQuery()
  573. wirq := WireManager.Query().SubQuery()
  574. subIPQ := NetworkAddressManager.fetchSubIpsQuery(api.NetworkAddressParentTypeGuestnetwork)
  575. subIP := subIPQ.SubQuery()
  576. gnwq := GuestnetworkManager.Query()
  577. q := gnwq.AppendField(
  578. gnwq.Field("guest_id"),
  579. gnwq.Field("index"),
  580. gnwq.Field("ip_addr"),
  581. gnwq.Field("ip6_addr"),
  582. gnwq.Field("mac_addr").Label("mac"),
  583. gnwq.Field("team_with"),
  584. gnwq.Field("network_id"), // caution: do not alias netq.id as network_id
  585. gnwq.Field("port_mappings"),
  586. gnwq.Field("ifname"),
  587. gnwq.Field("is_default"),
  588. wirq.Field("vpc_id"),
  589. subIP.Field("sub_ips"),
  590. )
  591. q = q.Join(netq, sqlchemy.Equals(netq.Field("id"), gnwq.Field("network_id")))
  592. q = q.Join(wirq, sqlchemy.Equals(wirq.Field("id"), netq.Field("wire_id")))
  593. q = q.LeftJoin(subIP, sqlchemy.Equals(q.Field("row_id"), subIP.Field("parent_id")))
  594. q = q.In("guest_id", guestIds)
  595. var descs []struct {
  596. GuestId string `json:"guest_id"`
  597. api.GuestnetworkShortDesc
  598. }
  599. if err := q.All(&descs); err != nil {
  600. if errors.Cause(err) != sql.ErrNoRows {
  601. log.Errorf("query guest nics info: %v", err)
  602. }
  603. return nil
  604. }
  605. ret := map[string][]api.GuestnetworkShortDesc{}
  606. for i := range descs {
  607. desc := &descs[i]
  608. guestId := desc.GuestId
  609. if _, ok := ret[guestId]; !ok {
  610. ret[guestId] = []api.GuestnetworkShortDesc{desc.GuestnetworkShortDesc}
  611. } else {
  612. ret[guestId] = append(ret[guestId], desc.GuestnetworkShortDesc)
  613. }
  614. }
  615. return ret
  616. }
  617. func (self *SGuest) GetRealIPs() []string {
  618. result := fetchGuestIPs([]string{self.Id}, tristate.False)
  619. if result == nil {
  620. return nil
  621. }
  622. if ret, ok := result[self.Id]; ok {
  623. return ret
  624. }
  625. return nil
  626. }
  627. func (self *SGuest) fetchNICShortDesc(ctx context.Context) []api.GuestnetworkShortDesc {
  628. nicsMap := fetchGuestNICs(ctx, []string{self.Id}, tristate.False)
  629. if nicsMap == nil {
  630. return nil
  631. }
  632. return nicsMap[self.Id]
  633. }
  634. type sGuestVpcsInfo struct {
  635. GuestId string
  636. Vpc []string
  637. VpcId []string
  638. ExternalAccessMode []string
  639. }
  640. func fetchGuestVpcs(guestIds []string) map[string]sGuestVpcsInfo {
  641. vpcs := VpcManager.Query().SubQuery()
  642. wires := WireManager.Query().SubQuery()
  643. networks := NetworkManager.Query().SubQuery()
  644. guestnetworks := GuestnetworkManager.Query().SubQuery()
  645. q := vpcs.Query(guestnetworks.Field("guest_id"), vpcs.Field("id"), vpcs.Field("name"), vpcs.Field("external_access_mode"))
  646. q = q.Join(wires, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
  647. q = q.Join(networks, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
  648. q = q.Join(guestnetworks, sqlchemy.Equals(networks.Field("id"), guestnetworks.Field("network_id")))
  649. q = q.Filter(sqlchemy.In(guestnetworks.Field("guest_id"), guestIds))
  650. q = q.Distinct()
  651. type sGuestVpcInfo struct {
  652. GuestId string
  653. Id string
  654. Name string
  655. ExternalAccessMode string
  656. }
  657. gvpcs := make([]sGuestVpcInfo, 0)
  658. err := q.All(&gvpcs)
  659. if err != nil {
  660. return nil
  661. }
  662. ret := make(map[string]sGuestVpcsInfo)
  663. for i := range gvpcs {
  664. gvpc, ok := ret[gvpcs[i].GuestId]
  665. if !ok {
  666. gvpc = sGuestVpcsInfo{
  667. GuestId: gvpcs[i].GuestId,
  668. Vpc: make([]string, 0),
  669. VpcId: make([]string, 0),
  670. ExternalAccessMode: make([]string, 0),
  671. }
  672. }
  673. gvpc.VpcId = append(gvpc.VpcId, gvpcs[i].Id)
  674. gvpc.Vpc = append(gvpc.Vpc, gvpcs[i].Name)
  675. gvpc.ExternalAccessMode = append(gvpc.ExternalAccessMode, gvpcs[i].ExternalAccessMode)
  676. ret[gvpcs[i].GuestId] = gvpc
  677. }
  678. return ret
  679. }
  680. func fetchSecgroups(guestIds []string) map[string][]apis.StandaloneShortDesc {
  681. secgroups := SecurityGroupManager.Query().SubQuery()
  682. guestsecgroups := GuestsecgroupManager.Query().SubQuery()
  683. guests := GuestManager.Query().SubQuery()
  684. q1 := guests.Query(guests.Field("id").Label("guest_id"),
  685. guests.Field("secgrp_id").Label("secgroup_id"))
  686. q1 = q1.Filter(sqlchemy.In(guests.Field("id"), guestIds))
  687. q2 := guestsecgroups.Query(guestsecgroups.Field("guest_id"), guestsecgroups.Field("secgroup_id"))
  688. q2 = q2.Filter(sqlchemy.In(guestsecgroups.Field("guest_id"), guestIds))
  689. uq := sqlchemy.Union(q1, q2)
  690. q := uq.Query(uq.Field("guest_id"), uq.Field("secgroup_id"), secgroups.Field("name").Label("secgroup_name"))
  691. q = q.Join(secgroups, sqlchemy.Equals(uq.Field("secgroup_id"), secgroups.Field("id")))
  692. type sGuestSecgroupInfo struct {
  693. SecgroupId string
  694. SecgroupName string
  695. GuestId string
  696. }
  697. gsgs := make([]sGuestSecgroupInfo, 0)
  698. err := q.All(&gsgs)
  699. if err != nil {
  700. return nil
  701. }
  702. ret := make(map[string][]apis.StandaloneShortDesc)
  703. for i := range gsgs {
  704. gsg, ok := ret[gsgs[i].GuestId]
  705. if !ok {
  706. gsg = make([]apis.StandaloneShortDesc, 0)
  707. }
  708. gsg = append(gsg, apis.StandaloneShortDesc{
  709. Id: gsgs[i].SecgroupId,
  710. Name: gsgs[i].SecgroupName,
  711. })
  712. ret[gsgs[i].GuestId] = gsg
  713. }
  714. return ret
  715. }
  716. func fetchGuestNetworkSecgroups(guestIds []string) map[string][]api.GuestnetworkSecgroupShortDesc {
  717. guestnetworks := GuestnetworkManager.Query().SubQuery()
  718. guestnetworksecgroups := GuestnetworksecgroupManager.Query().SubQuery()
  719. secgroups := SecurityGroupManager.Query().SubQuery()
  720. q := guestnetworksecgroups.Query(
  721. guestnetworksecgroups.Field("guest_id"),
  722. guestnetworksecgroups.Field("network_index"),
  723. guestnetworksecgroups.Field("secgroup_id"),
  724. guestnetworks.Field("mac_addr").Label("mac"),
  725. secgroups.Field("name").Label("secgroup_name"),
  726. )
  727. q = q.Join(guestnetworks, sqlchemy.AND(
  728. sqlchemy.Equals(guestnetworks.Field("guest_id"), guestnetworksecgroups.Field("guest_id")),
  729. sqlchemy.Equals(guestnetworks.Field("index"), guestnetworksecgroups.Field("network_index")),
  730. ))
  731. q = q.Join(secgroups, sqlchemy.Equals(secgroups.Field("id"), guestnetworksecgroups.Field("secgroup_id")))
  732. q = q.Filter(sqlchemy.In(guestnetworksecgroups.Field("guest_id"), guestIds))
  733. type sGuestNetworkSecgroupInfo struct {
  734. GuestId string
  735. NetworkIndex int
  736. SecgroupId string
  737. SecgroupName string
  738. Mac string
  739. }
  740. gnss := make([]sGuestNetworkSecgroupInfo, 0)
  741. err := q.All(&gnss)
  742. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  743. log.Errorf("fetchGuestNetworkSecgroups query error: %s", err)
  744. return nil
  745. }
  746. groupedSecgroups := make(map[string][]sGuestNetworkSecgroupInfo)
  747. for i := range gnss {
  748. groupedSecgroup, ok := groupedSecgroups[gnss[i].GuestId]
  749. if !ok {
  750. groupedSecgroup = make([]sGuestNetworkSecgroupInfo, 0)
  751. }
  752. groupedSecgroups[gnss[i].GuestId] = append(groupedSecgroup, gnss[i])
  753. }
  754. ret := make(map[string][]api.GuestnetworkSecgroupShortDesc)
  755. for guestId, secgroups := range groupedSecgroups {
  756. networkGroupedSecgroups := make(map[int][]sGuestNetworkSecgroupInfo)
  757. for i := range secgroups {
  758. secgroupInfos, ok := networkGroupedSecgroups[secgroups[i].NetworkIndex]
  759. if !ok {
  760. secgroupInfos = make([]sGuestNetworkSecgroupInfo, 0)
  761. }
  762. networkGroupedSecgroups[secgroups[i].NetworkIndex] = append(secgroupInfos, secgroups[i])
  763. }
  764. guestnetworkSecgroups := make([]api.GuestnetworkSecgroupShortDesc, 0)
  765. for networkIndex, secgroups := range networkGroupedSecgroups {
  766. //networkSecgroupsDesc := make([]api.GuestnetworkSecgroupShortDesc, 0)
  767. nsDesc := api.GuestnetworkSecgroupShortDesc{
  768. NetworkIndex: networkIndex,
  769. Mac: secgroups[0].Mac,
  770. }
  771. for i := range secgroups {
  772. nsDesc.Secgroups = append(nsDesc.Secgroups, apis.StandaloneShortDesc{
  773. Id: secgroups[i].SecgroupId,
  774. Name: secgroups[i].SecgroupName,
  775. })
  776. }
  777. guestnetworkSecgroups = append(guestnetworkSecgroups, nsDesc)
  778. }
  779. ret[guestId] = guestnetworkSecgroups
  780. }
  781. return ret
  782. }
  783. type sEipInfo struct {
  784. IpAddr string
  785. Mode string
  786. GuestId string
  787. }
  788. func fetchGuestEips(guestIds []string) map[string]sEipInfo {
  789. eips := ElasticipManager.Query().SubQuery()
  790. q := eips.Query(eips.Field("ip_addr"), eips.Field("mode"), eips.Field("associate_id").Label("guest_id"))
  791. q = q.Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER)
  792. q = q.In("associate_id", guestIds)
  793. geips := make([]sEipInfo, 0)
  794. err := q.All(&geips)
  795. if err != nil {
  796. return nil
  797. }
  798. ret := make(map[string]sEipInfo)
  799. for i := range geips {
  800. ret[geips[i].GuestId] = geips[i]
  801. }
  802. return ret
  803. }
  804. type sGuestKeypair struct {
  805. GuestId string
  806. Keypair string
  807. }
  808. func fetchGuestKeypairs(guestIds []string) map[string]sGuestKeypair {
  809. keypairs := KeypairManager.Query().SubQuery()
  810. guests := GuestManager.Query().SubQuery()
  811. q := guests.Query(guests.Field("id").Label("guest_id"), keypairs.Field("name").Label("keypair"))
  812. q = q.Join(keypairs, sqlchemy.Equals(guests.Field("keypair_id"), keypairs.Field("id")))
  813. q = q.Filter(sqlchemy.In(guests.Field("id"), guestIds))
  814. gkps := make([]sGuestKeypair, 0)
  815. err := q.All(&gkps)
  816. if err != nil {
  817. return nil
  818. }
  819. ret := make(map[string]sGuestKeypair)
  820. for i := range gkps {
  821. ret[gkps[i].GuestId] = gkps[i]
  822. }
  823. return ret
  824. }
  825. func fetchGuestGpuInstanceTypes(guestIds []string) (map[string]*GpuSpec, error) {
  826. ret := map[string]*GpuSpec{}
  827. sq := GuestManager.Query("instance_type").In("id", guestIds).SubQuery()
  828. q := ServerSkuManager.Query("name", "gpu_spec", "gpu_count").In("name", sq).IsNotEmpty("gpu_spec").Distinct()
  829. gpus := []struct {
  830. Name string
  831. GpuSpec string
  832. GpuCount string
  833. }{}
  834. err := q.All(&gpus)
  835. if err != nil {
  836. return ret, err
  837. }
  838. for _, gpu := range gpus {
  839. ret[gpu.Name] = &GpuSpec{Model: gpu.GpuSpec, Amount: gpu.GpuCount}
  840. }
  841. return ret, nil
  842. }
  843. func fetchGuestBackupInfo(hostIds []string) (map[string]api.BackupInfo, error) {
  844. ret := map[string]api.BackupInfo{}
  845. hosts := []SHost{}
  846. err := HostManager.Query().In("id", hostIds).All(&hosts)
  847. if err != nil {
  848. return nil, err
  849. }
  850. for _, host := range hosts {
  851. ret[host.Id] = api.BackupInfo{BackupHostName: host.Name, BackupHostStatus: host.HostStatus}
  852. }
  853. return ret, nil
  854. }
  855. func fetchContainers(guestIds []string) (map[string][]*api.PodContainerDesc, error) {
  856. ret := map[string][]*api.PodContainerDesc{}
  857. containers := []SContainer{}
  858. err := GetContainerManager().Query().In("guest_id", guestIds).Asc("created_at").All(&containers)
  859. if err != nil {
  860. return nil, err
  861. }
  862. for i := range containers {
  863. container := containers[i]
  864. _, ok := ret[container.GuestId]
  865. if !ok {
  866. ret[container.GuestId] = []*api.PodContainerDesc{}
  867. }
  868. desc := &api.PodContainerDesc{
  869. Id: container.GetId(),
  870. Name: container.GetName(),
  871. Status: container.Status,
  872. }
  873. if container.Spec != nil {
  874. desc.Image = container.Spec.Image
  875. }
  876. ret[container.GuestId] = append(ret[container.GuestId], desc)
  877. }
  878. return ret, nil
  879. }
  880. func fetchGuestIsolatedDevices(guestIds []string) map[string][]api.SIsolatedDevice {
  881. q := IsolatedDeviceManager.Query().In("guest_id", guestIds)
  882. devs := make([]SIsolatedDevice, 0)
  883. err := q.All(&devs)
  884. if err != nil {
  885. return nil
  886. }
  887. ret := make(map[string][]api.SIsolatedDevice)
  888. for i := range devs {
  889. dev := api.SIsolatedDevice{}
  890. dev.Id = devs[i].Id
  891. dev.HostId = devs[i].HostId
  892. dev.DevType = devs[i].DevType
  893. dev.Model = devs[i].Model
  894. dev.GuestId = devs[i].GuestId
  895. dev.Addr = devs[i].Addr
  896. dev.VendorDeviceId = devs[i].VendorDeviceId
  897. dev.NumaNode = byte(devs[i].NumaNode)
  898. gdevs, ok := ret[devs[i].GuestId]
  899. if !ok {
  900. gdevs = make([]api.SIsolatedDevice, 0)
  901. }
  902. gdevs = append(gdevs, dev)
  903. ret[devs[i].GuestId] = gdevs
  904. }
  905. return ret
  906. }
  907. func fetchGuestCdroms(guestIds []string) map[string][]SGuestcdrom {
  908. sq := GuestcdromManager.Query().In("id", guestIds).SubQuery()
  909. image := CachedimageManager.Query().SubQuery()
  910. q := sq.Query(
  911. sq.Field("id"),
  912. sq.Field("path"),
  913. sq.Field("boot_index"),
  914. sq.Field("image_id"),
  915. image.Field("size"),
  916. image.Field("name"),
  917. )
  918. q = q.LeftJoin(image, sqlchemy.Equals(sq.Field("image_id"), image.Field("id")))
  919. gcds := make([]SGuestcdrom, 0)
  920. err := q.All(&gcds)
  921. if err != nil {
  922. return nil
  923. }
  924. ret := make(map[string][]SGuestcdrom)
  925. for i := range gcds {
  926. ret[gcds[i].Id] = append(ret[gcds[i].Id], gcds[i])
  927. }
  928. return ret
  929. }
  930. func fetchGuestFloppys(guestIds []string) map[string][]SGuestfloppy {
  931. q := GuestFloppyManager.Query().In("id", guestIds)
  932. gfls := make([]SGuestfloppy, 0)
  933. err := q.All(&gfls)
  934. if err != nil {
  935. return nil
  936. }
  937. ret := make(map[string][]SGuestfloppy)
  938. for i := range gfls {
  939. ret[gfls[i].Id] = append(ret[gfls[i].Id], gfls[i])
  940. }
  941. return ret
  942. }
  943. func fetchScalingGroupGuest(guestIds ...string) map[string]SScalingGroupGuest {
  944. q := ScalingGroupGuestManager.Query().In("guest_id", guestIds)
  945. sggs := make([]SScalingGroupGuest, 0)
  946. err := q.All(&sggs)
  947. if err != nil {
  948. return nil
  949. }
  950. ret := make(map[string]SScalingGroupGuest)
  951. for i := range sggs {
  952. ret[sggs[i].GuestId] = sggs[i]
  953. }
  954. return ret
  955. }
  956. func (self *SGuest) SyncInstanceSnapshots(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider) compare.SyncResult {
  957. syncResult := compare.SyncResult{}
  958. extGuest, err := self.GetIVM(ctx)
  959. if err != nil {
  960. syncResult.Error(err)
  961. return syncResult
  962. }
  963. extSnapshots, err := extGuest.GetInstanceSnapshots()
  964. if errors.Cause(err) == errors.ErrNotImplemented {
  965. return syncResult
  966. }
  967. syncOwnerId := provider.GetOwnerId()
  968. localSnapshots, err := self.GetInstanceSnapshots()
  969. if err != nil {
  970. syncResult.Error(err)
  971. return syncResult
  972. }
  973. lockman.LockClass(ctx, InstanceSnapshotManager, db.GetLockClassKey(InstanceSnapshotManager, syncOwnerId))
  974. defer lockman.ReleaseClass(ctx, InstanceSnapshotManager, db.GetLockClassKey(InstanceSnapshotManager, syncOwnerId))
  975. removed := make([]SInstanceSnapshot, 0)
  976. commondb := make([]SInstanceSnapshot, 0)
  977. commonext := make([]cloudprovider.ICloudInstanceSnapshot, 0)
  978. added := make([]cloudprovider.ICloudInstanceSnapshot, 0)
  979. err = compare.CompareSets(localSnapshots, extSnapshots, &removed, &commondb, &commonext, &added)
  980. if err != nil {
  981. syncResult.Error(err)
  982. return syncResult
  983. }
  984. for i := 0; i < len(removed); i += 1 {
  985. err = removed[i].syncRemoveCloudInstanceSnapshot(ctx, userCred)
  986. if err != nil {
  987. syncResult.DeleteError(err)
  988. } else {
  989. syncResult.Delete()
  990. }
  991. }
  992. for i := 0; i < len(commondb); i += 1 {
  993. err = commondb[i].SyncWithCloudInstanceSnapshot(ctx, userCred, commonext[i], self)
  994. if err != nil {
  995. syncResult.UpdateError(err)
  996. } else {
  997. syncResult.Update()
  998. }
  999. }
  1000. for i := 0; i < len(added); i += 1 {
  1001. _, err := InstanceSnapshotManager.newFromCloudInstanceSnapshot(ctx, userCred, added[i], self)
  1002. if err != nil {
  1003. syncResult.AddError(err)
  1004. } else {
  1005. syncResult.Add()
  1006. }
  1007. }
  1008. return syncResult
  1009. }