diff --git a/pkg/apis/compute/loadbalancerbackendgroup.go b/pkg/apis/compute/loadbalancerbackendgroup.go index 6969cdecf7..3d0665ad5f 100644 --- a/pkg/apis/compute/loadbalancerbackendgroup.go +++ b/pkg/apis/compute/loadbalancerbackendgroup.go @@ -21,6 +21,8 @@ type LoadbalancerBackendGroupDetails struct { LoadbalancerResourceInfo SLoadbalancerBackendGroup + + LbListenerCount int `json:"lb_listener_count"` } type LoadbalancerBackendGroupResourceInfo struct { diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 83839050c0..0584fe0969 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -639,6 +639,31 @@ type ICloudLoadbalancer interface { GetILoadBalancerListenerById(listenerId string) (ICloudLoadbalancerListener, error) } +type ICloudLoadbalancerRedirect interface { + GetRedirect() string + GetRedirectCode() int64 + GetRedirectScheme() string + GetRedirectHost() string + GetRedirectPath() string +} + +type ICloudloadbalancerHealthCheck interface { + GetHealthCheck() string + GetHealthCheckType() string + GetHealthCheckTimeout() int + GetHealthCheckInterval() int + GetHealthCheckRise() int + GetHealthCheckFail() int + + GetHealthCheckReq() string + GetHealthCheckExp() string + + // HTTP && HTTPS + GetHealthCheckDomain() string + GetHealthCheckURI() string + GetHealthCheckCode() string +} + type ICloudLoadbalancerListener interface { IVirtualResource @@ -650,24 +675,13 @@ type ICloudLoadbalancerListener interface { GetAclId() string GetEgressMbps() int - - GetHealthCheck() string - GetHealthCheckType() string - GetHealthCheckTimeout() int - GetHealthCheckInterval() int - GetHealthCheckRise() int - GetHealthCheckFail() int - - GetHealthCheckReq() string - GetHealthCheckExp() string - GetBackendGroupId() string GetBackendServerPort() int + GetClientIdleTimeout() int + GetBackendConnectTimeout() int + // HTTP && HTTPS - GetHealthCheckDomain() string - GetHealthCheckURI() string - GetHealthCheckCode() string CreateILoadBalancerListenerRule(rule *SLoadbalancerListenerRule) (ICloudLoadbalancerListenerRule, error) GetILoadBalancerListenerRuleById(ruleId string) (ICloudLoadbalancerListenerRule, error) GetILoadbalancerListenerRules() ([]ICloudLoadbalancerListenerRule, error) @@ -683,6 +697,10 @@ type ICloudLoadbalancerListener interface { GetTLSCipherPolicy() string HTTP2Enabled() bool + // http redirect + ICloudLoadbalancerRedirect + ICloudloadbalancerHealthCheck + Start() error Stop() error Sync(ctx context.Context, listener *SLoadbalancerListener) error @@ -692,6 +710,8 @@ type ICloudLoadbalancerListener interface { type ICloudLoadbalancerListenerRule interface { IVirtualResource + // http redirect + ICloudLoadbalancerRedirect IsDefault() bool GetDomain() string diff --git a/pkg/compute/models/loadbalancerbackendgroups.go b/pkg/compute/models/loadbalancerbackendgroups.go index 5337d67751..b63237b4e0 100644 --- a/pkg/compute/models/loadbalancerbackendgroups.go +++ b/pkg/compute/models/loadbalancerbackendgroups.go @@ -30,6 +30,7 @@ import ( "yunion.io/x/onecloud/pkg/cloudcommon/db" "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman" "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman" + "yunion.io/x/onecloud/pkg/cloudcommon/policy" "yunion.io/x/onecloud/pkg/cloudcommon/validators" "yunion.io/x/onecloud/pkg/cloudprovider" "yunion.io/x/onecloud/pkg/httperrors" @@ -492,6 +493,23 @@ func (man *SLoadbalancerBackendGroupManager) FetchCustomizeColumns( } } + for i := range objs { + q := LoadbalancerListenerManager.Query().IsFalse("pending_deleted").Equals("backend_group_id", objs[i].(*SLoadbalancerBackendGroup).GetId()) + ownerId, queryScope, err := db.FetchCheckQueryOwnerScope(ctx, userCred, query, LoadbalancerListenerManager, policy.PolicyActionList, true) + if err != nil { + log.Errorf("FetchCheckQueryOwnerScope error: %v", err) + return rows + } + + q = LoadbalancerListenerManager.FilterByOwner(q, ownerId, queryScope) + count, err := q.CountWithError() + if err != nil { + log.Errorf("db.CountWithError error: %v", err) + } + + rows[i].LbListenerCount = count + } + return rows } diff --git a/pkg/compute/models/loadbalancerlistenerrules.go b/pkg/compute/models/loadbalancerlistenerrules.go index 008f033c44..3a588792d6 100644 --- a/pkg/compute/models/loadbalancerlistenerrules.go +++ b/pkg/compute/models/loadbalancerlistenerrules.go @@ -23,6 +23,7 @@ import ( "yunion.io/x/log" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/util/compare" + "yunion.io/x/pkg/utils" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/apis" @@ -738,6 +739,15 @@ func (lbr *SLoadbalancerListenerRule) constructFieldsFromCloudListenerRule(userC lbr.Path = extRule.GetPath() lbr.Status = extRule.GetStatus() lbr.Condition = extRule.GetCondition() + + if utils.IsInStringArray(extRule.GetRedirect(), []string{api.LB_REDIRECT_OFF, api.LB_REDIRECT_RAW}) { + lbr.Redirect = extRule.GetRedirect() + lbr.RedirectCode = int(extRule.GetRedirectCode()) + lbr.RedirectScheme = extRule.GetRedirectScheme() + lbr.RedirectHost = extRule.GetRedirectHost() + lbr.RedirectPath = extRule.GetRedirectPath() + } + if groupId := extRule.GetBackendGroupId(); len(groupId) > 0 { if lbr.GetProviderName() == api.CLOUD_PROVIDER_HUAWEI { group, err := db.FetchByExternalId(HuaweiCachedLbbgManager, groupId) diff --git a/pkg/compute/models/loadbalancerlisteners.go b/pkg/compute/models/loadbalancerlisteners.go index 8ca09479c2..bef2f76c9e 100644 --- a/pkg/compute/models/loadbalancerlisteners.go +++ b/pkg/compute/models/loadbalancerlisteners.go @@ -1004,9 +1004,23 @@ func (lblis *SLoadbalancerListener) constructFieldsFromCloudListener(userCred mc lblis.HealthCheckInterval = extListener.GetHealthCheckInterval() lblis.HealthCheckRise = extListener.GetHealthCheckRise() lblis.HealthCheckFall = extListener.GetHealthCheckFail() + lblis.HealthCheckDomain = extListener.GetHealthCheckDomain() + lblis.HealthCheckURI = extListener.GetHealthCheckURI() + lblis.HealthCheckExp = extListener.GetHealthCheckExp() + lblis.HealthCheckHttpCode = extListener.GetHealthCheckCode() } } + if utils.IsInStringArray(extListener.GetRedirect(), []string{api.LB_REDIRECT_OFF, api.LB_REDIRECT_RAW}) { + lblis.Redirect = extListener.GetRedirect() + lblis.RedirectCode = int(extListener.GetRedirectCode()) + lblis.RedirectScheme = extListener.GetRedirectScheme() + lblis.RedirectHost = extListener.GetRedirectHost() + lblis.RedirectPath = extListener.GetRedirectPath() + } + + lblis.ClientIdleTimeout = extListener.GetClientIdleTimeout() + lblis.BackendConnectTimeout = extListener.GetBackendConnectTimeout() lblis.BackendServerPort = extListener.GetBackendServerPort() switch lblis.ListenerType { @@ -1040,6 +1054,7 @@ func (lblis *SLoadbalancerListener) constructFieldsFromCloudListener(userCred mc lblis.StickySessionCookieTimeout = extListener.GetStickySessionCookieTimeout() } } + lblis.EnableHttp2 = extListener.HTTP2Enabled() lblis.XForwardedFor = extListener.XForwardedForEnabled() lblis.Gzip = extListener.GzipEnabled() } diff --git a/pkg/multicloud/aliyun/loadbalancerhttplistener.go b/pkg/multicloud/aliyun/loadbalancerhttplistener.go index 82b0a519dc..4af50ded42 100644 --- a/pkg/multicloud/aliyun/loadbalancerhttplistener.go +++ b/pkg/multicloud/aliyun/loadbalancerhttplistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerHTTPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AliyunTags lb *SLoadbalancer @@ -368,3 +369,11 @@ func (listerner *SLoadbalancerHTTPListener) Sync(ctx context.Context, lblis *clo func (listerner *SLoadbalancerHTTPListener) GetProjectId() string { return listerner.lb.GetProjectId() } + +func (listerner *SLoadbalancerHTTPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerHTTPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/aliyun/loadbalancerhttpslistener.go b/pkg/multicloud/aliyun/loadbalancerhttpslistener.go index 92c18814ba..154dcaf184 100644 --- a/pkg/multicloud/aliyun/loadbalancerhttpslistener.go +++ b/pkg/multicloud/aliyun/loadbalancerhttpslistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerHTTPSListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AliyunTags lb *SLoadbalancer @@ -398,3 +399,11 @@ func (listerner *SLoadbalancerHTTPSListener) Sync(ctx context.Context, lblis *cl func (listerner *SLoadbalancerHTTPSListener) GetProjectId() string { return listerner.lb.GetProjectId() } + +func (listerner *SLoadbalancerHTTPSListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerHTTPSListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/aliyun/loadbalancerlistenerrule.go b/pkg/multicloud/aliyun/loadbalancerlistenerrule.go index d86e218bc4..0972599cbc 100644 --- a/pkg/multicloud/aliyun/loadbalancerlistenerrule.go +++ b/pkg/multicloud/aliyun/loadbalancerlistenerrule.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerListenerRule struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AliyunTags httpListener *SLoadbalancerHTTPListener httpsListener *SLoadbalancerHTTPSListener diff --git a/pkg/multicloud/aliyun/loadbalancertcplistener.go b/pkg/multicloud/aliyun/loadbalancertcplistener.go index 86cefd38eb..a3da489a56 100644 --- a/pkg/multicloud/aliyun/loadbalancertcplistener.go +++ b/pkg/multicloud/aliyun/loadbalancertcplistener.go @@ -28,6 +28,7 @@ import ( type SLoadbalancerTCPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AliyunTags lb *SLoadbalancer @@ -357,3 +358,11 @@ func (listerner *SLoadbalancerTCPListener) Sync(ctx context.Context, lblis *clou func (listerner *SLoadbalancerTCPListener) GetProjectId() string { return listerner.lb.GetProjectId() } + +func (listerner *SLoadbalancerTCPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerTCPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/aliyun/loadbalancerudplistener.go b/pkg/multicloud/aliyun/loadbalancerudplistener.go index ea719623c6..1f1141d201 100644 --- a/pkg/multicloud/aliyun/loadbalancerudplistener.go +++ b/pkg/multicloud/aliyun/loadbalancerudplistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerUDPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AliyunTags lb *SLoadbalancer @@ -283,3 +284,11 @@ func (listerner *SLoadbalancerUDPListener) Sync(ctx context.Context, lblis *clou func (listerner *SLoadbalancerUDPListener) GetProjectId() string { return listerner.lb.GetProjectId() } + +func (listerner *SLoadbalancerUDPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerUDPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/apsara/loadbalancerhttplistener.go b/pkg/multicloud/apsara/loadbalancerhttplistener.go index 2e0319a6da..328d2af93e 100644 --- a/pkg/multicloud/apsara/loadbalancerhttplistener.go +++ b/pkg/multicloud/apsara/loadbalancerhttplistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerHTTPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.ApsaraTags lb *SLoadbalancer @@ -368,3 +369,11 @@ func (listerner *SLoadbalancerHTTPListener) Sync(ctx context.Context, lblis *clo func (listerner *SLoadbalancerHTTPListener) GetProjectId() string { return "" } + +func (listerner *SLoadbalancerHTTPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerHTTPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/apsara/loadbalancerhttpslistener.go b/pkg/multicloud/apsara/loadbalancerhttpslistener.go index f44690a4c2..a68cbe43a3 100644 --- a/pkg/multicloud/apsara/loadbalancerhttpslistener.go +++ b/pkg/multicloud/apsara/loadbalancerhttpslistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerHTTPSListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.ApsaraTags lb *SLoadbalancer @@ -398,3 +399,11 @@ func (listerner *SLoadbalancerHTTPSListener) Sync(ctx context.Context, lblis *cl func (listerner *SLoadbalancerHTTPSListener) GetProjectId() string { return "" } + +func (listerner *SLoadbalancerHTTPSListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerHTTPSListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/apsara/loadbalancerlistenerrule.go b/pkg/multicloud/apsara/loadbalancerlistenerrule.go index 92efee1acf..3599376aec 100644 --- a/pkg/multicloud/apsara/loadbalancerlistenerrule.go +++ b/pkg/multicloud/apsara/loadbalancerlistenerrule.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerListenerRule struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.ApsaraTags httpListener *SLoadbalancerHTTPListener httpsListener *SLoadbalancerHTTPSListener diff --git a/pkg/multicloud/apsara/loadbalancertcplistener.go b/pkg/multicloud/apsara/loadbalancertcplistener.go index 34dae43972..50a8b1397d 100644 --- a/pkg/multicloud/apsara/loadbalancertcplistener.go +++ b/pkg/multicloud/apsara/loadbalancertcplistener.go @@ -28,6 +28,7 @@ import ( type SLoadbalancerTCPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.ApsaraTags lb *SLoadbalancer @@ -357,3 +358,11 @@ func (listerner *SLoadbalancerTCPListener) Sync(ctx context.Context, lblis *clou func (listerner *SLoadbalancerTCPListener) GetProjectId() string { return "" } + +func (listerner *SLoadbalancerTCPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerTCPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/apsara/loadbalancerudplistener.go b/pkg/multicloud/apsara/loadbalancerudplistener.go index c254e7d96d..7931d16fa0 100644 --- a/pkg/multicloud/apsara/loadbalancerudplistener.go +++ b/pkg/multicloud/apsara/loadbalancerudplistener.go @@ -27,6 +27,7 @@ import ( type SLoadbalancerUDPListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.ApsaraTags lb *SLoadbalancer @@ -283,3 +284,11 @@ func (listerner *SLoadbalancerUDPListener) Sync(ctx context.Context, lblis *clou func (listerner *SLoadbalancerUDPListener) GetProjectId() string { return "" } + +func (listerner *SLoadbalancerUDPListener) GetClientIdleTimeout() int { + return 0 +} + +func (listerner *SLoadbalancerUDPListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/aws/loadbalancerlistener.go b/pkg/multicloud/aws/loadbalancerlistener.go index 1148c1193f..e1867c3a75 100644 --- a/pkg/multicloud/aws/loadbalancerlistener.go +++ b/pkg/multicloud/aws/loadbalancerlistener.go @@ -35,6 +35,7 @@ import ( type SElbListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AwsTags region *SRegion lb *SElb @@ -442,6 +443,14 @@ func (self *SElbListener) HTTP2Enabled() bool { return false } +func (self *SElbListener) GetClientIdleTimeout() int { + return 0 +} + +func (self *SElbListener) GetBackendConnectTimeout() int { + return 0 +} + func (self *SElbListener) Start() error { return nil } diff --git a/pkg/multicloud/aws/loadbalancerlistenerrule.go b/pkg/multicloud/aws/loadbalancerlistenerrule.go index 4fbcd5761e..07cbac226e 100644 --- a/pkg/multicloud/aws/loadbalancerlistenerrule.go +++ b/pkg/multicloud/aws/loadbalancerlistenerrule.go @@ -33,6 +33,7 @@ import ( type SElbListenerRule struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.AwsTags listener *SElbListener region *SRegion diff --git a/pkg/multicloud/azure/azure.go b/pkg/multicloud/azure/azure.go index da91a561b7..2fa35491f7 100644 --- a/pkg/multicloud/azure/azure.go +++ b/pkg/multicloud/azure/azure.go @@ -965,7 +965,7 @@ func (self *SAzureClient) GetCapabilities() []string { cloudprovider.CLOUD_CAPABILITY_PROJECT, cloudprovider.CLOUD_CAPABILITY_COMPUTE, cloudprovider.CLOUD_CAPABILITY_NETWORK, - // cloudprovider.CLOUD_CAPABILITY_LOADBALANCER, + cloudprovider.CLOUD_CAPABILITY_LOADBALANCER, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE, cloudprovider.CLOUD_CAPABILITY_RDS, cloudprovider.CLOUD_CAPABILITY_CACHE, diff --git a/pkg/multicloud/azure/loadbalancer.go b/pkg/multicloud/azure/loadbalancer.go new file mode 100644 index 0000000000..d699f7420b --- /dev/null +++ b/pkg/multicloud/azure/loadbalancer.go @@ -0,0 +1,665 @@ +package azure + +import ( + "context" + "strings" + + "github.com/pkg/errors" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/pkg/utils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" +) + +type SLoadbalancer struct { + region *SRegion + lbbgs []cloudprovider.ICloudLoadbalancerBackendGroup + listeners []cloudprovider.ICloudLoadbalancerListener + + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Tags map[string]string `json:"tags"` + Location string `json:"location"` + Properties SLoadbalancerProperties `json:"properties"` + Sku Sku `json:"sku"` +} + +func (self *SLoadbalancer) GetId() string { + return self.ID +} + +func (self *SLoadbalancer) GetName() string { + return self.Name +} + +func (self *SLoadbalancer) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadbalancer) GetStatus() string { + switch self.Properties.ProvisioningState { + case "Deleting": + return api.LB_STATUS_DELETING + case "Failed": + return api.LB_STATUS_START_FAILED + case "Updating": + return api.LB_SYNC_CONF + } + + switch self.Properties.OperationalState { + case "Running": + return api.LB_STATUS_ENABLED + case "Stopped": + return api.LB_STATUS_DISABLED + case "Starting", "Stopping": + return api.LB_SYNC_CONF + default: + if self.Properties.ProvisioningState == "Succeeded" { + return api.LB_STATUS_ENABLED + } + + return api.LB_STATUS_UNKNOWN + } +} + +func (self *SLoadbalancer) Refresh() error { + lb, err := self.region.GetILoadBalancerById(self.GetId()) + if err != nil { + return errors.Wrap(err, "GetILoadBalancerById.Refresh") + } + + err = jsonutils.Update(self, lb) + if err != nil { + return errors.Wrap(err, "jsonutils.Update") + } + + self.lbbgs = nil + self.listeners = nil + return nil +} + +func (self *SLoadbalancer) IsEmulated() bool { + return false +} + +func (self *SLoadbalancer) GetSysTags() map[string]string { + data := map[string]string{} + data["loadbalance_type"] = self.Type + data["properties"] = jsonutils.Marshal(self.Properties).String() + return data +} + +func (self *SLoadbalancer) GetTags() (map[string]string, error) { + return self.Tags, nil +} + +func (self *SLoadbalancer) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadbalancer) GetProjectId() string { + return getResourceGroup(self.ID) +} + +func (self *SLoadbalancer) getAddresses() [][]string { + ret := [][]string{[]string{}, []string{}} + for _, fip := range self.Properties.FrontendIPConfigurations { + eip := fip.Properties.PublicIPAddress + if eip != nil && len(eip.Properties.IPAddress) > 0 { + ret[0] = append(ret[0], fip.Properties.PublicIPAddress.Properties.IPAddress) + continue + } + + if len(fip.Properties.PrivateIPAddress) > 0 { + ret[1] = append(ret[1], fip.Properties.PrivateIPAddress) + continue + } + } + + return ret +} + +func (self *SLoadbalancer) GetAddress() string { + ips := self.getAddresses() + if len(ips[0]) > 0 { + return ips[0][0] + } else if len(ips[1]) > 0 { + return ips[1][0] + } else { + return "" + } +} + +func (self *SLoadbalancer) GetAddressType() string { + ips := self.getAddresses() + if len(ips[0]) > 0 { + return api.LB_ADDR_TYPE_INTERNET + } else if len(ips[1]) > 0 { + return api.LB_ADDR_TYPE_INTRANET + } else { + return api.LB_ADDR_TYPE_INTRANET + } +} + +func (self *SLoadbalancer) GetNetworkType() string { + return api.LB_NETWORK_TYPE_VPC +} + +func (self *SLoadbalancer) getNetworkIds() []string { + ret := []string{} + for _, fip := range self.Properties.FrontendIPConfigurations { + subnet := fip.Properties.Subnet + if len(subnet.ID) > 0 { + ret = append(ret, subnet.ID) + } + } + + return ret +} + +func (self *SLoadbalancer) getLbbgNetworkIds() []string { + ret := []string{} + for _, b := range self.Properties.BackendAddressPools { + bips := b.Properties.BackendIPConfigurations + if len(bips) > 0 { + for _, ip := range bips { + if strings.Contains(ip.ID, "Microsoft.Network/networkInterfaces") { + nic, _ := self.region.GetNetworkInterface(strings.Split(ip.ID, "/ipConfigurations")[0]) + if nic != nil && len(nic.Properties.IPConfigurations) > 0 { + ipc := nic.Properties.IPConfigurations[0] + if len(ipc.Properties.Subnet.ID) > 0 { + return []string{ipc.Properties.Subnet.ID} + } + } + } + } + } + } + + return ret +} + +func (self *SLoadbalancer) GetNetworkIds() []string { + return self.getNetworkIds() +} + +func (self *SLoadbalancer) GetVpcId() string { + if self.Type == "Microsoft.Network/loadBalancers" { + subnets := self.GetNetworkIds() + if len(subnets) == 0 { + subnets = self.getLbbgNetworkIds() + } + + if len(subnets) > 0 { + network, err := self.region.GetNetwork(subnets[0]) + if network != nil { + return strings.Split(network.GetId(), "/subnets")[0] + } + + log.Errorf("GetNetwork %s: %s", subnets[0], err) + } + } else { + gips := self.Properties.GatewayIPConfigurations + for i := range gips { + netId := gips[i].Properties.Subnet.ID + if len(netId) > 0 { + network, err := self.region.GetNetwork(netId) + if network != nil { + return strings.Split(network.GetId(), "/subnets")[0] + } + log.Errorf("GetNetwork %s: %s", netId, err) + } + } + } + + return "" +} + +func (self *SLoadbalancer) GetZoneId() string { + ips := self.Properties.FrontendIPConfigurations + if len(ips) > 0 && len(ips[0].Zones) > 0 { + return ips[0].Zones[0] + } + + return "" +} + +func (self *SLoadbalancer) GetZone1Id() string { + ips := self.Properties.FrontendIPConfigurations + if len(ips) > 0 && len(ips[0].Zones) > 1 { + return ips[0].Zones[1] + } + + return "" +} + +func (self *SLoadbalancer) GetLoadbalancerSpec() string { + if len(self.Properties.Sku.Name) > 0 { + return self.Properties.Sku.Name + } + + if len(self.Sku.Name) > 0 { + return self.Sku.Name + } + return "" +} + +func (self *SLoadbalancer) GetChargeType() string { + return api.LB_CHARGE_TYPE_POSTPAID +} + +func (self *SLoadbalancer) GetEgressMbps() int { + return 0 +} + +func (self *SLoadbalancer) getEipIds() []string { + ret := []string{} + for _, fip := range self.Properties.FrontendIPConfigurations { + eip := fip.Properties.PublicIPAddress + if eip != nil && len(eip.ID) > 0 { + ret = append(ret, eip.ID) + continue + } + } + + return ret +} + +func (self *SLoadbalancer) GetIEIP() (cloudprovider.ICloudEIP, error) { + eips := self.getEipIds() + if len(eips) > 0 { + return self.region.GetIEipById(eips[0]) + } + + return nil, nil +} + +func (self *SLoadbalancer) Delete(ctx context.Context) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete") +} + +func (self *SLoadbalancer) Start() error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Start") +} + +func (self *SLoadbalancer) Stop() error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Stop") +} + +/* +应用型LB: urlPathMaps(defaultBackendAddressPool+defaultBackendHttpSettings+requestRoutingRules+httpListeners)= Onecloud监听器 +4层LB: loadBalancingRules(前端) = Onecloud监听器 +*/ +func (self *SLoadbalancer) GetILoadBalancerListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { + if self.listeners != nil { + return self.listeners, nil + } + + var err error + if self.Type == "Microsoft.Network/applicationGateways" { + self.listeners, err = self.getAppLBListeners() + } else { + self.listeners, err = self.getNetworkLBListeners() + } + + return self.listeners, err +} + +func (self *SLoadbalancer) getFrontendIPConfiguration(id string) *FrontendIPConfiguration { + fips := self.Properties.FrontendIPConfigurations + for i := range fips { + if fips[i].ID == id { + return &fips[i] + } + } + log.Debugf("getFrontendIPConfiguration %s not found", id) + return nil +} + +func (self *SLoadbalancer) getHttpListener(id string) *HTTPListener { + ss := self.Properties.HTTPListeners + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + + for j := range ss[i].Properties.RequestRoutingRules { + if ss[i].Properties.RequestRoutingRules[j].ID == id { + return &ss[i] + } + } + } + log.Debugf("getHttpListener %s not found", id) + return nil +} + +func (self *SLoadbalancer) getBackendAddressPool(id string) *BackendAddressPool { + ss := self.Properties.BackendAddressPools + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getBackendAddressPool %s not found", id) + return nil +} + +func (self *SLoadbalancer) getBackendHTTPSettingsCollection(id string) *BackendHTTPSettingsCollection { + ss := self.Properties.BackendHTTPSettingsCollection + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getBackendHTTPSettingsCollection %s not found", id) + return nil +} + +func (self *SLoadbalancer) getRedirectConfiguration(id string) *RedirectConfiguration { + ss := self.Properties.RedirectConfigurations + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getRedirectConfiguration %s not found", id) + return nil +} + +func (self *SLoadbalancer) getProbe(id string) *Probe { + ss := self.Properties.Probes + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getProbe %s not found", id) + return nil +} + +func (self *SLoadbalancer) getFrontendPort(id string) *FrontendPort { + ss := self.Properties.FrontendPorts + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getFrontendPort %s not found", id) + return nil +} + +func (self *SLoadbalancer) getRequestRoutingRule(id string) *RequestRoutingRule { + ss := self.Properties.RequestRoutingRules + for i := range ss { + if ss[i].ID == id { + return &ss[i] + } + } + log.Debugf("getRequestRoutingRule %s not found", id) + return nil +} + +/* +应用型LB: urlPathMaps(defaultBackendAddressPool+defaultBackendHttpSettings+requestRoutingRules+httpListeners)= Onecloud监听器 +*/ +func (self *SLoadbalancer) getAppLBListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { + lbls := []cloudprovider.ICloudLoadbalancerListener{} + for i := range self.Properties.URLPathMaps { + u := self.Properties.URLPathMaps[i] + lbl := self.getAppLBListener(&u) + if lbl != nil { + lbls = append(lbls, lbl) + } + } + + return lbls, nil +} + +func (self *SLoadbalancer) getAppLBListener(u *URLPathMap) *SLoadBalancerListener { + var redirect *RedirectConfiguration + var listener *HTTPListener + var fp *FrontendIPConfiguration + var fpp *FrontendPort + if len(u.Properties.RequestRoutingRules) == 0 { + return nil + } + + if u.Properties.DefaultRedirectConfiguration != nil { + redirect = self.getRedirectConfiguration(u.Properties.DefaultRedirectConfiguration.ID) + } + + // httpListener, urlPathMap + rrr := self.getRequestRoutingRule(u.Properties.RequestRoutingRules[0].ID) + // frontendPort, frontendIPConfiguration, sslCertificate, requestRoutingRules + listener = self.getHttpListener(rrr.Properties.HTTPListener.ID) + // frontendPorts + fp = self.getFrontendIPConfiguration(listener.Properties.FrontendIPConfiguration.ID) + fpp = self.getFrontendPort(listener.Properties.FrontendPort.ID) + + // 配置有异常?? + if fpp == nil || listener == nil { + return nil + } + + var backendGroup *BackendAddressPool + if u.Properties.DefaultBackendAddressPool != nil { + backendGroup = self.getBackendAddressPool(u.Properties.DefaultBackendAddressPool.ID) + } + + var backendSetting *BackendHTTPSettingsCollection + var backendPort int + if u.Properties.DefaultBackendHTTPSettings != nil { + backendSetting = self.getBackendHTTPSettingsCollection(u.Properties.DefaultBackendHTTPSettings.ID) + backendPort = backendSetting.Properties.Port + } + + var healthcheck *Probe + if backendSetting != nil && backendSetting.Properties.Probe != nil { + healthcheck = self.getProbe(backendSetting.Properties.Probe.ID) + } + + return &SLoadBalancerListener{ + lb: self, + fp: fp, + listener: listener, + backendSetting: backendSetting, + backendGroup: backendGroup, + redirect: redirect, + healthcheck: healthcheck, + Name: u.Name, + ID: u.ID, + ProvisioningState: u.Properties.ProvisioningState, + IPVersion: "", + Protocol: listener.Properties.Protocol, + LoadDistribution: "", + FrontendPort: fpp.Properties.Port, + BackendPort: backendPort, + ClientIdleTimeout: 0, + EnableFloatingIP: false, + EnableTcpReset: false, + rules: u.Properties.PathRules, + } +} + +func (self *SLoadbalancer) getNetworkLBListeners() ([]cloudprovider.ICloudLoadbalancerListener, error) { + lbls := []cloudprovider.ICloudLoadbalancerListener{} + for i := range self.Properties.LoadBalancingRules { + u := self.Properties.LoadBalancingRules[i] + lbl := self.getNetworkLBListener(&u) + lbls = append(lbls, &lbl) + } + + return lbls, nil +} + +func (self *SLoadbalancer) getNetworkLBListener(u *LoadBalancingRule) SLoadBalancerListener { + fp := self.getFrontendIPConfiguration(u.Properties.FrontendIPConfiguration.ID) + backendGroup := self.getBackendAddressPool(u.Properties.BackendAddressPool.ID) + healthcheck := self.getProbe(u.Properties.Probe.ID) + + return SLoadBalancerListener{ + lb: self, + fp: fp, + backendGroup: backendGroup, + healthcheck: healthcheck, + Name: u.Name, + ID: u.ID, + ProvisioningState: u.Properties.ProvisioningState, + IPVersion: "", + Protocol: u.Properties.Protocol, + LoadDistribution: u.Properties.LoadDistribution, + FrontendPort: u.Properties.FrontendPort, + BackendPort: u.Properties.BackendPort, + ClientIdleTimeout: u.Properties.IdleTimeoutInMinutes * 60, + EnableFloatingIP: u.Properties.EnableFloatingIP, + EnableTcpReset: u.Properties.EnableTCPReset, + } +} + +// 应用型LB: HTTP 设置 + 后端池 = onecloud 后端服务器组 +// 4层LB: loadBalancingRules(backendPort)+ 后端池 = onecloud 后端服务器组 +func (self *SLoadbalancer) GetILoadBalancerBackendGroups() ([]cloudprovider.ICloudLoadbalancerBackendGroup, error) { + if self.lbbgs != nil { + return self.lbbgs, nil + } + + lbls, err := self.GetILoadBalancerListeners() + if err != nil { + return nil, errors.Wrap(err, "GetILoadBalancerListeners") + } + + bgIds := []string{} + ilbbgs := []cloudprovider.ICloudLoadbalancerBackendGroup{} + for i := range lbls { + lbl := lbls[i].(*SLoadBalancerListener) + if lbl.backendGroup == nil { + continue + } + + bg := SLoadbalancerBackendGroup{ + lb: self, + Pool: *lbl.backendGroup, + DefaultPort: lbl.BackendPort, + HttpSettings: lbl.backendSetting, + BackendIps: lbl.backendGroup.Properties.BackendIPConfigurations, + } + + if !utils.IsInStringArray(bg.GetId(), bgIds) { + bgIds = append(bgIds, bg.GetId()) + ilbbgs = append(ilbbgs, &bg) + } + + // sync rules lbbg + if utils.IsInStringArray(lbl.GetListenerType(), []string{api.LB_LISTENER_TYPE_HTTP, api.LB_LISTENER_TYPE_HTTPS}) { + rules, err := lbl.GetILoadbalancerListenerRules() + if err != nil { + return nil, errors.Wrap(err, "GetILoadbalancerListenerRules") + } + + for j := range rules { + rule := rules[j].(*SLoadbalancerListenerRule) + if rule.lbbg != nil && !utils.IsInStringArray(rule.lbbg.GetId(), bgIds) { + bgIds = append(bgIds, bg.GetId()) + ilbbgs = append(ilbbgs, &bg) + } + } + } + } + + self.lbbgs = ilbbgs + return ilbbgs, nil +} + +func (self *SLoadbalancer) GetILoadBalancerBackendGroupById(groupId string) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + lbbgs, err := self.GetILoadBalancerBackendGroups() + if err != nil { + return nil, errors.Wrap(err, "GetILoadBalancerBackendGroups") + } + + for i := range lbbgs { + if lbbgs[i].GetId() == groupId { + return lbbgs[i], nil + } + } + + return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerBackendGroupById") +} + +func (self *SLoadbalancer) CreateILoadBalancerBackendGroup(group *cloudprovider.SLoadbalancerBackendGroup) (cloudprovider.ICloudLoadbalancerBackendGroup, error) { + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerBackendGroup") +} + +func (self *SLoadbalancer) CreateILoadBalancerListener(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) (cloudprovider.ICloudLoadbalancerListener, error) { + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerListener") +} + +func (self *SLoadbalancer) getNetworkLBListenerById(id string) (cloudprovider.ICloudLoadbalancerListener, error) { + for i := range self.Properties.LoadBalancingRules { + u := self.Properties.LoadBalancingRules[i] + if u.ID == id { + lbl := self.getNetworkLBListener(&u) + return &lbl, nil + } + } + + return nil, errors.Wrap(cloudprovider.ErrNotFound, "getNetworkLBListenerById") +} + +func (self *SLoadbalancer) getAppLBListenerById(id string) (cloudprovider.ICloudLoadbalancerListener, error) { + for i := range self.Properties.URLPathMaps { + u := self.Properties.URLPathMaps[i] + if u.ID == id { + return self.getAppLBListener(&u), nil + } + } + + return nil, errors.Wrap(cloudprovider.ErrNotFound, "getAppLBListenerById") +} + +func (self *SLoadbalancer) GetILoadBalancerListenerById(listenerId string) (cloudprovider.ICloudLoadbalancerListener, error) { + if self.Type == "Microsoft.Network/applicationGateways" { + return self.getAppLBListenerById(listenerId) + } else { + return self.getNetworkLBListenerById(listenerId) + } +} + +func (self *SLoadbalancer) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { + icerts := []cloudprovider.ICloudLoadbalancerCertificate{} + ssl := self.Properties.SSLCertificates + for i := range ssl { + s := ssl[i] + cert := SLoadbalancerCert{ + lb: self, + Name: s.Name, + ID: s.ID, + PublicKey: s.Properties.PublicCertData, + } + + icerts = append(icerts, &cert) + } + + return icerts, nil +} + +func (self *SLoadbalancer) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { + ssl := self.Properties.SSLCertificates + for i := range ssl { + s := ssl[i] + if s.ID == certId { + return &SLoadbalancerCert{ + lb: self, + Name: s.Name, + ID: s.ID, + PublicKey: s.Properties.PublicCertData, + }, nil + } + } + + return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById") +} diff --git a/pkg/multicloud/azure/loadbalancer_props.go b/pkg/multicloud/azure/loadbalancer_props.go new file mode 100644 index 0000000000..b4a66a567a --- /dev/null +++ b/pkg/multicloud/azure/loadbalancer_props.go @@ -0,0 +1,353 @@ +package azure + +type SLoadbalancerProperties struct { + Sku Sku `json:"sku"` + ProvisioningState string `json:"provisioningState"` + OperationalState string `json:"operationalState"` + ResourceGUID string `json:"resourceGuid"` + GatewayIPConfigurations []GatewayIPConfiguration `json:"gatewayIPConfigurations"` + SSLCertificates []SSLCertificate `json:"sslCertificates"` + FrontendIPConfigurations []FrontendIPConfiguration `json:"frontendIPConfigurations"` + FrontendPorts []FrontendPort `json:"frontendPorts"` + BackendAddressPools []BackendAddressPool `json:"backendAddressPools"` + BackendHTTPSettingsCollection []BackendHTTPSettingsCollection `json:"backendHttpSettingsCollection"` + LoadBalancingRules []LoadBalancingRule `json:"loadBalancingRules"` + Probes []Probe `json:"probes"` + InboundNatRules []InboundNatRule `json:"inboundNatRules"` + HTTPListeners []HTTPListener `json:"httpListeners"` + URLPathMaps []URLPathMap `json:"urlPathMaps"` + RequestRoutingRules []RequestRoutingRule `json:"requestRoutingRules"` + RedirectConfigurations []RedirectConfiguration `json:"redirectConfigurations"` + WebApplicationFirewallConfiguration WebApplicationFirewallConfiguration `json:"webApplicationFirewallConfiguration"` + EnableHttp2 bool `json:"enableHttp2"` +} + +type BackendAddressPool struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Properties BackendAddressPoolProperties `json:"properties"` + Type string `json:"type"` +} + +type BackendAddressPoolProperties struct { + ProvisioningState string `json:"provisioningState"` + LoadBalancingRules []Subnet `json:"loadBalancingRules"` + BackendIPConfigurations []BackendIPConfiguration `json:"backendIPConfigurations"` + // loadBalancerBackendAddresses +} + +type BackendIPConfiguration struct { + ID string `json:"id"` +} + +type RedirectConfiguration struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Properties RedirectConfigurationProperties `json:"properties"` + Type string `json:"type"` +} + +type RedirectConfigurationProperties struct { + ProvisioningState string `json:"provisioningState"` + RedirectType string `json:"redirectType"` + TargetUrl string `json:"targetUrl"` + TargetListener PublicIPAddressElement `json:"targetListener"` + IncludePath bool `json:"includePath"` + IncludeQueryString bool `json:"includeQueryString"` + URLPathMaps []PublicIPAddressElement `json:"urlPathMaps,omitempty"` + PathRules []PublicIPAddressElement `json:"pathRules,omitempty"` +} + +type WebApplicationFirewallConfiguration struct { + Enabled bool `json:"enabled"` + FirewallMode string `json:"firewallMode"` + RuleSetType string `json:"ruleSetType"` + RuleSetVersion string `json:"ruleSetVersion"` + DisabledRuleGroups []interface{} `json:"disabledRuleGroups"` +} + +type URLPathMap struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Properties URLPathMapProperties `json:"properties"` + Type string `json:"type"` +} + +type URLPathMapProperties struct { + ProvisioningState string `json:"provisioningState"` + DefaultBackendAddressPool *PublicIPAddressElement `json:"defaultBackendAddressPool,omitempty"` + DefaultBackendHTTPSettings *PublicIPAddressElement `json:"defaultBackendHttpSettings,omitempty"` + PathRules []PathRule `json:"pathRules"` + RequestRoutingRules []PublicIPAddressElement `json:"requestRoutingRules"` + DefaultRedirectConfiguration *PublicIPAddressElement `json:"defaultRedirectConfiguration,omitempty"` +} + +type PublicIPAddressElement struct { + ID string `json:"id"` +} + +type PathRule struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Properties PathRuleProperties `json:"properties"` + Type string `json:"type"` +} + +type PathRuleProperties struct { + ProvisioningState string `json:"provisioningState"` + Paths []string `json:"paths"` + BackendAddressPool *PublicIPAddressElement `json:"backendAddressPool,omitempty"` + BackendHTTPSettings *PublicIPAddressElement `json:"backendHttpSettings,omitempty"` + RedirectConfiguration *PublicIPAddressElement `json:"redirectConfiguration,omitempty"` +} + +type BackendAddress struct { + IPAddress string `json:"ipAddress"` +} + +type BackendHTTPSettingsCollection struct { + Name string `json:"name"` + ID string `json:"id"` + Properties BackendHTTPSettingsCollectionProperties `json:"properties"` +} + +type BackendHTTPSettingsCollectionProperties struct { + Port int `json:"port"` + Protocol string `json:"protocol"` + Probe *ProbeId `json:"probe"` + ConnectionDraining ConnectionDraining `json:"connectionDraining"` + CookieBasedAffinity string `json:"cookieBasedAffinity"` + AffinityCookieName string `json:"affinityCookieName"` + HostName string `json:"hostName"` + RequestTimeout int `json:"requestTimeout"` +} + +type ConnectionDraining struct { + Enabled bool `json:"enabled"` + DrainTimeoutInSEC string `json:"drainTimeoutInSec"` +} + +type ProbeId struct { + ID string `json:"id"` +} + +type FrontendPort struct { + Name string `json:"name"` + ID string `json:"id"` + Properties FrontendPortProperties `json:"properties"` +} + +type FrontendPortProperties struct { + Port int `json:"port"` +} + +type GatewayIPConfiguration struct { + Name string `json:"name"` + ID string `json:"id"` + Properties GatewayIPConfigurationProperties `json:"properties"` +} + +type GatewayIPConfigurationProperties struct { + Subnet PublicIPAddress `json:"subnet"` +} + +type RequestRoutingRule struct { + Name string `json:"name"` + ID string `json:"id"` + Properties RequestRoutingRuleProperties `json:"properties"` +} + +type RequestRoutingRuleProperties struct { + RuleType string `json:"ruleType"` + HTTPListener PublicIPAddress `json:"httpListener"` + BackendAddressPool PublicIPAddress `json:"backendAddressPool"` + BackendHTTPSettings PublicIPAddress `json:"backendHttpSettings"` +} + +type SSLCertificate struct { + Name string `json:"name"` + ID string `json:"id"` + Properties SSLCertificateProperties `json:"properties"` +} + +type SSLCertificateProperties struct { + ProvisioningState string `json:"provisioningState"` + PublicCertData string `json:"public_cert_data"` + Data string `json:"data"` + Password string `json:"password"` +} + +type Sku struct { + Name string `json:"name"` + Tier string `json:"tier"` + Capacity string `json:"capacity"` +} + +type Subnet struct { + ID string `json:"id"` +} + +type FrontendIPConfiguration struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Zones []string `json:"zones"` + Properties FrontendIPConfigurationProperties `json:"properties"` +} + +type FrontendIPConfigurationProperties struct { + ProvisioningState string `json:"provisioningState"` + PrivateIPAddress string `json:"privateIPAddress"` + PublicIPAddress *PublicIPAddress `json:"publicIPAddress,omitempty"` + PrivateIPAllocationMethod string `json:"privateIPAllocationMethod"` + PrivateIPAddressVersion string `json:"privateIPAddressVersion"` + Subnet Subnet `json:"subnet"` + LoadBalancingRules []Subnet `json:"loadBalancingRules"` + InboundNatRules []Subnet `json:"inboundNatRules"` +} + +type InboundNatRule struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Properties InboundNatRuleProperties `json:"properties"` +} + +type InboundNatRuleProperties struct { + ProvisioningState string `json:"provisioningState"` + FrontendIPConfiguration Subnet `json:"frontendIPConfiguration"` + FrontendPort int64 `json:"frontendPort"` + BackendPort int64 `json:"backendPort"` + EnableFloatingIP bool `json:"enableFloatingIP"` + IdleTimeoutInMinutes int64 `json:"idleTimeoutInMinutes"` + Protocol string `json:"protocol"` + EnableTCPReset bool `json:"enableTcpReset"` +} + +type SLoadbalancerSku struct { + Name string `json:"name"` +} + +type Probe struct { + lb *SLoadbalancer + + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Properties ProbeProperties `json:"properties"` +} + +type ProbeProperties struct { + // tcp/udp/http/https + ProvisioningState string `json:"provisioningState"` + Protocol string `json:"protocol"` + Port int `json:"port"` + RequestPath string `json:"requestPath"` + IntervalInSeconds int `json:"intervalInSeconds"` + NumberOfProbes int `json:"numberOfProbes"` + // http/ https only + Host string `json:"host"` + Path string `json:"path"` + Interval int `json:"interval"` + Timeout int `json:"timeout"` + UnhealthyThreshold int `json:"unhealthyThreshold"` + PickHostNameFromBackendHTTPSettings bool `json:"pickHostNameFromBackendHttpSettings"` + MinServers int `json:"minServers"` + Match Match `json:"match"` + LoadBalancingRules []Subnet `json:"loadBalancingRules"` +} + +type Match struct { + Body string `json:"body"` + StatusCodes []string `json:"statusCodes"` +} + +type LoadBalancingRule struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Properties LoadBalancingRuleProperties `json:"properties"` +} + +type LoadBalancingRuleProperties struct { + ProvisioningState string `json:"provisioningState"` + FrontendIPConfiguration Subnet `json:"frontendIPConfiguration"` + FrontendPort int `json:"frontendPort"` + BackendPort int `json:"backendPort"` + EnableFloatingIP bool `json:"enableFloatingIP"` + IdleTimeoutInMinutes int `json:"idleTimeoutInMinutes"` + Protocol string `json:"protocol"` + EnableTCPReset bool `json:"enableTcpReset"` + LoadDistribution string `json:"loadDistribution"` + BackendAddressPool Subnet `json:"backendAddressPool"` + Probe Subnet `json:"probe"` +} + +type HTTPListener struct { + Name string `json:"name"` + ID string `json:"id"` + Properties HTTPListenerProperties `json:"properties"` +} + +type HTTPListenerProperties struct { + FrontendIPConfiguration PublicIPAddress `json:"frontendIPConfiguration"` + FrontendPort PublicIPAddress `json:"frontendPort"` + HostName string `json:"hostName"` + Protocol string `json:"protocol"` + SSLCertificate PublicIPAddress `json:"sslCertificate"` + RequestRoutingRules []Subnet `json:"requestRoutingRules"` + RequireServerNameIndication bool `json:"requireServerNameIndication"` +} + +type ContentProperties struct { + ProvisioningState string `json:"provisioningState"` + ResourceGUID string `json:"resourceGuid"` + IPConfigurations []NetworkInterfaceIPConfiguration `json:"ipConfigurations"` + DNSSettings DNSSettings `json:"dnsSettings"` + MACAddress string `json:"macAddress"` + EnableAcceleratedNetworking bool `json:"enableAcceleratedNetworking"` + EnableIPForwarding bool `json:"enableIPForwarding"` + NetworkSecurityGroup NetworkSecurityGroup `json:"networkSecurityGroup"` + Primary bool `json:"primary"` + VirtualMachine NetworkSecurityGroup `json:"virtualMachine"` + HostedWorkloads []interface{} `json:"hostedWorkloads"` + TapConfigurations []interface{} `json:"tapConfigurations"` +} + +type DNSSettings struct { + DNSServers []interface{} `json:"dnsServers"` + AppliedDNSServers []interface{} `json:"appliedDnsServers"` + InternalDomainNameSuffix string `json:"internalDomainNameSuffix"` +} + +type NetworkInterfaceIPConfiguration struct { + Name string `json:"name"` + ID string `json:"id"` + Etag string `json:"etag"` + Type string `json:"type"` + Properties IPConfigurationProperties `json:"properties"` +} + +type IPConfigurationProperties struct { + ProvisioningState string `json:"provisioningState"` + PrivateIPAddress string `json:"privateIPAddress"` + PrivateIPAllocationMethod string `json:"privateIPAllocationMethod"` + PublicIPAddress NetworkSecurityGroup `json:"publicIPAddress"` + Subnet NetworkSecurityGroup `json:"subnet"` + Primary bool `json:"primary"` + PrivateIPAddressVersion string `json:"privateIPAddressVersion"` + LoadBalancerBackendAddressPools []NetworkSecurityGroup `json:"loadBalancerBackendAddressPools"` + LoadBalancerInboundNatRules []NetworkSecurityGroup `json:"loadBalancerInboundNatRules"` +} + +type NetworkSecurityGroup struct { + ID string `json:"id"` +} diff --git a/pkg/multicloud/azure/loadbalancerbackend.go b/pkg/multicloud/azure/loadbalancerbackend.go new file mode 100644 index 0000000000..59143167af --- /dev/null +++ b/pkg/multicloud/azure/loadbalancerbackend.go @@ -0,0 +1,80 @@ +package azure + +import ( + "context" + "strconv" + "strings" + + "github.com/pkg/errors" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +type SLoadbalancerBackend struct { + multicloud.SResourceBase + + lbbg *SLoadbalancerBackendGroup + // networkInterfaces 通过接口地址反查虚拟机地址 + Name string `json:"name"` + ID string `json:"id"` + Type string `json:"type"` + BackendPort int +} + +func (self *SLoadbalancerBackend) GetId() string { + return self.ID + "::" + strconv.Itoa(self.BackendPort) +} + +func (self *SLoadbalancerBackend) GetName() string { + return self.Name +} + +func (self *SLoadbalancerBackend) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadbalancerBackend) GetStatus() string { + return api.LB_STATUS_ENABLED +} + +func (self *SLoadbalancerBackend) GetSysTags() map[string]string { + return nil +} + +func (self *SLoadbalancerBackend) GetTags() (map[string]string, error) { + return nil, nil +} + +func (self *SLoadbalancerBackend) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadbalancerBackend) GetProjectId() string { + return getResourceGroup(self.ID) +} + +func (self *SLoadbalancerBackend) GetWeight() int { + return 0 +} + +func (self *SLoadbalancerBackend) GetPort() int { + return self.BackendPort +} + +func (self *SLoadbalancerBackend) GetBackendType() string { + return api.LB_BACKEND_GUEST +} + +func (self *SLoadbalancerBackend) GetBackendRole() string { + return api.LB_BACKEND_ROLE_DEFAULT +} + +func (self *SLoadbalancerBackend) GetBackendId() string { + return self.ID +} + +func (self *SLoadbalancerBackend) SyncConf(ctx context.Context, port, weight int) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SyncConf") +} diff --git a/pkg/multicloud/azure/loadbalancerbackendgroup.go b/pkg/multicloud/azure/loadbalancerbackendgroup.go new file mode 100644 index 0000000000..07fa27048e --- /dev/null +++ b/pkg/multicloud/azure/loadbalancerbackendgroup.go @@ -0,0 +1,189 @@ +package azure + +import ( + "context" + "strconv" + "strings" + + "github.com/pkg/errors" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +// todo: 虚拟机规模集不支持 +// 注: 因为与onecloud后端服务器组存在配置差异,不支持同步未关联的后端服务器组 +// 应用型LB: HTTP 设置 + 后端池 = onecloud 后端服务器组 +// 4层LB: loadBalancingRules(backendPort)+ 后端池 = onecloud 后端服务器组 +type SLoadbalancerBackendGroup struct { + lb *SLoadbalancer + lbbs []cloudprovider.ICloudLoadbalancerBackend + + Pool BackendAddressPool + DefaultPort int + HttpSettings *BackendHTTPSettingsCollection + + BackendIps []BackendIPConfiguration +} + +func (self *SLoadbalancerBackendGroup) GetId() string { + return self.Pool.ID + "::" + strconv.Itoa(self.DefaultPort) +} + +func (self *SLoadbalancerBackendGroup) GetName() string { + if self.HttpSettings != nil { + return self.Pool.Name + "::" + self.HttpSettings.Name + } + + return self.Pool.Name + "::" + strconv.Itoa(self.DefaultPort) +} + +func (self *SLoadbalancerBackendGroup) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadbalancerBackendGroup) GetStatus() string { + switch self.Pool.Properties.ProvisioningState { + case "Succeeded": + return api.LB_STATUS_ENABLED + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (self *SLoadbalancerBackendGroup) Refresh() error { + lbbg, err := self.lb.GetILoadBalancerBackendGroupById(self.GetId()) + if err != nil { + return errors.Wrap(err, "GetILoadBalancerBackendGroupById") + } + + err = jsonutils.Update(self, lbbg) + if err != nil { + return errors.Wrap(err, "refresh.Update") + } + + self.lbbs = nil + return nil +} + +func (self *SLoadbalancerBackendGroup) IsEmulated() bool { + return true +} + +func (self *SLoadbalancerBackendGroup) GetSysTags() map[string]string { + return nil +} + +func (self *SLoadbalancerBackendGroup) GetTags() (map[string]string, error) { + return map[string]string{}, nil +} + +func (self *SLoadbalancerBackendGroup) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadbalancerBackendGroup) GetProjectId() string { + return getResourceGroup(self.GetId()) +} + +func (self *SLoadbalancerBackendGroup) IsDefault() bool { + return false +} + +func (self *SLoadbalancerBackendGroup) GetType() string { + return api.LB_BACKENDGROUP_TYPE_NORMAL +} + +func (self *SLoadbalancerBackendGroup) GetLoadbalancerId() string { + return self.lb.GetId() +} + +func (self *SLoadbalancerBackendGroup) GetILoadbalancerBackends() ([]cloudprovider.ICloudLoadbalancerBackend, error) { + if self.lbbs != nil { + return self.lbbs, nil + } + + var ret []cloudprovider.ICloudLoadbalancerBackend + ips := self.Pool.Properties.BackendIPConfigurations + for i := range ips { + ip := ips[i] + nic, err := self.lb.region.GetNetworkInterface(strings.Split(ip.ID, "/ipConfigurations")[0]) + if err != nil { + return nil, errors.Wrap(err, "GetNetworkInterface") + } + + if len(nic.Properties.VirtualMachine.ID) == 0 { + continue + } + + name := nic.Properties.VirtualMachine.Name + vid := nic.Properties.VirtualMachine.ID + if len(name) == 0 && len(vid) > 0 { + segs := strings.Split(vid, "/virtualMachines/") + name = segs[len(segs)-1] + } + bg := SLoadbalancerBackend{ + SResourceBase: multicloud.SResourceBase{}, + lbbg: self, + Name: name, + ID: vid, + Type: api.LB_BACKEND_GUEST, + BackendPort: self.DefaultPort, + } + + ret = append(ret, &bg) + } + + self.lbbs = ret + return ret, nil +} + +func (self *SLoadbalancerBackendGroup) GetILoadbalancerBackendById(backendId string) (cloudprovider.ICloudLoadbalancerBackend, error) { + lbbs, err := self.GetILoadbalancerBackends() + if err != nil { + return nil, errors.Wrap(err, "GetILoadbalancerBackends") + } + + for i := range lbbs { + if lbbs[i].GetId() == backendId { + return lbbs[i], nil + } + } + + return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadbalancerBackendById") +} + +func (self *SLoadbalancerBackendGroup) GetProtocolType() string { + return "" +} + +func (self *SLoadbalancerBackendGroup) GetScheduler() string { + return "" +} + +func (self *SLoadbalancerBackendGroup) GetHealthCheck() (*cloudprovider.SLoadbalancerHealthCheck, error) { + return nil, nil +} + +func (self *SLoadbalancerBackendGroup) GetStickySession() (*cloudprovider.SLoadbalancerStickySession, error) { + return nil, nil +} + +func (self *SLoadbalancerBackendGroup) AddBackendServer(serverId string, weight int, port int) (cloudprovider.ICloudLoadbalancerBackend, error) { + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "AddBackendServer") +} + +func (self *SLoadbalancerBackendGroup) RemoveBackendServer(serverId string, weight int, port int) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "RemoveBackendServer") +} + +func (self *SLoadbalancerBackendGroup) Delete(ctx context.Context) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete") +} + +func (self *SLoadbalancerBackendGroup) Sync(ctx context.Context, group *cloudprovider.SLoadbalancerBackendGroup) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Sync") +} diff --git a/pkg/multicloud/azure/loadbalancercert.go b/pkg/multicloud/azure/loadbalancercert.go new file mode 100644 index 0000000000..735555fe87 --- /dev/null +++ b/pkg/multicloud/azure/loadbalancercert.go @@ -0,0 +1,167 @@ +package azure + +import ( + "bytes" + "crypto/sha1" + "crypto/x509" + "encoding/pem" + "fmt" + "strings" + "time" + + "github.com/pkg/errors" + + "yunion.io/x/jsonutils" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" +) + +type SLoadbalancerCert struct { + lb *SLoadbalancer + cert *x509.Certificate + Name string `json:"name"` + ID string `json:"id"` + PublicKey string `json:"public_key"` +} + +func (self *SLoadbalancerCert) GetId() string { + return self.ID +} + +func (self *SLoadbalancerCert) GetName() string { + return self.Name +} + +func (self *SLoadbalancerCert) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadbalancerCert) GetStatus() string { + return api.LB_STATUS_ENABLED +} + +func (self *SLoadbalancerCert) Refresh() error { + cert, err := self.lb.GetILoadBalancerCertificateById(self.GetId()) + if err != nil { + return errors.Wrap(err, "GetILoadBalancerCertificateById") + } + + err = jsonutils.Update(self, cert) + if err != nil { + return errors.Wrap(err, "Update") + } + + return nil +} + +func (self *SLoadbalancerCert) IsEmulated() bool { + return false +} + +func (self *SLoadbalancerCert) GetSysTags() map[string]string { + return nil +} + +func (self *SLoadbalancerCert) GetTags() (map[string]string, error) { + return nil, nil +} + +func (self *SLoadbalancerCert) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadbalancerCert) GetProjectId() string { + return getResourceGroup(self.GetId()) +} + +func (self *SLoadbalancerCert) Sync(name, privateKey, publickKey string) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Sync") +} + +func (self *SLoadbalancerCert) Delete() error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete") +} + +func (self *SLoadbalancerCert) ParsePublicKey() (*x509.Certificate, error) { + if self.cert != nil { + return self.cert, nil + } + + publicKey := self.GetPublickKey() + if len(publicKey) == 0 { + return nil, fmt.Errorf("SElbCertificate ParsePublicKey public key is empty") + } + + block, _ := pem.Decode([]byte(publicKey)) + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + return nil, errors.Wrap(err, "ParseCertificate") + } + + self.cert = cert + return cert, nil +} + +func (self *SLoadbalancerCert) GetCommonName() string { + cert, err := self.ParsePublicKey() + if err != nil { + return "" + } + + return cert.Issuer.CommonName +} + +func (self *SLoadbalancerCert) GetSubjectAlternativeNames() string { + _, err := self.ParsePublicKey() + if err != nil { + return "" + } + + return "" +} + +func (self *SLoadbalancerCert) GetFingerprint() string { + publicKey := self.GetPublickKey() + if len(publicKey) == 0 { + return "" + } + + _fp := sha1.Sum([]byte(publicKey)) + fp := fmt.Sprintf("sha1:% x", _fp) + return strings.Replace(fp, " ", ":", -1) +} + +func (self *SLoadbalancerCert) GetExpireTime() time.Time { + cert, err := self.ParsePublicKey() + if err != nil { + return time.Time{} + } + + return cert.NotAfter +} + +func (self *SLoadbalancerCert) GetPublickKey() string { + if len(self.PublicKey) > 0 { + var pk bytes.Buffer + pk.WriteString("-----BEGIN CERTIFICATE-----\r\n") + content := bytes.NewBufferString(self.PublicKey) + for { + l := content.Next(64) + if len(l) == 64 { + pk.WriteString(fmt.Sprintf("%s\r\n", l)) + } else { + pk.WriteString(fmt.Sprintf("%s\r\n", l)) + break + } + } + pk.WriteString("-----END CERTIFICATE-----") + return pk.String() + } + + return "" +} + +func (self *SLoadbalancerCert) GetPrivateKey() string { + return "" +} diff --git a/pkg/multicloud/azure/loadbalancerlistener.go b/pkg/multicloud/azure/loadbalancerlistener.go new file mode 100644 index 0000000000..8b36439843 --- /dev/null +++ b/pkg/multicloud/azure/loadbalancerlistener.go @@ -0,0 +1,569 @@ +package azure + +import ( + "context" + "net/url" + "regexp" + "strconv" + "strings" + + "yunion.io/x/jsonutils" + "yunion.io/x/log" + "yunion.io/x/pkg/errors" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +// todo: 目前不支持 入站 NAT 规则 +// todo: HTTP 设置(端口+协议,其余信息丢弃) + 后端池 = onecloud 路径的路由 的 onecloud 后端服务器组 +/* +应用型LB: urlPathMaps(defaultBackendAddressPool+defaultBackendHttpSettings+requestRoutingRules+httpListeners)= Onecloud监听器 +4层LB: loadBalancingRules(前端) = Onecloud监听器 +*/ +type SLoadBalancerListener struct { + multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase + + lb *SLoadbalancer + lbrs []cloudprovider.ICloudLoadbalancerListenerRule + + /* + IPVersion string + FrontendIP string // 前端IP + FrontendIPId string // 前端IP ID + */ + fp *FrontendIPConfiguration + + /* + Protocol string // 监听协议 + HostName string // 监听器 监听域名 + FrontendPort int // 前端端口 + */ + listener *HTTPListener + + /* + Protocol string // 后端协议 + BackendPort int // 后端端口 + IdleTimeoutInMinutes int // 空闲超时(分钟) + LoadDistribution string // 会话保持方法SourceIP|SourceIPProtocol + CookieBasedAffinity string // cookies 关联 + CookieName string // cookie 名称 + EnabledConnectionDraining bool // 排出超时这应用于通过 API 调用从后端池明确删除的后端实例,以及运行状况探测报告的运行不正常的实例。 + ConnectionDrainingSec int // 排出超时时长(秒) + RequestTimeout int // 请求超时时间(秒) + probe // 健康检查 + */ + backendSetting *BackendHTTPSettingsCollection + + // + backendGroup *BackendAddressPool + + /* + redirectType string // 重定向类型 + targetListener // 重定向到监听 + */ + redirect *RedirectConfiguration + + /* + "protocol": "Http", + "host": "baidu.com", + "path": "/test", + "interval": 30, + "timeout": 30, + "unhealthyThreshold": 3, + "pickHostNameFromBackendHttpSettings": false, + "minServers": 0, + "match": { + "body": "500", + "statusCodes": [ + "200-399" + ] + }, + */ + healthcheck *Probe + + Name string + ID string + ProvisioningState string + IPVersion string + Protocol string // 监听协议 + LoadDistribution string // 调度算法 + FrontendPort int // 前端端口 + BackendPort int // 后端端口 + ClientIdleTimeout int // 客户端连接超时 + EnableFloatingIP bool // 浮动 IP + EnableTcpReset bool + + rules []PathRule +} + +func (self *SLoadBalancerListener) GetId() string { + return self.ID +} + +func (self *SLoadBalancerListener) GetName() string { + return self.Name +} + +func (self *SLoadBalancerListener) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadBalancerListener) GetStatus() string { + switch self.ProvisioningState { + case "Succeeded": + return api.LB_STATUS_ENABLED + case "Failed": + return api.LB_STATUS_DISABLED + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (self *SLoadBalancerListener) Refresh() error { + lbl, err := self.lb.GetILoadBalancerListenerById(self.GetId()) + if err != nil { + return errors.Wrap(err, "GetILoadBalancerListenerById") + } + + err = jsonutils.Update(self, lbl) + if err != nil { + return errors.Wrap(err, "refresh.Update") + } + + self.lbrs = nil + return nil +} + +func (self *SLoadBalancerListener) IsEmulated() bool { + return false +} + +func (self *SLoadBalancerListener) GetSysTags() map[string]string { + return nil +} + +func (self *SLoadBalancerListener) GetTags() (map[string]string, error) { + return nil, nil +} + +func (self *SLoadBalancerListener) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadBalancerListener) GetProjectId() string { + return getResourceGroup(self.GetId()) +} + +func (self *SLoadBalancerListener) GetListenerType() string { + switch strings.ToLower(self.Protocol) { + case "tcp": + return api.LB_LISTENER_TYPE_TCP + case "udp": + return api.LB_LISTENER_TYPE_UDP + case "http": + return api.LB_LISTENER_TYPE_HTTP + case "https": + return api.LB_LISTENER_TYPE_HTTPS + default: + return "" + } +} + +func (self *SLoadBalancerListener) GetListenerPort() int { + return int(self.FrontendPort) +} + +func (self *SLoadBalancerListener) GetScheduler() string { + switch self.LoadDistribution { + case "SourceIPProtocol", "SourceIP": + return api.LB_SCHEDULER_SCH + default: + return "" + } +} + +func (self *SLoadBalancerListener) GetAclStatus() string { + return api.LB_BOOL_OFF +} + +func (self *SLoadBalancerListener) GetAclType() string { + return "" +} + +func (self *SLoadBalancerListener) GetAclId() string { + return "" +} + +func (self *SLoadBalancerListener) GetEgressMbps() int { + return 0 +} + +func (self *SLoadBalancerListener) GetHealthCheck() string { + // if self.probe != nil + if self.healthcheck != nil { + return api.LB_BOOL_ON + } + + return api.LB_BOOL_OFF +} + +func (self *SLoadBalancerListener) GetHealthCheckType() string { + if self.healthcheck == nil { + return "" + } + switch strings.ToLower(self.healthcheck.Properties.Protocol) { + case "tcp": + return api.LB_HEALTH_CHECK_TCP + case "udp": + return api.LB_HEALTH_CHECK_UDP + case "http": + return api.LB_HEALTH_CHECK_HTTP + case "https": + return api.LB_HEALTH_CHECK_HTTPS + default: + return "" + } +} + +func (self *SLoadBalancerListener) GetHealthCheckTimeout() int { + if self.healthcheck == nil { + return 0 + } + switch self.GetHealthCheckType() { + case api.LB_HEALTH_CHECK_HTTP, api.LB_HEALTH_CHECK_HTTPS: + return self.healthcheck.Properties.Timeout + } + + return self.healthcheck.Properties.IntervalInSeconds +} + +func (self *SLoadBalancerListener) GetHealthCheckInterval() int { + if self.healthcheck == nil { + return 0 + } + switch self.GetHealthCheckType() { + case api.LB_HEALTH_CHECK_HTTP, api.LB_HEALTH_CHECK_HTTPS: + return self.healthcheck.Properties.Interval + } + + return self.healthcheck.Properties.IntervalInSeconds +} + +func (self *SLoadBalancerListener) GetHealthCheckRise() int { + return 0 +} + +func (self *SLoadBalancerListener) GetHealthCheckFail() int { + if self.healthcheck == nil { + return 0 + } + switch self.GetHealthCheckType() { + case api.LB_HEALTH_CHECK_HTTP, api.LB_HEALTH_CHECK_HTTPS: + return self.healthcheck.Properties.UnhealthyThreshold + } + + return self.healthcheck.Properties.IntervalInSeconds +} + +func (self *SLoadBalancerListener) GetHealthCheckReq() string { + return "" +} + +func (self *SLoadBalancerListener) GetHealthCheckExp() string { + return "" +} + +func (self *SLoadBalancerListener) GetBackendGroupId() string { + if self.backendGroup != nil { + return self.backendGroup.ID + "::" + strconv.Itoa(self.BackendPort) + } + + return "" +} + +func (self *SLoadBalancerListener) GetBackendServerPort() int { + return self.BackendPort +} + +func (self *SLoadBalancerListener) GetHealthCheckDomain() string { + if self.healthcheck == nil { + return "" + } + switch self.GetHealthCheckType() { + case api.LB_HEALTH_CHECK_HTTP, api.LB_HEALTH_CHECK_HTTPS: + return self.healthcheck.Properties.Host + } + + return "" +} + +func (self *SLoadBalancerListener) GetHealthCheckURI() string { + if self.healthcheck == nil { + return "" + } + switch self.GetHealthCheckType() { + case api.LB_HEALTH_CHECK_HTTP, api.LB_HEALTH_CHECK_HTTPS: + return self.healthcheck.Properties.Path + } + + return "" +} + +/* +todo: 和onecloud code不兼容? +与此处输入的 HTTP 状态代码或代码范围相匹配的响应将被视为成功。请输入逗号分隔的代码列表(例如 200, 201)或者输入一个代码范围(例如 220-226) +*/ +func (self *SLoadBalancerListener) GetHealthCheckCode() string { + return "" +} + +func (self *SLoadBalancerListener) CreateILoadBalancerListenerRule(rule *cloudprovider.SLoadbalancerListenerRule) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerListenerRule") +} + +func (self *SLoadBalancerListener) GetILoadBalancerListenerRuleById(ruleId string) (cloudprovider.ICloudLoadbalancerListenerRule, error) { + lbrs, err := self.GetILoadbalancerListenerRules() + if err != nil { + return nil, errors.Wrap(err, "GetILoadbalancerListenerRules") + } + + for i := range lbrs { + if lbrs[i].GetId() == ruleId { + return lbrs[i], nil + } + } + + return nil, errors.Wrap(err, "GetILoadBalancerListenerRuleById") +} + +func (self *SLoadBalancerListener) GetILoadbalancerListenerRules() ([]cloudprovider.ICloudLoadbalancerListenerRule, error) { + if self.lbrs != nil { + return self.lbrs, nil + } + + irules := []cloudprovider.ICloudLoadbalancerListenerRule{} + for i := range self.rules { + r := self.rules[i] + var redirect *RedirectConfiguration + var lbbg *SLoadbalancerBackendGroup + if r.Properties.RedirectConfiguration != nil { + redirect = self.lb.getRedirectConfiguration(r.Properties.RedirectConfiguration.ID) + } else { + if r.Properties.BackendAddressPool == nil || r.Properties.BackendHTTPSettings == nil { + continue + } + + pool := self.lb.getBackendAddressPool(r.Properties.BackendAddressPool.ID) + if pool == nil { + log.Debugf("getBackendAddressPool %s not found", r.Properties.BackendAddressPool.ID) + continue + } + backsetting := self.lb.getBackendHTTPSettingsCollection(r.Properties.BackendHTTPSettings.ID) + if backsetting == nil { + log.Debugf("getBackendHTTPSettingsCollection %s not found", r.Properties.BackendHTTPSettings.ID) + continue + } + + lbbg = &SLoadbalancerBackendGroup{ + lb: self.lb, + Pool: *pool, + DefaultPort: backsetting.Properties.Port, + HttpSettings: backsetting, + BackendIps: pool.Properties.BackendIPConfigurations, + } + } + + domain := "" + if self.listener != nil { + domain = self.listener.Properties.HostName + } + + rule := SLoadbalancerListenerRule{ + SResourceBase: multicloud.SResourceBase{}, + listener: self, + lbbg: lbbg, + redirect: redirect, + Name: r.Name, + ID: r.ID, + Domain: domain, + Properties: r.Properties, + } + irules = append(irules, &rule) + } + + return irules, nil +} + +func (self *SLoadBalancerListener) GetStickySession() string { + if self.backendSetting == nil { + return api.LB_BOOL_OFF + } + + if self.backendSetting.Properties.CookieBasedAffinity == "Enabled" { + return api.LB_BOOL_ON + } else { + return api.LB_BOOL_OFF + } +} + +func (self *SLoadBalancerListener) GetStickySessionType() string { + if self.GetStickySession() == api.LB_BOOL_ON { + return api.LB_STICKY_SESSION_TYPE_INSERT + } + return "" +} + +func (self *SLoadBalancerListener) GetStickySessionCookie() string { + if self.backendSetting == nil { + return "" + } + + return self.backendSetting.Properties.AffinityCookieName +} + +func (self *SLoadBalancerListener) GetStickySessionCookieTimeout() int { + if self.backendSetting == nil { + return 0 + } + + if self.backendSetting.Properties.ConnectionDraining.Enabled { + _sec := strings.TrimSpace(self.backendSetting.Properties.ConnectionDraining.DrainTimeoutInSEC) + sec, _ := strconv.ParseInt(_sec, 10, 64) + return int(sec) + } + + return 0 +} + +func (self *SLoadBalancerListener) XForwardedForEnabled() bool { + return false +} + +func (self *SLoadBalancerListener) GzipEnabled() bool { + return false +} + +func (self *SLoadBalancerListener) GetCertificateId() string { + if self.listener != nil { + return self.listener.Properties.SSLCertificate.ID + } + + return "" +} + +func (self *SLoadBalancerListener) GetTLSCipherPolicy() string { + return "" +} + +func (self *SLoadBalancerListener) HTTP2Enabled() bool { + return self.lb.Properties.EnableHttp2 +} + +func (self *SLoadBalancerListener) Start() error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Start") +} + +func (self *SLoadBalancerListener) Stop() error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Stop") +} + +func (self *SLoadBalancerListener) Sync(ctx context.Context, listener *cloudprovider.SLoadbalancerListener) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Sync") +} + +func (self *SLoadBalancerListener) Delete(ctx context.Context) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete") +} + +func (self *SLoadBalancerListener) GetRedirect() string { + if self.redirect != nil { + return api.LB_REDIRECT_RAW + } + + return api.LB_REDIRECT_OFF +} + +func (self *SLoadBalancerListener) GetRedirectCode() int64 { + if self.redirect == nil { + return 0 + } + + switch self.redirect.Properties.RedirectType { + case "Permanent": + return api.LB_REDIRECT_CODE_301 + case "Found": + return api.LB_REDIRECT_CODE_302 + case "Temporary", "SeeOther": + return api.LB_REDIRECT_CODE_307 + default: + return 0 + } +} + +func (self *SLoadBalancerListener) getRedirectUrl() *url.URL { + if self.redirect == nil { + return nil + } + + if len(self.redirect.Properties.TargetUrl) == 0 { + return nil + } + + _url := self.redirect.Properties.TargetUrl + if matched, _ := regexp.MatchString("^\\w{0,5}://", _url); !matched { + _url = "http://" + _url + } + + u, err := url.Parse(_url) + if err != nil { + log.Debugf("url Parse %s : %s", self.redirect.Properties.TargetUrl, err) + return nil + } + + return u +} +func (self *SLoadBalancerListener) GetRedirectScheme() string { + u := self.getRedirectUrl() + if u == nil { + return "" + } + + return strings.ToLower(u.Scheme) +} + +func (self *SLoadBalancerListener) GetRedirectHost() string { + u := self.getRedirectUrl() + if u == nil { + if self.redirect != nil && len(self.redirect.Properties.TargetListener.ID) > 0 { + segs := strings.Split(self.redirect.Properties.TargetListener.ID, "/") + return segs[len(segs)-1] + } + return "" + } + + return u.Host +} + +func (self *SLoadBalancerListener) GetRedirectPath() string { + u := self.getRedirectUrl() + if u == nil { + return "" + } + + return u.Path +} + +func (self *SLoadBalancerListener) GetClientIdleTimeout() int { + return self.ClientIdleTimeout +} + +func (self *SLoadBalancerListener) GetBackendConnectTimeout() int { + if self.backendSetting == nil { + return 0 + } + + return self.backendSetting.Properties.RequestTimeout +} diff --git a/pkg/multicloud/azure/loadbalancerlistenerrule.go b/pkg/multicloud/azure/loadbalancerlistenerrule.go new file mode 100644 index 0000000000..497ee55d40 --- /dev/null +++ b/pkg/multicloud/azure/loadbalancerlistenerrule.go @@ -0,0 +1,178 @@ +package azure + +import ( + "context" + "net/url" + "regexp" + "strings" + + "yunion.io/x/log" + "yunion.io/x/pkg/errors" + + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/cloudprovider" + "yunion.io/x/onecloud/pkg/multicloud" +) + +type SLoadbalancerListenerRule struct { + multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase + + listener *SLoadBalancerListener + lbbg *SLoadbalancerBackendGroup + redirect *RedirectConfiguration + // urlPathMaps -> pathRules + Name string `json:"name"` + ID string `json:"id"` + Domain string `json:"domain"` + Properties PathRuleProperties `json:"properties"` +} + +func (self *SLoadbalancerListenerRule) GetId() string { + return self.ID +} + +func (self *SLoadbalancerListenerRule) GetName() string { + return self.Name +} + +func (self *SLoadbalancerListenerRule) GetGlobalId() string { + return strings.ToLower(self.GetId()) +} + +func (self *SLoadbalancerListenerRule) GetStatus() string { + switch self.Properties.ProvisioningState { + case "Succeeded": + return api.LB_STATUS_ENABLED + case "Failed": + return api.LB_STATUS_DISABLED + default: + return api.LB_STATUS_UNKNOWN + } +} + +func (self *SLoadbalancerListenerRule) GetSysTags() map[string]string { + return nil +} + +func (self *SLoadbalancerListenerRule) GetTags() (map[string]string, error) { + return nil, nil +} + +func (self *SLoadbalancerListenerRule) SetTags(tags map[string]string, replace bool) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags") +} + +func (self *SLoadbalancerListenerRule) GetProjectId() string { + return getResourceGroup(self.GetId()) +} + +func (self *SLoadbalancerListenerRule) IsDefault() bool { + return false +} + +func (self *SLoadbalancerListenerRule) GetDomain() string { + return self.Domain +} + +func (self *SLoadbalancerListenerRule) GetPath() string { + if len(self.Properties.Paths) > 0 { + return self.Properties.Paths[0] + } + + return "" +} + +func (self *SLoadbalancerListenerRule) GetCondition() string { + return "" +} + +func (self *SLoadbalancerListenerRule) GetBackendGroupId() string { + if self.lbbg != nil { + return self.lbbg.GetId() + } + + return "" +} + +func (self *SLoadbalancerListenerRule) Delete(ctx context.Context) error { + return errors.Wrap(cloudprovider.ErrNotImplemented, "Delete") +} + +func (self *SLoadbalancerListenerRule) GetRedirect() string { + if self.redirect != nil { + return api.LB_REDIRECT_RAW + } + + return api.LB_REDIRECT_OFF +} + +func (self *SLoadbalancerListenerRule) GetRedirectCode() int64 { + if self.redirect == nil { + return 0 + } + + switch self.redirect.Properties.RedirectType { + case "Permanent": + return api.LB_REDIRECT_CODE_301 + case "Found": + return api.LB_REDIRECT_CODE_302 + case "Temporary", "SeeOther": + return api.LB_REDIRECT_CODE_307 + default: + return 0 + } +} + +func (self *SLoadbalancerListenerRule) getRedirectUrl() *url.URL { + if self.redirect == nil { + return nil + } + + if len(self.redirect.Properties.TargetUrl) == 0 { + return nil + } + + _url := self.redirect.Properties.TargetUrl + if matched, _ := regexp.MatchString("^\\w{0,5}://", _url); !matched { + _url = "http://" + _url + } + + u, err := url.Parse(_url) + if err != nil { + log.Debugf("url Parse %s : %s", self.redirect.Properties.TargetUrl, err) + return nil + } + + return u +} +func (self *SLoadbalancerListenerRule) GetRedirectScheme() string { + u := self.getRedirectUrl() + if u == nil { + return "" + } + + return strings.ToLower(u.Scheme) +} + +func (self *SLoadbalancerListenerRule) GetRedirectHost() string { + u := self.getRedirectUrl() + if u == nil { + if self.redirect != nil && len(self.redirect.Properties.TargetListener.ID) > 0 { + segs := strings.Split(self.redirect.Properties.TargetListener.ID, "/") + return segs[len(segs)-1] + } + return "" + } + + return u.Host +} + +func (self *SLoadbalancerListenerRule) GetRedirectPath() string { + u := self.getRedirectUrl() + if u == nil { + return "" + } + + return u.Path +} diff --git a/pkg/multicloud/azure/region.go b/pkg/multicloud/azure/region.go index 35777aab7f..0ca8257da6 100644 --- a/pkg/multicloud/azure/region.go +++ b/pkg/multicloud/azure/region.go @@ -432,40 +432,122 @@ func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCre return region.CreateSecurityGroup(conf.Name) } +func (region *SRegion) getIAppLBs() ([]cloudprovider.ICloudLoadbalancer, error) { + lbs := []SLoadbalancer{} + params := url.Values{} + params.Set("api-version", "2021-02-01") + err := region.list("Microsoft.Network/applicationGateways", params, &lbs) + if err != nil { + return nil, errors.Wrapf(err, "list") + } + + ilbs := make([]cloudprovider.ICloudLoadbalancer, len(lbs)) + for i := range lbs { + lbs[i].region = region + ilbs[i] = &lbs[i] + } + + return ilbs, nil +} + +func (region *SRegion) getINetworkLBs() ([]cloudprovider.ICloudLoadbalancer, error) { + lbs := []SLoadbalancer{} + params := url.Values{} + params.Set("api-version", "2021-02-01") + err := region.list("Microsoft.Network/loadBalancers", params, &lbs) + if err != nil { + return nil, errors.Wrapf(err, "list") + } + + ilbs := make([]cloudprovider.ICloudLoadbalancer, len(lbs)) + for i := range lbs { + lbs[i].region = region + ilbs[i] = &lbs[i] + } + + return ilbs, nil +} + func (region *SRegion) GetILoadBalancers() ([]cloudprovider.ICloudLoadbalancer, error) { - return nil, cloudprovider.ErrNotImplemented + appLbs, err := region.getIAppLBs() + if err != nil { + return nil, errors.Wrap(err, "GetIAppLBs") + } + + netLbs, err := region.getINetworkLBs() + if err != nil { + return nil, errors.Wrap(err, "GetINetworkLBs") + } + + lbs := []cloudprovider.ICloudLoadbalancer{} + lbs = append(lbs, appLbs...) + lbs = append(lbs, netLbs...) + return lbs, nil } func (region *SRegion) GetILoadBalancerById(loadbalancerId string) (cloudprovider.ICloudLoadbalancer, error) { - return nil, cloudprovider.ErrNotImplemented + lb := SLoadbalancer{} + params := url.Values{} + params.Set("api-version", "2021-02-01") + err := region.get(loadbalancerId, params, &lb) + if err != nil { + return nil, errors.Wrapf(err, "get") + } + + lb.region = region + return &lb, nil } func (region *SRegion) GetILoadBalancerAclById(aclId string) (cloudprovider.ICloudLoadbalancerAcl, error) { - return nil, cloudprovider.ErrNotImplemented + return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetILoadBalancerAclById") } func (region *SRegion) GetILoadBalancerCertificateById(certId string) (cloudprovider.ICloudLoadbalancerCertificate, error) { - return nil, cloudprovider.ErrNotImplemented -} + segs := strings.Split(certId, "/sslCertificates") + if len(segs[0]) > 0 { + lb, err := region.GetILoadBalancerById(segs[0]) + if err != nil { + return nil, errors.Wrap(err, "GetILoadBalancerById") + } -func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { - return nil, cloudprovider.ErrNotImplemented -} + return lb.(*SLoadbalancer).GetILoadBalancerCertificateById(certId) + } -func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { - return nil, cloudprovider.ErrNotImplemented + return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetILoadBalancerCertificateById") } func (region *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadbalancerCertificate, error) { - return nil, cloudprovider.ErrNotImplemented + lbs, err := region.GetILoadBalancers() + if err != nil { + return nil, errors.Wrap(err, "GetILoadBalancers") + } + + certs := []cloudprovider.ICloudLoadbalancerCertificate{} + for i := range lbs { + _certs, err := lbs[i].(*SLoadbalancer).GetILoadBalancerCertificates() + if err != nil { + return nil, errors.Wrap(err, "GetILoadBalancerCertificates") + } + certs = append(certs, _certs...) + } + + return certs, nil +} + +func (region *SRegion) CreateILoadBalancerCertificate(cert *cloudprovider.SLoadbalancerCertificate) (cloudprovider.ICloudLoadbalancerCertificate, error) { + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerCertificate") +} + +func (region *SRegion) GetILoadBalancerAcls() ([]cloudprovider.ICloudLoadbalancerAcl, error) { + return nil, errors.Wrap(cloudprovider.ErrNotSupported, "GetILoadBalancerAcls") } func (region *SRegion) CreateILoadBalancer(loadbalancer *cloudprovider.SLoadbalancer) (cloudprovider.ICloudLoadbalancer, error) { - return nil, cloudprovider.ErrNotImplemented + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "GetILoadBalancerCertificates") } func (region *SRegion) CreateILoadBalancerAcl(acl *cloudprovider.SLoadbalancerAccessControlList) (cloudprovider.ICloudLoadbalancerAcl, error) { - return nil, cloudprovider.ErrNotImplemented + return nil, errors.Wrap(cloudprovider.ErrNotImplemented, "CreateILoadBalancerAcl") } func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) { diff --git a/pkg/multicloud/azure/shell/loadbalancer.go b/pkg/multicloud/azure/shell/loadbalancer.go new file mode 100644 index 0000000000..6f9d51fa46 --- /dev/null +++ b/pkg/multicloud/azure/shell/loadbalancer.go @@ -0,0 +1,125 @@ +package shell + +import ( + "strings" + + "yunion.io/x/onecloud/pkg/multicloud/azure" + "yunion.io/x/onecloud/pkg/util/shellutils" +) + +func init() { + type LoadbalancerListOptions struct { + } + shellutils.R(&LoadbalancerListOptions{}, "lb-list", "List loadbalancers", func(cli *azure.SRegion, args *LoadbalancerListOptions) error { + lbs, err := cli.GetILoadBalancers() + if err != nil { + return err + } + printList(lbs, len(lbs), 0, 0, []string{}) + return nil + }) + + type LoadbalancerOptions struct { + ID string `help:"ID of loadbalancer"` + } + shellutils.R(&LoadbalancerOptions{}, "lb-show", "Show loadbalancer", func(cli *azure.SRegion, args *LoadbalancerOptions) error { + lb, err := cli.GetILoadBalancerById(args.ID) + if err != nil { + return err + } + printObject(lb) + return nil + }) + + shellutils.R(&LoadbalancerListOptions{}, "lbcert-list", "List loadbalancers certs", func(cli *azure.SRegion, args *LoadbalancerListOptions) error { + certs, err := cli.GetILoadBalancerCertificates() + if err != nil { + return err + } + printList(certs, len(certs), 0, 0, []string{}) + return nil + }) + + type LoadbalancerCertOptions struct { + ID string `help:"ID of loadbalancer cert"` + } + + shellutils.R(&LoadbalancerCertOptions{}, "lbcert-show", "Show loadbalancer cert", func(cli *azure.SRegion, args *LoadbalancerCertOptions) error { + cert, err := cli.GetILoadBalancerCertificateById(args.ID) + if err != nil { + return err + } + printObject(cert) + return nil + }) + + shellutils.R(&LoadbalancerOptions{}, "lbl-list", "List loadbalancer listeners", func(cli *azure.SRegion, args *LoadbalancerOptions) error { + lb, err := cli.GetILoadBalancerById(args.ID) + if err != nil { + return err + } + lbl, err := lb.GetILoadBalancerListeners() + if err != nil { + return err + } + printList(lbl, len(lbl), 0, 0, []string{}) + return nil + }) + + shellutils.R(&LoadbalancerOptions{}, "lbbg-list", "List loadbalancer listeners", func(cli *azure.SRegion, args *LoadbalancerOptions) error { + lb, err := cli.GetILoadBalancerById(args.ID) + if err != nil { + return err + } + lbbgs, err := lb.GetILoadBalancerBackendGroups() + if err != nil { + return err + } + printList(lbbgs, len(lbbgs), 0, 0, []string{}) + return nil + }) + + type LoadbalancerBackendOptions struct { + BGID string `help:"ID of loadbalancer backendgroup"` + } + shellutils.R(&LoadbalancerBackendOptions{}, "lbb-list", "List loadbalancer listeners", func(cli *azure.SRegion, args *LoadbalancerBackendOptions) error { + lb, err := cli.GetILoadBalancerById(strings.Split(args.BGID, "/backendAddressPools")[0]) + if err != nil { + return err + } + lbbg, err := lb.GetILoadBalancerBackendGroupById(args.BGID) + if err != nil { + return err + } + + lbbs, err := lbbg.GetILoadbalancerBackends() + if err != nil { + return err + } + + printList(lbbs, len(lbbs), 0, 0, []string{}) + return nil + }) + + type LoadbalancerRuleOptions struct { + LISTENID string `help:"ID of loadbalancer listener"` + } + shellutils.R(&LoadbalancerRuleOptions{}, "lbr-list", "List loadbalancer listener rules", func(cli *azure.SRegion, args *LoadbalancerRuleOptions) error { + lb, err := cli.GetILoadBalancerById(strings.Split(args.LISTENID, "/urlPathMaps")[0]) + if err != nil { + return err + } + lbl, err := lb.GetILoadBalancerListenerById(args.LISTENID) + if err != nil { + return err + } + + lbrs, err := lbl.GetILoadbalancerListenerRules() + if err != nil { + return err + } + + printList(lbrs, len(lbrs), 0, 0, []string{}) + return nil + }) +} diff --git a/pkg/multicloud/huawei/loadbalancer_listener.go b/pkg/multicloud/huawei/loadbalancer_listener.go index 9c0e3d1e03..787caf17db 100644 --- a/pkg/multicloud/huawei/loadbalancer_listener.go +++ b/pkg/multicloud/huawei/loadbalancer_listener.go @@ -36,6 +36,7 @@ type Loadbalancer struct { type SElbListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.HuaweiTags lb *SLoadbalancer acl *SElbACL @@ -683,3 +684,11 @@ func (self *SRegion) CreateLoadBalancerPolicy(listenerID string, rule *cloudprov return l7policy, nil } + +func (self *SElbListener) GetClientIdleTimeout() int { + return 0 +} + +func (self *SElbListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/huawei/loadbalancer_listener_rule.go b/pkg/multicloud/huawei/loadbalancer_listener_rule.go index b149aece66..a23108e826 100644 --- a/pkg/multicloud/huawei/loadbalancer_listener_rule.go +++ b/pkg/multicloud/huawei/loadbalancer_listener_rule.go @@ -26,6 +26,7 @@ import ( type SElbListenerPolicy struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.HuaweiTags region *SRegion lb *SLoadbalancer diff --git a/pkg/multicloud/lbredirect_base.go b/pkg/multicloud/lbredirect_base.go new file mode 100644 index 0000000000..c4f94c87e8 --- /dev/null +++ b/pkg/multicloud/lbredirect_base.go @@ -0,0 +1,24 @@ +package multicloud + +type SLoadbalancerRedirectBase struct { +} + +func (self *SLoadbalancerRedirectBase) GetRedirect() string { + return "" +} + +func (self *SLoadbalancerRedirectBase) GetRedirectCode() int64 { + return 0 +} + +func (self *SLoadbalancerRedirectBase) GetRedirectScheme() string { + return "" +} + +func (self *SLoadbalancerRedirectBase) GetRedirectHost() string { + return "" +} + +func (self *SLoadbalancerRedirectBase) GetRedirectPath() string { + return "" +} diff --git a/pkg/multicloud/openstack/loadbalancerl7rule.go b/pkg/multicloud/openstack/loadbalancerl7rule.go index 2559c50a35..73f84cca93 100644 --- a/pkg/multicloud/openstack/loadbalancerl7rule.go +++ b/pkg/multicloud/openstack/loadbalancerl7rule.go @@ -38,6 +38,7 @@ type SLoadbalancerL7RuleCreateParams struct { type SLoadbalancerL7Rule struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.OpenStackTags policy *SLoadbalancerL7Policy CreatedAt string `json:"created_at"` diff --git a/pkg/multicloud/openstack/loadbalancerlistener.go b/pkg/multicloud/openstack/loadbalancerlistener.go index 41147b5833..0d70d649f1 100644 --- a/pkg/multicloud/openstack/loadbalancerlistener.go +++ b/pkg/multicloud/openstack/loadbalancerlistener.go @@ -85,6 +85,7 @@ type SInsertHeaders struct { type SLoadbalancerListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.OpenStackTags region *SRegion l7policies []SLoadbalancerL7Policy @@ -763,3 +764,11 @@ func (listener *SLoadbalancerListener) Sync(ctx context.Context, lblis *cloudpro func (listener *SLoadbalancerListener) GetProjectId() string { return listener.ProjectID } + +func (listener *SLoadbalancerListener) GetClientIdleTimeout() int { + return 0 +} + +func (listener *SLoadbalancerListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/qcloud/loadbalancer_listener.go b/pkg/multicloud/qcloud/loadbalancer_listener.go index 62d47c600d..19e9ed3791 100644 --- a/pkg/multicloud/qcloud/loadbalancer_listener.go +++ b/pkg/multicloud/qcloud/loadbalancer_listener.go @@ -70,6 +70,7 @@ type healthCheck struct { type SLBListener struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.QcloudTags lb *SLoadbalancer @@ -873,3 +874,11 @@ func certificateParams(t LB_TYPE, params map[string]string, cert *certificate, p func (self *SLBListener) GetProjectId() string { return self.lb.GetProjectId() } + +func (self *SLBListener) GetClientIdleTimeout() int { + return 0 +} + +func (self *SLBListener) GetBackendConnectTimeout() int { + return 0 +} diff --git a/pkg/multicloud/qcloud/loadbalancer_listenerrule.go b/pkg/multicloud/qcloud/loadbalancer_listenerrule.go index 5a340ec71e..2e828622a3 100644 --- a/pkg/multicloud/qcloud/loadbalancer_listenerrule.go +++ b/pkg/multicloud/qcloud/loadbalancer_listenerrule.go @@ -29,6 +29,7 @@ import ( type SLBListenerRule struct { multicloud.SResourceBase + multicloud.SLoadbalancerRedirectBase multicloud.QcloudTags listener *SLBListener