mirror of
https://github.com/labring/sealos.git
synced 2026-09-24 15:46:19 +08:00
[WIP] support Infra huawei (#772)
* refactor(dev): huawei feature * refactor(dev): huawei feature VPC feature * refactor(dev): types consts to infra module * refactor(dev): add deepCopy * refactor(dev): huawei feature lic
This commit is contained in:
@@ -75,10 +75,14 @@ generator-contributors:
|
||||
git log --format='%aN <%aE>' | sort -uf > CONTRIBUTORS
|
||||
|
||||
|
||||
DEEPCOPY_BIN = $(shell pwd)/bin/deepcopy-gen
|
||||
install-deepcopy: ## check license if not exist install go-lint tools
|
||||
$(call go-get-tool,$(DEEPCOPY_BIN),k8s.io/code-generator/cmd/deepcopy-gen@latest)
|
||||
|
||||
HEAD_FILE := hack/template/boilerplate.go.txt
|
||||
INPUT_DIR := github.com/fanux/sealos/pkg/types/v1beta1
|
||||
deepcopy:
|
||||
deepcopy-gen \
|
||||
deepcopy:install-deepcopy
|
||||
$(DEEPCOPY_BIN) \
|
||||
--input-dirs="$(INPUT_DIR)" \
|
||||
-O zz_generated.deepcopy \
|
||||
--go-header-file "$(HEAD_FILE)" \
|
||||
|
||||
@@ -8,6 +8,7 @@ require (
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/google/uuid v1.1.2 // indirect
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.0.72
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/onsi/ginkgo v1.11.0
|
||||
github.com/onsi/gomega v1.7.0
|
||||
@@ -24,7 +25,7 @@ require (
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/ini.v1 v1.61.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
k8s.io/api v0.18.0
|
||||
k8s.io/apimachinery v0.18.0
|
||||
k8s.io/client-go v0.18.0
|
||||
|
||||
@@ -223,6 +223,8 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.0.72 h1:gfQoGtygEg2ZX5fxHyIynxGqdZvb3dfIXK5BBN2+LHI=
|
||||
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.0.72/go.mod h1:Z+vVu7nV/6xqti0P2evPEqhzh86ArBELsXTOU9zsnoM=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
@@ -383,6 +385,7 @@ github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdh
|
||||
github.com/sealyun/lvscare v1.1.2-alpha.2 h1:SlnEAXOPn5gC6l8tgvbn9fApyJaQ0ecQHSV3cEfvQYY=
|
||||
github.com/sealyun/lvscare v1.1.2-alpha.2/go.mod h1:FtOEdsXuYtw9Jwd/Jct25K+PcpUFSDemvF4VgNygjj0=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
|
||||
@@ -19,32 +19,22 @@ package aliyun
|
||||
import (
|
||||
"time"
|
||||
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
"github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
Scheme = "https"
|
||||
IPProtocol = "tcp"
|
||||
APIServerPortRange = "6443/6443"
|
||||
SSHPortRange = "22/22"
|
||||
SourceCidrIP = "0.0.0.0/0"
|
||||
CidrBlock = "172.16.0.0/24"
|
||||
Policy = "accept"
|
||||
DestinationResource = "InstanceType"
|
||||
InstanceChargeType = "PostPaid"
|
||||
InternetChargeType = "PayByTraffic"
|
||||
Product = "product"
|
||||
Role = "role"
|
||||
Arch = "arch"
|
||||
Stopped = "Stopped"
|
||||
AvailableTypeStatus = "WithStock"
|
||||
Bandwidth = "100"
|
||||
AliDomain = "www.sealyun.com/"
|
||||
TryTimes = 10
|
||||
TrySleepTime = time.Second
|
||||
JustGetInstanceInfo = 0
|
||||
)
|
||||
|
||||
const AliyunProvider v1beta1.Provider = "AliyunProvider"
|
||||
|
||||
type ResourceName string
|
||||
|
||||
const (
|
||||
@@ -56,29 +46,29 @@ const (
|
||||
ShouldBeDeleteInstancesIDs ResourceName = "ShouldBeDeleteInstancesIDs"
|
||||
)
|
||||
|
||||
func (r ResourceName) ClusterValue(infra v2.InfraSpec) string {
|
||||
func (r ResourceName) ClusterValue(infra v1beta1.InfraSpec) string {
|
||||
return infra.Cluster.Annotations[string(r)]
|
||||
}
|
||||
|
||||
func (r ResourceName) ClusterSetValue(infra v2.InfraSpec, val string) {
|
||||
func (r ResourceName) ClusterSetValue(infra v1beta1.InfraSpec, val string) {
|
||||
infra.Cluster.Annotations[string(r)] = val
|
||||
}
|
||||
|
||||
func (r ResourceName) Value(status v2.InfraStatus) string {
|
||||
func (r ResourceName) Value(status v1beta1.InfraStatus) string {
|
||||
return status.Cluster.Annotations[string(r)]
|
||||
}
|
||||
|
||||
func (r ResourceName) SetValue(status v2.InfraStatus, val string) {
|
||||
func (r ResourceName) SetValue(status v1beta1.InfraStatus, val string) {
|
||||
status.Cluster.Annotations[string(r)] = val
|
||||
}
|
||||
|
||||
type ImageArch string
|
||||
|
||||
func ConvertImageArch(arch v2.Arch) ImageArch {
|
||||
func ConvertImageArch(arch v1beta1.Arch) ImageArch {
|
||||
switch arch {
|
||||
case v2.ARM64:
|
||||
case v1beta1.ARM64:
|
||||
return "arm64"
|
||||
case v2.AMD64:
|
||||
case v1beta1.AMD64:
|
||||
return "x86_64"
|
||||
}
|
||||
return ""
|
||||
|
||||
@@ -35,9 +35,6 @@ type Instance struct {
|
||||
PrimaryIPAddress string
|
||||
}
|
||||
|
||||
type EcsManager struct {
|
||||
}
|
||||
|
||||
func (a *AliProvider) InputIPlist(host *v1beta1.Host) (ipList []string, err error) {
|
||||
if host == nil {
|
||||
return nil, err
|
||||
@@ -89,7 +86,7 @@ func (a *AliProvider) ChangeInstanceType(instanceID string, host *v1beta1.Host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if instanceStatus != Stopped {
|
||||
if instanceStatus != "Stopped" {
|
||||
err = a.PowerOffInstance(instanceID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -314,14 +311,14 @@ func (a *AliProvider) RunInstances(host *v1beta1.Host, count int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AliProvider) AuthorizeSecurityGroup(securityGroupID, portRange string) bool {
|
||||
func (a *AliProvider) AuthorizeSecurityGroup(securityGroupID string, exportPort v1beta1.ExportPort) bool {
|
||||
request := ecs.CreateAuthorizeSecurityGroupRequest()
|
||||
request.Scheme = Scheme
|
||||
request.SecurityGroupId = securityGroupID
|
||||
request.IpProtocol = IPProtocol
|
||||
request.PortRange = portRange
|
||||
request.SourceCidrIp = SourceCidrIP
|
||||
request.Policy = Policy
|
||||
request.IpProtocol = string(exportPort.Protocol)
|
||||
request.PortRange = exportPort.PortRange
|
||||
request.SourceCidrIp = exportPort.CidrIP
|
||||
request.Policy = "accept"
|
||||
|
||||
response := ecs.CreateAuthorizeSecurityGroupResponse()
|
||||
err := a.RetryEcsRequest(request, response)
|
||||
|
||||
@@ -180,8 +180,8 @@ func (a *AliProvider) GetAvailableResource(host *v1beta1.Host, systemCategory, d
|
||||
request.Scheme = Scheme
|
||||
request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
request.ZoneId = a.Infra.Status.Cluster.ZoneID
|
||||
request.DestinationResource = DestinationResource
|
||||
request.InstanceChargeType = InstanceChargeType
|
||||
request.DestinationResource = "InstanceType"
|
||||
request.InstanceChargeType = "PostPaid"
|
||||
request.SpotStrategy = a.Infra.Status.Cluster.SpotStrategy
|
||||
request.SystemDiskCategory = systemCategory
|
||||
request.DataDiskCategory = dataCategory
|
||||
@@ -198,7 +198,7 @@ func (a *AliProvider) GetAvailableResource(host *v1beta1.Host, systemCategory, d
|
||||
for _, i := range response.AvailableZones.AvailableZone {
|
||||
for _, f := range i.AvailableResources.AvailableResource {
|
||||
for _, r := range f.SupportedResources.SupportedResource {
|
||||
if r.StatusCategory == AvailableTypeStatus {
|
||||
if r.StatusCategory == "WithStock" {
|
||||
instanceType = append(instanceType, r.Value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
"github.com/fanux/sealos/pkg/utils"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/fanux/sealos/pkg/types/validation"
|
||||
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
"github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
"github.com/fanux/sealos/pkg/utils/logger"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
@@ -52,7 +52,7 @@ const (
|
||||
type AliProvider struct {
|
||||
EcsClient ecs.Client
|
||||
VpcClient vpc.Client
|
||||
Infra *v2.Infra
|
||||
Infra *v1beta1.Infra
|
||||
}
|
||||
|
||||
type AliFunc func() error
|
||||
@@ -237,21 +237,20 @@ func (a *AliProvider) Reconcile() error {
|
||||
}
|
||||
|
||||
func (a *AliProvider) Apply() error {
|
||||
if err := v2.Default(a.Infra, defaultInfra); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := validation.ValidateInfra(a.Infra); len(err) != 0 {
|
||||
return err.ToAggregate()
|
||||
}
|
||||
return a.Reconcile()
|
||||
}
|
||||
|
||||
func defaultInfra(infra *v2.Infra) error {
|
||||
func DefaultInfra(infra *v1beta1.Infra) error {
|
||||
//https://help.aliyun.com/document_detail/63440.htm?spm=a2c4g.11186623.0.0.f5952752gkxpB7#t9856.html
|
||||
if infra.Spec.Cluster.IsSeize {
|
||||
if infra.Spec.Cluster.Metadata.IsSeize {
|
||||
infra.Status.Cluster.SpotStrategy = "SpotAsPriceGo"
|
||||
} else {
|
||||
infra.Status.Cluster.SpotStrategy = "NoSpot"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DefaultValidate(infra *v1beta1.Infra) field.ErrorList {
|
||||
allErrors := field.ErrorList{}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
@@ -68,10 +68,9 @@ func (a *AliProvider) CreateVSwitch() error {
|
||||
request := vpc.CreateCreateVSwitchRequest()
|
||||
request.Scheme = Scheme
|
||||
request.ZoneId = a.Infra.Status.Cluster.ZoneID
|
||||
request.CidrBlock = CidrBlock
|
||||
request.CidrBlock = a.Infra.Spec.Cluster.Metadata.Network.PrivateCidrIP
|
||||
request.VpcId = VpcID.Value(a.Infra.Status)
|
||||
request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
//response, err := d.Client.CreateVSwitch(request)
|
||||
response := vpc.CreateCreateVSwitchResponse()
|
||||
err := a.RetryVpcRequest(request, response)
|
||||
if err != nil {
|
||||
@@ -110,11 +109,10 @@ func (a *AliProvider) CreateSecurityGroup() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if !a.AuthorizeSecurityGroup(response.SecurityGroupId, SSHPortRange) {
|
||||
return fmt.Errorf("authorize securitygroup ssh port failed")
|
||||
}
|
||||
if !a.AuthorizeSecurityGroup(response.SecurityGroupId, APIServerPortRange) {
|
||||
return fmt.Errorf("authorize securitygroup apiserver port failed")
|
||||
for _, port := range a.Infra.Spec.Cluster.Metadata.Network.ExportPorts {
|
||||
if !a.AuthorizeSecurityGroup(response.SecurityGroupId, port) {
|
||||
return fmt.Errorf("authorize securitygroup port: %v failed", port)
|
||||
}
|
||||
}
|
||||
SecurityGroupID.SetValue(a.Infra.Status, response.SecurityGroupId)
|
||||
return nil
|
||||
@@ -197,8 +195,8 @@ func (a *AliProvider) BindEipForMaster0() error {
|
||||
func (a *AliProvider) allocateEipAddress() (eIP, eIPID string, err error) {
|
||||
request := vpc.CreateAllocateEipAddressRequest()
|
||||
request.Scheme = Scheme
|
||||
request.Bandwidth = Bandwidth
|
||||
request.InternetChargeType = InternetChargeType
|
||||
request.Bandwidth = a.Infra.Spec.Cluster.Metadata.Network.Bandwidth
|
||||
request.InternetChargeType = "PayByTraffic"
|
||||
response := vpc.CreateAllocateEipAddressResponse()
|
||||
err = a.RetryVpcRequest(request, response)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
)
|
||||
|
||||
const (
|
||||
Scheme = "https"
|
||||
IPProtocol = "tcp"
|
||||
APIServerPortRange = "6443/6443"
|
||||
SSHPortRange = "22/22"
|
||||
SourceCidrIP = "0.0.0.0/0"
|
||||
CidrBlock = "172.16.0.0/24"
|
||||
Policy = "accept"
|
||||
DestinationResource = "InstanceType"
|
||||
InstanceChargeType = "PostPaid"
|
||||
InternetChargeType = "PayByTraffic"
|
||||
Product = "product"
|
||||
Role = "role"
|
||||
Arch = "arch"
|
||||
Stopped = "Stopped"
|
||||
AvailableTypeStatus = "WithStock"
|
||||
Bandwidth = "100"
|
||||
HwDomain = "www.sealyun.com/"
|
||||
TryTimes = 10
|
||||
TrySleepTime = time.Second
|
||||
JustGetInstanceInfo = 0
|
||||
)
|
||||
|
||||
const HuaweiProvider v2.Provider = "HuaweiProvider"
|
||||
|
||||
type ResourceName string
|
||||
|
||||
const (
|
||||
EipID ResourceName = HwDomain + "EipID"
|
||||
VpcID ResourceName = HwDomain + "VpcID"
|
||||
VSwitchID ResourceName = HwDomain + "VSwitchID"
|
||||
SecurityGroupID ResourceName = HwDomain + "SecurityGroupID"
|
||||
ZoneID ResourceName = HwDomain + "ZoneID"
|
||||
ShouldBeDeleteInstancesIDs ResourceName = "ShouldBeDeleteInstancesIDs"
|
||||
)
|
||||
|
||||
func (r ResourceName) ClusterValue(infra v2.InfraSpec) string {
|
||||
return infra.Cluster.Annotations[string(r)]
|
||||
}
|
||||
|
||||
func (r ResourceName) ClusterSetValue(infra v2.InfraSpec, val string) {
|
||||
infra.Cluster.Annotations[string(r)] = val
|
||||
}
|
||||
|
||||
func (r ResourceName) Value(status v2.InfraStatus) string {
|
||||
return status.Cluster.Annotations[string(r)]
|
||||
}
|
||||
|
||||
func (r ResourceName) SetValue(status v2.InfraStatus, val string) {
|
||||
status.Cluster.Annotations[string(r)] = val
|
||||
}
|
||||
|
||||
type ImageArch string
|
||||
|
||||
func ConvertImageArch(arch v2.Arch) ImageArch {
|
||||
switch arch {
|
||||
case v2.ARM64:
|
||||
return "arm64"
|
||||
case v2.AMD64:
|
||||
return "x86_64"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/fanux/sealos/pkg/utils"
|
||||
"github.com/fanux/sealos/pkg/utils/logger"
|
||||
v2 "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ecs/v2"
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ecs/v2/model"
|
||||
)
|
||||
|
||||
//type Instance struct {
|
||||
// CPU int
|
||||
// Memory int
|
||||
// InstanceID string
|
||||
// PrimaryIPAddress string
|
||||
//}
|
||||
//
|
||||
|
||||
func (a *HwProvider) GetAvailableZoneID() error {
|
||||
if a.Infra.Status.Cluster.ZoneID != "" {
|
||||
logger.Debug("zoneID using status value")
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
logger.Info("create resource success %s: %s", "GetAvailableZoneID", a.Infra.Status.Cluster.ZoneID)
|
||||
}()
|
||||
|
||||
if len(a.Infra.Spec.Cluster.ZoneIDs) != 0 {
|
||||
a.Infra.Status.Cluster.ZoneID = a.Infra.Spec.Cluster.ZoneIDs[utils.Rand(len(a.Infra.Spec.Cluster.ZoneIDs))]
|
||||
return nil
|
||||
}
|
||||
resp, err := a.RetryEcsRequest(&model.NovaListAvailabilityZonesRequest{}, v2.GenReqDefForNovaListAvailabilityZones())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if zones, ok := resp.(*model.NovaListAvailabilityZonesResponse); ok {
|
||||
if zones.HttpStatusCode != 200 || zones.AvailabilityZoneInfo == nil || len(*zones.AvailabilityZoneInfo) == 0 {
|
||||
return errors.New("not available ZoneID ")
|
||||
}
|
||||
if zones.AvailabilityZoneInfo != nil {
|
||||
zoneID := (*zones.AvailabilityZoneInfo)[utils.Rand(len(*zones.AvailabilityZoneInfo))].ZoneName
|
||||
a.Infra.Status.Cluster.ZoneID = zoneID
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//func (a *HwProvider) InputIPlist(host *v1beta1.Host) (ipList []string, err error) {
|
||||
// if host == nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// instances, err := a.GetInstancesInfo(host, host.Count)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// for _, instance := range instances {
|
||||
// ipList = append(ipList, instance.PrimaryIPAddress)
|
||||
// }
|
||||
// return ipList, nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) GetInstanceStatus(instanceID string) (instanceStatus string, err error) {
|
||||
// request := ecs.CreateDescribeInstanceStatusRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = &[]string{instanceID}
|
||||
// response := ecs.CreateDescribeInstanceStatusResponse()
|
||||
// err = a.RetryEcsRequest(request, response)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("get GetAvailableZoneID status failed %v , error :%v", instanceID, err)
|
||||
// }
|
||||
// if len(response.InstanceStatuses.InstanceStatus) == 0 {
|
||||
// return "", fmt.Errorf("GetAvailableZoneID list is empty")
|
||||
// }
|
||||
// return response.InstanceStatuses.InstanceStatus[0].Status, nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) PowerOffInstance(instanceID string) error {
|
||||
// request := ecs.CreateStopInstancesRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = &[]string{instanceID}
|
||||
//
|
||||
// response := ecs.CreateStopInstancesResponse()
|
||||
// return a.RetryEcsRequest(request, response)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) StartInstance(instanceID string) error {
|
||||
// request := ecs.CreateStartInstanceRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = instanceID
|
||||
// response := ecs.CreateStartInstanceResponse()
|
||||
// return a.RetryEcsRequest(request, response)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) ChangeInstanceType(instanceID string, host *v1beta1.Host) error {
|
||||
// instanceStatus, err := a.GetInstanceStatus(instanceID)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if instanceStatus != Stopped {
|
||||
// err = a.PowerOffInstance(instanceID)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// expectInstanceType, err := a.GetAvailableInstanceType(host)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// request := ecs.CreateModifyInstanceSpecRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = instanceID
|
||||
// response := ecs.CreateModifyInstanceSpecResponse()
|
||||
// err = a.RetryEcsInstanceType(request, response, expectInstanceType, host.Roles)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return a.StartInstance(instanceID)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) GetInstancesInfo(host *v1beta1.Host, expectCount int) (instances []Instance, err error) {
|
||||
// var count int
|
||||
// tag := make(map[string]string)
|
||||
// tag[Product] = a.Infra.Name
|
||||
// tag[Role] = strings.Join(host.Roles, ",")
|
||||
// tag[Arch] = string(host.Arch)
|
||||
// if expectCount == 0 {
|
||||
// count = -1
|
||||
// } else {
|
||||
// count = expectCount
|
||||
// }
|
||||
// instancesTags := CreateDescribeInstancesTag(tag)
|
||||
// request := ecs.CreateDescribeInstancesRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
// request.VSwitchId = VSwitchID.Value(a.Infra.Status)
|
||||
// request.SecurityGroupId = SecurityGroupID.Value(a.Infra.Status)
|
||||
// request.Tag = &instancesTags
|
||||
// response := ecs.CreateDescribeInstancesResponse()
|
||||
// err = a.TryGetInstance(request, response, count)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// for _, i := range response.Instances.Instance {
|
||||
// instances = append(instances,
|
||||
// Instance{
|
||||
// CPU: i.Cpu,
|
||||
// Memory: i.Memory / 1024,
|
||||
// InstanceID: i.InstanceId,
|
||||
// PrimaryIPAddress: i.NetworkInterfaces.NetworkInterface[0].PrimaryIpAddress})
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) ReconcileInstances(host *v1beta1.Host, status *v1beta1.HostStatus) error {
|
||||
// var instances []Instance
|
||||
// var instancesIDs string
|
||||
// var IPList []string
|
||||
// instancesIDs = status.IDs
|
||||
// switch host.ToRole() {
|
||||
// case v1beta1.Master:
|
||||
// if host.Count == 0 {
|
||||
// return errors.New("master count not set")
|
||||
// }
|
||||
// case v1beta1.Node:
|
||||
// if host == nil {
|
||||
// return nil
|
||||
// }
|
||||
// }
|
||||
// if host == nil {
|
||||
// return errors.New("hosts not set")
|
||||
// }
|
||||
// var err error
|
||||
// if instancesIDs != "" {
|
||||
// instances, err = a.GetInstancesInfo(host, JustGetInstanceInfo)
|
||||
// }
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if i := host.Count; len(instances) < i {
|
||||
// err = a.RunInstances(host, i-len(instances))
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// ipList, err := a.InputIPlist(host)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// IPList = utils.AppendIPList(IPList, ipList)
|
||||
// logger.Info("get scale up IP list %v, append iplist %v, host count %d", ipList, IPList, host.Count)
|
||||
// }
|
||||
//
|
||||
// for _, instance := range instances {
|
||||
// if instance.CPU != host.CPU || instance.Memory != host.Memory {
|
||||
// err = a.ChangeInstanceType(instance.InstanceID, host)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// status.IPs = IPList
|
||||
// logger.Info("reconcile %s instances success %v ", host.String(), IPList)
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) DeleteInstances() error {
|
||||
// instanceIDs := strings.Split(ShouldBeDeleteInstancesIDs.Value(a.Infra.Status), ",")
|
||||
// if len(instanceIDs) == 0 {
|
||||
// return nil
|
||||
// }
|
||||
// request := ecs.CreateDeleteInstancesRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = &instanceIDs
|
||||
// request.Force = requests.NewBoolean(true)
|
||||
// response := ecs.CreateDeleteInstancesResponse()
|
||||
// err := a.RetryEcsRequest(request, response)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// ShouldBeDeleteInstancesIDs.SetValue(a.Infra.Status, "")
|
||||
// if v1beta1.In(a.Infra.Status.Cluster.Master0ID, instanceIDs) {
|
||||
// logger.Debug("delete instance success,need delete about instance info[master0id,master0InternalIP,eip,eipID]")
|
||||
// a.Infra.Status.Cluster.Master0ID = ""
|
||||
// a.Infra.Status.Cluster.Master0InternalIP = ""
|
||||
// a.Infra.Status.Cluster.EIP = ""
|
||||
// delete(a.Infra.Status.Cluster.Annotations, string(EipID))
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func CreateDescribeInstancesTag(tags map[string]string) (instanceTags []ecs.DescribeInstancesTag) {
|
||||
// for k, v := range tags {
|
||||
// instanceTags = append(instanceTags, ecs.DescribeInstancesTag{Key: k, Value: v})
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func CreateInstanceDataDisk(dataDisks []v1beta1.Disk, category string) (instanceDisks []ecs.RunInstancesDataDisk) {
|
||||
// for _, v := range dataDisks {
|
||||
// instanceDisks = append(instanceDisks,
|
||||
// ecs.RunInstancesDataDisk{Size: strconv.Itoa(v.Capacity), Category: category})
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) RunInstances(host *v1beta1.Host, count int) error {
|
||||
// if host == nil {
|
||||
// return errors.New("host not set")
|
||||
// }
|
||||
// j := a.Infra.Status.FindHostsByRoles(host.Roles)
|
||||
// if j == -1 {
|
||||
// return fmt.Errorf("failed to get status, %v", "not find host status,pelase retry")
|
||||
// }
|
||||
// systemDiskSize := host.Disks[0]
|
||||
// var instanceType []string
|
||||
// var err error
|
||||
// var imageID string
|
||||
// if imageID, err = a.GetAvailableImageID(host); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// a.Infra.Status.Hosts[j].ImageID = imageID
|
||||
// a.Infra.Status.Hosts[j].Arch = host.Arch
|
||||
// instanceType, err = a.GetAvailableInstanceType(host)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// tag := make(map[string]string)
|
||||
// tag[Product] = a.Infra.Name
|
||||
// tag[Role] = strings.Join(host.Roles, ",")
|
||||
// tag[Arch] = string(host.Arch)
|
||||
// instancesTag := CreateInstanceTag(tag)
|
||||
//
|
||||
// dataDisks := host.Disks[1:]
|
||||
// datadisk := CreateInstanceDataDisk(dataDisks, a.Infra.Status.Hosts[j].DataCategory)
|
||||
//
|
||||
// request := ecs.CreateRunInstancesRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.ImageId = imageID
|
||||
//
|
||||
// request.Password = a.Infra.Spec.Cluster.AccessChannels.SSH.Passwd
|
||||
// request.SecurityGroupId = SecurityGroupID.Value(a.Infra.Status)
|
||||
// request.VSwitchId = VSwitchID.Value(a.Infra.Status)
|
||||
// request.SystemDiskSize = strconv.Itoa(systemDiskSize.Capacity)
|
||||
// request.SystemDiskCategory = a.Infra.Status.Hosts[j].SystemCategory
|
||||
// request.DataDisk = &datadisk
|
||||
// request.SpotStrategy = a.Infra.Status.Cluster.SpotStrategy
|
||||
// request.Amount = requests.NewInteger(count)
|
||||
// request.Tag = &instancesTag
|
||||
// response := ecs.CreateRunInstancesResponse()
|
||||
// err = a.RetryEcsInstanceType(request, response, instanceType, host.Roles)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// instancesIDs := strings.Join(response.InstanceIdSets.InstanceIdSet, ",")
|
||||
// a.Infra.Status.Hosts[j].IDs += instancesIDs
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) AuthorizeSecurityGroup(securityGroupID, portRange string) bool {
|
||||
// request := ecs.CreateAuthorizeSecurityGroupRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.SecurityGroupId = securityGroupID
|
||||
// request.IpProtocol = IPProtocol
|
||||
// request.PortRange = portRange
|
||||
// request.SourceCidrIp = SourceCidrIP
|
||||
// request.Policy = Policy
|
||||
//
|
||||
// response := ecs.CreateAuthorizeSecurityGroupResponse()
|
||||
// err := a.RetryEcsRequest(request, response)
|
||||
// if err != nil {
|
||||
// logger.Error("%v", err)
|
||||
// return false
|
||||
// }
|
||||
// return response.BaseResponse.IsSuccess()
|
||||
//}
|
||||
//func CreateInstanceTag(tags map[string]string) (instanceTags []ecs.RunInstancesTag) {
|
||||
// for k, v := range tags {
|
||||
// instanceTags = append(instanceTags, ecs.RunInstancesTag{Key: k, Value: v})
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
@@ -0,0 +1,206 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
//func (a *HwProvider) GetAvailableImageID(host *v1beta1.Host) (string, error) {
|
||||
// if host.OS.ID != "" {
|
||||
// logger.Info("host tags is %v,using imageID is %s", host.Roles, host.OS.ID)
|
||||
// return host.OS.ID, nil
|
||||
// }
|
||||
// logger.Warn("tips: imageID not set,so imageID is random.that will maybe let instanceType not find.")
|
||||
// request := ecs.CreateDescribeImagesRequest()
|
||||
// request.ImageOwnerAlias = "system"
|
||||
// request.PageSize = "100"
|
||||
// request.Architecture = string(ConvertImageArch(host.Arch))
|
||||
// request.OSType = "linux"
|
||||
// response := ecs.CreateDescribeImagesResponse()
|
||||
// err := a.RetryEcsRequest(request, response)
|
||||
// if err != nil {
|
||||
// return "", fmt.Errorf("get ImageID failed , error :%v", err)
|
||||
// }
|
||||
// if response.TotalCount == 0 {
|
||||
// return "", fmt.Errorf("ImageID list is empty")
|
||||
// }
|
||||
// var images []string
|
||||
//
|
||||
// for _, image := range response.Images.Image {
|
||||
// flag := true
|
||||
// imagesName := strings.ToLower(image.Platform)
|
||||
// imagesName = strings.ReplaceAll(imagesName, " ", "_")
|
||||
// if strings.ToLower(host.OS.Name) != "" {
|
||||
// if imagesName != strings.ToLower(host.OS.Name) {
|
||||
// flag = false
|
||||
// }
|
||||
// }
|
||||
// if strings.ToLower(host.OS.Version) != "" {
|
||||
// imageID := strings.ReplaceAll(image.ImageName, imagesName, "")
|
||||
// imageIDArr := strings.Split(imageID, "_")
|
||||
// var versions []string
|
||||
// for _, v := range imageIDArr {
|
||||
// if v == string(ConvertImageArch(host.Arch)) {
|
||||
// break
|
||||
// } else {
|
||||
// versions = append(versions, v)
|
||||
// }
|
||||
// }
|
||||
// version := strings.Join(versions, ".")
|
||||
// //7.1,7,7.3,8.7
|
||||
// if !strings.HasPrefix(version, strings.ToLower(host.OS.Version)) {
|
||||
// flag = false
|
||||
// }
|
||||
// }
|
||||
// if flag {
|
||||
// logger.Debug("host tags is %v,search imageID is %s", host.Roles, image.ImageId)
|
||||
// images = append(images, image.ImageId)
|
||||
// }
|
||||
// }
|
||||
// if len(images) == 0 {
|
||||
// return "", fmt.Errorf("search ImageID list is empty")
|
||||
// }
|
||||
// logger.Info("host tags is %v,using first imageID is %s", host.Roles, images[0])
|
||||
// return images[utils.Rand(len(images))], nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) GetDefaultDiskCategories(host *v1beta1.Host) (system []string, data []string) {
|
||||
// categories := []string{"cloud", "cloud_efficiency", "cloud_ssd", "cloud_essd"}
|
||||
// if host.Disks[0].Category != "" {
|
||||
// system = []string{host.Disks[0].Category}
|
||||
// } else {
|
||||
// logger.Warn("host tags is %v,system category not set", host.Roles)
|
||||
// system = categories
|
||||
// }
|
||||
// if len(host.Disks) > 1 {
|
||||
// if host.Disks[1].Category != "" {
|
||||
// data = []string{host.Disks[1].Category}
|
||||
// } else {
|
||||
// logger.Warn("host tags is %v,data category not set", host.Roles)
|
||||
// data = categories
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) GetAvailableInstanceType(host *v1beta1.Host) ([]string, error) {
|
||||
// if host.EcsType != "" {
|
||||
// return []string{host.EcsType}, nil
|
||||
// }
|
||||
// var systemInstanceTypes []string
|
||||
// j := a.Infra.Status.FindHostsByRoles(host.Roles)
|
||||
// if j == -1 {
|
||||
// return nil, fmt.Errorf("failed to get host, %v", "not find host status,pelase retry")
|
||||
// }
|
||||
// var err error
|
||||
// systemDisk, dataDisk := a.GetDefaultDiskCategories(host)
|
||||
//
|
||||
// for _, sys := range systemDisk {
|
||||
// if len(dataDisk) > 0 {
|
||||
// for _, data := range dataDisk {
|
||||
// logger.Debug("host tags is %v,search systemDiskCategory=%s,dataDiskCategory=%s", host.Roles, sys, data)
|
||||
// systemInstanceTypes, err = a.GetAvailableResource(host, sys, data)
|
||||
// if err == nil {
|
||||
// for i := 0; i < len(host.Disks); i++ {
|
||||
// host.Disks[i].Category = data
|
||||
// }
|
||||
// host.Disks[0].Category = sys
|
||||
// a.Infra.Status.Hosts[j].DataCategory = data
|
||||
// a.Infra.Status.Hosts[j].SystemCategory = sys
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// logger.Debug("host tags is %v,search systemDiskCategory=%s", host.Roles, sys)
|
||||
// systemInstanceTypes, err = a.GetAvailableResource(host, sys, "")
|
||||
// if err == nil {
|
||||
// host.Disks[0].Category = sys
|
||||
// a.Infra.Status.Hosts[j].SystemCategory = sys
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if len(systemInstanceTypes) < 1 {
|
||||
// return nil, fmt.Errorf("host tags is %v,systemInstanceType not find", host.Roles)
|
||||
// }
|
||||
//
|
||||
// var instanceTypes []string
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
//
|
||||
// request := ecs.CreateDescribeImageSupportInstanceTypesRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
// request.ImageId = a.Infra.Status.Hosts[j].ImageID
|
||||
//
|
||||
// //response := ecs.CreateDescribeImageSupportInstanceTypesResponse()
|
||||
// //err = a.EcsClient.DoAction(request, response)
|
||||
// //if err != nil {
|
||||
// // return nil, err
|
||||
// //}
|
||||
// //for _, i := range response.InstanceTypes.InstanceType {
|
||||
// // if i.CpuCoreCount == host.CPU && int(i.MemorySize) == host.Memory {
|
||||
// // if v1beta1.In(i.InstanceTypeId, systemInstanceTypes) {
|
||||
// // logger.Debug("host tags is %v,append InstanceType is %s", host.Roles, i.InstanceTypeId)
|
||||
// // instanceTypes = append(instanceTypes, i.InstanceTypeId)
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
// if len(instanceTypes) < 1 {
|
||||
// return nil, fmt.Errorf("host tags is %v,instanceType not find", host.Roles)
|
||||
// }
|
||||
// return instanceTypes, nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) GetAvailableResource(host *v1beta1.Host, systemCategory, dataCategory string) (instanceType []string, err error) {
|
||||
// request := ecs.CreateDescribeAvailableResourceRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
// request.ZoneId = a.Infra.Status.Cluster.ZoneID
|
||||
// request.DestinationResource = DestinationResource
|
||||
// request.InstanceChargeType = InstanceChargeType
|
||||
// request.SpotStrategy = a.Infra.Status.Cluster.SpotStrategy
|
||||
// request.SystemDiskCategory = systemCategory
|
||||
// request.DataDiskCategory = dataCategory
|
||||
// request.Cores = requests.NewInteger(host.CPU)
|
||||
// request.Memory = requests.NewFloat(float64(host.Memory))
|
||||
// //response := ecs.CreateDescribeAvailableResourceResponse()
|
||||
// //err = a.EcsClient.DoAction(request, response)
|
||||
// //if err != nil {
|
||||
// // return nil, err
|
||||
// //}
|
||||
// //if len(response.AvailableZones.AvailableZone) < 1 {
|
||||
// // return nil, fmt.Errorf("available zone not find")
|
||||
// //}
|
||||
// //for _, i := range response.AvailableZones.AvailableZone {
|
||||
// // for _, f := range i.AvailableResources.AvailableResource {
|
||||
// // for _, r := range f.SupportedResources.SupportedResource {
|
||||
// // if r.StatusCategory == AvailableTypeStatus {
|
||||
// // instanceType = append(instanceType, r.Value)
|
||||
// // }
|
||||
// // }
|
||||
// // }
|
||||
// //}
|
||||
// j := a.Infra.Status.FindHostsByRoles(host.Roles)
|
||||
// if j == -1 {
|
||||
// return nil, fmt.Errorf("failed to get ecs instance type, %v", "not find host status,pelase retry")
|
||||
// }
|
||||
//
|
||||
// if a.Infra.Status.Hosts[j].InstanceType != "" {
|
||||
// defaultInstanceType := []string{a.Infra.Status.Hosts[j].InstanceType}
|
||||
// instanceType = append(defaultInstanceType, instanceType...)
|
||||
// }
|
||||
//
|
||||
// return
|
||||
//}
|
||||
@@ -0,0 +1,279 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
"github.com/fanux/sealos/pkg/utils"
|
||||
"github.com/fanux/sealos/pkg/utils/logger"
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core"
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/auth/basic"
|
||||
ecs "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/ecs/v2"
|
||||
|
||||
vpc "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v2"
|
||||
)
|
||||
|
||||
type ActionName string
|
||||
|
||||
const (
|
||||
CreateVPC ActionName = "CreateVPC"
|
||||
CreateVSwitch ActionName = "CreateVSwitch"
|
||||
CreateSecurityGroup ActionName = "CreateSecurityGroup"
|
||||
ReconcileInstance ActionName = "ReconcileInstance"
|
||||
BindEIP ActionName = "BindEIP"
|
||||
ReleaseEIP ActionName = "ReleaseEIP"
|
||||
ClearInstances ActionName = "ClearInstances"
|
||||
DeleteVSwitch ActionName = "DeleteVSwitch"
|
||||
DeleteSecurityGroup ActionName = "DeleteSecurityGroup"
|
||||
DeleteVPC ActionName = "DeleteVPC"
|
||||
GetZoneID ActionName = "GetAvailableZoneID"
|
||||
)
|
||||
|
||||
type HwProvider struct {
|
||||
EcsClient ecs.EcsClient
|
||||
VpcClient vpc.VpcClient
|
||||
Infra *v2.Infra
|
||||
}
|
||||
|
||||
type HwFunc func() error
|
||||
|
||||
func (a *HwProvider) ReconcileResource(resourceKey ResourceName, action HwFunc) error {
|
||||
if resourceKey.Value(a.Infra.Status) != "" {
|
||||
logger.Debug("using resource status value %s: %s", resourceKey, resourceKey.Value(a.Infra.Status))
|
||||
return nil
|
||||
}
|
||||
if err := action(); err != nil {
|
||||
logger.Error("reconcile resource %s failed err: %s", resourceKey, err)
|
||||
return err
|
||||
}
|
||||
if resourceKey.Value(a.Infra.Status) != "" {
|
||||
logger.Info("create resource success %s: %s", resourceKey, resourceKey.Value(a.Infra.Status))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HwProvider) DeleteResource(resourceKey ResourceName, action HwFunc) {
|
||||
val := resourceKey.Value(a.Infra.Status)
|
||||
if val == "" {
|
||||
logger.Warn("delete resource not exists %s", resourceKey)
|
||||
return
|
||||
}
|
||||
if err := action(); err != nil {
|
||||
logger.Error("delete resource %s failed err: %s", resourceKey, err)
|
||||
} else {
|
||||
logger.Info("delete resource Success %s: %s", resourceKey, val)
|
||||
}
|
||||
}
|
||||
|
||||
var RecocileFuncMap = map[ActionName]func(provider *HwProvider) error{
|
||||
CreateVPC: func(hwProvider *HwProvider) error {
|
||||
return hwProvider.ReconcileResource(VpcID, hwProvider.CreateVPC)
|
||||
},
|
||||
|
||||
//CreateVSwitch: func(hwProvider *HwProvider) error {
|
||||
// return hwProvider.ReconcileResource(VSwitchID, hwProvider.CreateVSwitch)
|
||||
//},
|
||||
//CreateSecurityGroup: func(hwProvider *HwProvider) error {
|
||||
// return hwProvider.ReconcileResource(SecurityGroupID, hwProvider.CreateSecurityGroup)
|
||||
//},
|
||||
//ReconcileInstance: func(hwProvider *HwProvider) error {
|
||||
// var errorMsg []string
|
||||
// current := sets.NewString()
|
||||
// spec := sets.NewString()
|
||||
// for _, h := range hwProvider.Infra.Status.Hosts {
|
||||
// current.Insert(strings.Join(h.Roles, ","))
|
||||
// }
|
||||
// for _, h := range hwProvider.Infra.Spec.Hosts {
|
||||
// spec.Insert(strings.Join(h.Roles, ","))
|
||||
// host := &h
|
||||
// statusIndex := hwProvider.Infra.Status.FindHostsByRoles(h.Roles)
|
||||
// if statusIndex < 0 {
|
||||
// errorMsg = append(errorMsg, fmt.Sprintf("infra status not fount in role tag: %v", h.Roles))
|
||||
// continue
|
||||
// }
|
||||
// status := &hwProvider.Infra.Status.Hosts[statusIndex]
|
||||
// err := hwProvider.ReconcileInstances(host, status)
|
||||
// if err != nil {
|
||||
// errorMsg = append(errorMsg, err.Error())
|
||||
// status.Ready = false
|
||||
// } else {
|
||||
// status.Ready = true
|
||||
// }
|
||||
// }
|
||||
// deleteData := current.Difference(spec)
|
||||
// var instanceIDs []string
|
||||
// finalStatus := hwProvider.Infra.Status.Hosts
|
||||
// for _, roles := range deleteData.List() {
|
||||
// statusIndex := hwProvider.Infra.Status.FindHostsByRolesString(roles)
|
||||
// ids := hwProvider.Infra.Status.Hosts[statusIndex].IDs
|
||||
// instanceIDs = append(instanceIDs, ids)
|
||||
// finalStatus = append(finalStatus[:statusIndex], finalStatus[statusIndex+1:]...)
|
||||
// }
|
||||
// if len(instanceIDs) != 0 {
|
||||
// ShouldBeDeleteInstancesIDs.SetValue(hwProvider.Infra.Status, strings.Join(instanceIDs, ","))
|
||||
// hwProvider.DeleteResource(ShouldBeDeleteInstancesIDs, hwProvider.DeleteInstances)
|
||||
// hwProvider.Infra.Status.Hosts = finalStatus
|
||||
// }
|
||||
//
|
||||
// if len(errorMsg) == 0 {
|
||||
// return nil
|
||||
// }
|
||||
// return errors.New(strings.Join(errorMsg, " && "))
|
||||
//},
|
||||
GetZoneID: func(hwProvider *HwProvider) error {
|
||||
return hwProvider.ReconcileResource(ZoneID, hwProvider.GetAvailableZoneID)
|
||||
},
|
||||
//BindEIP: func(hwProvider *HwProvider) error {
|
||||
// return hwProvider.ReconcileResource(EipID, hwProvider.BindEipForMaster0)
|
||||
//},
|
||||
}
|
||||
|
||||
var DeleteFuncMap = map[ActionName]func(provider *HwProvider){
|
||||
//ReleaseEIP: func(hwProvider *HwProvider) {
|
||||
// hwProvider.DeleteResource(EipID, hwProvider.ReleaseEipAddress)
|
||||
//},
|
||||
//ClearInstances: func(hwProvider *HwProvider) {
|
||||
// var instanceIDs []string
|
||||
// for _, h := range hwProvider.Infra.Status.Hosts {
|
||||
// instances, err := hwProvider.GetInstancesInfo(h.ToHost(), JustGetInstanceInfo)
|
||||
// if err != nil {
|
||||
// logger.Error("get %s instanceInfo failed %v", strings.Join(h.Roles, ","), err)
|
||||
// }
|
||||
// for _, instance := range instances {
|
||||
// instanceIDs = append(instanceIDs, instance.InstanceID)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if len(instanceIDs) != 0 {
|
||||
// ShouldBeDeleteInstancesIDs.SetValue(hwProvider.Infra.Status, strings.Join(instanceIDs, ","))
|
||||
// }
|
||||
// hwProvider.DeleteResource(ShouldBeDeleteInstancesIDs, hwProvider.DeleteInstances)
|
||||
//},
|
||||
//DeleteVSwitch: func(hwProvider *HwProvider) {
|
||||
// hwProvider.DeleteResource(VSwitchID, hwProvider.DeleteVSwitch)
|
||||
//},
|
||||
//DeleteSecurityGroup: func(hwProvider *HwProvider) {
|
||||
// hwProvider.DeleteResource(SecurityGroupID, hwProvider.DeleteSecurityGroup)
|
||||
//},
|
||||
DeleteVPC: func(hwProvider *HwProvider) {
|
||||
hwProvider.DeleteResource(VpcID, hwProvider.DeleteVPC)
|
||||
},
|
||||
}
|
||||
|
||||
func (a *HwProvider) basicAuth() basic.Credentials {
|
||||
//https://developer.huaweicloud.com/endpoint?ECS
|
||||
core.NewHcHttpClientBuilder()
|
||||
return basic.NewCredentialsBuilder().
|
||||
WithAk(a.Infra.Spec.Credential.AccessKey).
|
||||
WithSk(a.Infra.Spec.Credential.AccessSecret).
|
||||
WithProjectId(a.Infra.Spec.Credential.ProjectID).
|
||||
Build()
|
||||
}
|
||||
|
||||
func (a *HwProvider) NewClient() (err error) {
|
||||
regionID := a.Infra.Spec.Cluster.RegionIDs[utils.Rand(len(a.Infra.Spec.Cluster.RegionIDs))]
|
||||
a.Infra.Status.Cluster.RegionID = regionID
|
||||
logger.Info("using regionID is %s", regionID)
|
||||
ecsEndpoint := fmt.Sprintf("https://ecs.%s.myhuaweicloud.com", regionID)
|
||||
vpcEndpoint := fmt.Sprintf("https://vpc.%s.myhuaweicloud.com", regionID)
|
||||
logger.Info("using ecs endpoint is %s", ecsEndpoint)
|
||||
logger.Info("using vpc endpoint is %s", vpcEndpoint)
|
||||
//var err error
|
||||
defer func() {
|
||||
if info := recover(); info != nil {
|
||||
err = fmt.Errorf("%v", info)
|
||||
}
|
||||
}()
|
||||
ecsClient := ecs.NewEcsClient(
|
||||
ecs.EcsClientBuilder().
|
||||
WithEndpoint(ecsEndpoint).
|
||||
WithCredential(a.basicAuth()).
|
||||
Build())
|
||||
vpcClient := vpc.NewVpcClient(
|
||||
vpc.VpcClientBuilder().
|
||||
WithEndpoint(vpcEndpoint).
|
||||
WithCredential(a.basicAuth()).
|
||||
Build())
|
||||
a.EcsClient = *ecsClient
|
||||
a.VpcClient = *vpcClient
|
||||
return
|
||||
}
|
||||
|
||||
func (a *HwProvider) ClearCluster() {
|
||||
todolist := []ActionName{
|
||||
//ReleaseEIP,
|
||||
//ClearInstances,
|
||||
//DeleteVSwitch,
|
||||
//DeleteSecurityGroup,
|
||||
DeleteVPC,
|
||||
}
|
||||
for _, name := range todolist {
|
||||
DeleteFuncMap[name](a)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *HwProvider) Reconcile() error {
|
||||
if a.Infra.DeletionTimestamp != nil {
|
||||
logger.Info("deletionTimestamp not nil will clear infra")
|
||||
a.ClearCluster()
|
||||
return nil
|
||||
}
|
||||
todolist := []ActionName{
|
||||
GetZoneID,
|
||||
CreateVPC,
|
||||
//CreateVSwitch,
|
||||
//CreateSecurityGroup,
|
||||
//ReconcileInstance,
|
||||
//BindEIP,
|
||||
}
|
||||
|
||||
for _, actionName := range todolist {
|
||||
err := RecocileFuncMap[actionName](a)
|
||||
if err != nil {
|
||||
logger.Warn("actionName: %s,err: %v ,skip it", actionName, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HwProvider) Apply() error {
|
||||
return a.Reconcile()
|
||||
}
|
||||
|
||||
func DefaultInfra(infra *v2.Infra) error {
|
||||
//if infra.Spec.Cluster.IsSeize {
|
||||
// infra.Status.Cluster.SpotStrategy = "SpotAsPriceGo"
|
||||
//} else {
|
||||
// infra.Status.Cluster.SpotStrategy = "NoSpot"
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DefaultValidate(infra *v2.Infra) field.ErrorList {
|
||||
allErrors := field.ErrorList{}
|
||||
//if provide == v1beta1.HuaweiProvider {
|
||||
// if len(credential.ProjectID) == 0 {
|
||||
// logger.Warn("in huawei cloud , you need fetch projectID in you iam, please visit https://support.huaweicloud.com/apm_faq/apm_03_0001.html")
|
||||
// allErrors = append(allErrors, field.Invalid(fldPath.Key("projectID"), credential.ProjectID,
|
||||
// "projectID not empty"))
|
||||
// }
|
||||
//}
|
||||
return allErrors
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/fanux/sealos/pkg/utils/logger"
|
||||
v2 "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v2"
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/vpc/v2/model"
|
||||
)
|
||||
|
||||
func (a *HwProvider) CreateVPC() error {
|
||||
if vpcID := VpcID.ClusterValue(a.Infra.Spec); vpcID != "" {
|
||||
VpcID.SetValue(a.Infra.Status, vpcID)
|
||||
logger.Debug("VpcID using default value")
|
||||
return nil
|
||||
}
|
||||
request := &model.CreateVpcRequest{}
|
||||
request.Body = &model.CreateVpcRequestBody{
|
||||
Vpc: &model.CreateVpcOption{
|
||||
Cidr: &a.Infra.Spec.Cluster.Metadata.Network.PrivateCidrIP,
|
||||
},
|
||||
}
|
||||
resp, err := a.RetryVpcRequest(request, v2.GenReqDefForCreateVpc())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if vpc, ok := resp.(*model.CreateVpcResponse); ok {
|
||||
if vpc.HttpStatusCode != 200 || vpc.Vpc == nil {
|
||||
return errors.New("not available vpcID ")
|
||||
}
|
||||
VpcID.SetValue(a.Infra.Status, vpc.Vpc.Id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HwProvider) DeleteVPC() error {
|
||||
if VpcID.ClusterValue(a.Infra.Spec) != "" && VpcID.Value(a.Infra.Status) != "" {
|
||||
return nil
|
||||
}
|
||||
request := &model.DeleteVpcRequest{}
|
||||
resp, err := a.RetryVpcRequest(request, v2.GenReqDefForDeleteVpc())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if vpcResp, ok := resp.(*model.DeleteVpcResponse); ok {
|
||||
if vpcResp.HttpStatusCode != 200 {
|
||||
return errors.New("delete vpc field,return httpCode is not 200")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
//func (a *HwProvider) CreateVSwitch() error {
|
||||
// if vSwitchID := VSwitchID.ClusterValue(a.Infra.Spec); vSwitchID != "" {
|
||||
// logger.Debug("VSwitchID using default value")
|
||||
// VSwitchID.SetValue(a.Infra.Status, vSwitchID)
|
||||
// return nil
|
||||
// }
|
||||
// request := vpc.CreateCreateVSwitchRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.ZoneId = a.Infra.Status.Cluster.ZoneID
|
||||
// request.CidrBlock = CidrBlock
|
||||
// request.VpcId = VpcID.Value(a.Infra.Status)
|
||||
// request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
// //response, err := d.Client.CreateVSwitch(request)
|
||||
// response := vpc.CreateCreateVSwitchResponse()
|
||||
// err := a.RetryVpcRequest(request, response)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// VSwitchID.SetValue(a.Infra.Status, response.VSwitchId)
|
||||
//
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) DeleteVSwitch() error {
|
||||
// if VSwitchID.ClusterValue(a.Infra.Spec) != "" && VSwitchID.Value(a.Infra.Status) != "" {
|
||||
// return nil
|
||||
// }
|
||||
// request := vpc.CreateDeleteVSwitchRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.VSwitchId = VSwitchID.Value(a.Infra.Status)
|
||||
//
|
||||
// response := vpc.CreateDeleteVSwitchResponse()
|
||||
// return a.RetryVpcRequest(request, response)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) CreateSecurityGroup() error {
|
||||
// if securityGroupID := SecurityGroupID.ClusterValue(a.Infra.Spec); securityGroupID != "" {
|
||||
// logger.Debug("securityGroupID using default value")
|
||||
// SecurityGroupID.SetValue(a.Infra.Status, securityGroupID)
|
||||
// return nil
|
||||
// }
|
||||
// request := ecs.CreateCreateSecurityGroupRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.RegionId = a.Infra.Status.Cluster.RegionID
|
||||
// request.VpcId = VpcID.Value(a.Infra.Status)
|
||||
// response := ecs.CreateCreateSecurityGroupResponse()
|
||||
// err := a.RetryEcsRequest(request, response)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// if !a.AuthorizeSecurityGroup(response.SecurityGroupId, SSHPortRange) {
|
||||
// return fmt.Errorf("authorize securitygroup ssh port failed")
|
||||
// }
|
||||
// if !a.AuthorizeSecurityGroup(response.SecurityGroupId, APIServerPortRange) {
|
||||
// return fmt.Errorf("authorize securitygroup apiserver port failed")
|
||||
// }
|
||||
// SecurityGroupID.SetValue(a.Infra.Status, response.SecurityGroupId)
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) DeleteSecurityGroup() error {
|
||||
// if SecurityGroupID.ClusterValue(a.Infra.Spec) != "" && SecurityGroupID.Value(a.Infra.Status) != "" {
|
||||
// return nil
|
||||
// }
|
||||
// request := ecs.CreateDeleteSecurityGroupRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.SecurityGroupId = SecurityGroupID.Value(a.Infra.Status)
|
||||
//
|
||||
// response := ecs.CreateDeleteSecurityGroupResponse()
|
||||
// return a.RetryEcsRequest(request, response)
|
||||
//}
|
||||
|
||||
//
|
||||
//func (a *HwProvider) BindEipForMaster0() error {
|
||||
// var host *v1beta1.Host
|
||||
// for i, h := range a.Infra.Status.Hosts {
|
||||
// if v1beta1.In(v1beta1.Master, h.Roles) && h.Ready {
|
||||
// host = &a.Infra.Spec.Hosts[i]
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// if host == nil {
|
||||
// return fmt.Errorf("bind eip for master error: ready master host not fount")
|
||||
// }
|
||||
// instances, err := a.GetInstancesInfo(host, JustGetInstanceInfo)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if len(instances) == 0 {
|
||||
// return errors.New("can not find master0 ")
|
||||
// }
|
||||
// master0 := instances[0]
|
||||
// eIP, eIPID, err := a.allocateEipAddress()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// err = a.associateEipAddress(master0.InstanceID, eIPID)
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// a.Infra.Status.Cluster.EIP = eIP
|
||||
// EipID.SetValue(a.Infra.Status, eIPID)
|
||||
// a.Infra.Status.Cluster.Master0ID = master0.InstanceID
|
||||
// a.Infra.Status.Cluster.Master0InternalIP = master0.PrimaryIPAddress
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) allocateEipAddress() (eIP, eIPID string, err error) {
|
||||
// request := vpc.CreateAllocateEipAddressRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.Bandwidth = Bandwidth
|
||||
// request.InternetChargeType = InternetChargeType
|
||||
// response := vpc.CreateAllocateEipAddressResponse()
|
||||
// err = a.RetryVpcRequest(request, response)
|
||||
// if err != nil {
|
||||
// return "", "", err
|
||||
// }
|
||||
// return response.EipAddress, response.AllocationId, nil
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) associateEipAddress(instanceID, eipID string) error {
|
||||
// request := vpc.CreateAssociateEipAddressRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.InstanceId = instanceID
|
||||
// request.AllocationId = eipID
|
||||
//
|
||||
// response := vpc.CreateAssociateEipAddressResponse()
|
||||
// return a.RetryVpcRequest(request, response)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) unAssociateEipAddress() error {
|
||||
// request := vpc.CreateUnassociateEipAddressRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.AllocationId = EipID.Value(a.Infra.Status)
|
||||
// request.Force = requests.NewBoolean(true)
|
||||
// response := vpc.CreateUnassociateEipAddressResponse()
|
||||
// return a.RetryVpcRequest(request, response)
|
||||
//}
|
||||
//
|
||||
//func (a *HwProvider) ReleaseEipAddress() error {
|
||||
// err := a.unAssociateEipAddress()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// request := vpc.CreateReleaseEipAddressRequest()
|
||||
// request.Scheme = Scheme
|
||||
// request.AllocationId = EipID.Value(a.Infra.Status)
|
||||
// response := vpc.CreateReleaseEipAddressResponse()
|
||||
// return a.RetryVpcRequest(request, response)
|
||||
//}
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright © 2021 sealos.
|
||||
//
|
||||
// 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 huawei
|
||||
|
||||
import (
|
||||
"github.com/huaweicloud/huaweicloud-sdk-go-v3/core/def"
|
||||
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses"
|
||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/ecs"
|
||||
"github.com/fanux/sealos/pkg/utils"
|
||||
)
|
||||
|
||||
func (a *HwProvider) RetryVpcRequest(request interface{}, def *def.HttpRequestDef) (interface{}, error) {
|
||||
var respInterface interface{}
|
||||
var err error
|
||||
allErr := utils.Retry(TryTimes, TrySleepTime, func() error {
|
||||
respInterface, err = a.VpcClient.HcClient.Sync(request, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return respInterface, allErr
|
||||
}
|
||||
|
||||
func (a *HwProvider) RetryEcsRequest(request interface{}, def *def.HttpRequestDef) (interface{}, error) {
|
||||
return a.RetryEcsAction(request, def, TryTimes)
|
||||
}
|
||||
|
||||
func (a *HwProvider) RetryEcsAction(request interface{}, def *def.HttpRequestDef, tryTimes int) (interface{}, error) {
|
||||
var respInterface interface{}
|
||||
var err error
|
||||
allErr := utils.Retry(tryTimes, TrySleepTime, func() error {
|
||||
respInterface, err = a.EcsClient.HcClient.Sync(request, def)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return respInterface, allErr
|
||||
}
|
||||
|
||||
func (a *HwProvider) RetryEcsInstanceType(request requests.AcsRequest, response responses.AcsResponse, instances, instanceRole []string) error {
|
||||
//for i := 0; i < len(instances); i++ {
|
||||
// switch req := request.(type) {
|
||||
// case *ecs.ModifyInstanceSpecRequest:
|
||||
// req.InstanceType = instances[i]
|
||||
// case *ecs.RunInstancesRequest:
|
||||
// req.InstanceType = instances[i]
|
||||
// }
|
||||
// err := a.RetryEcsAction(request, response, 4)
|
||||
// if err == nil {
|
||||
// logger.Info("use instance type: %s", instances[i])
|
||||
// j := a.Infra.Status.FindHostsByRoles(instanceRole)
|
||||
// if j == -1 {
|
||||
// return fmt.Errorf("failed to get ecs instance type, %v", "not find host status,pelase retry")
|
||||
// }
|
||||
// a.Infra.Status.Hosts[j].InstanceType = instances[i]
|
||||
// break
|
||||
// } else {
|
||||
// logger.Warn("failed to get ecs instance type: %s", instances[i])
|
||||
// if i == len(instances)-1 {
|
||||
// return fmt.Errorf("failed to get ecs instance type, %v", err)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *HwProvider) TryGetInstance(request *ecs.DescribeInstancesRequest, response *ecs.DescribeInstancesResponse, expectCount int) error {
|
||||
return utils.Retry(TryTimes, TrySleepTime, func() error {
|
||||
//err := a.EcsClient.DoAction(request, response)
|
||||
//var ipList []string
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
//instances := response.Instances.Instance
|
||||
//if expectCount == -1 {
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//if len(instances) != expectCount {
|
||||
// return errors.New("the number of instances is not as expected")
|
||||
//}
|
||||
//for _, instance := range instances {
|
||||
// if instance.NetworkInterfaces.NetworkInterface[0].PrimaryIpAddress == "" {
|
||||
// return errors.New("PrimaryIpAddress cannt nob be nil")
|
||||
// }
|
||||
// if len(ipList) != 0 && !utils.NotIn(instance.NetworkInterfaces.NetworkInterface[0].PrimaryIpAddress, ipList) {
|
||||
// return errors.New("PrimaryIpAddress cannt nob be same")
|
||||
// }
|
||||
//
|
||||
// ipList = append(ipList, instance.NetworkInterfaces.NetworkInterface[0].PrimaryIpAddress)
|
||||
//}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
+27
-1
@@ -18,6 +18,9 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fanux/sealos/pkg/infra/huawei"
|
||||
"github.com/fanux/sealos/pkg/types/validation"
|
||||
|
||||
"github.com/fanux/sealos/pkg/infra/aliyun"
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
)
|
||||
@@ -45,17 +48,40 @@ func loadConfig(infra *v2.Infra) {
|
||||
func newAliProvider(infra *v2.Infra) (Interface, error) {
|
||||
aliProvider := new(aliyun.AliProvider)
|
||||
aliProvider.Infra = infra
|
||||
if err := v2.Default(aliProvider.Infra, aliyun.DefaultInfra); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validation.ValidateInfra(aliProvider.Infra, aliyun.DefaultValidate); len(err) != 0 {
|
||||
return nil, err.ToAggregate()
|
||||
}
|
||||
if err := aliProvider.NewClient(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return aliProvider, nil
|
||||
}
|
||||
|
||||
func newHwProvider(infra *v2.Infra) (Interface, error) {
|
||||
hwProvider := new(huawei.HwProvider)
|
||||
hwProvider.Infra = infra
|
||||
if err := v2.Default(hwProvider.Infra, huawei.DefaultInfra); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := validation.ValidateInfra(hwProvider.Infra, huawei.DefaultValidate); len(err) != 0 {
|
||||
return nil, err.ToAggregate()
|
||||
}
|
||||
if err := hwProvider.NewClient(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return hwProvider, nil
|
||||
}
|
||||
|
||||
func NewDefaultProvider(infra *v2.Infra) (Interface, error) {
|
||||
loadConfig(infra)
|
||||
switch infra.Spec.Provider {
|
||||
case v2.AliyunProvider:
|
||||
case aliyun.AliyunProvider:
|
||||
return newAliProvider(infra)
|
||||
case huawei.HuaweiProvider:
|
||||
return newHwProvider(infra)
|
||||
default:
|
||||
return nil, fmt.Errorf("the provider is invalid, please set the provider correctly")
|
||||
}
|
||||
|
||||
+64
-24
@@ -19,6 +19,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/fanux/sealos/pkg/infra/aliyun"
|
||||
"github.com/fanux/sealos/pkg/infra/huawei"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
v2 "github.com/fanux/sealos/pkg/types/v1beta1"
|
||||
@@ -26,7 +29,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestApply(t *testing.T) {
|
||||
func TestAliApply(t *testing.T) {
|
||||
//setup infra
|
||||
infra := v2.Infra{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@@ -46,30 +49,11 @@ func TestApply(t *testing.T) {
|
||||
Port: 22,
|
||||
},
|
||||
},
|
||||
IsSeize: true,
|
||||
Metadata: v2.ClusterMeta{
|
||||
IsSeize: true,
|
||||
},
|
||||
},
|
||||
Hosts: []v2.Host{
|
||||
//{
|
||||
// Roles: []string{"master", "ssd"},
|
||||
// CPU: 2,
|
||||
// Memory: 4,
|
||||
// Count: 1,
|
||||
// Disks: []v2.Disk{},
|
||||
// OS: v2.OS{
|
||||
// Name: "centos",
|
||||
// },
|
||||
//},
|
||||
//{
|
||||
// Roles: []string{"node", "ssd"},
|
||||
// CPU: 2,
|
||||
// Memory: 4,
|
||||
// Count: 1,
|
||||
// Disks: []v2.Disk{},
|
||||
// Arch: v2.ARM64,
|
||||
// OS: v2.OS{
|
||||
// Name: "centos",
|
||||
// },
|
||||
//},
|
||||
{
|
||||
Roles: []string{"master", "ssdxxx"},
|
||||
CPU: 2,
|
||||
@@ -81,7 +65,7 @@ func TestApply(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
Provider: v2.AliyunProvider,
|
||||
Provider: aliyun.AliyunProvider,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -143,3 +127,59 @@ func TestApply(t *testing.T) {
|
||||
infra.ObjectMeta.DeletionTimestamp = &now
|
||||
t.Log(fmt.Sprintf("%v", aliProvider.Apply()))
|
||||
}
|
||||
|
||||
func TestHuaweiApply(t *testing.T) {
|
||||
//setup infra
|
||||
infra := v2.Infra{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Infra",
|
||||
APIVersion: v2.SchemeGroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-infra",
|
||||
},
|
||||
Spec: v2.InfraSpec{
|
||||
Credential: v2.Credential{ProjectID: "06b264130780105b2f50c0145ba32d41"},
|
||||
Cluster: v2.Cluster{
|
||||
RegionIDs: []string{"cn-north-4"},
|
||||
ZoneIDs: []string{""},
|
||||
AccessChannels: v2.AccessChannels{
|
||||
SSH: v2.SSH{
|
||||
Passwd: "Fanux#123",
|
||||
Port: 22,
|
||||
},
|
||||
},
|
||||
Metadata: v2.ClusterMeta{IsSeize: true},
|
||||
},
|
||||
Hosts: []v2.Host{
|
||||
{
|
||||
Roles: []string{"master", "ssdxxx"},
|
||||
CPU: 2,
|
||||
Memory: 4,
|
||||
Count: 1,
|
||||
Disks: []v2.Disk{},
|
||||
OS: v2.OS{
|
||||
Name: "ubuntu",
|
||||
},
|
||||
},
|
||||
},
|
||||
Provider: huawei.HuaweiProvider,
|
||||
},
|
||||
}
|
||||
|
||||
hwProvider, err := NewDefaultProvider(&infra)
|
||||
if err != nil {
|
||||
fmt.Printf("%v", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v", hwProvider.Apply())
|
||||
// todo
|
||||
t.Run("default", func(t *testing.T) {
|
||||
|
||||
})
|
||||
//teardown
|
||||
time.Sleep(20 * time.Second)
|
||||
now := metav1.Now()
|
||||
infra.ObjectMeta.DeletionTimestamp = &now
|
||||
t.Log(fmt.Sprintf("%v", hwProvider.Apply()))
|
||||
}
|
||||
|
||||
@@ -19,6 +19,28 @@ package v1beta1
|
||||
import (
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/fanux/sealos/pkg/utils"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
const (
|
||||
SourceCidrIP = "0.0.0.0/0"
|
||||
SSHPort = "22/22"
|
||||
APIServerPort = "6443/6443"
|
||||
)
|
||||
|
||||
var (
|
||||
sshExportPort = ExportPort{
|
||||
Protocol: ProtocolTCP,
|
||||
CidrIP: SourceCidrIP,
|
||||
PortRange: SSHPort,
|
||||
}
|
||||
apiserverExportPort = ExportPort{
|
||||
Protocol: ProtocolTCP,
|
||||
CidrIP: SourceCidrIP,
|
||||
PortRange: APIServerPort,
|
||||
}
|
||||
)
|
||||
|
||||
func Default(infra *Infra, fn func(infra *Infra) error) error {
|
||||
@@ -36,6 +58,36 @@ func defaultCluster(infra *Infra) {
|
||||
if infra.Spec.Cluster.Annotations == nil {
|
||||
infra.Spec.Cluster.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
if infra.Spec.Cluster.RegionIDs != nil {
|
||||
infra.Spec.Cluster.RegionIDs = utils.RemoveSliceEmpty(infra.Spec.Cluster.RegionIDs)
|
||||
}
|
||||
if infra.Spec.Cluster.ZoneIDs != nil {
|
||||
infra.Spec.Cluster.ZoneIDs = utils.RemoveSliceEmpty(infra.Spec.Cluster.ZoneIDs)
|
||||
}
|
||||
if infra.Spec.Cluster.Metadata.Network.Bandwidth == "" {
|
||||
infra.Spec.Cluster.Metadata.Network.Bandwidth = "100"
|
||||
}
|
||||
if len(infra.Spec.Cluster.Metadata.Network.ExportPorts) == 0 {
|
||||
infra.Spec.Cluster.Metadata.Network.ExportPorts = []ExportPort{
|
||||
sshExportPort,
|
||||
apiserverExportPort,
|
||||
}
|
||||
} else {
|
||||
ports := sets.NewString()
|
||||
for _, port := range infra.Spec.Cluster.Metadata.Network.ExportPorts {
|
||||
ports.Insert(port.PortRange)
|
||||
}
|
||||
if !ports.Has(SSHPort) {
|
||||
infra.Spec.Cluster.Metadata.Network.ExportPorts = append(infra.Spec.Cluster.Metadata.Network.ExportPorts, sshExportPort)
|
||||
}
|
||||
if !ports.Has(APIServerPort) {
|
||||
infra.Spec.Cluster.Metadata.Network.ExportPorts = append(infra.Spec.Cluster.Metadata.Network.ExportPorts, apiserverExportPort)
|
||||
}
|
||||
}
|
||||
if infra.Spec.Cluster.Metadata.Network.PrivateCidrIP == "" {
|
||||
infra.Spec.Cluster.Metadata.Network.PrivateCidrIP = "172.16.0.0/24"
|
||||
}
|
||||
}
|
||||
|
||||
func defaultHosts(infra *Infra) {
|
||||
|
||||
@@ -26,10 +26,6 @@ import (
|
||||
|
||||
type Provider string
|
||||
|
||||
const (
|
||||
AliyunProvider Provider = "AliyunProvider"
|
||||
)
|
||||
|
||||
type Arch string
|
||||
|
||||
const (
|
||||
@@ -80,18 +76,44 @@ type Disk struct {
|
||||
type Credential struct {
|
||||
AccessKey string `json:"accessKey"`
|
||||
AccessSecret string `json:"accessSecret"`
|
||||
ProjectID string `json:"ProjectID,omitempty"`
|
||||
}
|
||||
|
||||
type AccessChannels struct {
|
||||
SSH SSH `json:"ssh,omitempty"`
|
||||
}
|
||||
|
||||
type ClusterMeta struct {
|
||||
IsSeize bool `json:"isSeize,omitempty"`
|
||||
|
||||
Network ClusterNetworkMeta `json:"network"`
|
||||
}
|
||||
|
||||
type ClusterNetworkMeta struct {
|
||||
Bandwidth string `json:"bandwidth"`
|
||||
ExportPorts []ExportPort `json:"exportPorts,omitempty"`
|
||||
PrivateCidrIP string `json:"privateCidrIP,omitempty"`
|
||||
}
|
||||
|
||||
type Protocol string
|
||||
|
||||
const (
|
||||
ProtocolTCP Protocol = "tcp"
|
||||
ProtocolUDP Protocol = "udp"
|
||||
)
|
||||
|
||||
type ExportPort struct {
|
||||
Protocol Protocol `json:"protocol"`
|
||||
CidrIP string `json:"cidrIP"`
|
||||
PortRange string `json:"portRange"`
|
||||
}
|
||||
|
||||
type Cluster struct {
|
||||
RegionIDs []string `json:"regionIDs,omitempty"`
|
||||
ZoneIDs []string `json:"zoneIDs,omitempty"`
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
AccessChannels AccessChannels `json:"accessChannels"`
|
||||
IsSeize bool `json:"isSeize,omitempty"`
|
||||
Metadata ClusterMeta `json:"metadata,omitempty"`
|
||||
}
|
||||
|
||||
// InfraSpec defines the desired state of Infra
|
||||
|
||||
@@ -60,6 +60,7 @@ func (in *Cluster) DeepCopyInto(out *Cluster) {
|
||||
}
|
||||
}
|
||||
out.AccessChannels = in.AccessChannels
|
||||
in.Metadata.DeepCopyInto(&out.Metadata)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -73,6 +74,44 @@ func (in *Cluster) DeepCopy() *Cluster {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterMeta) DeepCopyInto(out *ClusterMeta) {
|
||||
*out = *in
|
||||
in.Network.DeepCopyInto(&out.Network)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterMeta.
|
||||
func (in *ClusterMeta) DeepCopy() *ClusterMeta {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterMeta)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterNetworkMeta) DeepCopyInto(out *ClusterNetworkMeta) {
|
||||
*out = *in
|
||||
if in.ExportPorts != nil {
|
||||
in, out := &in.ExportPorts, &out.ExportPorts
|
||||
*out = make([]ExportPort, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterNetworkMeta.
|
||||
func (in *ClusterNetworkMeta) DeepCopy() *ClusterNetworkMeta {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterNetworkMeta)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) {
|
||||
*out = *in
|
||||
@@ -128,6 +167,22 @@ func (in *Disk) DeepCopy() *Disk {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExportPort) DeepCopyInto(out *ExportPort) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExportPort.
|
||||
func (in *ExportPort) DeepCopy() *ExportPort {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExportPort)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Host) DeepCopyInto(out *Host) {
|
||||
*out = *in
|
||||
|
||||
@@ -72,14 +72,29 @@ func validateCluster(cluster *v1beta1.Cluster, fldPath *field.Path) field.ErrorL
|
||||
return allErrors
|
||||
}
|
||||
|
||||
func ValidateInfra(infra *v1beta1.Infra) field.ErrorList {
|
||||
func validateCredential(credential *v1beta1.Credential, fldPath *field.Path) field.ErrorList {
|
||||
allErrors := field.ErrorList{}
|
||||
|
||||
if len(credential.AccessKey) == 0 {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath.Key("accessKey"), credential.AccessKey,
|
||||
"accessKey not empty"))
|
||||
}
|
||||
if len(credential.AccessSecret) == 0 {
|
||||
allErrors = append(allErrors, field.Invalid(fldPath.Key("accessSecret"), credential.AccessSecret,
|
||||
"accessSecret not empty"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
func ValidateInfra(infra *v1beta1.Infra, fun func(infra *v1beta1.Infra) field.ErrorList) field.ErrorList {
|
||||
allErrors := apimachineryvalidation.ValidateObjectMeta(&infra.ObjectMeta, false, ValidateInfraName, field.NewPath("metadata"))
|
||||
allErrors = append(allErrors, validateInfraSpec(&infra.Spec, field.NewPath("spec"))...)
|
||||
allErrors = append(allErrors, fun(infra)...)
|
||||
return allErrors
|
||||
}
|
||||
func validateInfraSpec(spec *v1beta1.InfraSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrors := field.ErrorList{}
|
||||
|
||||
allErrors = append(allErrors, validateCredential(&spec.Credential, fldPath.Child("credential"))...)
|
||||
allErrors = append(allErrors, validateCluster(&spec.Cluster, fldPath.Child("cluster"))...)
|
||||
var roles []string
|
||||
roleSet := sets.NewString()
|
||||
|
||||
@@ -129,3 +129,12 @@ func IsEmptyLine(str string) bool {
|
||||
func TrimWS(str string) string {
|
||||
return strings.Trim(str, " \n\t")
|
||||
}
|
||||
|
||||
func RemoveSliceEmpty(list []string) (fList []string) {
|
||||
for i := range list {
|
||||
if strings.TrimSpace(list[i]) != "" {
|
||||
fList = append(fList, list[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user