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