loadbalancermember.go 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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 openstack
  15. import (
  16. "context"
  17. "fmt"
  18. "net/url"
  19. "time"
  20. "yunion.io/x/jsonutils"
  21. "yunion.io/x/log"
  22. "yunion.io/x/pkg/errors"
  23. api "yunion.io/x/cloudmux/pkg/apis/compute"
  24. "yunion.io/x/cloudmux/pkg/cloudprovider"
  25. "yunion.io/x/cloudmux/pkg/multicloud"
  26. )
  27. type SLoadbalancerMemberCreateParams struct {
  28. Name string `json:"name,omitempty"`
  29. Weight *int `json:"weight,omitempty"`
  30. AdminStateUp bool `json:"admin_state_up,omitempty"`
  31. SubnetID string `json:"subnet_id,omitempty"`
  32. Address string `json:"address,omitempty"`
  33. ProtocolPort *int `json:"protocol_port,omitempty"`
  34. MonitorPort *int `json:"monitor_port,omitempty"`
  35. Backup *bool `json:"backup,omitempty"`
  36. Tags []string `json:"tags,omitempty"`
  37. }
  38. type SLoadbalancerMember struct {
  39. multicloud.SResourceBase
  40. OpenStackTags
  41. poolID string
  42. region *SRegion
  43. MonitorPort int `json:"monitor_port"`
  44. ProjectID string `json:"project_id"`
  45. Name string `json:"name"`
  46. Weight int `json:"weight"`
  47. Backup bool `json:"backup"`
  48. AdminStateUp bool `json:"admin_state_up"`
  49. SubnetID string `json:"subnet_id"`
  50. CreatedAt string `json:"created_at"`
  51. ProvisioningStatus string `json:"provisioning_status"`
  52. MonitorAddress string `json:"monitor_address"`
  53. UpdatedAt string `json:"updated_at"`
  54. Address string `json:"address"`
  55. ProtocolPort int `json:"protocol_port"`
  56. ID string `json:"id"`
  57. OperatingStatus string `json:"operating_status"`
  58. Tags []string `json:"tags"`
  59. }
  60. func (member *SLoadbalancerMember) GetName() string {
  61. return member.Name
  62. }
  63. func (member *SLoadbalancerMember) GetId() string {
  64. return member.ID
  65. }
  66. func (member *SLoadbalancerMember) GetGlobalId() string {
  67. return member.GetId()
  68. }
  69. func (member *SLoadbalancerMember) GetStatus() string {
  70. switch member.ProvisioningStatus {
  71. case "ACTIVE":
  72. return api.LB_STATUS_ENABLED
  73. case "PENDING_CREATE":
  74. return api.LB_CREATING
  75. case "PENDING_UPDATE":
  76. return api.LB_SYNC_CONF
  77. case "PENDING_DELETE":
  78. return api.LB_STATUS_DELETING
  79. case "DELETED":
  80. return api.LB_STATUS_DELETED
  81. default:
  82. return api.LB_STATUS_UNKNOWN
  83. }
  84. }
  85. func (member *SLoadbalancerMember) IsEmulated() bool {
  86. return false
  87. }
  88. func (region *SRegion) GetLoadbalancerMenberById(poolId string, MenberId string) (*SLoadbalancerMember, error) {
  89. body, err := region.lbGet(fmt.Sprintf("/v2/lbaas/pools/%s/members/%s", poolId, MenberId))
  90. if err != nil {
  91. return nil, errors.Wrapf(err, "region.Get(/v2/lbaas/pools/%s/members/%s)", poolId, MenberId)
  92. }
  93. member := SLoadbalancerMember{}
  94. member.region = region
  95. member.poolID = poolId
  96. return &member, body.Unmarshal(&member, "member")
  97. }
  98. func (region *SRegion) GetLoadbalancerMenbers(poolId string) ([]SLoadbalancerMember, error) {
  99. members := []SLoadbalancerMember{}
  100. resource := fmt.Sprintf("/v2/lbaas/pools/%s/members", poolId)
  101. query := url.Values{}
  102. for {
  103. resp, err := region.lbList(resource, query)
  104. if err != nil {
  105. return nil, errors.Wrap(err, "lbList")
  106. }
  107. part := struct {
  108. Members []SLoadbalancerMember
  109. MembersLinks SNextLinks
  110. }{}
  111. err = resp.Unmarshal(&part)
  112. if err != nil {
  113. return nil, errors.Wrap(err, "resp.Unmarshal")
  114. }
  115. members = append(members, part.Members...)
  116. marker := part.MembersLinks.GetNextMark()
  117. if len(marker) == 0 {
  118. break
  119. }
  120. query.Set("marker", marker)
  121. }
  122. for i := 0; i < len(members); i++ {
  123. members[i].poolID = poolId
  124. members[i].region = region
  125. }
  126. return members, nil
  127. }
  128. // serverId 转ip,对接不准确
  129. func (region *SRegion) CreateLoadbalancerMember(poolId, serverId string, weight, port int) (*SLoadbalancerMember, error) {
  130. ports, err := region.GetPorts("", serverId)
  131. if len(ports) < 1 {
  132. return nil, errors.Wrap(err, "server have no port")
  133. }
  134. fixedip := SFixedIP{}
  135. for i := 0; i < len(ports); i++ {
  136. if len(ports[i].FixedIps) > 0 {
  137. fixedip = ports[i].FixedIps[0]
  138. break
  139. }
  140. }
  141. if len(fixedip.IpAddress) < 1 || len(fixedip.SubnetID) < 1 {
  142. return nil, errors.Wrap(err, "server have no fixedip")
  143. }
  144. type CreateParams struct {
  145. Member SLoadbalancerMemberCreateParams `json:"member"`
  146. }
  147. memberParams := CreateParams{}
  148. memberParams.Member.AdminStateUp = true
  149. memberParams.Member.Address = fixedip.IpAddress
  150. memberParams.Member.SubnetID = fixedip.SubnetID
  151. memberParams.Member.ProtocolPort = &port
  152. memberParams.Member.Weight = &weight
  153. body, err := region.lbPost(fmt.Sprintf("/v2/lbaas/pools/%s/members", poolId), jsonutils.Marshal(memberParams))
  154. if err != nil {
  155. return nil, errors.Wrapf(err, `region.lbPost(/v2/lbaas/pools/%s/members, jsonutils.Marshal(memberParams))`, poolId)
  156. }
  157. member := SLoadbalancerMember{}
  158. member.region = region
  159. member.poolID = poolId
  160. return &member, body.Unmarshal(&member, "member")
  161. }
  162. func (region *SRegion) DeleteLoadbalancerMember(poolId, memberId string) error {
  163. _, err := region.lbDelete(fmt.Sprintf("/v2/lbaas/pools/%s/members/%s", poolId, memberId))
  164. if err != nil {
  165. return errors.Wrapf(err, "region.lbDelete(fmt.Sprintf(/v2/lbaas/pools/%s/members/%s)", poolId, memberId)
  166. }
  167. return nil
  168. }
  169. func (member *SLoadbalancerMember) Refresh() error {
  170. newMember, err := member.region.GetLoadbalancerMenberById(member.poolID, member.ID)
  171. if err != nil {
  172. return err
  173. }
  174. return jsonutils.Update(member, newMember)
  175. }
  176. func (member *SLoadbalancerMember) GetWeight() int {
  177. return member.Weight
  178. }
  179. func (member *SLoadbalancerMember) GetPort() int {
  180. return member.ProtocolPort
  181. }
  182. func (member *SLoadbalancerMember) GetBackendType() string {
  183. return api.LB_BACKEND_GUEST
  184. }
  185. func (member *SLoadbalancerMember) GetBackendRole() string {
  186. return api.LB_BACKEND_ROLE_DEFAULT
  187. }
  188. // 网络地址映射设备
  189. func (member *SLoadbalancerMember) GetBackendId() string {
  190. ports, err := member.region.GetPorts("", "")
  191. if err != nil {
  192. log.Errorln(errors.Wrap(err, "member.region.GetPorts()"))
  193. }
  194. for i := 0; i < len(ports); i++ {
  195. for j := 0; j < len(ports[i].FixedIps); j++ {
  196. fixedIP := ports[i].FixedIps[j]
  197. if fixedIP.SubnetID == member.SubnetID && fixedIP.IpAddress == member.Address {
  198. return ports[i].DeviceID
  199. }
  200. }
  201. }
  202. return ""
  203. }
  204. func (member *SLoadbalancerMember) GetIpAddress() string {
  205. return ""
  206. }
  207. func (member *SLoadbalancerMember) GetProjectId() string {
  208. return member.ProjectID
  209. }
  210. func (region *SRegion) UpdateLoadBalancerMemberWtight(poolId, memberId string, weight int) error {
  211. params := jsonutils.NewDict()
  212. poolParam := jsonutils.NewDict()
  213. poolParam.Add(jsonutils.NewInt(int64(weight)), "weight")
  214. params.Add(poolParam, "member")
  215. _, err := region.lbUpdate(fmt.Sprintf("/v2/lbaas/pools/%s/members/%s", poolId, memberId), params)
  216. if err != nil {
  217. return errors.Wrapf(err, "region.lbUpdate(fmt.Sprintf(/v2/lbaas/pools/%s/members/%s", poolId, memberId)
  218. }
  219. return nil
  220. }
  221. func (member *SLoadbalancerMember) Update(ctx context.Context, opts *cloudprovider.SLoadbalancerBackend) error {
  222. if opts.Port > 0 {
  223. log.Warningf("Elb backend Update unsupport modify port")
  224. }
  225. // ensure member status
  226. err := waitLbResStatus(member, 10*time.Second, 8*time.Minute)
  227. if err != nil {
  228. return errors.Wrap(err, "waitLbResStatus(member, 10*time.Second, 8*time.Minute)")
  229. }
  230. err = member.region.UpdateLoadBalancerMemberWtight(member.poolID, member.ID, opts.Weight)
  231. if err != nil {
  232. return errors.Wrapf(err, "member.region.UpdateLoadBalancerMemberWtight(%s,%s,%d)", member.poolID, member.ID, opts.Weight)
  233. }
  234. err = waitLbResStatus(member, 10*time.Second, 8*time.Minute)
  235. if err != nil {
  236. return errors.Wrap(err, "waitLbResStatus(member, 10*time.Second, 8*time.Minute)")
  237. }
  238. return nil
  239. }