network_additional_wires.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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. "strings"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/pkg/errors"
  21. "yunion.io/x/pkg/utils"
  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/mcclient"
  26. "yunion.io/x/onecloud/pkg/util/netutils2"
  27. )
  28. type SNetworkAdditionalWireManager struct {
  29. db.SModelBaseManager
  30. }
  31. var NetworkAdditionalWireManager *SNetworkAdditionalWireManager
  32. func init() {
  33. NetworkAdditionalWireManager = &SNetworkAdditionalWireManager{
  34. SModelBaseManager: db.NewModelBaseManager(
  35. SNetworkAdditionalWire{},
  36. "network_additional_wire_tbl",
  37. "network_additional_wire",
  38. "network_additional_wires",
  39. ),
  40. }
  41. NetworkAdditionalWireManager.SetVirtualObject(NetworkAdditionalWireManager)
  42. }
  43. type SNetworkAdditionalWire struct {
  44. db.SModelBase
  45. NetworkId string `width:"36" charset:"ascii" nullable:"false" primary:"true"`
  46. WireId string `width:"36" charset:"ascii" nullable:"false" primary:"true"`
  47. Synced *bool
  48. Marked *bool
  49. }
  50. func (manager *SNetworkAdditionalWireManager) newRecord(ctx context.Context, netId, wireId string, synced *bool, marked *bool) error {
  51. rec := &SNetworkAdditionalWire{
  52. NetworkId: netId,
  53. WireId: wireId,
  54. Synced: synced,
  55. Marked: marked,
  56. }
  57. err := manager.TableSpec().InsertOrUpdate(ctx, rec)
  58. return errors.Wrap(err, "InsertOrUpdate")
  59. }
  60. func (manager *SNetworkAdditionalWireManager) NewQuery(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, useRawQuery bool) *sqlchemy.SQuery {
  61. return manager.Query()
  62. }
  63. func (manager *SNetworkAdditionalWireManager) Query(fields ...string) *sqlchemy.SQuery {
  64. q := manager.SModelBaseManager.Query(fields...)
  65. q = q.Filter(sqlchemy.OR(
  66. sqlchemy.IsTrue(q.Field("synced")),
  67. sqlchemy.IsTrue(q.Field("marked")),
  68. ))
  69. return q
  70. }
  71. func (manager *SNetworkAdditionalWireManager) networkIdQuery(wireId string) *sqlchemy.SQuery {
  72. q := manager.Query("network_id").Equals("wire_id", wireId)
  73. return q
  74. }
  75. func (manager *SNetworkAdditionalWireManager) fetchNetworkAdditionalWireIdsQuery(netId string) *sqlchemy.SQuery {
  76. q := manager.Query("wire_id").Equals("network_id", netId)
  77. return q
  78. }
  79. func (manager *SNetworkAdditionalWireManager) DeleteNetwork(ctx context.Context, netId string) error {
  80. False := false
  81. wireIds, err := manager.FetchNetworkAdditionalWireIds(netId)
  82. if err != nil {
  83. return errors.Wrap(err, "FetchNetworkAdditionalWireIds")
  84. }
  85. for _, wireId := range wireIds {
  86. err := manager.newRecord(ctx, netId, wireId, &False, &False)
  87. if err != nil {
  88. return errors.Wrap(err, "newRecord")
  89. }
  90. }
  91. return nil
  92. }
  93. func (manager *SNetworkAdditionalWireManager) DeleteWire(ctx context.Context, wireId string) error {
  94. False := false
  95. netIds, err := manager.FetchWireAdditionalNetworkIds(wireId)
  96. if err != nil {
  97. return errors.Wrap(err, "FetchWireAdditionalNetworkIds")
  98. }
  99. for _, netId := range netIds {
  100. err := manager.newRecord(ctx, netId, wireId, &False, &False)
  101. if err != nil {
  102. return errors.Wrap(err, "newRecord")
  103. }
  104. }
  105. return nil
  106. }
  107. func (manager *SNetworkAdditionalWireManager) FetchNetworkAdditionalWireIds(netId string) ([]string, error) {
  108. q := manager.fetchNetworkAdditionalWireIdsQuery(netId)
  109. ret := make([]SNetworkAdditionalWire, 0)
  110. err := db.FetchModelObjects(manager, q, &ret)
  111. if err != nil {
  112. return nil, errors.Wrap(err, "FetchModelObjects")
  113. }
  114. wireIds := make([]string, len(ret))
  115. for i := range ret {
  116. wireIds[i] = ret[i].WireId
  117. }
  118. return wireIds, nil
  119. }
  120. func (manager *SNetworkAdditionalWireManager) FetchWireAdditionalNetworkIds(wireId string) ([]string, error) {
  121. q := manager.networkIdQuery(wireId)
  122. ret := make([]SNetworkAdditionalWire, 0)
  123. err := db.FetchModelObjects(manager, q, &ret)
  124. if err != nil {
  125. return nil, errors.Wrap(err, "FetchModelObjects")
  126. }
  127. netIds := make([]string, len(ret))
  128. for i := range ret {
  129. netIds[i] = ret[i].NetworkId
  130. }
  131. return netIds, nil
  132. }
  133. func (manager *SNetworkAdditionalWireManager) FetchNetworkAdditionalWires(netId string) ([]api.SSimpleWire, error) {
  134. subq := manager.fetchNetworkAdditionalWireIdsQuery(netId).SubQuery()
  135. q := WireManager.Query("id", "name")
  136. q = q.Join(subq, sqlchemy.Equals(q.Field("id"), subq.Field("wire_id")))
  137. ret := make([]SWire, 0)
  138. err := db.FetchModelObjects(WireManager, q, &ret)
  139. if err != nil {
  140. return nil, errors.Wrap(err, "FetchModelObjects")
  141. }
  142. wires := make([]api.SSimpleWire, len(ret))
  143. for i := range ret {
  144. wires[i].WireId = ret[i].Id
  145. wires[i].Wire = ret[i].Name
  146. }
  147. return wires, nil
  148. }
  149. func (net *SNetwork) syncAdditionalWires(ctx context.Context, wireIds []string) error {
  150. // find out all vmware wires in the same zone
  151. wires, err := WireManager.FetchWires(func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  152. managersQ := CloudproviderManager.Query().Equals("provider", api.CLOUD_PROVIDER_VMWARE).SubQuery()
  153. q = q.Join(managersQ, sqlchemy.Equals(q.Field("manager_id"), managersQ.Field("id")))
  154. return q
  155. })
  156. if err != nil {
  157. return errors.Wrap(err, "FetchWires")
  158. }
  159. for i := range wires {
  160. w := &wires[i]
  161. if net.WireId == w.Id {
  162. continue
  163. }
  164. connected := net.checkNetWireConnectivity(ctx, w)
  165. var markedPtr *bool
  166. if wireIds != nil {
  167. marked := false
  168. if utils.IsInArray(w.Id, wireIds) {
  169. marked = true
  170. }
  171. markedPtr = &marked
  172. }
  173. err := NetworkAdditionalWireManager.newRecord(ctx, net.Id, w.Id, &connected, markedPtr)
  174. if err != nil {
  175. return errors.Wrap(err, "NetworkAdditionalWireManager.newRecord")
  176. }
  177. }
  178. return nil
  179. }
  180. func (net *SNetwork) checkNetWireConnectivity(ctx context.Context, wire *SWire) bool {
  181. vmIps := wire.GetMetadata(ctx, "vm_ips", nil)
  182. if len(vmIps) > 0 {
  183. ips, err := netutils2.ExpandCompactIps(vmIps)
  184. if err != nil {
  185. log.Errorf("ExpandCompactIps net %s wire %s vm_ips %s fail %s", net.Name, wire.Name, vmIps, err)
  186. } else {
  187. for _, ip := range ips {
  188. if net.Contains(ip) {
  189. return true
  190. }
  191. }
  192. }
  193. }
  194. vmMacs := wire.GetMetadata(ctx, "vm_macs", nil)
  195. if len(vmMacs) > 0 {
  196. macs := strings.Split(vmMacs, ",")
  197. for _, mac := range macs {
  198. gns, err := GuestnetworkManager.fetchGuestNetworks(func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  199. q = q.Equals("network_id", net.Id).Equals("mac_addr", mac)
  200. return q
  201. })
  202. if err != nil {
  203. log.Errorf("fetchGuestNetworks net %s wire %s mac %s fail %s", net.Name, wire.Name, mac, err)
  204. } else if len(gns) > 0 {
  205. return true
  206. }
  207. }
  208. }
  209. return false
  210. }