From eef90b58e773cc5bc8e669226125920dffe373f7 Mon Sep 17 00:00:00 2001 From: rainzm Date: Mon, 26 Oct 2020 17:34:54 +0800 Subject: [PATCH] fix(region): roll back the optimization of cachedimage list --- pkg/compute/models/cachedimages.go | 111 ++++++++++++++++---------- pkg/compute/models/managedresource.go | 61 +++++++------- 2 files changed, 101 insertions(+), 71 deletions(-) diff --git a/pkg/compute/models/cachedimages.go b/pkg/compute/models/cachedimages.go index b1a9440e4b..a94c8feb91 100644 --- a/pkg/compute/models/cachedimages.go +++ b/pkg/compute/models/cachedimages.go @@ -684,6 +684,20 @@ func (manager *SCachedimageManager) ListItemFilter( return nil, errors.Wrapf(err, "SSharableBaseResourceManager.ListItemFilter") } + q, err = managedResourceFilterByAccount(q, query.ManagedResourceListInput, "id", func() *sqlchemy.SQuery { + cachedImages := CachedimageManager.Query().SubQuery() + storagecachedImages := StoragecachedimageManager.Query().SubQuery() + storageCaches := StoragecacheManager.Query().SubQuery() + + subq := cachedImages.Query(cachedImages.Field("id")) + subq = subq.Join(storagecachedImages, sqlchemy.Equals(cachedImages.Field("id"), storagecachedImages.Field("cachedimage_id"))) + subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id"))) + return subq + }) + if err != nil { + return nil, errors.Wrap(err, "managedResourceFilterByAccount") + } + q, err = manager.SSharableVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.SharableVirtualResourceListInput) if err != nil { return nil, errors.Wrap(err, "SSharableVirtualResourceBaseManager.ListItemFilter") @@ -694,61 +708,76 @@ func (manager *SCachedimageManager) ListItemFilter( return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter") } - { + q, err = managedResourceFilterByRegion(q, query.RegionalFilterListInput, "id", func() *sqlchemy.SQuery { storagecachedImages := StoragecachedimageManager.Query().SubQuery() storageCaches := StoragecacheManager.Query().SubQuery() - var storages *sqlchemy.SSubQuery - - if query.Valid == nil { - storages = StorageManager.Query().SubQuery() - } else if *query.Valid { - storages = StorageManager.Query().In("status", []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}).IsTrue("enabled").SubQuery() - } else { - stroage := StorageManager.Query() - storages = stroage.Filter(sqlchemy.OR(sqlchemy.NotIn(stroage.Field("status"), []string{}), sqlchemy.IsFalse(stroage.Field("enabled")))).SubQuery() - } + storages := StorageManager.Query().SubQuery() zones := ZoneManager.Query().SubQuery() subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id")) subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id"))) subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id"))) subq = subq.Join(zones, sqlchemy.Equals(storages.Field("zone_id"), zones.Field("id"))) - - if len(query.HostSchedtagId) > 0 { - schedTagObj, err := SchedtagManager.FetchByIdOrName(userCred, query.HostSchedtagId) - if err != nil { - if errors.Cause(err) == sql.ErrNoRows { - return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", SchedtagManager.Keyword(), query.HostSchedtagId) - } else { - return nil, errors.Wrap(err, "SchedtagManager.FetchByIdOrName") - } - } - hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery() - hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", schedTagObj.GetId()).SubQuery() - subq = subq.Join(hoststorages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id"))) - subq = subq.Join(hostschedtags, sqlchemy.Equals(hostschedtags.Field("host_id"), hoststorages.Field("host_id"))) - } subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE)) - subq, err = managedResourceFilterByAccount(subq, query.ManagedResourceListInput, "", nil) - if err != nil { - return nil, errors.Wrap(err, "managedResourceFilterByAccount") - } + return subq + }) + if err != nil { + return nil, errors.Wrap(err, "managedResourceFilterByRegion") + } - subq, err = _managedResourceFilterByRegion(subq, query.RegionalFilterListInput) - if err != nil { - return nil, errors.Wrap(err, "_managedResourceFilterByRegion") - } + q, err = managedResourceFilterByZone(q, query.ZonalFilterListInput, "id", func() *sqlchemy.SQuery { + storagecachedImages := StoragecachedimageManager.Query().SubQuery() + storageCaches := StoragecacheManager.Query().SubQuery() + storages := StorageManager.Query().SubQuery() - subq, err = _managedResourceFilterByZone(subq, query.ZonalFilterListInput) - if err != nil { - return nil, errors.Wrap(err, "_managedResourceFilterByZone") - } - - q = q.In("id", subq) + subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id")) + subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id"))) + subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id"))) + subq = subq.Filter(sqlchemy.Equals(storagecachedImages.Field("status"), api.CACHED_IMAGE_STATUS_ACTIVE)) + return subq + }) + if err != nil { + return nil, errors.Wrap(err, "managedResourceFilterByZone") } if len(query.ImageType) > 0 { - q = q.Equals("image_type", query.ImageType) + q = q.In("image_type", query.ImageType) + } + + if len(query.HostSchedtagId) > 0 { + schedTagObj, err := SchedtagManager.FetchByIdOrName(userCred, query.HostSchedtagId) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", SchedtagManager.Keyword(), query.HostSchedtagId) + } else { + return nil, errors.Wrap(err, "SchedtagManager.FetchByIdOrName") + } + } + subq := StoragecachedimageManager.Query("cachedimage_id") + storages := StorageManager.Query("id", "storagecache_id").SubQuery() + hoststorages := HoststorageManager.Query("host_id", "storage_id").SubQuery() + hostschedtags := HostschedtagManager.Query().Equals("schedtag_id", schedTagObj.GetId()).SubQuery() + subq = subq.Join(storages, sqlchemy.Equals(storages.Field("storagecache_id"), subq.Field("storagecache_id"))) + subq = subq.Join(hoststorages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id"))) + subq = subq.Join(hostschedtags, sqlchemy.Equals(hostschedtags.Field("host_id"), hoststorages.Field("host_id"))) + q = q.In("id", subq.SubQuery()) + } + + if query.Valid != nil { + storagecachedImages := StoragecachedimageManager.Query().SubQuery() + storageCaches := StoragecacheManager.Query().SubQuery() + // filter invalid storage and cachedimage + storage := StorageManager.Query() + storages := storage.Filter(sqlchemy.OR(sqlchemy.NotIn(storage.Field("status"), []string{api.STORAGE_ENABLED, api.STORAGE_ONLINE}), sqlchemy.IsFalse(storage.Field("enabled")))).SubQuery() + + subq := storagecachedImages.Query(storagecachedImages.Field("cachedimage_id")) + subq = subq.Join(storageCaches, sqlchemy.Equals(storagecachedImages.Field("storagecache_id"), storageCaches.Field("id"))) + subq = subq.Join(storages, sqlchemy.Equals(storageCaches.Field("id"), storages.Field("storagecache_id"))) + if *query.Valid { + q = q.NotIn("id", subq.SubQuery()) + } else { + q = q.In("id", subq.SubQuery()) + } } return q, nil diff --git a/pkg/compute/models/managedresource.go b/pkg/compute/models/managedresource.go index 1231a9fe41..75d4e13b85 100644 --- a/pkg/compute/models/managedresource.go +++ b/pkg/compute/models/managedresource.go @@ -557,7 +557,7 @@ func _managedResourceFilterByAccount(managerIdFieldName string, q *sqlchemy.SQue return q, nil } -func _managedResourceFilterByZone(q *sqlchemy.SQuery, query api.ZonalFilterListInput) (*sqlchemy.SQuery, error) { +func managedResourceFilterByZone(q *sqlchemy.SQuery, query api.ZonalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { zoneList := query.ZoneList() if len(query.ZoneIds) >= 1 { zoneQ := ZoneManager.Query("id") @@ -565,57 +565,58 @@ func _managedResourceFilterByZone(q *sqlchemy.SQuery, query api.ZonalFilterListI sqlchemy.In(zoneQ.Field("id"), zoneList), sqlchemy.In(zoneQ.Field("name"), zoneList), )) - q = q.Filter(sqlchemy.In(q.Field("zone_id"), zoneQ.SubQuery())) + if len(filterField) == 0 { + q = q.Filter(sqlchemy.In(q.Field("zone_id"), zoneQ.SubQuery())) + } else { + sq := subqFunc() + sq = sq.Filter(sqlchemy.In(sq.Field("zone_id"), zoneQ.SubQuery())) + q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) + } } else if len(query.ZoneId) > 0 { zoneObj, _, err := ValidateZoneResourceInput(nil, query.ZoneResourceInput) if err != nil { return nil, errors.Wrap(err, "ValidateZoneResourceInput") } - q = q.Filter(sqlchemy.Equals(q.Field("zone_id"), zoneObj.GetId())) + if len(filterField) == 0 { + q = q.Filter(sqlchemy.Equals(q.Field("zone_id"), zoneObj.GetId())) + } else { + sq := subqFunc() + sq = sq.Filter(sqlchemy.Equals(sq.Field("zone_id"), zoneObj.GetId())) + q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) + } } + return q, nil } -func managedResourceFilterByZone(q *sqlchemy.SQuery, query api.ZonalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - return filterFieldFromSubQuery(q, filterField, subqFunc, func(s *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - return _managedResourceFilterByZone(s, query) - }) -} - -func filterFieldFromSubQuery(q *sqlchemy.SQuery, filterField string, subqFunc func() *sqlchemy.SQuery, filterAdd func(query *sqlchemy.SQuery) (*sqlchemy.SQuery, error)) (*sqlchemy.SQuery, error) { - if len(filterField) == 0 { - return filterAdd(q) - } - sq, err := filterAdd(subqFunc()) - if err != nil { - return nil, err - } - q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) - return q, nil -} - -func _managedResourceFilterByRegion(q *sqlchemy.SQuery, query api.RegionalFilterListInput) (*sqlchemy.SQuery, error) { +func managedResourceFilterByRegion(q *sqlchemy.SQuery, query api.RegionalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { regionStr := query.CloudregionId if len(regionStr) > 0 { regionObj, _, err := ValidateCloudregionResourceInput(nil, query.CloudregionResourceInput) if err != nil { return nil, errors.Wrap(err, "ValidateCloudregionResourceInput") } - q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), regionObj.GetId())) + if len(filterField) == 0 { + q = q.Filter(sqlchemy.Equals(q.Field("cloudregion_id"), regionObj.GetId())) + } else { + sq := subqFunc() + sq = sq.Filter(sqlchemy.Equals(sq.Field("cloudregion_id"), regionObj.GetId())) + q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) + } } if len(query.City) > 0 { subq := CloudregionManager.Query("id").Equals("city", query.City).SubQuery() - q = q.Filter(sqlchemy.In(q.Field("cloudregion_id"), subq)) + if len(filterField) == 0 { + q = q.Filter(sqlchemy.In(q.Field("cloudregion_id"), subq)) + } else { + sq := subqFunc() + sq = sq.Filter(sqlchemy.In(sq.Field("cloudregion_id"), subq)) + q = q.Filter(sqlchemy.In(q.Field(filterField), sq.SubQuery())) + } } return q, nil } -func managedResourceFilterByRegion(q *sqlchemy.SQuery, query api.RegionalFilterListInput, filterField string, subqFunc func() *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - return filterFieldFromSubQuery(q, filterField, subqFunc, func(s *sqlchemy.SQuery) (*sqlchemy.SQuery, error) { - return _managedResourceFilterByRegion(s, query) - }) -} - func _filterByCloudType(managerIdFieldName string, q *sqlchemy.SQuery, input api.ManagedResourceListInput, filterField string, subqFunc func() *sqlchemy.SQuery) *sqlchemy.SQuery { cloudEnvStr := input.CloudEnv