yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/loadbalancer_backend.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 qcloud 16 17 import ( 18 "context" 19 "fmt" 20 21 "yunion.io/x/jsonutils" 22 23 api "yunion.io/x/cloudmux/pkg/apis/compute" 24 "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 "yunion.io/x/cloudmux/pkg/multicloud" 27 ) 28 29 type SLBBackend struct { 30 multicloud.SResourceBase 31 QcloudTags 32 group *SLBBackendGroup 33 34 PublicIPAddresses []string `json:"PublicIpAddresses"` 35 Weight int `json:"Weight"` 36 InstanceID string `json:"InstanceId"` 37 InstanceName string `json:"InstanceName"` 38 PrivateIPAddresses []string `json:"PrivateIpAddresses"` 39 RegisteredTime string `json:"RegisteredTime"` 40 Type string `json:"Type"` 41 Port int `json:"Port"` 42 } 43 44 // ========================================================== 45 type SListenerBackend struct { 46 Rules []rule `json:"Rules"` 47 Targets []SLBBackend `json:"Targets"` 48 Protocol string `json:"Protocol"` 49 ListenerID string `json:"ListenerId"` 50 Port int64 `json:"Port"` 51 } 52 53 type rule struct { 54 URL string `json:"Url"` 55 Domain string `json:"Domain"` 56 LocationID string `json:"LocationId"` 57 Targets []SLBBackend `json:"Targets"` 58 } 59 60 // ========================================================== 61 62 // backend InstanceID + protocol +Port + ip + rip全局唯一 63 func (self *SLBBackend) GetId() string { 64 return fmt.Sprintf("%s/%s-%d", self.group.GetId(), self.InstanceID, self.Port) 65 } 66 67 func (self *SLBBackend) GetName() string { 68 return self.GetId() 69 } 70 71 func (self *SLBBackend) GetGlobalId() string { 72 return self.GetId() 73 } 74 75 func (self *SLBBackend) GetStatus() string { 76 return api.LB_STATUS_ENABLED 77 } 78 79 func (self *SLBBackend) Refresh() error { 80 backends, err := self.group.GetBackends() 81 if err != nil { 82 return err 83 } 84 85 for _, backend := range backends { 86 if backend.GetId() == self.GetId() { 87 return jsonutils.Update(self, backend) 88 } 89 } 90 91 return cloudprovider.ErrNotFound 92 } 93 94 func (self *SLBBackend) IsEmulated() bool { 95 return false 96 } 97 98 func (self *SLBBackend) GetWeight() int { 99 return self.Weight 100 } 101 102 func (self *SLBBackend) GetPort() int { 103 return self.Port 104 } 105 106 func (self *SLBBackend) GetBackendType() string { 107 return api.LB_BACKEND_GUEST 108 } 109 110 func (self *SLBBackend) GetBackendRole() string { 111 return api.LB_BACKEND_ROLE_DEFAULT 112 } 113 114 func (self *SLBBackend) GetBackendId() string { 115 return self.InstanceID 116 } 117 118 func (self *SLBBackend) GetIpAddress() string { 119 return "" 120 } 121 122 // 传统型: https://cloud.tencent.com/document/product/214/31790 123 func (self *SRegion) getClassicBackends(lbId, listenerId string) ([]SLBBackend, error) { 124 params := map[string]string{"LoadBalancerId": lbId} 125 126 resp, err := self.clbRequest("DescribeClassicalLBTargets", params) 127 if err != nil { 128 return nil, err 129 } 130 131 backends := []SLBBackend{} 132 err = resp.Unmarshal(&backends, "Targets") 133 if err != nil { 134 return nil, err 135 } 136 return backends, nil 137 } 138 139 // 应用型: https://cloud.tencent.com/document/product/214/30684 140 func (self *SRegion) getBackends(lbId, listenerId, ruleId string) ([]SLBBackend, error) { 141 params := map[string]string{"LoadBalancerId": lbId} 142 143 if len(listenerId) > 0 { 144 params["ListenerIds.0"] = listenerId 145 } 146 147 resp, err := self.clbRequest("DescribeTargets", params) 148 if err != nil { 149 return nil, err 150 } 151 152 lbackends := []SListenerBackend{} 153 err = resp.Unmarshal(&lbackends, "Listeners") 154 if err != nil { 155 return nil, err 156 } 157 158 for _, entry := range lbackends { 159 if (entry.Protocol == "HTTP" || entry.Protocol == "HTTPS") && len(ruleId) == 0 { 160 return nil, fmt.Errorf("GetBackends for http/https listener %s must specific rule id", listenerId) 161 } 162 163 if len(ruleId) > 0 { 164 for _, r := range entry.Rules { 165 if r.LocationID == ruleId { 166 return r.Targets, nil 167 } 168 } 169 } else { 170 return entry.Targets, nil 171 } 172 } 173 174 // todo: 这里是返回空列表还是404? 175 return []SLBBackend{}, nil 176 } 177 178 // 注意http、https监听器必须指定ruleId 179 func (self *SRegion) GetLBBackends(t LB_TYPE, lbId, listenerId, ruleId string) ([]SLBBackend, error) { 180 if len(lbId) == 0 { 181 return nil, fmt.Errorf("GetLBBackends loadbalancer id should not be empty") 182 } 183 184 if t == LB_TYPE_APPLICATION { 185 return self.getBackends(lbId, listenerId, ruleId) 186 } else if t == LB_TYPE_CLASSIC { 187 return self.getClassicBackends(lbId, listenerId) 188 } else { 189 return nil, fmt.Errorf("GetLBBackends unsupported loadbalancer type %d", t) 190 } 191 } 192 193 func (self *SLBBackend) GetProjectId() string { 194 return self.group.GetProjectId() 195 } 196 197 func (self *SLBBackend) SyncConf(ctx context.Context, port, weight int) error { 198 lockman.LockRawObject(ctx, "qcloud.SLBBackend.SyncConf", self.group.lb.region.client.ownerId) 199 defer lockman.ReleaseRawObject(ctx, "qcloud.SLBBackend.SyncConf", self.group.lb.region.client.ownerId) 200 201 err := self.group.UpdateBackendServer(self.InstanceID, self.Weight, self.Port, weight, port) 202 if err != nil { 203 return err 204 } 205 206 self.Port = port 207 self.Weight = weight 208 return nil 209 }