diff --git a/pkg/apis/compute/guests.go b/pkg/apis/compute/guests.go index 009398f3af..f287b89026 100644 --- a/pkg/apis/compute/guests.go +++ b/pkg/apis/compute/guests.go @@ -15,6 +15,7 @@ package compute import ( + "fmt" "time" "yunion.io/x/onecloud/pkg/apis" @@ -270,6 +271,19 @@ type GuestDiskInfo struct { Image string `json:"image,omitemtpy"` } +func (self GuestDiskInfo) ShortDesc() string { + fs := "" + if len(self.ImageId) > 0 { + fs = "root" + } else if len(self.FsFormat) > 0 { + fs = self.FsFormat + } else { + fs = "none" + } + return fmt.Sprintf("disk%d:%dM/%s/%s/%s/%s/%s", self.Index, self.SizeMb, + self.DiskFormat, self.Driver, self.CacheMode, self.AioMode, fs) +} + type GuestJointResourceDetails struct { apis.VirtualJointResourceBaseDetails diff --git a/pkg/compute/models/guest_queries.go b/pkg/compute/models/guest_queries.go index 436ee8a501..8b8732518a 100644 --- a/pkg/compute/models/guest_queries.go +++ b/pkg/compute/models/guest_queries.go @@ -57,13 +57,17 @@ func (manager *SGuestManager) FetchCustomizeColumns( } if len(fields) == 0 || fields.Contains("disk") { - gds := fetchGuestDiskSizes(guestIds) + gds := fetchGuestDisksInfo(guestIds) if gds != nil { for i := range rows { - if gd, ok := gds[guestIds[i]]; ok { - rows[i].DiskSizeMb = gd.DiskSizeMb - rows[i].DiskCount = gd.DiskCount + rows[i].DisksInfo, _ = gds[guestIds[i]] + rows[i].DiskCount = len(rows[i].DisksInfo) + shortDescs := []string{} + for _, info := range rows[i].DisksInfo { + rows[i].DiskSizeMb += int64(info.SizeMb) + shortDescs = append(shortDescs, info.ShortDesc()) } + rows[i].Disks = strings.Join(shortDescs, "\n") } } } @@ -214,25 +218,63 @@ type sGustDiskSize struct { DiskCount int } -func fetchGuestDiskSizes(guestIds []string) map[string]sGustDiskSize { +type sGuestDiskInfo struct { + api.GuestDiskInfo + GuestId string +} + +func fetchGuestDisksInfo(guestIds []string) map[string][]api.GuestDiskInfo { disks := DiskManager.Query().SubQuery() guestdisks := GuestdiskManager.Query().SubQuery() - - q := disks.Query(guestdisks.Field("guest_id"), sqlchemy.SUM("disk_size_mb", disks.Field("disk_size")), sqlchemy.COUNT("disk_count")) + storages := StorageManager.Query().SubQuery() + q := disks.Query( + disks.Field("id"), + disks.Field("name"), + disks.Field("fs_format"), + guestdisks.Field("index"), + disks.Field("disk_size").Label("size"), + disks.Field("disk_format"), + guestdisks.Field("driver"), + guestdisks.Field("cache_mode"), + guestdisks.Field("aio_mode"), + storages.Field("medium_type"), + storages.Field("storage_type"), + guestdisks.Field("iops"), + guestdisks.Field("bps"), + disks.Field("template_id").Label("image_id"), + guestdisks.Field("guest_id"), + ) q = q.Join(guestdisks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id"))) + q = q.Join(storages, sqlchemy.Equals(disks.Field("storage_id"), storages.Field("id"))) q = q.Filter(sqlchemy.In(guestdisks.Field("guest_id"), guestIds)) q = q.GroupBy(guestdisks.Field("guest_id")) - - gds := make([]sGustDiskSize, 0) + gds := []sGuestDiskInfo{} err := q.All(&gds) - if err != nil && err != sql.ErrNoRows { - log.Errorf("query sGustDiskSize fail: %v", err) + if err != nil { return nil } - - ret := make(map[string]sGustDiskSize) + imageIds := []string{} + ret := map[string][]api.GuestDiskInfo{} for i := range gds { - ret[gds[i].GuestId] = gds[i] + if len(gds[i].ImageId) > 0 { + imageIds = append(imageIds, gds[i].ImageId) + } + _, ok := ret[gds[i].GuestId] + if !ok { + ret[gds[i].GuestId] = []api.GuestDiskInfo{} + } + ret[gds[i].GuestId] = append(ret[gds[i].GuestId], gds[i].GuestDiskInfo) + } + imageNames, err := db.FetchIdNameMap2(CachedimageManager, imageIds) + if err != nil { + return ret + } + for guestId, infos := range ret { + for i := range infos { + if len(infos[i].ImageId) > 0 { + ret[guestId][i].Image, _ = imageNames[infos[i].ImageId] + } + } } return ret } @@ -242,15 +284,19 @@ func (guest *SGuest) GetDisksSize() int { } func (guest *SGuest) getDiskSize() int { - result := fetchGuestDiskSizes([]string{guest.Id}) + result := fetchGuestDisksInfo([]string{guest.Id}) if result == nil { return -1 } - if gs, ok := result[guest.Id]; ok { - return int(gs.DiskSizeMb) - } else { + gds, ok := result[guest.Id] + if !ok { return -1 } + size := 0 + for _, gd := range gds { + size += gd.SizeMb + } + return size } func fetchGuestIPs(guestIds []string, virtual tristate.TriState) map[string][]string { diff --git a/pkg/compute/models/guestdisks.go b/pkg/compute/models/guestdisks.go index db2f354fe8..3a01fb4394 100644 --- a/pkg/compute/models/guestdisks.go +++ b/pkg/compute/models/guestdisks.go @@ -16,7 +16,6 @@ package models import ( "context" - "fmt" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -249,62 +248,6 @@ func (self *SGuestdisk) GetJsonDescAtHost(host *SHost) jsonutils.JSONObject { return desc } -func (self *SGuestdisk) GetDetailedInfo() api.GuestDiskInfo { - desc := api.GuestDiskInfo{} - disk := self.GetDisk() - if disk == nil { - return desc - } - desc.Id = disk.Id - desc.Name = disk.Name - desc.FsFormat = disk.FsFormat - desc.DiskType = disk.DiskType - desc.Index = self.Index - desc.SizeMb = disk.DiskSize - desc.DiskFormat = disk.DiskFormat - desc.Driver = self.Driver - desc.CacheMode = self.CacheMode - desc.AioMode = self.AioMode - desc.Iops = self.Iops - desc.Bps = self.Bps - - imageId := disk.GetTemplateId() - if len(imageId) > 0 { - desc.ImageId = imageId - cachedImageObj, _ := CachedimageManager.FetchById(imageId) - if cachedImageObj != nil { - cachedImage := cachedImageObj.(*SCachedimage) - desc.Image = cachedImage.GetName() - } - } - - storage := disk.GetStorage() - if storage == nil { - return desc - } - desc.MediumType = storage.MediumType - desc.StorageType = storage.StorageType - return desc -} - -func (self *SGuestdisk) GetDetailedString() string { - disk := self.GetDisk() - if disk == nil { - return "" - } - - var fs string - if len(disk.GetTemplateId()) > 0 { - fs = "root" - } else if len(disk.GetFsFormat()) > 0 { - fs = disk.GetFsFormat() - } else { - fs = "none" - } - return fmt.Sprintf("disk%d:%dM/%s/%s/%s/%s/%s", self.Index, disk.DiskSize, - disk.DiskFormat, self.Driver, self.CacheMode, self.AioMode, fs) -} - func (self *SGuestdisk) Delete(ctx context.Context, userCred mcclient.TokenCredential) error { return db.DeleteModel(ctx, userCred, self) } diff --git a/pkg/compute/models/guests.go b/pkg/compute/models/guests.go index bdca14aebe..4a6d42054b 100644 --- a/pkg/compute/models/guests.go +++ b/pkg/compute/models/guests.go @@ -1960,8 +1960,6 @@ func (self *SGuest) moreExtraInfo( } } else { out.Networks = self.getNetworksDetails() - out.Disks = self.getDisksDetails() - out.DisksInfo = self.getDisksInfoDetails() out.VirtualIps = strings.Join(self.getVirtualIPs(), ",") out.SecurityRules = self.getSecurityGroupsRules() @@ -2118,26 +2116,6 @@ func (self *SGuest) getNetworksDetails() string { return buf.String() } -func (self *SGuest) getDisksDetails() string { - var buf bytes.Buffer - for _, disk := range self.GetDisks() { - if details := disk.GetDetailedString(); len(details) > 0 { - buf.WriteString(details) - buf.WriteString("\n") - } - } - return buf.String() -} - -func (self *SGuest) getDisksInfoDetails() []api.GuestDiskInfo { - disks := self.GetDisks() - details := make([]api.GuestDiskInfo, len(disks)) - for i := range details { - details[i] = disks[i].GetDetailedInfo() - } - return details -} - func (self *SGuest) GetCdrom() *SGuestcdrom { return self.getCdrom(false) }