networkresource.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/util/reflectutils"
  22. "yunion.io/x/sqlchemy"
  23. api "yunion.io/x/onecloud/pkg/apis/compute"
  24. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  25. "yunion.io/x/onecloud/pkg/httperrors"
  26. "yunion.io/x/onecloud/pkg/mcclient"
  27. "yunion.io/x/onecloud/pkg/util/stringutils2"
  28. )
  29. type SNetworkResourceBase struct {
  30. NetworkId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional" json:"network_id"`
  31. }
  32. type SNetworkResourceBaseManager struct {
  33. SWireResourceBaseManager
  34. }
  35. func ValidateNetworkResourceInput(ctx context.Context, userCred mcclient.TokenCredential, query api.NetworkResourceInput) (*SNetwork, api.NetworkResourceInput, error) {
  36. netObj, err := NetworkManager.FetchByIdOrName(ctx, userCred, query.NetworkId)
  37. if err != nil {
  38. if err == sql.ErrNoRows {
  39. return nil, query, errors.Wrapf(httperrors.ErrResourceNotFound, "%s %s", NetworkManager.Keyword(), query.NetworkId)
  40. } else {
  41. return nil, query, errors.Wrap(err, "NetworkManager.FetchByIdOrName")
  42. }
  43. }
  44. query.NetworkId = netObj.GetId()
  45. return netObj.(*SNetwork), query, nil
  46. }
  47. func (self *SNetworkResourceBase) GetNetwork() (*SNetwork, error) {
  48. obj, err := NetworkManager.FetchById(self.NetworkId)
  49. if err != nil {
  50. return nil, errors.Wrapf(err, "GetNetwork(%s)", self.NetworkId)
  51. }
  52. return obj.(*SNetwork), nil
  53. }
  54. func (self *SNetworkResourceBase) GetWire() (*SWire, error) {
  55. net, err := self.GetNetwork()
  56. if err != nil {
  57. return nil, err
  58. }
  59. return net.GetWire()
  60. }
  61. func (self *SNetworkResourceBase) GetZone() (*SZone, error) {
  62. wire, err := self.GetWire()
  63. if err != nil {
  64. return nil, err
  65. }
  66. return wire.GetZone()
  67. }
  68. func (self *SNetworkResourceBase) GetVpc() (*SVpc, error) {
  69. wire, err := self.GetWire()
  70. if err != nil {
  71. return nil, err
  72. }
  73. return wire.GetVpc()
  74. }
  75. func (self *SNetworkResourceBase) GetRegion() (*SCloudregion, error) {
  76. vpc, err := self.GetVpc()
  77. if err != nil {
  78. return nil, err
  79. }
  80. return vpc.GetRegion()
  81. }
  82. func (manager *SNetworkResourceBaseManager) FetchCustomizeColumns(
  83. ctx context.Context,
  84. userCred mcclient.TokenCredential,
  85. query jsonutils.JSONObject,
  86. objs []interface{},
  87. fields stringutils2.SSortedStrings,
  88. isList bool,
  89. ) []api.NetworkResourceInfo {
  90. rows := make([]api.NetworkResourceInfo, len(objs))
  91. netIds := make([]string, len(objs))
  92. for i := range objs {
  93. var base *SNetworkResourceBase
  94. err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
  95. if err != nil {
  96. log.Errorf("Cannot find SNetworkResourceBase in object %T", objs[i])
  97. continue
  98. }
  99. netIds[i] = base.NetworkId
  100. }
  101. networks := make(map[string]SNetwork)
  102. err := db.FetchStandaloneObjectsByIds(NetworkManager, netIds, networks)
  103. if err != nil {
  104. log.Errorf("FetchStandaloneObjectsByIds fail %s", err)
  105. return rows
  106. }
  107. wireList := make([]interface{}, len(rows))
  108. for i := range rows {
  109. rows[i] = api.NetworkResourceInfo{}
  110. if _, ok := networks[netIds[i]]; ok {
  111. network := networks[netIds[i]]
  112. rows[i].Network = network.Name
  113. rows[i].WireId = network.WireId
  114. }
  115. wireList[i] = &SWireResourceBase{rows[i].WireId}
  116. }
  117. wireRows := manager.SWireResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, wireList, fields, isList)
  118. for i := range rows {
  119. rows[i].WireResourceInfo = wireRows[i]
  120. }
  121. return rows
  122. }
  123. func (manager *SNetworkResourceBaseManager) ListItemFilter(
  124. ctx context.Context,
  125. q *sqlchemy.SQuery,
  126. userCred mcclient.TokenCredential,
  127. query api.NetworkFilterListInput,
  128. ) (*sqlchemy.SQuery, error) {
  129. if len(query.NetworkId) > 0 {
  130. netObj, _, err := ValidateNetworkResourceInput(ctx, userCred, query.NetworkResourceInput)
  131. if err != nil {
  132. return nil, errors.Wrap(err, "ValidateNetworkResourceInput")
  133. }
  134. q = q.Equals("network_id", netObj.GetId())
  135. }
  136. netQ := NetworkManager.Query("id").Snapshot()
  137. netQ, err := manager.SWireResourceBaseManager.ListItemFilter(ctx, netQ, userCred, query.WireFilterListInput)
  138. if err != nil {
  139. return nil, errors.Wrap(err, "SWireResourceBaseManager.ListItemFilter")
  140. }
  141. if netQ.IsAltered() {
  142. q = q.Filter(sqlchemy.In(q.Field("network_id"), netQ.SubQuery()))
  143. }
  144. return q, nil
  145. }
  146. func (manager *SNetworkResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  147. switch field {
  148. case "network":
  149. netQuery := NetworkManager.Query("name", "id").SubQuery()
  150. q = q.AppendField(netQuery.Field("name", field)).Distinct()
  151. q = q.Join(netQuery, sqlchemy.Equals(q.Field("network_id"), netQuery.Field("id")))
  152. return q, nil
  153. default:
  154. nets := NetworkManager.Query("id", "wire_id").SubQuery()
  155. q = q.LeftJoin(nets, sqlchemy.Equals(q.Field("network_id"), nets.Field("id")))
  156. q, err := manager.SWireResourceBaseManager.QueryDistinctExtraField(q, field)
  157. if err == nil {
  158. return q, nil
  159. }
  160. }
  161. return q, httperrors.ErrNotFound
  162. }
  163. func (manager *SNetworkResourceBaseManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  164. switch resource {
  165. case NetworkManager.Keyword():
  166. netQuery := NetworkManager.Query().SubQuery()
  167. for _, field := range fields {
  168. q = q.AppendField(netQuery.Field(field))
  169. }
  170. q = q.Join(netQuery, sqlchemy.Equals(q.Field("network_id"), netQuery.Field("id")))
  171. return q, nil
  172. }
  173. return q, httperrors.ErrNotFound
  174. }
  175. func (manager *SNetworkResourceBaseManager) OrderByExtraFields(
  176. ctx context.Context,
  177. q *sqlchemy.SQuery,
  178. userCred mcclient.TokenCredential,
  179. query api.NetworkFilterListInput,
  180. ) (*sqlchemy.SQuery, error) {
  181. if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
  182. return q, nil
  183. }
  184. orderQ := NetworkManager.Query("id")
  185. orderSubQ := orderQ.SubQuery()
  186. orderQ, orders, fields := manager.GetOrderBySubQuery(orderQ, orderSubQ, orderQ.Field("id"), userCred, query, nil, nil)
  187. q = q.LeftJoin(orderSubQ, sqlchemy.Equals(q.Field("network_id"), orderSubQ.Field("id")))
  188. q = db.OrderByFields(q, orders, fields)
  189. return q, nil
  190. }
  191. func (manager *SNetworkResourceBaseManager) GetOrderBySubQuery(
  192. q *sqlchemy.SQuery,
  193. subq *sqlchemy.SSubQuery,
  194. joinField sqlchemy.IQueryField,
  195. userCred mcclient.TokenCredential,
  196. query api.NetworkFilterListInput,
  197. orders []string,
  198. fields []sqlchemy.IQueryField,
  199. ) (*sqlchemy.SQuery, []string, []sqlchemy.IQueryField) {
  200. if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
  201. return q, orders, fields
  202. }
  203. netQ := NetworkManager.Query().SubQuery()
  204. q = q.LeftJoin(netQ, sqlchemy.Equals(joinField, netQ.Field("id")))
  205. q = q.AppendField(netQ.Field("name").Label("network"))
  206. orders = append(orders, query.OrderByNetwork)
  207. fields = append(fields, subq.Field("network"))
  208. q, orders, fields = manager.SWireResourceBaseManager.GetOrderBySubQuery(q, subq, netQ.Field("wire_id"), userCred, query.WireFilterListInput, orders, fields)
  209. return q, orders, fields
  210. }
  211. func (manager *SNetworkResourceBaseManager) GetOrderByFields(query api.NetworkFilterListInput) []string {
  212. orders := make([]string, 0)
  213. wireOrders := manager.SWireResourceBaseManager.GetOrderByFields(query.WireFilterListInput)
  214. orders = append(orders, wireOrders...)
  215. orders = append(orders, query.OrderByNetwork)
  216. return orders
  217. }
  218. func (manager *SNetworkResourceBaseManager) ListItemExportKeys(ctx context.Context,
  219. q *sqlchemy.SQuery,
  220. userCred mcclient.TokenCredential,
  221. keys stringutils2.SSortedStrings,
  222. ) (*sqlchemy.SQuery, error) {
  223. if keys.ContainsAny(manager.GetExportKeys()...) {
  224. var err error
  225. subq := NetworkManager.Query("id", "name", "wire_id").SubQuery()
  226. q = q.LeftJoin(subq, sqlchemy.Equals(q.Field("network_id"), subq.Field("id")))
  227. if keys.Contains("network") {
  228. q = q.AppendField(subq.Field("name", "network"))
  229. }
  230. if keys.ContainsAny(manager.SWireResourceBaseManager.GetExportKeys()...) {
  231. q, err = manager.SWireResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  232. if err != nil {
  233. return nil, errors.Wrap(err, "SWireResourceBaseManager.ListItemExportKeys")
  234. }
  235. }
  236. }
  237. return q, nil
  238. }
  239. func (manager *SNetworkResourceBaseManager) GetExportKeys() []string {
  240. keys := []string{"network"}
  241. keys = append(keys, manager.SWireResourceBaseManager.GetExportKeys()...)
  242. return keys
  243. }
  244. func (self *SNetworkResourceBase) GetChangeOwnerCandidateDomainIds() []string {
  245. network, _ := self.GetNetwork()
  246. if network != nil {
  247. return network.GetChangeOwnerCandidateDomainIds()
  248. }
  249. return nil
  250. }