mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-19 07:37:55 +08:00
462 lines
11 KiB
Go
462 lines
11 KiB
Go
package google
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"strings"
|
||
|
||
"yunion.io/x/jsonutils"
|
||
"yunion.io/x/log"
|
||
"yunion.io/x/pkg/errors"
|
||
"yunion.io/x/pkg/utils"
|
||
|
||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||
)
|
||
|
||
// 全球负载均衡 https://cloud.google.com/compute/docs/reference/rest/v1/globalAddresses/list
|
||
// 区域负载均衡 https://cloud.google.com/compute/docs/reference/rest/v1/addresses
|
||
// https://cloud.google.com/compute/docs/reference/rest/v1/targetHttpProxies/get
|
||
// https://cloud.google.com/compute/docs/reference/rest/v1/targetGrpcProxies/get
|
||
// https://cloud.google.com/compute/docs/reference/rest/v1/targetHttpsProxies/get
|
||
// https://cloud.google.com/compute/docs/reference/rest/v1/targetSslProxies/get
|
||
// https://cloud.google.com/compute/docs/reference/rest/v1/targetTcpProxies/get
|
||
|
||
type SLoadbalancer struct {
|
||
SResourceBase
|
||
region *SRegion
|
||
urlMap *SUrlMap // http & https LB
|
||
backendServices []SBackendServices // tcp & udp LB. 或者 http & https 后端
|
||
instanceGroups []SInstanceGroup
|
||
healthChecks []HealthChecks
|
||
|
||
forwardRules []SForwardingRule // 服务IP地址
|
||
isHttpLb bool // 标记是否为http/https lb
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetStatus() string {
|
||
return api.LB_STATUS_ENABLED
|
||
}
|
||
|
||
func (self *SLoadbalancer) Refresh() error {
|
||
lb, err := self.region.GetLoadbalancer(self.GetGlobalId())
|
||
if err != nil {
|
||
return errors.Wrap(err, "GetLoadbalancer")
|
||
}
|
||
|
||
err = jsonutils.Update(self, &lb)
|
||
if err != nil {
|
||
return errors.Wrap(err, "Refresh.Update")
|
||
}
|
||
|
||
self.healthChecks = nil
|
||
self.instanceGroups = nil
|
||
self.forwardRules = nil
|
||
if self.isHttpLb {
|
||
bss, err := self.GetBackendServices()
|
||
if err != nil {
|
||
return errors.Wrap(err, "GetForwardingRules")
|
||
}
|
||
self.backendServices = bss
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (self *SLoadbalancer) IsEmulated() bool {
|
||
return true
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetSysTags() map[string]string {
|
||
frs, err := self.GetForwardingRules()
|
||
if err != nil {
|
||
return nil
|
||
}
|
||
|
||
ips := []string{}
|
||
for i := range frs {
|
||
if len(frs[i].IPAddress) > 0 {
|
||
ips = append(ips, frs[i].IPAddress)
|
||
}
|
||
}
|
||
data := map[string]string{}
|
||
data["FrontendIPs"] = strings.Join(ips, ",")
|
||
return data
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetTags() (map[string]string, error) {
|
||
return map[string]string{}, nil
|
||
}
|
||
|
||
func (self *SLoadbalancer) SetTags(tags map[string]string, replace bool) error {
|
||
return cloudprovider.ErrNotSupported
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetProjectId() string {
|
||
return self.region.GetProjectId()
|
||
}
|
||
|
||
/*
|
||
对应forwardingRules地址,存在多个前端IP的情况下,只展示按拉丁字母排序最前的一个地址。其他地址需要到详情中查看
|
||
External
|
||
Internal
|
||
InternalManaged
|
||
InternalSelfManaged
|
||
Invalid
|
||
UndefinedLoadBalancingScheme
|
||
*/
|
||
func (self *SLoadbalancer) GetAddress() string {
|
||
frs, err := self.GetForwardingRules()
|
||
if err != nil {
|
||
log.Errorf("GetAddress.GetForwardingRules %s", err)
|
||
}
|
||
|
||
for i := range frs {
|
||
sche := strings.ToLower(frs[i].LoadBalancingScheme)
|
||
if !utils.IsInStringArray(sche, []string{"invalid", "undefinedloadbalancingscheme"}) {
|
||
return frs[i].IPAddress
|
||
}
|
||
}
|
||
|
||
return ""
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetAddressType() string {
|
||
frs, err := self.GetForwardingRules()
|
||
if err != nil {
|
||
return api.LB_ADDR_TYPE_INTRANET
|
||
}
|
||
|
||
for i := range frs {
|
||
sche := strings.ToLower(frs[i].LoadBalancingScheme)
|
||
if !utils.IsInStringArray(sche, []string{"invalid", "undefinedloadbalancingscheme"}) {
|
||
if sche == "external" {
|
||
return api.LB_ADDR_TYPE_INTERNET
|
||
} else {
|
||
return api.LB_ADDR_TYPE_INTRANET
|
||
}
|
||
}
|
||
}
|
||
|
||
return api.LB_ADDR_TYPE_INTERNET
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetNetworkType() string {
|
||
return api.LB_NETWORK_TYPE_VPC
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetNetworkIds() []string {
|
||
igs, err := self.GetInstanceGroups()
|
||
if err != nil {
|
||
log.Errorf("GetInstanceGroups %s", err)
|
||
return nil
|
||
}
|
||
|
||
selfLinks := make([]string, 0)
|
||
networkIds := make([]string, 0)
|
||
for i := range igs {
|
||
if utils.IsInStringArray(igs[i].Subnetwork, selfLinks) {
|
||
selfLinks = append(selfLinks, igs[i].Subnetwork)
|
||
network := SResourceBase{
|
||
Name: "",
|
||
SelfLink: igs[i].Network,
|
||
}
|
||
networkIds = append(networkIds, network.GetGlobalId())
|
||
}
|
||
}
|
||
|
||
return networkIds
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetVpcId() string {
|
||
networkIds := self.GetNetworkIds()
|
||
if len(networkIds) == 0 {
|
||
return ""
|
||
}
|
||
if len(networkIds) >= 1 {
|
||
vpc, err := self.region.GetVpc(networkIds[0])
|
||
if err == nil && vpc != nil {
|
||
return vpc.GetGlobalId()
|
||
}
|
||
}
|
||
return ""
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetZoneId() string {
|
||
igs, err := self.GetInstanceGroups()
|
||
if err != nil {
|
||
log.Errorf("GetInstanceGroups %s", err)
|
||
return ""
|
||
}
|
||
|
||
for i := range igs {
|
||
if len(igs[i].Zone) > 0 {
|
||
zone := SResourceBase{
|
||
Name: "",
|
||
SelfLink: igs[i].Zone,
|
||
}
|
||
|
||
return zone.GetGlobalId()
|
||
}
|
||
}
|
||
|
||
return ""
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetZone1Id() string {
|
||
return ""
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetLoadbalancerSpec() string {
|
||
if self.isHttpLb {
|
||
return "regional_http_lb"
|
||
}
|
||
|
||
return fmt.Sprintf("regional_%s", strings.ToLower(self.backendServices[0].Protocol))
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetChargeType() string {
|
||
return api.LB_CHARGE_TYPE_BY_TRAFFIC
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetEgressMbps() int {
|
||
return 0
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||
frs, err := self.GetForwardingRules()
|
||
if err != nil {
|
||
log.Errorf("GetAddress.GetForwardingRules %s", err)
|
||
}
|
||
|
||
for i := range frs {
|
||
if strings.ToLower(frs[i].LoadBalancingScheme) == "external" {
|
||
eips, err := self.region.GetEips(frs[i].IPAddress, 0, "")
|
||
if err != nil {
|
||
log.Errorf("GetEips %s", err)
|
||
}
|
||
|
||
if len(eips) > 0 {
|
||
return &eips[0], nil
|
||
}
|
||
}
|
||
}
|
||
|
||
return nil, nil
|
||
}
|
||
|
||
func (self *SLoadbalancer) Delete(ctx context.Context) error {
|
||
return cloudprovider.ErrNotImplemented
|
||
}
|
||
|
||
func (self *SLoadbalancer) Start() error {
|
||
return cloudprovider.ErrNotSupported
|
||
}
|
||
|
||
func (self *SLoadbalancer) Stop() error {
|
||
return cloudprovider.ErrNotSupported
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) {
|
||
lbls, err := self.GetLoadbalancerListeners()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetLoadbalancerListeners")
|
||
}
|
||
|
||
ilbls := make([]cloudprovider.ICloudLoadbalancerListener, len(lbls))
|
||
for i := range lbls {
|
||
ilbls[i] = &lbls[i]
|
||
}
|
||
|
||
return ilbls, nil
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||
lbbgs, err := self.GetLoadbalancerBackendGroups()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
|
||
}
|
||
|
||
ilbbgs := make([]cloudprovider.ICloudLoadbalancerBackendGroup, len(lbbgs))
|
||
for i := range lbbgs {
|
||
ilbbgs[i] = &lbbgs[i]
|
||
}
|
||
|
||
return ilbbgs, nil
|
||
}
|
||
|
||
func (self *SLoadbalancer) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||
return nil, cloudprovider.ErrNotSupported
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) {
|
||
lbbgs, err := self.GetLoadbalancerBackendGroups()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
|
||
}
|
||
|
||
for i := range lbbgs {
|
||
if lbbgs[i].GetGlobalId() == groupId {
|
||
return &lbbgs[i], nil
|
||
}
|
||
}
|
||
|
||
return nil, cloudprovider.ErrNotFound
|
||
}
|
||
|
||
func (self *SLoadbalancer) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||
return nil, cloudprovider.ErrNotSupported
|
||
}
|
||
|
||
func (self *SLoadbalancer) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) {
|
||
lbls, err := self.GetLoadbalancerListeners()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetLoadbalancerBackendGroups")
|
||
}
|
||
|
||
for i := range lbls {
|
||
if lbls[i].GetGlobalId() == listenerId {
|
||
return &lbls[i], nil
|
||
}
|
||
}
|
||
|
||
return nil, cloudprovider.ErrNotFound
|
||
}
|
||
|
||
// GET https://compute.googleapis.com/compute/v1/projects/{project}/aggregated/targetHttpProxies 前端监听
|
||
// tcp lb backend type: backend service
|
||
func (self *SRegion) GetRegionalTcpLoadbalancers() ([]SLoadbalancer, error) {
|
||
bss, err := self.GetRegionalBackendServices("protocol eq TCP")
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetRegionalBackendServices")
|
||
}
|
||
|
||
lbs := make([]SLoadbalancer, len(bss))
|
||
for i := range bss {
|
||
lbs[i] = SLoadbalancer{
|
||
region: self,
|
||
SResourceBase: SResourceBase{
|
||
Name: bss[i].Name,
|
||
SelfLink: bss[i].SelfLink,
|
||
},
|
||
urlMap: nil,
|
||
backendServices: []SBackendServices{bss[i]},
|
||
forwardRules: nil,
|
||
}
|
||
}
|
||
|
||
return lbs, nil
|
||
}
|
||
|
||
// udp lb backend type: backend service
|
||
func (self *SRegion) GetRegionalUdpLoadbalancers() ([]SLoadbalancer, error) {
|
||
bss, err := self.GetRegionalBackendServices("protocol eq UDP")
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetRegionalBackendServices")
|
||
}
|
||
|
||
lbs := make([]SLoadbalancer, len(bss))
|
||
for i := range bss {
|
||
lbs[i] = SLoadbalancer{
|
||
region: self,
|
||
SResourceBase: SResourceBase{
|
||
Name: bss[i].Name,
|
||
SelfLink: bss[i].SelfLink,
|
||
},
|
||
urlMap: nil,
|
||
backendServices: []SBackendServices{bss[i]},
|
||
forwardRules: nil,
|
||
}
|
||
}
|
||
|
||
return lbs, nil
|
||
}
|
||
|
||
// http&https lb: urlmaps
|
||
func (self *SRegion) GetRegionalHTTPLoadbalancers() ([]SLoadbalancer, error) {
|
||
ums, err := self.GetRegionalUrlMaps("")
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetRegionalUrlMaps")
|
||
}
|
||
|
||
lbs := make([]SLoadbalancer, len(ums))
|
||
for i := range ums {
|
||
lbs[i] = SLoadbalancer{
|
||
region: self,
|
||
SResourceBase: SResourceBase{
|
||
Name: ums[i].Name,
|
||
SelfLink: ums[i].SelfLink,
|
||
},
|
||
urlMap: &ums[i],
|
||
backendServices: nil,
|
||
forwardRules: nil,
|
||
isHttpLb: true,
|
||
}
|
||
}
|
||
|
||
return lbs, nil
|
||
}
|
||
|
||
func (self *SRegion) GetRegionalLoadbalancers() ([]SLoadbalancer, error) {
|
||
lbs := make([]SLoadbalancer, 0)
|
||
funcs := []func() ([]SLoadbalancer, error){self.GetRegionalHTTPLoadbalancers, self.GetRegionalTcpLoadbalancers, self.GetRegionalUdpLoadbalancers}
|
||
for i := range funcs {
|
||
_lbs, err := funcs[i]()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetRegionalLoadbalancers")
|
||
}
|
||
lbs = append(lbs, _lbs...)
|
||
}
|
||
|
||
return lbs, nil
|
||
}
|
||
|
||
func (self *SRegion) GetLoadbalancer(resourceId string) (SLoadbalancer, error) {
|
||
lb := SLoadbalancer{}
|
||
var err error
|
||
if strings.Contains(resourceId, "/urlMaps/") {
|
||
ret := SUrlMap{}
|
||
err = self.GetBySelfId(resourceId, &ret)
|
||
lb.isHttpLb = true
|
||
lb.urlMap = &ret
|
||
lb.SResourceBase = SResourceBase{
|
||
Name: ret.Name,
|
||
SelfLink: ret.SelfLink,
|
||
}
|
||
} else {
|
||
ret := SBackendServices{}
|
||
err = self.GetBySelfId(resourceId, &ret)
|
||
lb.backendServices = []SBackendServices{ret}
|
||
lb.SResourceBase = SResourceBase{
|
||
Name: ret.Name,
|
||
SelfLink: ret.SelfLink,
|
||
}
|
||
}
|
||
|
||
if err != nil {
|
||
return lb, errors.Wrapf(err, "get")
|
||
}
|
||
|
||
lb.region = self
|
||
return lb, nil
|
||
}
|
||
|
||
func (self *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) {
|
||
lbs, err := self.GetRegionalLoadbalancers()
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetRegionalLoadbalancers")
|
||
}
|
||
ilbs := []cloudprovider.ICloudLoadbalancer{}
|
||
for i := range lbs {
|
||
ilbs = append(ilbs, &lbs[i])
|
||
}
|
||
return ilbs, nil
|
||
}
|
||
|
||
func (self *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) {
|
||
lb, err := self.GetLoadbalancer(loadbalancerId)
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetLoadbalancer")
|
||
}
|
||
return &lb, nil
|
||
}
|