Files
cloudpods/pkg/compute/regiondrivers/huawei.go
2020-04-08 19:32:51 +08:00

2592 lines
96 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package regiondrivers
import (
"context"
"database/sql"
"fmt"
"regexp"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/utils"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
api "yunion.io/x/onecloud/pkg/apis/compute"
"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/validators"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/billing"
"yunion.io/x/onecloud/pkg/util/choices"
"yunion.io/x/onecloud/pkg/util/rand"
"yunion.io/x/onecloud/pkg/util/seclib2"
)
type SHuaWeiRegionDriver struct {
SManagedVirtualizationRegionDriver
}
func init() {
driver := SHuaWeiRegionDriver{}
models.RegisterRegionDriver(&driver)
}
func (self *SHuaWeiRegionDriver) GetProvider() string {
return api.CLOUD_PROVIDER_HUAWEI
}
func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
zoneV := validators.NewModelIdOrNameValidator("zone", "zone", ownerId)
managerIdV := validators.NewModelIdOrNameValidator("manager", "cloudprovider", ownerId)
addressTypeV := validators.NewStringChoicesValidator("address_type", api.LB_ADDR_TYPES)
networkV := validators.NewModelIdOrNameValidator("network", "network", ownerId)
keyV := map[string]validators.IValidator{
"status": validators.NewStringChoicesValidator("status", api.LB_STATUS_SPEC).Default(api.LB_STATUS_ENABLED),
"address_type": addressTypeV.Default(api.LB_ADDR_TYPE_INTRANET),
"network": networkV,
"zone": zoneV,
"manager": managerIdV,
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
// 检查网络可用
network := networkV.Model.(*models.SNetwork)
_, _, vpc, _, err := network.ValidateElbNetwork(nil)
if err != nil {
return nil, err
}
if managerIdV.Model.GetId() != vpc.ManagerId {
return nil, httperrors.NewInputParameterError("Loadbalancer's manager (%s(%s)) does not match vpc's(%s(%s)) (%s)", managerIdV.Model.GetName(), managerIdV.Model.GetId(), vpc.GetName(), vpc.GetId(), vpc.ManagerId)
}
// 公网ELB需要指定EIP
if addressTypeV.Value == api.LB_ADDR_TYPE_INTERNET {
eipV := validators.NewModelIdOrNameValidator("eip", "eip", nil)
if err := eipV.Validate(data); err != nil {
return nil, err
}
eip := eipV.Model.(*models.SElasticip)
if eip.Status != api.EIP_STATUS_READY {
return nil, fmt.Errorf("eip status not ready")
}
if len(eip.ExternalId) == 0 {
return nil, fmt.Errorf("eip external id is empty")
}
data.Set("eip_id", jsonutils.NewString(eip.ExternalId))
}
region := zoneV.Model.(*models.SZone).GetRegion()
if region == nil {
return nil, fmt.Errorf("getting region failed")
}
data.Set("network_type", jsonutils.NewString(api.LB_NETWORK_TYPE_VPC))
data.Set("cloudregion_id", jsonutils.NewString(region.GetId()))
data.Set("vpc_id", jsonutils.NewString(vpc.GetId()))
return self.SManagedVirtualizationRegionDriver.ValidateCreateLoadbalancerData(ctx, userCred, ownerId, data)
}
// https://support.huaweicloud.com/api-elb/zh-cn_topic_0143878053.html
func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerAclData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// 访问控制: 与listener是1v1的
// 关系创建时即需要与具体的listener绑定不能再变更listner。
// required: listener_id, acl_type: "white", acl_status: "on", manager,cloudregion,acl_entries
data, err := self.SManagedVirtualizationRegionDriver.ValidateCreateLoadbalancerAclData(ctx, userCred, data)
if err != nil {
return data, err
}
// todo: ownId ??
listenerV := validators.NewModelIdOrNameValidator("listener", "loadbalancerlistener", nil)
err = listenerV.Validate(data)
if err != nil {
return data, err
}
return data, nil
}
// func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// // requiredcertificate PEM格式private_keyPEM格式name
// return nil, httperrors.NewNotImplementedError("%s does not currently support creating loadbalancer certificate", self.GetProvider())
// }
// func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerBackendGroupData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, lb *models.SLoadbalancer, backends []cloudprovider.SLoadbalancerBackend) (*jsonutils.JSONDict, error) {
// data, err := self.SManagedVirtualizationRegionDriver.ValidateCreateLoadbalancerBackendGroupData(ctx, userCred, data, lb, backends)
// if err != nil {
// return data, err
// }
//
// listener_id, _ := data.GetString("listener_id")
// if len(listener_id) > 0 {
// ilistener, err := models.LoadbalancerListenerManager.FetchById(listener_id)
// if err != nil {
// return nil, err
// }
//
// _lbbgId := ilistener.(*models.SLoadbalancerListener).BackendGroupId
// if len(_lbbgId) > 0 {
// return nil, fmt.Errorf("loadbalancer listener %s aready binding with backendgroup %s", listener_id, _lbbgId)
// }
// }
//
// {
// protocolTypeV := validators.NewStringChoicesValidator("protocol_type", api.HUAWEI_LBBG_PROTOCOL_TYPES)
// keyV := map[string]validators.IValidator{
// "protocol_type": protocolTypeV,
// "scheduler": validators.NewStringChoicesValidator("scheduler", api.HUAWEI_LBBG_SCHDULERS),
// "sticky_session": validators.NewStringChoicesValidator("sticky_session", api.LB_BOOL_VALUES).Default(api.LB_BOOL_OFF),
// "sticky_session_type": validators.NewStringChoicesValidator("sticky_session_type", api.LB_STICKY_SESSION_TYPES).Default(api.LB_STICKY_SESSION_TYPE_INSERT),
// "sticky_session_cookie": validators.NewRegexpValidator("sticky_session_cookie", regexp.MustCompile(`\w+`)).Optional(true),
// "sticky_session_cookie_timeout": validators.NewNonNegativeValidator("sticky_session_cookie_timeout").Optional(true),
// }
//
// for _, v := range keyV {
// if err := v.Validate(data); err != nil {
// return nil, err
// }
// }
// }
//
// {
// // health check default depends on input parameters
// _t, _ := data.GetString("protocol_type")
// checkTypeV := models.LoadbalancerListenerManager.CheckTypeV(_t)
// keyVHealth := map[string]validators.IValidator{
// "health_check": validators.NewStringChoicesValidator("health_check", api.LB_BOOL_VALUES).Default(api.LB_BOOL_OFF),
// "health_check_type": checkTypeV,
//
// "health_check_domain": validators.NewDomainNameValidator("health_check_domain").AllowEmpty(true).Default(""),
// "health_check_path": validators.NewURLPathValidator("health_check_path").Default(""),
// "health_check_rise": validators.NewRangeValidator("health_check_rise", 1, 10).Default(3),
// "health_check_timeout": validators.NewRangeValidator("health_check_timeout", 1, 50).Default(5),
// "health_check_interval": validators.NewRangeValidator("health_check_interval", 1, 50).Default(5),
// }
// for _, v := range keyVHealth {
// if err := v.Validate(data); err != nil {
// return nil, err
// }
// }
// }
// return data, nil
// }
func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, backendType string, lb *models.SLoadbalancer, backendGroup *models.SLoadbalancerBackendGroup, backend db.IModel) (*jsonutils.JSONDict, error) {
ownerId := ctx.Value("ownerId").(mcclient.IIdentityProvider)
man := models.LoadbalancerBackendManager
backendTypeV := validators.NewStringChoicesValidator("backend_type", api.LB_BACKEND_TYPES)
keyV := map[string]validators.IValidator{
"backend_type": backendTypeV,
"weight": validators.NewRangeValidator("weight", 0, 100).Default(10),
"port": validators.NewPortValidator("port"),
"send_proxy": validators.NewStringChoicesValidator("send_proxy", api.LB_SENDPROXY_CHOICES).Default(api.LB_SENDPROXY_OFF),
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
var basename string
switch backendType {
case api.LB_BACKEND_GUEST:
backendV := validators.NewModelIdOrNameValidator("backend", "server", ownerId)
err := backendV.Validate(data)
if err != nil {
return nil, err
}
guest := backendV.Model.(*models.SGuest)
err = man.ValidateBackendVpc(lb, guest, backendGroup)
if err != nil {
return nil, err
}
address, err := models.LoadbalancerBackendManager.GetGuestAddress(guest)
if err != nil {
return nil, errors.Wrap(err, "huaWeiRegionDriver.ValidateCreateLoadbalancerBackendData.GetGuestAddress")
}
data.Set("address", jsonutils.NewString(address))
basename = guest.Name
backend = backendV.Model
case api.LB_BACKEND_HOST:
if !db.IsAdminAllowCreate(userCred, man) {
return nil, fmt.Errorf("only sysadmin can specify host as backend")
}
backendV := validators.NewModelIdOrNameValidator("backend", "host", userCred)
err := backendV.Validate(data)
if err != nil {
return nil, err
}
host := backendV.Model.(*models.SHost)
{
if len(host.AccessIp) == 0 {
return nil, fmt.Errorf("host %s has no access ip", host.GetId())
}
data.Set("address", jsonutils.NewString(host.AccessIp))
}
basename = host.Name
backend = backendV.Model
case api.LB_BACKEND_IP:
if !db.IsAdminAllowCreate(userCred, man) {
return nil, fmt.Errorf("only sysadmin can specify ip address as backend")
}
backendV := validators.NewIPv4AddrValidator("backend")
err := backendV.Validate(data)
if err != nil {
return nil, err
}
ip := backendV.IP.String()
data.Set("address", jsonutils.NewString(ip))
basename = ip
default:
return nil, fmt.Errorf("internal error: unexpected backend type %s", backendType)
}
name, _ := data.GetString("name")
if name == "" {
name = fmt.Sprintf("%s-%s-%s-%s", backendGroup.Name, backendType, basename, rand.String(4))
}
data.Set("name", jsonutils.NewString(name))
data.Set("manager_id", jsonutils.NewString(lb.GetCloudproviderId()))
data.Set("cloudregion_id", jsonutils.NewString(lb.GetRegionId()))
return data, nil
}
func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict, lb *models.SLoadbalancer, backendGroup db.IModel) (*jsonutils.JSONDict, error) {
listenerTypeV := validators.NewStringChoicesValidator("listener_type", api.LB_LISTENER_TYPES)
listenerPortV := validators.NewPortValidator("listener_port")
aclStatusV := validators.NewStringChoicesValidator("acl_status", api.LB_BOOL_VALUES)
aclTypeV := validators.NewStringChoicesValidator("acl_type", api.LB_ACL_TYPES)
aclV := validators.NewModelIdOrNameValidator("acl", "loadbalanceracl", ownerId)
keyV := map[string]validators.IValidator{
"status": validators.NewStringChoicesValidator("status", api.LB_STATUS_SPEC).Default(api.LB_STATUS_ENABLED),
"listener_type": listenerTypeV,
"listener_port": listenerPortV,
"send_proxy": validators.NewStringChoicesValidator("send_proxy", api.LB_SENDPROXY_CHOICES).Default(api.LB_SENDPROXY_OFF),
"acl_status": aclStatusV.Default(api.LB_BOOL_OFF),
"acl_type": aclTypeV.Optional(true),
"acl": aclV.Optional(true),
"scheduler": validators.NewStringChoicesValidator("scheduler", api.LB_SCHEDULER_TYPES),
"sticky_session": validators.NewStringChoicesValidator("sticky_session", api.LB_BOOL_VALUES).Default(api.LB_BOOL_OFF),
"sticky_session_type": validators.NewStringChoicesValidator("sticky_session_type", api.LB_STICKY_SESSION_TYPES).Default(api.LB_STICKY_SESSION_TYPE_INSERT),
"sticky_session_cookie": validators.NewRegexpValidator("sticky_session_cookie", regexp.MustCompile(`\w+`)).Optional(true),
"sticky_session_cookie_timeout": validators.NewNonNegativeValidator("sticky_session_cookie_timeout").Optional(true),
"x_forwarded_for": validators.NewBoolValidator("x_forwarded_for").Default(true),
"gzip": validators.NewBoolValidator("gzip").Default(false),
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
// listener uniqueness
listenerType := listenerTypeV.Value
err := models.LoadbalancerListenerManager.CheckListenerUniqueness(ctx, lb, listenerType, listenerPortV.Value)
if err != nil {
return nil, err
}
// backendgroup check
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != lb.Id {
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, lb.Id)
}
// https additional certificate check
if listenerType == api.LB_LISTENER_TYPE_HTTPS {
certV := validators.NewModelIdOrNameValidator("certificate", "loadbalancercertificate", ownerId)
tlsCipherPolicyV := validators.NewStringChoicesValidator("tls_cipher_policy", api.LB_TLS_CIPHER_POLICIES).Default(api.LB_TLS_CIPHER_POLICY_1_2)
httpsV := map[string]validators.IValidator{
"certificate": certV,
"tls_cipher_policy": tlsCipherPolicyV,
"enable_http2": validators.NewBoolValidator("enable_http2").Default(true),
}
if err := RunValidators(httpsV, data, false); err != nil {
return nil, err
}
}
// health check default depends on input parameters
checkTypeV := models.LoadbalancerListenerManager.CheckTypeV(listenerType)
keyVHealth := map[string]validators.IValidator{
"health_check": validators.NewStringChoicesValidator("health_check", api.LB_BOOL_VALUES).Default(api.LB_BOOL_ON),
"health_check_type": checkTypeV,
"health_check_domain": validators.NewDomainNameValidator("health_check_domain").AllowEmpty(true).Default(""),
"health_check_path": validators.NewURLPathValidator("health_check_path").Default(""),
"health_check_http_code": validators.NewStringMultiChoicesValidator("health_check_http_code", api.LB_HEALTH_CHECK_HTTP_CODES).Sep(",").Default(api.LB_HEALTH_CHECK_HTTP_CODE_DEFAULT),
"health_check_rise": validators.NewRangeValidator("health_check_rise", 1, 10).Default(3),
"health_check_timeout": validators.NewRangeValidator("health_check_timeout", 1, 50).Default(10),
"health_check_interval": validators.NewRangeValidator("health_check_interval", 1, 50).Default(5),
}
if err := RunValidators(keyVHealth, data, false); err != nil {
return nil, err
}
if t, _ := data.Int("health_check_rise"); t > 0 {
data.Set("health_check_fall", jsonutils.NewInt(t))
}
// acl check
if err := models.LoadbalancerListenerManager.ValidateAcl(aclStatusV, aclTypeV, aclV, data, api.CLOUD_PROVIDER_HUAWEI); err != nil {
return nil, err
}
data.Set("manager_id", jsonutils.NewString(lb.GetCloudproviderId()))
data.Set("cloudregion_id", jsonutils.NewString(lb.GetRegionId()))
return self.SManagedVirtualizationRegionDriver.ValidateCreateLoadbalancerListenerData(ctx, userCred, ownerId, data, lb, backendGroup)
}
func (self *SHuaWeiRegionDriver) ValidateCreateLoadbalancerListenerRuleData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict, backendGroup db.IModel) (*jsonutils.JSONDict, error) {
domainV := validators.NewDomainNameValidator("domain")
pathV := validators.NewURLPathValidator("path")
keyV := map[string]validators.IValidator{
"status": validators.NewStringChoicesValidator("status", api.LB_STATUS_SPEC).Default(api.LB_STATUS_ENABLED),
"domain": domainV.AllowEmpty(true).Default(""),
"path": pathV.Default(""),
"http_request_rate": validators.NewNonNegativeValidator("http_request_rate").Default(0),
"http_request_rate_per_src": validators.NewNonNegativeValidator("http_request_rate_per_src").Default(0),
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
listenerId, err := data.GetString("listener_id")
if err != nil {
return nil, err
}
ilistener, err := db.FetchById(models.LoadbalancerListenerManager, listenerId)
if err != nil {
return nil, err
}
listener := ilistener.(*models.SLoadbalancerListener)
listenerType := listener.ListenerType
if listenerType != api.LB_LISTENER_TYPE_HTTP && listenerType != api.LB_LISTENER_TYPE_HTTPS {
return nil, httperrors.NewInputParameterError("listener type must be http/https, got %s", listenerType)
}
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != listener.LoadbalancerId {
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, listener.LoadbalancerId)
}
err = models.LoadbalancerListenerRuleCheckUniqueness(ctx, listener, domainV.Value, pathV.Value)
if err != nil {
return nil, err
}
_, err = self.SManagedVirtualizationRegionDriver.ValidateCreateLoadbalancerListenerRuleData(ctx, userCred, ownerId, data, backendGroup)
if err != nil {
return data, err
}
domain, _ := data.GetString("domain")
path, _ := data.GetString("path")
if domain == "" && path == "" {
return data, fmt.Errorf("'domain' or 'path' should not be empty.")
}
data.Set("cloudregion_id", jsonutils.NewString(listener.GetRegionId()))
data.Set("manager_id", jsonutils.NewString(listener.GetCloudproviderId()))
return data, nil
}
func (self *SHuaWeiRegionDriver) ValidateUpdateLoadbalancerListenerRuleData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, backendGroup db.IModel) (*jsonutils.JSONDict, error) {
lbr := ctx.Value("lbr").(*models.SLoadbalancerListenerRule)
if backendGroup, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && backendGroup.Id != lbr.BackendGroupId {
listenerM, err := models.LoadbalancerListenerManager.FetchById(lbr.ListenerId)
if err != nil {
return nil, httperrors.NewInputParameterError("loadbalancerlistenerrule %s(%s): fetching listener %s failed",
lbr.Name, lbr.Id, lbr.ListenerId)
}
listener := listenerM.(*models.SLoadbalancerListener)
if backendGroup.LoadbalancerId != listener.LoadbalancerId {
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
backendGroup.Name, backendGroup.Id, backendGroup.LoadbalancerId, listener.LoadbalancerId)
}
}
return data, nil
}
// func (self *SHuaWeiRegionDriver) ValidateUpdateLoadbalancerCertificateData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// // requiredcertificate PEM格式private_keyPEM格式name id
// return nil, nil
// }
func (self *SHuaWeiRegionDriver) ValidateDeleteLoadbalancerBackendGroupCondition(ctx context.Context, lbbg *models.SLoadbalancerBackendGroup) error {
//删除pool之前必须删除pool上的所有member和healthmonitor并且pool不能被l7policy关联若要解除关联关系可通过更新转发策略将转测策略的redirect_pool_id更新为null。
count, err := lbbg.RefCount()
if err != nil {
return err
}
if count != 0 {
return fmt.Errorf("backendgroup is binding with loadbalancer/listener/listenerrule.")
}
return nil
}
func (self *SHuaWeiRegionDriver) ValidateUpdateLoadbalancerBackendData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, lbbg *models.SLoadbalancerBackendGroup) (*jsonutils.JSONDict, error) {
keyV := map[string]validators.IValidator{
"weight": validators.NewRangeValidator("weight", 0, 100).Optional(true),
"port": validators.NewPortValidator("port").Optional(true),
"send_proxy": validators.NewStringChoicesValidator("send_proxy", api.LB_SENDPROXY_CHOICES).Optional(true),
}
if err := RunValidators(keyV, data, true); err != nil {
return nil, err
}
// 只能更新权重。不能更新端口
port, err := data.Int("port")
if err == nil && port != 0 {
return data, fmt.Errorf("can not update backend port.")
}
return data, nil
}
// func (self *SHuaWeiRegionDriver) ValidateDeleteLoadbalancerBackendCondition(ctx context.Context, lbb *models.SLoadbalancerBackend) error {
// // requiredbackendgroup id, serverId
// return nil
// }
func (self *SHuaWeiRegionDriver) ValidateUpdateLoadbalancerListenerData(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, lblis *models.SLoadbalancerListener, backendGroup db.IModel) (*jsonutils.JSONDict, error) {
ownerId := lblis.GetOwnerId()
// todo: fix me here
aclStatusV := validators.NewStringChoicesValidator("acl_status", api.LB_BOOL_VALUES)
aclStatusV.Default(lblis.AclStatus)
aclTypeV := validators.NewStringChoicesValidator("acl_type", api.LB_ACL_TYPES)
if api.LB_ACL_TYPES.Has(lblis.AclType) {
aclTypeV.Default(lblis.AclType)
}
aclV := validators.NewModelIdOrNameValidator("acl", "loadbalanceracl", ownerId)
if len(lblis.AclId) > 0 {
aclV.Default(lblis.AclId)
}
certV := validators.NewModelIdOrNameValidator("certificate", "loadbalancercertificate", ownerId)
tlsCipherPolicyV := validators.NewStringChoicesValidator("tls_cipher_policy", api.LB_TLS_CIPHER_POLICIES).Default(api.LB_TLS_CIPHER_POLICY_1_2)
keyV := map[string]validators.IValidator{
"send_proxy": validators.NewStringChoicesValidator("send_proxy", api.LB_SENDPROXY_CHOICES),
"scheduler": validators.NewStringChoicesValidator("scheduler", api.LB_SCHEDULER_TYPES),
"acl_status": aclStatusV,
"acl_type": aclTypeV,
"acl": aclV,
"sticky_session": validators.NewStringChoicesValidator("sticky_session", api.LB_BOOL_VALUES),
"sticky_session_type": validators.NewStringChoicesValidator("sticky_session_type", api.LB_STICKY_SESSION_TYPES),
"sticky_session_cookie": validators.NewRegexpValidator("sticky_session_cookie", regexp.MustCompile(`\w+`)),
"sticky_session_cookie_timeout": validators.NewNonNegativeValidator("sticky_session_cookie_timeout"),
"health_check": validators.NewStringChoicesValidator("health_check", api.LB_BOOL_VALUES),
"health_check_type": models.LoadbalancerListenerManager.CheckTypeV(lblis.ListenerType),
"health_check_domain": validators.NewDomainNameValidator("health_check_domain").AllowEmpty(true).Default(""),
"health_check_path": validators.NewURLPathValidator("health_check_path").Default(""),
"health_check_http_code": validators.NewStringMultiChoicesValidator("health_check_http_code", api.LB_HEALTH_CHECK_HTTP_CODES).Sep(",").Default(api.LB_HEALTH_CHECK_HTTP_CODE_DEFAULT),
"health_check_rise": validators.NewRangeValidator("health_check_rise", 1, 10).Default(3),
"health_check_timeout": validators.NewRangeValidator("health_check_timeout", 1, 50).Default(10),
"health_check_interval": validators.NewRangeValidator("health_check_interval", 1, 50).Default(5),
"x_forwarded_for": validators.NewBoolValidator("x_forwarded_for"),
"gzip": validators.NewBoolValidator("gzip"),
"certificate": certV,
"tls_cipher_policy": tlsCipherPolicyV,
"enable_http2": validators.NewBoolValidator("enable_http2"),
}
if err := RunValidators(keyV, data, true); err != nil {
return nil, err
}
if t, _ := data.Int("health_check_rise"); t > 0 {
data.Set("health_check_fall", jsonutils.NewInt(t))
}
{
if lbbg, ok := backendGroup.(*models.SLoadbalancerBackendGroup); ok && lbbg.LoadbalancerId != lblis.LoadbalancerId {
return nil, httperrors.NewInputParameterError("backend group %s(%s) belongs to loadbalancer %s instead of %s",
lbbg.Name, lbbg.Id, lbbg.LoadbalancerId, lblis.LoadbalancerId)
}
}
return self.SManagedVirtualizationRegionDriver.ValidateUpdateLoadbalancerListenerData(ctx, userCred, data, lblis, backendGroup)
}
func (self *SHuaWeiRegionDriver) createCachedLbbg(lb *models.SLoadbalancer, lblis *models.SLoadbalancerListener, lbr *models.SLoadbalancerListenerRule, lbbg *models.SLoadbalancerBackendGroup) (*models.SHuaweiCachedLbbg, error) {
// create loadbalancer backendgroup cache
cachedLbbg := &models.SHuaweiCachedLbbg{}
cachedLbbg.ManagerId = lb.GetCloudproviderId()
cachedLbbg.CloudregionId = lb.GetRegionId()
cachedLbbg.LoadbalancerId = lb.GetId()
cachedLbbg.BackendGroupId = lbbg.GetId()
if lbr != nil {
cachedLbbg.AssociatedType = api.LB_ASSOCIATE_TYPE_RULE
cachedLbbg.AssociatedId = lbr.GetId()
cachedLbbg.ProtocolType = lblis.ListenerType
} else {
cachedLbbg.AssociatedType = api.LB_ASSOCIATE_TYPE_LISTENER
cachedLbbg.AssociatedId = lblis.GetId()
cachedLbbg.ProtocolType = lblis.ListenerType
}
err := models.HuaweiCachedLbbgManager.TableSpec().Insert(cachedLbbg)
if err != nil {
return nil, err
}
cachedLbbg.SetModelManager(models.HuaweiCachedLbbgManager, cachedLbbg)
return cachedLbbg, nil
}
func (self *SHuaWeiRegionDriver) syncCloudlbbs(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, cachedLbbg *models.SHuaweiCachedLbbg, extlbbg cloudprovider.ICloudLoadbalancerBackendGroup, backends []cloudprovider.SLoadbalancerBackend) error {
ibackends, err := extlbbg.GetILoadbalancerBackends()
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.syncCloudLoadbalancerBackends.GetILoadbalancerBackends")
}
for i := range ibackends {
ibackend := ibackends[i]
err = extlbbg.RemoveBackendServer(ibackend.GetId(), ibackend.GetWeight(), ibackend.GetPort())
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.syncCloudLoadbalancerBackends.RemoveBackendServer")
}
}
for _, backend := range backends {
_, err = extlbbg.AddBackendServer(backend.ExternalID, backend.Weight, backend.Port)
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.syncCloudLoadbalancerBackends.AddBackendServer")
}
}
return nil
}
func (self *SHuaWeiRegionDriver) syncCachedLbbs(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, lbbg *models.SHuaweiCachedLbbg, extlbbg cloudprovider.ICloudLoadbalancerBackendGroup) error {
iBackends, err := extlbbg.GetILoadbalancerBackends()
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.syncLoadbalancerBackendCaches.GetILoadbalancerBackends")
}
if len(iBackends) > 0 {
provider := lb.GetCloudprovider()
if provider == nil {
return fmt.Errorf("failed to find cloudprovider for lb %s", lb.Name)
}
result := models.HuaweiCachedLbManager.SyncLoadbalancerBackends(ctx, userCred, provider, lbbg, iBackends, &models.SSyncRange{})
if result.IsError() {
return errors.Wrap(result.AllError(), "HuaWeiRegionDriver.syncLoadbalancerBackendCaches.SyncLoadbalancerBackends")
}
}
return nil
}
func (self *SHuaWeiRegionDriver) createLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, lbr *models.SLoadbalancerListenerRule, lbbg *models.SLoadbalancerBackendGroup, backends []cloudprovider.SLoadbalancerBackend) (jsonutils.JSONObject, error) {
if len(lblis.ListenerType) == 0 {
return nil, fmt.Errorf("loadbalancer backendgroup missing protocol type")
}
iRegion, err := lbbg.GetIRegion()
if err != nil {
return nil, err
}
lb := lbbg.GetLoadbalancer()
if lb == nil {
return nil, fmt.Errorf("failed to find loadbalancer for backendgroup %s", lbbg.Name)
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId)
if err != nil {
return nil, err
}
cachedLbbg, err := self.createCachedLbbg(lb, lblis, lbr, lbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.createLoadbalancerBackendGroupCache")
}
group, err := lbbg.GetHuaweiBackendGroupParams(lblis, lbr)
if err != nil {
return nil, err
}
iLoadbalancerBackendGroup, err := iLoadbalancer.CreateILoadBalancerBackendGroup(group)
if err != nil {
return nil, err
}
if err := db.SetExternalId(cachedLbbg, userCred, iLoadbalancerBackendGroup.GetGlobalId()); err != nil {
return nil, err
}
err = self.syncCloudlbbs(ctx, userCred, lb, cachedLbbg, iLoadbalancerBackendGroup, backends)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.createLoadbalancerBackendGroup.syncCloudLoadbalancerBackends")
}
err = self.syncCachedLbbs(ctx, userCred, lb, cachedLbbg, iLoadbalancerBackendGroup)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.createLoadbalancerBackendGroup.syncLoadbalancerBackendCaches")
}
return nil, nil
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, backends []cloudprovider.SLoadbalancerBackend, task taskman.ITask) error {
// 未指定listenerId或ruleId情况下跳过远端创建步骤
listenerId, _ := task.GetParams().GetString("listenerId")
ruleId, _ := task.GetParams().GetString("ruleId")
if len(listenerId) == 0 && len(ruleId) == 0 {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
return nil, nil
})
return nil
}
var rule *models.SLoadbalancerListenerRule
var listener *models.SLoadbalancerListener
if len(ruleId) > 0 {
_rule, err := db.FetchById(models.LoadbalancerListenerRuleManager, ruleId)
if err != nil {
return err
}
rule = _rule.(*models.SLoadbalancerListenerRule)
listener = rule.GetLoadbalancerListener()
} else {
_listener, err := db.FetchById(models.LoadbalancerListenerManager, listenerId)
if err != nil {
return err
}
listener = _listener.(*models.SLoadbalancerListener)
}
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
return self.createLoadbalancerBackendGroup(ctx, userCred, listener, rule, lbbg, backends)
})
return nil
}
func (self *SHuaWeiRegionDriver) createLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SCachedLoadbalancerAcl) (jsonutils.JSONObject, error) {
iRegion, err := lbacl.GetIRegion()
if err != nil {
return nil, err
}
listener, err := lbacl.GetListener()
if err != nil {
return nil, err
}
acl := &cloudprovider.SLoadbalancerAccessControlList{
ListenerId: listener.GetExternalId(),
Name: lbacl.Name,
Entrys: []cloudprovider.SLoadbalancerAccessControlListEntry{},
AccessControlEnable: listener.AclStatus == api.LB_BOOL_ON,
}
_originAcl, err := db.FetchById(models.LoadbalancerAclManager, lbacl.AclId)
if err != nil {
return nil, errors.Wrap(err, "huaWeiRegionDriver.FetchAcl")
}
originAcl := _originAcl.(*models.SLoadbalancerAcl)
if originAcl.AclEntries != nil {
for _, entry := range *originAcl.AclEntries {
acl.Entrys = append(acl.Entrys, cloudprovider.SLoadbalancerAccessControlListEntry{CIDR: entry.Cidr, Comment: entry.Comment})
}
}
iLoadbalancerAcl, err := iRegion.CreateILoadBalancerAcl(acl)
if err != nil {
return nil, err
}
lbacl.SetModelManager(models.CachedLoadbalancerAclManager, lbacl)
if err := db.SetExternalId(lbacl, userCred, iLoadbalancerAcl.GetGlobalId()); err != nil {
return nil, err
}
return nil, lbacl.SyncWithCloudLoadbalancerAcl(ctx, userCred, iLoadbalancerAcl, listener.GetOwnerId())
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SCachedLoadbalancerAcl, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
return self.createLoadbalancerAcl(ctx, userCred, lbacl)
})
return nil
}
func (self *SHuaWeiRegionDriver) updateCachedLbbg(ctx context.Context, cachedLbbg *models.SHuaweiCachedLbbg, backendGroupId string, externalBackendGroupId string, asscoicateId string, asscoicateType string) error {
_, err := db.UpdateWithLock(ctx, cachedLbbg, func() error {
if len(backendGroupId) > 0 {
cachedLbbg.BackendGroupId = backendGroupId
}
if len(externalBackendGroupId) > 0 {
cachedLbbg.ExternalId = externalBackendGroupId
}
if len(asscoicateId) > 0 {
cachedLbbg.AssociatedId = asscoicateId
}
if len(asscoicateType) > 0 {
cachedLbbg.AssociatedType = asscoicateType
}
return nil
})
if err != nil {
return err
}
return nil
}
func (self *SHuaWeiRegionDriver) validatorCachedLbbgConflict(ilb cloudprovider.ICloudLoadbalancer, lblis *models.SLoadbalancerListener, olbbg *models.SHuaweiCachedLbbg, nlbbg *models.SHuaweiCachedLbbg, rlbbg *models.SHuaweiCachedLbbg) error {
if rlbbg == nil {
return nil
}
if len(rlbbg.AssociatedId) > 0 && lblis.GetId() != rlbbg.AssociatedId {
return fmt.Errorf("sync required, backend group aready assoicate with %s %s", rlbbg.AssociatedType, rlbbg.AssociatedId)
}
if olbbg != nil && len(rlbbg.AssociatedId) > 0 && rlbbg.AssociatedId != olbbg.AssociatedId {
// 与本地关联状态不一致
return fmt.Errorf("sync required, backend group aready assoicate with %s %s", rlbbg.AssociatedType, rlbbg.AssociatedId)
}
if nlbbg != nil && len(nlbbg.ExternalId) > 0 {
// 需绑定的服务器组,被人为删除了
_, err := ilb.GetILoadBalancerBackendGroupById(nlbbg.GetExternalId())
if err != nil {
return fmt.Errorf("sync required, validatorCachedLbbgConflict.GetILoadBalancerBackendGroupById %s", err)
}
// 需绑定的服务器组,被人为关联了其他监听或者监听规则
listeners, err := ilb.GetILoadBalancerListeners()
if err != nil {
return fmt.Errorf("sync required, validatorCachedLbbgConflict.GetILoadBalancerListeners %s", err)
}
for i := range listeners {
listener := listeners[i]
if bgId := listener.GetBackendGroupId(); len(bgId) > 0 && bgId == nlbbg.ExternalId && listener.GetGlobalId() != lblis.GetExternalId() {
return fmt.Errorf("sync required, backend group aready assoicate with listener %s(external id )", listener.GetGlobalId())
}
rules, err := listener.GetILoadbalancerListenerRules()
if err != nil {
return fmt.Errorf("sync required, validatorCachedLbbgConflict.GetILoadbalancerListenerRules %s", err)
}
for j := range rules {
rule := rules[j]
if bgId := rule.GetBackendGroupId(); len(bgId) > 0 && bgId == nlbbg.ExternalId {
return fmt.Errorf("sync required, backend group aready assoicate with rule %s(external id )", rule.GetGlobalId())
}
}
}
}
return nil
}
func (self *SHuaWeiRegionDriver) removeCachedLbbg(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SHuaweiCachedLbbg) error {
backends, err := lbbg.GetCachedBackends()
if err != nil && err != sql.ErrNoRows {
return errors.Wrap(err, "huaweiRegionDriver.GetCachedBackends")
}
for i := range backends {
err = db.DeleteModel(ctx, userCred, &backends[i])
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.DeleteModel")
}
}
err = db.DeleteModel(ctx, userCred, lbbg)
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.DeleteModel")
}
return nil
}
func (self *SHuaWeiRegionDriver) RequestSyncLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
lbbg := lblis.GetLoadbalancerBackendGroup()
if lbbg == nil {
err := fmt.Errorf("failed to find lbbg for lblis %s", lblis.Name)
return nil, errors.Wrap(err, "HuaWeiRegionDriver.RequestSyncLoadbalancerbackendGroup.GetLoadbalancerBackendGroup")
}
iRegion, err := lbbg.GetIRegion()
if err != nil {
return nil, err
}
lb := lbbg.GetLoadbalancer()
ilb, err := iRegion.GetILoadBalancerById(lb.GetExternalId())
if err != nil {
return nil, err
}
provider := lb.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(fmt.Errorf("provider is nil"), "HuaWeiRegionDriver.RequestSyncLoadbalancerBackendGroup.GetCloudprovider")
}
ilisten, err := ilb.GetILoadBalancerListenerById(lblis.GetExternalId())
if err != nil {
return nil, err
}
// new group params
groupInput, err := lbbg.GetHuaweiBackendGroupParams(lblis, nil)
if err != nil {
return nil, errors.Wrap(err, "GetHuaweiBackendGroupParams")
}
// new backends params
backendsInput, err := lbbg.GetBackendsParams()
if err != nil {
return nil, err
}
{
var olbbg, nlbbg, rlbbg *models.SHuaweiCachedLbbg
// current related cachedLbbg
olbbg, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroupByAssociateId(lblis.GetId())
if err != nil {
if err != sql.ErrNoRows {
return nil, errors.Wrap(fmt.Errorf("provider is nil"), "HuaWeiRegionDriver.RequestSyncLoadbalancerBackendGroup.GetCachedBackendGroupByAssociateId")
}
}
// new related backendgroup
if olbbg == nil || olbbg.BackendGroupId != lbbg.GetId() {
nlbbg, err = models.HuaweiCachedLbbgManager.GetUsableCachedBackendGroup(lbbg.GetId(), lblis.ListenerType)
if err != nil {
if err != sql.ErrNoRows {
return nil, errors.Wrap(fmt.Errorf("provider is nil"), "HuaWeiRegionDriver.RequestSyncLoadbalancerBackendGroup.GetUsableCachedBackendGroup")
}
}
}
// remote relasted backendgroup
rlbbgId := ilisten.GetBackendGroupId()
if len(rlbbgId) > 0 {
_rlbbg, err := db.FetchByExternalId(models.HuaweiCachedLbbgManager, rlbbgId)
if err != nil {
if err != sql.ErrNoRows {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.RequestSyncLoadbalancerBackendGroup.FetchByExternalId")
}
}
rlbbg = _rlbbg.(*models.SHuaweiCachedLbbg)
}
// validator confilct
err = self.validatorCachedLbbgConflict(ilb, lblis, olbbg, nlbbg, rlbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.validatorCachedLbbgConflict")
}
// case 1新绑定,创建本地缓存,并创建远端服务器组
if olbbg == nil && nlbbg == nil && rlbbg == nil {
if _, err := self.createLoadbalancerBackendGroup(ctx, task.GetUserCred(), lblis, nil, lbbg, backendsInput); err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case1.createLoadbalancerBackendGroup")
}
}
// case 2新绑定,创建本地缓存
if olbbg == nil && nlbbg == nil && rlbbg != nil {
cachedLbbg, err := self.createCachedLbbg(lb, lblis, nil, lbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case2.createCachedLbbg")
}
err = db.SetExternalId(cachedLbbg, userCred, rlbbgId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case2.SetExternalId")
}
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(rlbbgId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case2.GetILoadBalancerBackendGroupById")
}
err = self.syncCloudlbbs(ctx, userCred, lb, cachedLbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case2.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, cachedLbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case2.syncCloudlbbs")
}
}
// case 3新绑定, 关联并同步
if olbbg == nil && nlbbg != nil && rlbbg == nil {
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(nlbbg.GetExternalId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.GetILoadBalancerBackendGroupById")
}
err = db.SetExternalId(nlbbg, userCred, ilbbg.GetGlobalId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case3.SetExternalId")
}
err = self.syncCloudlbbs(ctx, userCred, lb, nlbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case3.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, nlbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case3.syncCloudlbbs")
}
}
// case 4新绑定, 关联rlbbg并同步
if olbbg == nil && nlbbg != nil && rlbbg != nil {
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(rlbbgId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.GetILoadBalancerBackendGroupById")
}
err = db.SetExternalId(nlbbg, userCred, ilbbg.GetGlobalId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.SetExternalId")
}
err = self.syncCloudlbbs(ctx, userCred, lb, nlbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, nlbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.syncCloudlbbs")
}
}
// case 5已绑定,更新原有缓存
if olbbg != nil && nlbbg == nil && rlbbg == nil {
ilbbg, err := ilb.CreateILoadBalancerBackendGroup(groupInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case5.CreateILoadBalancerBackendGroup")
}
err = self.updateCachedLbbg(ctx, olbbg, lbbg.GetId(), ilbbg.GetGlobalId(), "", "")
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case5.updateCachedLbbg")
}
err = self.syncCloudlbbs(ctx, userCred, lb, olbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, olbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case4.syncCloudlbbs")
}
}
// case 6已绑定, 更新olbbg并同步
if olbbg != nil && nlbbg == nil && rlbbg != nil {
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(rlbbgId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.GetILoadBalancerBackendGroupById")
}
err = self.updateCachedLbbg(ctx, olbbg, lbbg.GetId(), ilbbg.GetGlobalId(), "", "")
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.updateCachedLbbg")
}
err = self.syncCloudlbbs(ctx, userCred, lb, olbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, olbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
}
// case 7已绑定, 更新olbbg并同步
if olbbg != nil && nlbbg != nil && rlbbg == nil {
err := self.removeCachedLbbg(ctx, userCred, olbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case7.removeCachedLbbg")
}
err = self.updateCachedLbbg(ctx, nlbbg, lbbg.GetId(), "", lblis.GetId(), api.LB_ASSOCIATE_TYPE_LISTENER)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case7.updateCachedLbbg")
}
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(nlbbg.GetExternalId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case7.GetILoadBalancerBackendGroupById")
}
err = self.syncCloudlbbs(ctx, userCred, lb, nlbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, nlbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
}
// case 8已绑定, 更新olbbg并同步
if olbbg != nil && nlbbg != nil && rlbbg != nil {
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(rlbbgId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case8.GetILoadBalancerBackendGroupById")
}
err = deleteHuaweiLoadbalancerBackendGroup(ctx, userCred, ilb, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case8.deleteHuaweiLoadbalancerBackendGroup")
}
err = deleteHuaweiCachedLbbg(ctx, userCred, lblis.GetId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case8.deleteHuaweiCachedLbbg")
}
err = self.updateCachedLbbg(ctx, nlbbg, lbbg.GetId(), "", lblis.GetId(), api.LB_ASSOCIATE_TYPE_LISTENER)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case8.updateCachedLbbg")
}
err = self.syncCloudlbbs(ctx, userCred, lb, nlbbg, ilbbg, backendsInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
err = self.syncCachedLbbs(ctx, userCred, lb, nlbbg, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.Case6.syncCloudlbbs")
}
}
}
// continue here
cachedLbbg, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroupByAssociateId(lblis.GetId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.GetCachedBackendGroupByAssociateId")
}
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(cachedLbbg.GetExternalId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.GetILoadBalancerBackendGroupById")
}
err = ilbbg.Sync(ctx, groupInput)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.LoadbalancerBackendGroup")
}
if err := cachedLbbg.SyncWithCloudLoadbalancerBackendgroup(ctx, task.GetUserCred(), lb, ilbbg, lb.GetOwnerId(), lb.GetCloudprovider()); err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Sync.SyncWithCloudLoadbalancerBackendgroup")
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestPullRegionLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, syncResults models.SSyncResultSet, provider *models.SCloudprovider, localRegion *models.SCloudregion, remoteRegion cloudprovider.ICloudRegion, syncRange *models.SSyncRange) error {
return nil
}
func (self *SHuaWeiRegionDriver) RequestPullLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, syncResults models.SSyncResultSet, provider *models.SCloudprovider, localLoadbalancer *models.SLoadbalancer, remoteLoadbalancer cloudprovider.ICloudLoadbalancer, syncRange *models.SSyncRange) error {
models.SyncHuaweiLoadbalancerBackendgroups(ctx, userCred, syncResults, provider, localLoadbalancer, remoteLoadbalancer, syncRange)
return nil
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
{
certId, _ := task.GetParams().GetString("certificate_id")
if len(certId) > 0 {
provider := lblis.GetCloudprovider()
if provider == nil {
return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name)
}
cert, err := models.LoadbalancerCertificateManager.FetchById(certId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.FetchById")
}
lbcert, err := models.CachedLoadbalancerCertificateManager.GetOrCreateCachedCertificate(ctx, userCred, provider, lblis, cert.(*models.SLoadbalancerCertificate))
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.GetOrCreateCachedCertificate")
}
if len(lbcert.ExternalId) == 0 {
_, err = self.createLoadbalancerCertificate(ctx, userCred, lbcert)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.createLoadbalancerCertificate")
}
}
_, err = db.Update(lblis, func() error {
lblis.CachedCertificateId = lbcert.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.UpdateCachedCertificateId")
}
}
}
params, err := lblis.GetHuaweiLoadbalancerListenerParams()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.GetHuaweiLoadbalancerListenerParams")
}
loadbalancer := lblis.GetLoadbalancer()
if loadbalancer == nil {
return nil, fmt.Errorf("failed to find loadbalancer for lblis %s", lblis.Name)
}
iRegion, err := loadbalancer.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.GetIRegion")
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.GetILoadBalancerById")
}
iListener, err := iLoadbalancer.CreateILoadBalancerListener(ctx, params)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.CreateILoadBalancerListener")
}
lblis.SetModelManager(models.LoadbalancerListenerManager, lblis)
if err := db.SetExternalId(lblis, userCred, iListener.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.SetExternalId")
}
{
aclId, _ := task.GetParams().GetString("acl_id")
if len(aclId) > 0 {
provider := lblis.GetCloudprovider()
if provider == nil {
return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name)
}
acl, err := models.LoadbalancerAclManager.FetchById(aclId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.FetchAclById")
}
lbacl, err := models.CachedLoadbalancerAclManager.GetOrCreateCachedAcl(ctx, userCred, provider, lblis, acl.(*models.SLoadbalancerAcl))
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.GetOrCreateCachedAcl")
}
if len(lbacl.ExternalId) == 0 {
_, err = self.createLoadbalancerAcl(ctx, userCred, lbacl)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.createLoadbalancerAcl")
}
}
_, err = db.Update(lblis, func() error {
lblis.CachedAclId = lbacl.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListener.UpdateCachedAclId")
}
}
}
return nil, lblis.SyncWithCloudLoadbalancerListener(ctx, userCred, loadbalancer, iListener, loadbalancer.GetOwnerId(), loadbalancer.GetCloudprovider())
})
return nil
}
func (self *SHuaWeiRegionDriver) syncLoadbalancerAcl(ctx context.Context, userCred mcclient.TokenCredential, lbacl *models.SCachedLoadbalancerAcl) (jsonutils.JSONObject, error) {
iRegion, err := lbacl.GetIRegion()
if err != nil {
return nil, err
}
acl := &cloudprovider.SLoadbalancerAccessControlList{
Name: lbacl.Name,
Entrys: []cloudprovider.SLoadbalancerAccessControlListEntry{},
}
lblis, err := lbacl.GetListener()
if err == nil {
if api.LB_BOOL_ON == lblis.AclStatus {
acl.AccessControlEnable = true
}
} else {
return nil, fmt.Errorf("huaweiRegionDriver.syncLoadbalancerAcl %s", err)
}
_localAcl, err := db.FetchById(models.LoadbalancerAclManager, lbacl.AclId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.FetchById.LoaclAcl")
}
localAcl := _localAcl.(*models.SLoadbalancerAcl)
if localAcl.AclEntries != nil {
for _, entry := range *localAcl.AclEntries {
acl.Entrys = append(acl.Entrys, cloudprovider.SLoadbalancerAccessControlListEntry{CIDR: entry.Cidr, Comment: entry.Comment})
}
}
lockman.LockRawObject(ctx, "acl", lbacl.Id)
defer lockman.ReleaseRawObject(ctx, "acl", lbacl.Id)
iLoadbalancerAcl, err := iRegion.GetILoadBalancerAclById(lbacl.ExternalId)
if err != nil {
return nil, err
}
return nil, iLoadbalancerAcl.Sync(acl)
}
func (self *SHuaWeiRegionDriver) RequestSyncLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
{
certId, _ := task.GetParams().GetString("certificate_id")
if len(certId) > 0 {
provider := lblis.GetCloudprovider()
if provider == nil {
return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name)
}
cert, err := models.LoadbalancerCertificateManager.FetchById(certId)
if err != nil {
return nil, err
}
lbcert, err := models.CachedLoadbalancerCertificateManager.GetOrCreateCachedCertificate(ctx, userCred, provider, lblis, cert.(*models.SLoadbalancerCertificate))
if err != nil {
return nil, err
}
if len(lbcert.ExternalId) == 0 {
_, err = self.createLoadbalancerCertificate(ctx, userCred, lbcert)
if err != nil {
return nil, err
}
}
_, err = db.Update(lblis, func() error {
lblis.CachedCertificateId = lbcert.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerListener.UpdateCachedCertificateId")
}
}
}
params, err := lblis.GetHuaweiLoadbalancerListenerParams()
if err != nil {
return nil, err
}
loadbalancer := lblis.GetLoadbalancer()
if loadbalancer == nil {
return nil, fmt.Errorf("failed to find loadbalancer for lblis %s", lblis.Name)
}
iRegion, err := loadbalancer.GetIRegion()
if err != nil {
return nil, err
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId)
if err != nil {
return nil, err
}
iListener, err := iLoadbalancer.GetILoadBalancerListenerById(lblis.ExternalId)
if err != nil {
return nil, err
}
if err := iListener.Sync(ctx, params); err != nil {
return nil, err
}
{
aclId, _ := task.GetParams().GetString("acl_id")
if len(aclId) > 0 {
provider := lblis.GetCloudprovider()
if provider == nil {
return nil, fmt.Errorf("failed to find provider for lblis %s", lblis.Name)
}
var lbacl *models.SCachedLoadbalancerAcl
// 先读取缓存缓存不存在的情况下从ACL表中取数据创建缓存
if _lbacl, err := models.CachedLoadbalancerAclManager.FetchById(aclId); err == nil && _lbacl != nil {
lbacl = _lbacl.(*models.SCachedLoadbalancerAcl)
} else {
acl, err := models.LoadbalancerAclManager.FetchById(aclId)
if err != nil {
return nil, err
}
lbacl, err = models.CachedLoadbalancerAclManager.GetOrCreateCachedAcl(ctx, userCred, provider, lblis, acl.(*models.SLoadbalancerAcl))
if err != nil {
return nil, err
}
}
if len(lbacl.ExternalId) == 0 {
_, err = self.createLoadbalancerAcl(ctx, userCred, lbacl)
if err != nil {
return nil, err
}
} else {
_, err = self.syncLoadbalancerAcl(ctx, userCred, lbacl)
if err != nil {
return nil, err
}
}
_, err = db.Update(lblis, func() error {
lblis.CachedAclId = lbacl.GetId()
return nil
})
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerListener.UpdateCachedAclId")
}
}
}
if err := iListener.Refresh(); err != nil {
return nil, err
}
return nil, lblis.SyncWithCloudLoadbalancerListener(ctx, userCred, loadbalancer, iListener, lblis.GetOwnerId(), lblis.GetCloudprovider())
})
return nil
}
func deleteHuaweiLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, ilb cloudprovider.ICloudLoadbalancer, irule cloudprovider.ICloudLoadbalancerListenerRule) error {
err := irule.Refresh()
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil
}
return errors.Wrap(err, "HuaWeiRegionDriver.Rule.Refresh")
}
lbbgId := irule.GetBackendGroupId()
err = irule.Delete(ctx)
if err != nil && err != cloudprovider.ErrNotFound {
return errors.Wrap(err, "HuaWeiRegionDriver.Rule.Delete")
}
// delete backendgroup
if len(lbbgId) > 0 {
ilbbg, err := ilb.GetILoadBalancerBackendGroupById(lbbgId)
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil
}
return errors.Wrap(err, "HuaWeiRegionDriver.Rule.GetILoadBalancerBackendGroupById")
}
err = deleteHuaweiLoadbalancerBackendGroup(ctx, userCred, ilb, ilbbg)
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.Rule.deleteHuaweiLoadbalancerBackendGroup")
}
}
return nil
}
func deleteHuaweiLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, ilb cloudprovider.ICloudLoadbalancer, ilbbg cloudprovider.ICloudLoadbalancerBackendGroup) error {
err := ilbbg.Refresh()
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil
}
return errors.Wrap(err, "HuaWeiRegionDriver.BackendGroup.Refresh")
}
ibackends, err := ilbbg.GetILoadbalancerBackends()
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.BackendGroup.GetILoadbalancerBackends")
}
for i := range ibackends {
ilbb := ibackends[i]
err = deleteHuaweiLoadbalancerBackend(ctx, userCred, ilb, ilbbg, ilbb)
if err != nil {
return errors.Wrap(err, "HuaWeiRegionDriver.BackendGroup.deleteHuaweiLoadbalancerBackend")
}
}
err = ilbbg.Delete(ctx)
if err != nil && err != cloudprovider.ErrNotFound {
return errors.Wrap(err, "HuaWeiRegionDriver.BackendGroup.Delete")
}
return nil
}
func deleteHuaweiLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, ilb cloudprovider.ICloudLoadbalancer, ilbbg cloudprovider.ICloudLoadbalancerBackendGroup, ilbb cloudprovider.ICloudLoadbalancerBackend) error {
err := ilbbg.RemoveBackendServer(ilbb.GetId(), ilbb.GetWeight(), ilbb.GetPort())
if err != nil && err != cloudprovider.ErrNotFound {
return errors.Wrap(err, "HuaWeiRegionDriver.Backend.Delete")
}
return nil
}
func deleteHuaweiLblisRule(ctx context.Context, userCred mcclient.TokenCredential, ruleId string) error {
rule, err := db.FetchById(models.LoadbalancerListenerRuleManager, ruleId)
if err != nil {
if err == sql.ErrNoRows {
return nil
}
return errors.Wrap(err, "deleteHuaweiLblisRule.FetchById")
}
err = deleteHuaweiCachedLbbg(ctx, userCred, ruleId)
if err != nil {
return errors.Wrap(err, "deleteHuaweiLblisRule.deleteHuaweiCachedLbbg")
}
err = db.DeleteModel(ctx, userCred, rule)
if err != nil {
return errors.Wrap(err, "deleteHuaweiLblisRule.DeleteModel")
}
return nil
}
func deleteHuaweiCachedLbbg(ctx context.Context, userCred mcclient.TokenCredential, associatedId string) error {
lbbg, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroupByAssociateId(associatedId)
if err != nil {
if err == sql.ErrNoRows {
return nil
}
return errors.Wrap(err, "deleteHuaweiCachedLbbg.GetCachedBackendGroupByAssociateId")
}
if err := deleteHuaweiCachedLbbsByLbbg(ctx, userCred, lbbg.GetId()); err != nil {
return errors.Wrap(err, "deleteHuaweiCachedLbbg.deleteHuaweiCachedLbbsByLbbg")
}
err = db.DeleteModel(ctx, userCred, lbbg)
if err != nil {
return errors.Wrap(err, "deleteHuaweiCachedLbbg.DeleteModel")
}
return nil
}
func deleteHuaweiCachedLbbsByLbbg(ctx context.Context, userCred mcclient.TokenCredential, cachedLbbgId string) error {
cachedLbbs := []models.SHuaweiCachedLb{}
q := models.HuaweiCachedLbManager.Query().IsFalse("pending_deleted").Equals("cached_backend_group_id", cachedLbbgId)
err := db.FetchModelObjects(models.HuaweiCachedLbManager, q, &cachedLbbs)
if err != nil {
if err == sql.ErrNoRows {
return nil
}
return errors.Wrap(err, "deleteHuaweiCachedLbbsByLbbg.FetchModelObjects")
}
for i := range cachedLbbs {
cachedLbb := cachedLbbs[i]
err = db.DeleteModel(ctx, userCred, &cachedLbb)
if err != nil {
return errors.Wrap(err, "deleteHuaweiCachedLbbsByLbbg.DeleteModel")
}
}
return nil
}
func deleteHuaweiCachedLbb(ctx context.Context, userCred mcclient.TokenCredential, cachedLbbId string) error {
lbb, err := db.FetchById(models.HuaweiCachedLbManager, cachedLbbId)
if err != nil {
if err == sql.ErrNoRows {
return nil
}
return errors.Wrap(err, "deleteHuaweiCachedLbb.FetchById")
}
err = db.DeleteModel(ctx, userCred, lbb)
if err != nil {
return errors.Wrap(err, "deleteHuaweiCachedLbb.DeleteModel")
}
return nil
}
func (self *SHuaWeiRegionDriver) RequestDeleteLoadbalancerListener(ctx context.Context, userCred mcclient.TokenCredential, lblis *models.SLoadbalancerListener, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
if jsonutils.QueryBoolean(task.GetParams(), "purge", false) {
return nil, nil
}
loadbalancer := lblis.GetLoadbalancer()
if loadbalancer == nil {
return nil, fmt.Errorf("failed to find loadbalancer for lblis %s", lblis.Name)
}
iRegion, err := loadbalancer.GetIRegion()
if err != nil {
return nil, err
}
if len(loadbalancer.ExternalId) == 0 {
return nil, nil
}
if len(lblis.ExternalId) == 0 {
return nil, nil
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId)
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil, nil
}
return nil, err
}
iListener, err := iLoadbalancer.GetILoadBalancerListenerById(lblis.ExternalId)
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil, nil
}
return nil, err
}
// 取消服务器组关联
backendgroupId := iListener.GetBackendGroupId()
if len(backendgroupId) > 0 {
params, err := lblis.GetHuaweiLoadbalancerListenerParams()
if err != nil {
return nil, err
}
params.BackendGroupID = ""
err = iListener.Sync(ctx, params)
if err != nil {
return nil, err
} else {
iListener.Refresh()
}
// 删除后端服务器组
ilbbg, err := iLoadbalancer.GetILoadBalancerBackendGroupById(backendgroupId)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.RequestDeleteLoadbalancerListener.GetILoadBalancerBackendGroup")
}
err = deleteHuaweiLoadbalancerBackendGroup(ctx, userCred, iLoadbalancer, ilbbg)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.RequestDeleteLoadbalancerListener.DeleteBackendGroup")
}
}
err = deleteHuaweiCachedLbbg(ctx, userCred, lblis.GetId())
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.RequestDeleteLoadbalancerListener.deleteHuaweiCachedLbbg")
}
// 删除访问控制
aclId := iListener.GetAclId()
if len(aclId) > 0 {
iAcl, err := iRegion.GetILoadBalancerAclById(aclId)
if err != nil {
return nil, err
}
err = iAcl.Delete()
if err != nil {
return nil, err
}
acl := lblis.GetCachedLoadbalancerAcl()
if acl != nil {
err := db.DeleteModel(ctx, userCred, acl)
if err != nil {
return nil, err
}
}
}
// remove rules
irules, err := iListener.GetILoadbalancerListenerRules()
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.GetILoadbalancerListenerRules")
}
for i := range irules {
irule := irules[i]
err = deleteHuaweiLoadbalancerListenerRule(ctx, userCred, iLoadbalancer, irule)
if err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.deleteHuaweiLoadbalancerListenerRule")
}
}
rules, err := lblis.GetLoadbalancerListenerRules()
if err != nil && err != sql.ErrNoRows {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.GetLoadbalancerListenerRules")
}
for i := range rules {
rule := rules[i]
if err := deleteHuaweiLblisRule(ctx, userCred, rule.GetId()); err != nil {
return nil, errors.Wrap(err, "HuaWeiRegionDriver.Rule.deleteHuaweiCachedLbbg")
}
}
return nil, iListener.Delete(ctx)
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestDeleteLoadbalancerBackendGroup(ctx context.Context, userCred mcclient.TokenCredential, lbbg *models.SLoadbalancerBackendGroup, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
if jsonutils.QueryBoolean(task.GetParams(), "purge", false) {
return nil, nil
}
iRegion, err := lbbg.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.")
}
loadbalancer := lbbg.GetLoadbalancer()
if loadbalancer == nil {
return nil, fmt.Errorf("failed to find loadbalancer for backendgroup %s", lbbg.Name)
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId)
if err != nil {
if err == cloudprovider.ErrNotFound {
return nil, nil
}
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.GetILoadBalancerById")
}
cachedLbbgs, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroups(lbbg.GetId())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.GetCachedBackendGroups")
}
for _, cachedLbbg := range cachedLbbgs {
if len(cachedLbbg.ExternalId) == 0 {
continue
}
iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(cachedLbbg.ExternalId)
if err != nil {
if err == cloudprovider.ErrNotFound {
if err := deleteHuaweiCachedLbbg(ctx, userCred, cachedLbbg.AssociatedId); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.deleteHuaweiCachedLbbg")
}
continue
}
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.GetILoadBalancerBackendGroupById")
}
ilbbs, err := iLoadbalancerBackendGroup.GetILoadbalancerBackends()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.GetILoadbalancerBackends")
}
for _, ilbb := range ilbbs {
iLoadbalancerBackendGroup.RemoveBackendServer(ilbb.GetId(), ilbb.GetWeight(), ilbb.GetPort())
_cachedLbb, err := db.FetchByExternalId(models.HuaweiCachedLbManager, ilbb.GetGlobalId())
if err != nil {
if err != sql.ErrNoRows {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.FetchByExternalId")
}
continue
}
cachedLbb := _cachedLbb.(*models.SHuaweiCachedLb)
err = db.DeleteModel(ctx, userCred, cachedLbb)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.DeleteModel")
}
}
err = iLoadbalancerBackendGroup.Delete(ctx)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.Delete")
}
cachedLbbg.SetModelManager(models.HuaweiCachedLbbgManager, &cachedLbbg)
err = db.DeleteModel(ctx, userCred, &cachedLbbg)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestDeleteLoadbalancerBackendGroup.DeleteModel")
}
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestDeleteLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
if jsonutils.QueryBoolean(task.GetParams(), "purge", false) {
return nil, nil
}
cachedlbbs, err := models.HuaweiCachedLbManager.GetBackendsByLocalBackendId(lbb.GetId())
if err != nil {
return nil, err
}
for _, cachedlbb := range cachedlbbs {
cachedlbbg, _ := cachedlbb.GetCachedBackendGroup()
if cachedlbbg == nil {
log.Warningf("failed to find lbbg for backend %s", cachedlbb.Name)
continue
}
lb := cachedlbbg.GetLoadbalancer()
if lb == nil {
return nil, fmt.Errorf("failed to find lb for backendgroup %s", cachedlbbg.Name)
}
iRegion, err := lb.GetIRegion()
if err != nil {
return nil, err
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId)
if err != nil {
return nil, err
}
iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(cachedlbbg.ExternalId)
if err != nil {
return nil, err
}
err = iLoadbalancerBackendGroup.RemoveBackendServer(cachedlbb.ExternalId, lbb.Weight, lbb.Port)
if err != nil {
return nil, err
}
err = db.DeleteModel(ctx, userCred, &cachedlbb)
if err != nil {
return nil, err
}
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancer(ctx context.Context, userCred mcclient.TokenCredential, lb *models.SLoadbalancer, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := lb.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.GetIRegion")
}
params, err := lb.GetCreateLoadbalancerParams(iRegion)
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.GetCreateLoadbalancerParams")
}
iLoadbalancer, err := iRegion.CreateILoadBalancer(params)
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.CreateILoadBalancer")
}
lb.SetModelManager(models.LoadbalancerManager, lb)
if err := db.SetExternalId(lb, userCred, iLoadbalancer.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.SetExternalId")
}
{
// bind eip
eipId, _ := task.GetParams().GetString("eip_id")
if len(eipId) > 0 {
ieip, err := iRegion.GetIEipById(eipId)
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.GetIEipById")
}
conf := &cloudprovider.AssociateConfig{
InstanceId: iLoadbalancer.GetGlobalId(),
AssociateType: api.EIP_ASSOCIATE_TYPE_LOADBALANCER,
}
err = ieip.Associate(conf)
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.Associate")
}
eip, err := db.FetchByExternalId(models.ElasticipManager, ieip.GetGlobalId())
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.FetchByExternalId")
}
err = eip.(*models.SElasticip).SyncWithCloudEip(ctx, userCred, lb.GetCloudprovider(), ieip, lb.GetOwnerId())
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.SyncWithCloudEip")
}
}
}
if err := lb.SyncWithCloudLoadbalancer(ctx, userCred, iLoadbalancer, nil, lb.GetCloudprovider()); err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.SyncWithCloudLoadbalancer")
}
lbbgs, err := iLoadbalancer.GetILoadBalancerBackendGroups()
if err != nil {
return nil, errors.Wrap(err, "Huawei.RequestCreateLoadbalancer.GetILoadBalancerBackendGroups")
}
if len(lbbgs) > 0 {
provider := lb.GetCloudprovider()
if provider == nil {
return nil, fmt.Errorf("failed to find cloudprovider for lb %s", lb.Name)
}
models.LoadbalancerBackendGroupManager.SyncLoadbalancerBackendgroups(ctx, userCred, provider, lb, lbbgs, &models.SSyncRange{})
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) ValidateDeleteLoadbalancerCondition(ctx context.Context, lb *models.SLoadbalancer) error {
listeners, err := lb.GetLoadbalancerListeners()
if err != nil {
return err
}
if len(listeners) > 0 {
return httperrors.NewConflictError("loadbalancer is using by %d listener.", len(listeners))
}
lbbgs, err := lb.GetLoadbalancerBackendgroups()
if err != nil {
return err
}
if len(lbbgs) > 0 {
return httperrors.NewConflictError("loadbalancer is using by %d backendgroup.", len(lbbgs))
}
return nil
}
func (self *SHuaWeiRegionDriver) RequestSyncLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
cachedlbbs, err := models.HuaweiCachedLbManager.GetBackendsByLocalBackendId(lbb.GetId())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetBackendsByLocalBackendId")
}
for _, cachedlbb := range cachedlbbs {
cachedlbbg, _ := cachedlbb.GetCachedBackendGroup()
if cachedlbbg == nil {
return nil, fmt.Errorf("failed to find lbbg for backend %s", cachedlbb.Name)
}
lb := cachedlbbg.GetLoadbalancer()
if lb == nil {
return nil, fmt.Errorf("failed to find lb for backendgroup %s", cachedlbbg.Name)
}
iRegion, err := lb.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetIRegion")
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(lb.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetILoadBalancerById")
}
iLoadbalancerBackendGroup, err := iLoadbalancer.GetILoadBalancerBackendGroupById(cachedlbbg.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetILoadBalancerBackendGroupById")
}
iBackend, err := iLoadbalancerBackendGroup.GetILoadbalancerBackendById(cachedlbb.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetILoadbalancerBackendById")
}
err = iBackend.SyncConf(ctx, lbb.Port, lbb.Weight)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.SyncConf")
}
iBackend, err = iLoadbalancerBackendGroup.GetILoadbalancerBackendById(cachedlbb.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.GetILoadbalancerBackendById")
}
err = cachedlbb.SyncWithCloudLoadbalancerBackend(ctx, userCred, iBackend, nil)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestSyncLoadbalancerBackend.SyncWithCloudLoadbalancerBackend")
}
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancerBackend(ctx context.Context, userCred mcclient.TokenCredential, lbb *models.SLoadbalancerBackend, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
lbbg := lbb.GetLoadbalancerBackendGroup()
if lbbg == nil {
return nil, fmt.Errorf("failed to find lbbg for backend %s", lbb.Name)
}
lb := lbbg.GetLoadbalancer()
if lb == nil {
return nil, fmt.Errorf("failed to find lb for backendgroup %s", lbbg.Name)
}
cachedlbbgs, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroups(lbbg.GetId())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.GetCachedBackendGroups")
}
guest := lbb.GetGuest()
if guest == nil {
return nil, fmt.Errorf("failed to find guest for lbb %s", lbb.Name)
}
var ibackend cloudprovider.ICloudLoadbalancerBackend
for _, cachedLbbg := range cachedlbbgs {
iLoadbalancerBackendGroup, err := cachedLbbg.GetICloudLoadbalancerBackendGroup()
if err != nil {
if err == cloudprovider.ErrNotFound {
if err := deleteHuaweiCachedLbbg(ctx, userCred, cachedLbbg.AssociatedId); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.deleteHuaweiCachedLbbg")
}
continue
}
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.GetICloudLoadbalancerBackendGroup")
}
ibackend, err = iLoadbalancerBackendGroup.AddBackendServer(guest.ExternalId, lbb.Weight, lbb.Port)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.AddBackendServer")
}
_, err = models.HuaweiCachedLbManager.CreateHuaweiCachedLb(ctx, userCred, lbb, &cachedLbbg, ibackend, cachedLbbg.GetOwnerId())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.CreateHuaweiCachedLb")
}
}
if ibackend != nil {
if err := lbb.SyncWithCloudLoadbalancerBackend(ctx, userCred, ibackend, nil, lb.GetCloudprovider()); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerBackend.SyncWithCloudLoadbalancerBackend")
}
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) RequestCreateLoadbalancerListenerRule(ctx context.Context, userCred mcclient.TokenCredential, lbr *models.SLoadbalancerListenerRule, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
listener := lbr.GetLoadbalancerListener()
if listener == nil {
return nil, fmt.Errorf("failed to find listener for listnener rule %s", lbr.Name)
}
loadbalancer := listener.GetLoadbalancer()
if loadbalancer == nil {
return nil, fmt.Errorf("failed to find loadbalancer for listener %s", listener.Name)
}
iRegion, err := loadbalancer.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.GetIRegion")
}
iLoadbalancer, err := iRegion.GetILoadBalancerById(loadbalancer.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.GetILoadBalancerById")
}
iListener, err := iLoadbalancer.GetILoadBalancerListenerById(listener.ExternalId)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.GetILoadBalancerListenerById")
}
rule := &cloudprovider.SLoadbalancerListenerRule{
Name: lbr.Name,
Domain: lbr.Domain,
Path: lbr.Path,
}
if len(lbr.BackendGroupId) > 0 {
group := lbr.GetLoadbalancerBackendGroup()
if group == nil {
return nil, fmt.Errorf("failed to find backend group for listener rule %s", lbr.Name)
}
cachedLbbg, err := models.HuaweiCachedLbbgManager.GetCachedBackendGroupByAssociateId(lbr.GetId())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.GetCachedBackendGroupByAssociateId")
}
if cachedLbbg == nil {
return nil, fmt.Errorf("usable cached backend group not found")
}
rule.BackendGroupID = cachedLbbg.ExternalId
rule.BackendGroupType = group.Type
}
iListenerRule, err := iListener.CreateILoadBalancerListenerRule(rule)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.CreateILoadBalancerListenerRule")
}
//
lbr.SetModelManager(models.LoadbalancerListenerRuleManager, lbr)
if err := db.SetExternalId(lbr, userCred, iListenerRule.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.RequestCreateLoadbalancerListenerRule.SetExternalId")
}
return nil, lbr.SyncWithCloudLoadbalancerListenerRule(ctx, userCred, iListenerRule, nil, loadbalancer.GetCloudprovider())
})
return nil
}
func (self *SHuaWeiRegionDriver) DealNatGatewaySpec(spec string) string {
switch spec {
case "1":
return api.NAT_SPEC_SMALL
case "2":
return api.NAT_SPEC_MIDDLE
case "3":
return api.NAT_SPEC_LARGE
case "4":
return api.NAT_SPEC_XLARGE
}
// can't arrive
return ""
}
func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, input api.DBInstanceCreateInput, skus []models.SDBInstanceSku, network *models.SNetwork) (api.DBInstanceCreateInput, error) {
if len(input.MasterInstanceId) > 0 && input.Engine == api.DBINSTANCE_TYPE_SQLSERVER {
return input, httperrors.NewInputParameterError("Not support create read-only dbinstance for %s", input.Engine)
}
if len(input.Name) < 4 || len(input.Name) > 64 {
return input, httperrors.NewInputParameterError("Huawei dbinstance name length shoud be 4~64 characters")
}
if input.DiskSizeGB < 40 || input.DiskSizeGB > 4000 {
return input, httperrors.NewInputParameterError("%s require disk size must in 40 ~ 4000 GB", self.GetProvider())
}
if input.DiskSizeGB%10 > 0 {
return input, httperrors.NewInputParameterError("The disk_size_gb must be an integer multiple of 10")
}
if len(input.Password) == 0 {
return input, httperrors.NewMissingParameterError("password")
}
return input, nil
}
func (self *SHuaWeiRegionDriver) InitDBInstanceUser(instance *models.SDBInstance, task taskman.ITask, desc *cloudprovider.SManagedDBInstanceCreateConfig) error {
user := "root"
if desc.Engine == api.DBINSTANCE_TYPE_SQLSERVER {
user = "rdsuser"
}
account := models.SDBInstanceAccount{}
account.DBInstanceId = instance.Id
account.Name = user
account.Status = api.DBINSTANCE_USER_AVAILABLE
account.ExternalId = user
account.SetModelManager(models.DBInstanceAccountManager, &account)
err := models.DBInstanceAccountManager.TableSpec().Insert(&account)
if err != nil {
return err
}
return account.SetPassword(desc.Password)
}
func (self *SHuaWeiRegionDriver) IsSupportedBillingCycle(bc billing.SBillingCycle, resource string) bool {
switch resource {
case models.DBInstanceManager.KeywordPlural():
years := bc.GetYears()
months := bc.GetMonths()
if (years >= 1 && years <= 3) || (months >= 1 && months <= 9) {
return true
}
}
return false
}
func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceAccountCreateInput) (api.DBInstanceAccountCreateInput, error) {
if utils.IsInStringArray(instance.Engine, []string{api.DBINSTANCE_TYPE_POSTGRESQL, api.DBINSTANCE_TYPE_SQLSERVER}) {
return input, httperrors.NewInputParameterError("Not support create account for huawei cloud %s instance", instance.Engine)
}
if len(input.Name) == len(input.Password) {
for i := range input.Name {
if input.Name[i] != input.Password[len(input.Password)-i-1] {
return input, nil
}
}
return input, httperrors.NewInputParameterError("Huawei rds password cannot be in the same reverse order as the account")
}
return input, nil
}
func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceDatabaseData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceDatabaseCreateInput) (api.DBInstanceDatabaseCreateInput, error) {
if utils.IsInStringArray(instance.Engine, []string{api.DBINSTANCE_TYPE_POSTGRESQL, api.DBINSTANCE_TYPE_SQLSERVER}) {
return input, httperrors.NewInputParameterError("Not support create database for huawei cloud %s instance", instance.Engine)
}
return input, nil
}
func (self *SHuaWeiRegionDriver) ValidateCreateDBInstanceBackupData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, instance *models.SDBInstance, input api.DBInstanceBackupCreateInput) (api.DBInstanceBackupCreateInput, error) {
if len(input.Name) < 4 || len(input.Name) > 64 {
return input, httperrors.NewInputParameterError("Huawei DBInstance backup name length shoud be 4~64 characters")
}
if len(input.Databases) > 0 && instance.Engine != api.DBINSTANCE_TYPE_SQLSERVER {
return input, httperrors.NewInputParameterError("Huawei only supports specified databases with %s", api.DBINSTANCE_TYPE_SQLSERVER)
}
return input, nil
}
func (self *SHuaWeiRegionDriver) ValidateChangeDBInstanceConfigData(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, input *api.SDBInstanceChangeConfigInput) error {
if input.DiskSizeGB != 0 && input.DiskSizeGB < instance.DiskSizeGB {
return httperrors.NewUnsupportOperationError("Huawei DBInstance Disk cannot be thrink")
}
if len(input.Category) > 0 && input.Category != instance.Category {
return httperrors.NewUnsupportOperationError("Huawei DBInstance category cannot change")
}
if len(input.StorageType) > 0 && input.StorageType != instance.StorageType {
return httperrors.NewUnsupportOperationError("Huawei DBInstance storage type cannot change")
}
return nil
}
func (self *SHuaWeiRegionDriver) IsSupportDBInstancePublicConnection() bool {
//目前华为云未对外开放打开远程连接的API接口
return false
}
func (self *SHuaWeiRegionDriver) ValidateResetDBInstancePassword(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string) error {
return httperrors.NewUnsupportOperationError("Huawei current not support reset dbinstance account password")
}
func (self *SHuaWeiRegionDriver) IsSupportKeepDBInstanceManualBackup() bool {
return true
}
func (self *SHuaWeiRegionDriver) ValidateDBInstanceAccountPrivilege(ctx context.Context, userCred mcclient.TokenCredential, instance *models.SDBInstance, account string, privilege string) error {
if account == "root" {
return httperrors.NewInputParameterError("No need to grant or revoke privilege for admin account")
}
if !utils.IsInStringArray(privilege, []string{api.DATABASE_PRIVILEGE_RW, api.DATABASE_PRIVILEGE_R}) {
return httperrors.NewInputParameterError("Unknown privilege %s", privilege)
}
return nil
}
func validatorSlaveZones(ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict, optional bool) error {
s, err := data.GetString("slave_zones")
if err != nil {
if optional {
return nil
}
return fmt.Errorf("missing parameter slave_zones")
}
zones := strings.Split(s, ",")
ret := []string{}
zoneV := validators.NewModelIdOrNameValidator("zone", "zone", ownerId)
for _, zone := range zones {
_data := jsonutils.NewDict()
_data.Add(jsonutils.NewString(zone), "zone")
if err := zoneV.Validate(_data); err != nil {
return errors.Wrap(err, "validatorSlaveZones")
} else {
ret = append(ret, zoneV.Model.GetId())
}
}
if sku, err := data.GetString("sku"); err != nil || len(sku) == 0 {
return httperrors.NewMissingParameterError("sku")
} else {
chargeType, _ := data.GetString("charge_type")
_skuModel, err := db.FetchByIdOrName(models.ElasticcacheSkuManager, ownerId, sku)
if err != nil {
return err
}
skuModel := _skuModel.(*models.SElasticcacheSku)
for _, zoneId := range zones {
if err := ValidateElasticcacheSku(zoneId, chargeType, skuModel); err != nil {
return err
}
}
}
data.Set("slave_zones", jsonutils.NewString(strings.Join(ret, ",")))
return nil
}
func ValidateElasticcacheSku(zoneId string, chargeType string, sku *models.SElasticcacheSku) error {
if sku.ZoneId != zoneId {
return httperrors.NewResourceNotFoundError("zone mismatch, elastic cache sku zone %s != %s", sku.ZoneId, zoneId)
}
if chargeType == billing_api.BILLING_TYPE_PREPAID {
if sku.PrepaidStatus != api.SkuStatusAvailable {
return httperrors.NewOutOfResourceError("sku %s is soldout", sku.Name)
}
} else {
if sku.PostpaidStatus != api.SkuStatusAvailable {
return httperrors.NewOutOfResourceError("sku %s is soldout", sku.Name)
}
}
return nil
}
func (self *SHuaWeiRegionDriver) ValidateCreateElasticcacheData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
zoneV := validators.NewModelIdOrNameValidator("zone", "zone", ownerId)
networkV := validators.NewModelIdOrNameValidator("network", "network", ownerId)
// secgroupV := validators.NewModelIdOrNameValidator("security_group", "secgroup", ownerId)
// todo: fix me
instanceTypeV := validators.NewModelIdOrNameValidator("instance_type", "elasticcachesku", ownerId)
chargeTypeV := validators.NewStringChoicesValidator("billing_type", choices.NewChoices(billing_api.BILLING_TYPE_PREPAID, billing_api.BILLING_TYPE_POSTPAID))
networkTypeV := validators.NewStringChoicesValidator("network_type", choices.NewChoices(api.LB_NETWORK_TYPE_VPC, api.LB_NETWORK_TYPE_CLASSIC)).Default(api.LB_NETWORK_TYPE_VPC).Optional(true)
engineV := validators.NewStringChoicesValidator("engine", choices.NewChoices("redis", "memcache"))
engineVersionV := validators.NewStringChoicesValidator("engine_version", choices.NewChoices("3.0", "4.0", "5.0"))
privateIpV := validators.NewIPv4AddrValidator("private_ip").Optional(true)
maintainStartTimeV := validators.NewStringChoicesValidator("maintain_start_time", choices.NewChoices("22:00:00", "02:00:00", "06:00:00", "10:00:00", "14:00:00", "18:00:00")).Default("02:00:00").Optional(true)
keyV := map[string]validators.IValidator{
"zone": zoneV,
"billing_type": chargeTypeV,
"network_type": networkTypeV,
"network": networkV,
"instance_type": instanceTypeV,
// "security_group": secgroupV,
"engine": engineV,
"engine_version": engineVersionV,
"private_ip": privateIpV,
"mantain_start_time": maintainStartTimeV,
}
if err := RunValidators(keyV, data, false); err != nil {
return nil, err
}
// validate password
if password, _ := data.GetString("password"); len(password) > 0 {
if !seclib2.MeetComplxity(password) {
return nil, httperrors.NewWeakPasswordError()
}
}
// validate sku
sku := instanceTypeV.Model.(*models.SElasticcacheSku)
zoneId, _ := data.GetString("zone_id")
billingType, _ := data.GetString("billing_type")
if err := ValidateElasticcacheSku(zoneId, billingType, sku); err != nil {
return nil, err
} else {
data.Set("instance_type", jsonutils.NewString(sku.InstanceSpec))
data.Set("node_type", jsonutils.NewString(sku.NodeType))
data.Set("local_category", jsonutils.NewString(sku.LocalCategory))
data.Set("capacity_mb", jsonutils.NewInt(int64(sku.MemorySizeMB)))
}
// validate slave zones
if err := validatorSlaveZones(ownerId, data, true); err != nil {
return nil, err
}
// validate capacity
if capacityMB, err := data.Int("capacity_mb"); err != nil {
return nil, errors.Wrap(err, "invalid parameter capacity_mb")
} else {
// todo: fix me
// Redis引擎单机和主备类型实例取值2、4、8、16、32、64。集群实例规格支持64G、128G、256G、512G和1024G。
data.Set("capacity_mb", jsonutils.NewInt(capacityMB))
}
// MaintainEndTime
// 开始时间必须为22:00:00、02:00:00、06:00:00、10:00:00、14:00:00和18:00:00。
data.Remove("mantain_end_time")
if startTime, err := data.GetString("maintain_start_time"); err == nil {
maintainTimes := []string{"22:00:00", "02:00:00", "06:00:00", "10:00:00", "14:00:00", "18:00:00", "22:00:00"}
for i := range maintainTimes {
if maintainTimes[i] == startTime {
data.Add(jsonutils.NewString(maintainTimes[i+1]), "mantain_end_time")
break
}
}
}
// billing cycle
if billingType == billing_api.BILLING_TYPE_PREPAID {
billingCycle, err := data.GetString("billing_cycle")
if err != nil {
return nil, httperrors.NewMissingParameterError("billing_cycle")
}
cycle, err := billing.ParseBillingCycle(billingCycle)
if err != nil {
return nil, httperrors.NewInputParameterError("invalid billing_cycle %s", billingCycle)
}
data.Set("billing_cycle", jsonutils.NewString(cycle.String()))
}
network := networkV.Model.(*models.SNetwork)
vpc := network.GetVpc()
if vpc == nil {
return nil, httperrors.NewNotFoundError("network %s related vpc not found", network.GetId())
}
data.Set("vpc_id", jsonutils.NewString(vpc.Id))
data.Set("manager_id", jsonutils.NewString(vpc.ManagerId))
data.Set("cloudregion_id", jsonutils.NewString(sku.CloudregionId))
return data, nil
}
func (self *SHuaWeiRegionDriver) RequestCreateElasticcache(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
taskman.LocalTaskRun(task, func() (jsonutils.JSONObject, error) {
iRegion, err := ec.GetIRegion()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetIRegion")
}
provider := ec.GetCloudprovider()
if provider == nil {
return nil, errors.Wrap(httperrors.ErrInvalidStatus, "huaweiRegionDriver.CreateElasticcache.GetProvider")
}
params, err := ec.GetCreateHuaweiElasticcacheParams(task.GetParams())
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetCreateHuaweiElasticcacheParams")
}
iec, err := iRegion.CreateIElasticcaches(params)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.CreateIElasticcaches")
}
err = cloudprovider.WaitStatusWithDelay(iec, api.ELASTIC_CACHE_STATUS_RUNNING, 30*time.Second, 15*time.Second, 600*time.Second)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.WaitStatusWithDelay")
}
ec.SetModelManager(models.ElasticcacheManager, ec)
if err := db.SetExternalId(ec, userCred, iec.GetGlobalId()); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.SetExternalId")
}
{
// todo: 开启外网访问
}
if err := ec.SyncWithCloudElasticcache(ctx, userCred, provider, iec); err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.SyncWithCloudElasticcache")
}
// sync accounts
{
iaccounts, err := iec.GetICloudElasticcacheAccounts()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetICloudElasticcacheAccounts")
}
result := models.ElasticcacheAccountManager.SyncElasticcacheAccounts(ctx, userCred, ec, iaccounts)
log.Debugf("huaweiRegionDriver.CreateElasticcache.SyncElasticcacheAccounts %s", result.Result())
account, err := ec.GetAdminAccount()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetAdminAccount")
}
err = account.SavePassword(params.Password)
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.SavePassword")
}
}
// sync acl
{
iacls, err := iec.GetICloudElasticcacheAcls()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetICloudElasticcacheAcls")
}
result := models.ElasticcacheAclManager.SyncElasticcacheAcls(ctx, userCred, ec, iacls)
log.Debugf("huaweiRegionDriver.CreateElasticcache.SyncElasticcacheAcls %s", result.Result())
}
// sync parameters
{
iparams, err := iec.GetICloudElasticcacheParameters()
if err != nil {
return nil, errors.Wrap(err, "huaweiRegionDriver.CreateElasticcache.GetICloudElasticcacheParameters")
}
result := models.ElasticcacheParameterManager.SyncElasticcacheParameters(ctx, userCred, ec, iparams)
log.Debugf("huaweiRegionDriver.CreateElasticcache.SyncElasticcacheParameters %s", result.Result())
}
return nil, nil
})
return nil
}
func (self *SHuaWeiRegionDriver) ValidateCreateElasticcacheAccountData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return nil, httperrors.NewUnsupportOperationError("% not support create account", self.GetProvider())
}
func (self *SHuaWeiRegionDriver) RequestElasticcacheAccountResetPassword(ctx context.Context, userCred mcclient.TokenCredential, ea *models.SElasticcacheAccount, task taskman.ITask) error {
iregion, err := ea.GetIRegion()
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.GetIRegion")
}
_ec, err := db.FetchById(models.ElasticcacheManager, ea.ElasticcacheId)
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.FetchById")
}
ec := _ec.(*models.SElasticcache)
iec, err := iregion.GetIElasticcacheById(ec.GetExternalId())
if err == cloudprovider.ErrNotFound {
return nil
} else if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.GetIElasticcacheById")
}
iea, err := iec.GetICloudElasticcacheAccount(ea.GetExternalId())
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.GetICloudElasticcacheBackup")
}
data := task.GetParams()
if data == nil {
return errors.Wrap(fmt.Errorf("data is nil"), "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.GetParams")
}
input, err := ea.GetUpdateHuaweiElasticcacheAccountParams(*data)
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.GetUpdateHuaweiElasticcacheAccountParams")
}
err = iea.UpdateAccount(input)
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.UpdateAccount")
}
if input.Password != nil {
err = ea.SavePassword(*input.Password)
if err != nil {
return errors.Wrap(err, "huaweiRegionDriver.RequestElasticcacheAccountResetPassword.SavePassword")
}
}
return ea.SetStatus(userCred, api.ELASTIC_CACHE_ACCOUNT_STATUS_AVAILABLE, "")
}
func (self *SHuaWeiRegionDriver) RequestUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ec *models.SElasticcache, task taskman.ITask) error {
return errors.Wrap(fmt.Errorf("not support update huawei elastic cache auth_mode"), "HuaWeiRegionDriver.RequestUpdateElasticcacheAuthMode")
}
func (self *SHuaWeiRegionDriver) AllowCreateElasticcacheBackup(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error {
if elasticcache.LocalCategory == api.ELASTIC_CACHE_ARCH_TYPE_SINGLE {
return httperrors.NewBadRequestError("huawei %s mode elastic not support create backup", elasticcache.LocalCategory)
}
return nil
}
func (self *SHuaWeiRegionDriver) AllowUpdateElasticcacheAuthMode(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, elasticcache *models.SElasticcache) error {
return fmt.Errorf("not support update huawei elastic cache auth_mode")
}
func (self *SHuaWeiRegionDriver) IsSupportedDBInstance() bool {
return true
}
func (self *SHuaWeiRegionDriver) IsSupportedElasticcache() bool {
return true
}
func (self *SHuaWeiRegionDriver) GetBackendStatusForAdd() []string {
return []string{api.VM_RUNNING, api.VM_READY}
}
func (self *SHuaWeiRegionDriver) IsDBInstanceNeedSecgroup() bool {
return true
}