mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-05-10 15:53:11 +08:00
448 lines
12 KiB
Go
448 lines
12 KiB
Go
// 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 cloudprovider
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"yunion.io/x/jsonutils"
|
||
"yunion.io/x/log"
|
||
"yunion.io/x/pkg/errors"
|
||
"yunion.io/x/pkg/utils"
|
||
|
||
"yunion.io/x/onecloud/pkg/httperrors"
|
||
"yunion.io/x/onecloud/pkg/mcclient"
|
||
"yunion.io/x/onecloud/pkg/util/httputils"
|
||
)
|
||
|
||
const (
|
||
ErrNoSuchProvder = errors.Error("no such provider")
|
||
)
|
||
|
||
type SCloudaccountCredential struct {
|
||
// 账号所在的项目
|
||
ProjectName string `json:"project_name"`
|
||
|
||
// 账号所在的域
|
||
// default: Default
|
||
DomainName string `json:"domain_name"`
|
||
|
||
// 用户名
|
||
Username string `json:"username"`
|
||
|
||
// 密码
|
||
Password string `json:"password"`
|
||
|
||
// 认证地址
|
||
AuthUrl string `json:"auto_url"`
|
||
|
||
// 秘钥id
|
||
AccessKeyId string `json:"access_key_id"`
|
||
|
||
// 秘钥key
|
||
AccessKeySecret string `json:"access_key_secret"`
|
||
|
||
// 环境
|
||
Environment string `json:"environment"`
|
||
|
||
// 目录ID
|
||
DirectoryId string `json:"directory_id"`
|
||
|
||
// 客户端ID
|
||
ClientId string `json:"client_id"`
|
||
|
||
// 客户端秘钥
|
||
ClientSecret string `json:"client_secret"`
|
||
|
||
// 主机IP
|
||
Host string `json:"host"`
|
||
|
||
// 主机端口
|
||
Port int `json:"port"`
|
||
|
||
// 端点
|
||
Endpoint string `json:"endpoint"`
|
||
|
||
// app id
|
||
AppId string `json:"app_id"`
|
||
|
||
//秘钥ID
|
||
SecretId string `json:"secret_id"`
|
||
|
||
//秘钥key
|
||
SecretKey string `json:"secret_key"`
|
||
|
||
// Google服务账号email
|
||
ClientEmail string `json:"client_email"`
|
||
// Google服务账号project id
|
||
ProjectId string `json:"project_id"`
|
||
// Google服务账号秘钥id
|
||
PrivateKeyId string `json:"private_key_id"`
|
||
// Google服务账号秘钥
|
||
PrivateKey string `json:"private_key"`
|
||
}
|
||
|
||
type SCloudaccount struct {
|
||
// 账号信息,各个平台字段不尽相同,以下是各个平台账号创建所需要的字段
|
||
//
|
||
//
|
||
//
|
||
// | 云平台 |字段 | 翻译 | 是否必传 | 默认值 | 可否更新 | 获取方式 |
|
||
// | ------ |------ | ------ | --------- | -------- |-------- |-------- |
|
||
// |Aliyun |access_key_id |秘钥ID | 是 | | 是 | |
|
||
// |Aliyun |access_key_secret |秘钥Key | 是 | | 是 | |
|
||
// |Qcloud |app_id |APP ID | 是 | | 否 | |
|
||
// |Qcloud |secret_id |秘钥ID | 是 | | 是 | |
|
||
// |Qcloud |secret_key |秘钥Key | 是 | | 是 | |
|
||
// |OpenStack |project_name |用户所在项目 | 是 | | 是 | |
|
||
// |OpenStack |username |用户名 | 是 | | 是 | |
|
||
// |OpenStack |password |用户密码 | 是 | | 是 | |
|
||
// |OpenStack |auth_url |认证地址 | 是 | | 否 | |
|
||
// |OpenStack |domain_name |用户所在的域 | 否 |Default | 是 | |
|
||
// |VMware |username |用户名 | 是 | | 是 | |
|
||
// |VMware |password |密码 | 是 | | 是 | |
|
||
// |VMware |host |主机IP或域名 | 是 | | 否 | |
|
||
// |VMware |port |主机端口 | 否 |443 | 否 | |
|
||
// |Azure |directory_id |目录ID | 是 | | 否 | |
|
||
// |Azure |environment |区域 | 是 | | 否 | |
|
||
// |Azure |client_id |客户端ID | 是 | | 是 | |
|
||
// |Azure |client_secret |客户端密码 | 是 | | 是 | |
|
||
// |Huawei |access_key_id |秘钥ID | 是 | | 是 | |
|
||
// |Huawei |access_key_secret |秘钥 | 是 | | 是 | |
|
||
// |Huawei |environment |区域 | 是 | | 否 | |
|
||
// |Aws |access_key_id |秘钥ID | 是 | | 是 | |
|
||
// |Aws |access_key_secret |秘钥 | 是 | | 是 | |
|
||
// |Aws |environment |区域 | 是 | | 否 | |
|
||
// |Ucloud |access_key_id |秘钥ID | 是 | | 是 | |
|
||
// |Ucloud |access_key_secret |秘钥 | 是 | | 是 | |
|
||
// |Google |project_id |项目ID | 是 | | 否 | |
|
||
// |Google |client_email |客户端email | 是 | | 否 | |
|
||
// |Google |private_key_id |秘钥ID | 是 | | 是 | |
|
||
// |Google |private_key |秘钥Key | 是 | | 是 | |
|
||
Account string `json:"account"`
|
||
|
||
// swagger:ignore
|
||
Secret string
|
||
|
||
// 认证地址
|
||
AccessUrl string `json:"access_url"`
|
||
}
|
||
|
||
type ProviderConfig struct {
|
||
// Id, Name are properties of Cloudprovider object
|
||
Id string
|
||
Name string
|
||
|
||
// Vendor are names like Aliyun, OpenStack, etc.
|
||
Vendor string
|
||
URL string
|
||
Account string
|
||
Secret string
|
||
|
||
ProxyFunc httputils.TransportProxyFunc
|
||
}
|
||
|
||
type ICloudProviderFactory interface {
|
||
GetProvider(cfg ProviderConfig) (ICloudProvider, error)
|
||
|
||
GetClientRC(url, account, secret string) (map[string]string, error)
|
||
|
||
GetId() string
|
||
GetName() string
|
||
|
||
ValidateChangeBandwidth(instanceId string, bandwidth int64) error
|
||
ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input SCloudaccountCredential) (SCloudaccount, error)
|
||
ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input SCloudaccountCredential, cloudaccount string) (SCloudaccount, error)
|
||
GetSupportedBrands() []string
|
||
|
||
IsPublicCloud() bool
|
||
IsOnPremise() bool
|
||
IsSupportPrepaidResources() bool
|
||
NeedSyncSkuFromCloud() bool
|
||
|
||
IsCloudeventRegional() bool
|
||
GetMaxCloudEventSyncDays() int
|
||
GetMaxCloudEventKeepDays() int
|
||
}
|
||
|
||
type ICloudProvider interface {
|
||
GetFactory() ICloudProviderFactory
|
||
|
||
GetSysInfo() (jsonutils.JSONObject, error)
|
||
GetVersion() string
|
||
|
||
GetIRegions() []ICloudRegion
|
||
GetIProjects() ([]ICloudProject, error)
|
||
GetIRegionById(id string) (ICloudRegion, error)
|
||
|
||
GetOnPremiseIRegion() (ICloudRegion, error)
|
||
|
||
GetBalance() (float64, string, error)
|
||
|
||
GetSubAccounts() ([]SSubAccount, error)
|
||
GetAccountId() string
|
||
|
||
// region external id 是以provider 做为前缀.因此可以通过该判断条件过滤出同一个provider的regions列表
|
||
// 但是华为云有点特殊一个provider只对应一个region,因此需要进一步指定region名字,才能找到provider对应的region
|
||
GetCloudRegionExternalIdPrefix() string
|
||
|
||
GetStorageClasses(regionId string) []string
|
||
|
||
GetCapabilities() []string
|
||
GetICloudQuotas() ([]ICloudQuota, error)
|
||
GetICloudPolicyDefinitions() ([]ICloudPolicyDefinition, error)
|
||
}
|
||
|
||
func IsSupportProject(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_PROJECT, prod.GetCapabilities())
|
||
}
|
||
|
||
func IsSupportCompute(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_COMPUTE, prod.GetCapabilities())
|
||
}
|
||
|
||
func IsSupportLoadbalancer(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_LOADBALANCER, prod.GetCapabilities())
|
||
}
|
||
|
||
func IsSupportObjectstore(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_OBJECTSTORE, prod.GetCapabilities())
|
||
}
|
||
|
||
func IsSupportRds(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_RDS, prod.GetCapabilities())
|
||
}
|
||
|
||
func IsSupportElasticCache(prod ICloudProvider) bool {
|
||
return utils.IsInStringArray(CLOUD_CAPABILITY_CACHE, prod.GetCapabilities())
|
||
}
|
||
|
||
var providerTable map[string]ICloudProviderFactory
|
||
|
||
func init() {
|
||
providerTable = make(map[string]ICloudProviderFactory)
|
||
}
|
||
|
||
func RegisterFactory(factory ICloudProviderFactory) {
|
||
providerTable[factory.GetId()] = factory
|
||
}
|
||
|
||
func GetProviderFactory(provider string) (ICloudProviderFactory, error) {
|
||
factory, ok := providerTable[provider]
|
||
if ok {
|
||
return factory, nil
|
||
}
|
||
log.Errorf("Provider %s not registerd", provider)
|
||
return nil, fmt.Errorf("No such provider %s", provider)
|
||
}
|
||
|
||
func GetRegistedProviderIds() []string {
|
||
providers := []string{}
|
||
for id := range providerTable {
|
||
providers = append(providers, id)
|
||
}
|
||
return providers
|
||
}
|
||
|
||
func GetProvider(cfg ProviderConfig) (ICloudProvider, error) {
|
||
driver, err := GetProviderFactory(cfg.Vendor)
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetProviderFactory")
|
||
}
|
||
return driver.GetProvider(cfg)
|
||
}
|
||
|
||
func GetClientRC(accessUrl, account, secret, provider string) (map[string]string, error) {
|
||
driver, err := GetProviderFactory(provider)
|
||
if err != nil {
|
||
return nil, errors.Wrap(err, "GetProviderFactory")
|
||
}
|
||
return driver.GetClientRC(accessUrl, account, secret)
|
||
}
|
||
|
||
func IsSupported(provider string) bool {
|
||
_, ok := providerTable[provider]
|
||
return ok
|
||
}
|
||
|
||
func IsValidCloudAccount(cfg ProviderConfig) (string, error) {
|
||
factory, ok := providerTable[cfg.Vendor]
|
||
if ok {
|
||
provider, err := factory.GetProvider(cfg)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return provider.GetAccountId(), nil
|
||
} else {
|
||
return "", ErrNoSuchProvder
|
||
}
|
||
}
|
||
|
||
type SBaseProvider struct {
|
||
factory ICloudProviderFactory
|
||
}
|
||
|
||
func (provider *SBaseProvider) GetFactory() ICloudProviderFactory {
|
||
return provider.factory
|
||
}
|
||
|
||
func (self *SBaseProvider) GetOnPremiseIRegion() (ICloudRegion, error) {
|
||
return nil, ErrNotImplemented
|
||
}
|
||
|
||
func (self *SBaseProvider) GetICloudQuotas() ([]ICloudQuota, error) {
|
||
return nil, ErrNotImplemented
|
||
}
|
||
|
||
func (self *SBaseProvider) GetICloudPolicyDefinitions() ([]ICloudPolicyDefinition, error) {
|
||
return nil, ErrNotImplemented
|
||
}
|
||
|
||
func (self *SBaseProvider) GetCloudRegionExternalIdPrefix() string {
|
||
return self.factory.GetId()
|
||
}
|
||
|
||
func NewBaseProvider(factory ICloudProviderFactory) SBaseProvider {
|
||
return SBaseProvider{factory: factory}
|
||
}
|
||
|
||
func GetPublicProviders() []string {
|
||
providers := make([]string, 0)
|
||
for p, d := range providerTable {
|
||
if d.IsPublicCloud() {
|
||
providers = append(providers, p)
|
||
}
|
||
}
|
||
return providers
|
||
}
|
||
|
||
func GetPrivateProviders() []string {
|
||
providers := make([]string, 0)
|
||
for p, d := range providerTable {
|
||
if !d.IsPublicCloud() && !d.IsOnPremise() {
|
||
providers = append(providers, p)
|
||
}
|
||
}
|
||
return providers
|
||
}
|
||
|
||
func GetOnPremiseProviders() []string {
|
||
providers := make([]string, 0)
|
||
for p, d := range providerTable {
|
||
if !d.IsPublicCloud() && d.IsOnPremise() {
|
||
providers = append(providers, p)
|
||
}
|
||
}
|
||
return providers
|
||
}
|
||
|
||
func GetProviderCloudEnv(provider string) string {
|
||
p, err := GetProviderFactory(provider)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
if p.IsPublicCloud() {
|
||
return CLOUD_ENV_PUBLIC_CLOUD
|
||
}
|
||
if p.IsOnPremise() {
|
||
return CLOUD_ENV_ON_PREMISE
|
||
}
|
||
return CLOUD_ENV_PRIVATE_CLOUD
|
||
}
|
||
|
||
type baseProviderFactory struct {
|
||
}
|
||
|
||
func (factory *baseProviderFactory) ValidateChangeBandwidth(instanceId string, bandwidth int64) error {
|
||
return nil
|
||
}
|
||
|
||
func (factory *baseProviderFactory) GetSupportedBrands() []string {
|
||
return []string{}
|
||
}
|
||
|
||
func (factory *baseProviderFactory) GetProvider(providerId, providerName, url, username, password string) (ICloudProvider, error) {
|
||
return nil, httperrors.NewNotImplementedError("Not Implemented GetProvider")
|
||
}
|
||
|
||
func (factory *baseProviderFactory) IsOnPremise() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *baseProviderFactory) IsCloudeventRegional() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *baseProviderFactory) GetMaxCloudEventSyncDays() int {
|
||
return 7
|
||
}
|
||
|
||
func (factory *baseProviderFactory) GetMaxCloudEventKeepDays() int {
|
||
return 7
|
||
}
|
||
|
||
type SPremiseBaseProviderFactory struct {
|
||
baseProviderFactory
|
||
}
|
||
|
||
func (factory *SPremiseBaseProviderFactory) IsPublicCloud() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *SPremiseBaseProviderFactory) IsSupportPrepaidResources() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *SPremiseBaseProviderFactory) IsOnPremise() bool {
|
||
return true
|
||
}
|
||
|
||
func (factory *SPremiseBaseProviderFactory) NeedSyncSkuFromCloud() bool {
|
||
return false
|
||
}
|
||
|
||
type SPublicCloudBaseProviderFactor struct {
|
||
baseProviderFactory
|
||
}
|
||
|
||
func (factory *SPublicCloudBaseProviderFactor) IsPublicCloud() bool {
|
||
return true
|
||
}
|
||
|
||
func (factory *SPublicCloudBaseProviderFactor) IsSupportPrepaidResources() bool {
|
||
return true
|
||
}
|
||
|
||
func (factory *SPublicCloudBaseProviderFactor) NeedSyncSkuFromCloud() bool {
|
||
return false
|
||
}
|
||
|
||
type SPrivateCloudBaseProviderFactor struct {
|
||
baseProviderFactory
|
||
}
|
||
|
||
func (factory *SPrivateCloudBaseProviderFactor) IsPublicCloud() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *SPrivateCloudBaseProviderFactor) IsSupportPrepaidResources() bool {
|
||
return false
|
||
}
|
||
|
||
func (factory *SPrivateCloudBaseProviderFactor) NeedSyncSkuFromCloud() bool {
|
||
return true
|
||
}
|