yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/qcloud/provider/provider.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package provider
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"strings"
    21  
    22  	"yunion.io/x/jsonutils"
    23  	"yunion.io/x/pkg/errors"
    24  	"yunion.io/x/pkg/utils"
    25  
    26  	api "yunion.io/x/cloudmux/pkg/apis/compute"
    27  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    28  	"yunion.io/x/onecloud/pkg/httperrors"
    29  	"yunion.io/x/onecloud/pkg/mcclient"
    30  	"yunion.io/x/cloudmux/pkg/multicloud/qcloud"
    31  )
    32  
    33  type SQcloudProviderFactory struct {
    34  	cloudprovider.SPublicCloudBaseProviderFactory
    35  }
    36  
    37  func (self *SQcloudProviderFactory) GetId() string {
    38  	return qcloud.CLOUD_PROVIDER_QCLOUD
    39  }
    40  
    41  func (self *SQcloudProviderFactory) GetName() string {
    42  	return qcloud.CLOUD_PROVIDER_QCLOUD_CN
    43  }
    44  
    45  func (self *SQcloudProviderFactory) IsCloudeventRegional() bool {
    46  	return true
    47  }
    48  
    49  func (self *SQcloudProviderFactory) GetMaxCloudEventSyncDays() int {
    50  	return 7
    51  }
    52  
    53  func (self *SQcloudProviderFactory) GetMaxCloudEventKeepDays() int {
    54  	return 30
    55  }
    56  
    57  func (self *SQcloudProviderFactory) IsSupportCloudIdService() bool {
    58  	return true
    59  }
    60  
    61  func (self *SQcloudProviderFactory) IsSupportCreateCloudgroup() bool {
    62  	return true
    63  }
    64  
    65  func (self *SQcloudProviderFactory) IsSupportSAMLAuth() bool {
    66  	return true
    67  }
    68  
    69  func (self *SQcloudProviderFactory) IsSupportCrossCloudEnvVpcPeering() bool {
    70  	return false
    71  }
    72  
    73  func (self *SQcloudProviderFactory) IsSupportCrossRegionVpcPeering() bool {
    74  	return true
    75  }
    76  
    77  func (self *SQcloudProviderFactory) IsSupportVpcPeeringVpcCidrOverlap() bool {
    78  	return false
    79  }
    80  
    81  func (self *SQcloudProviderFactory) ValidateCrossRegionVpcPeeringBandWidth(bandwidth int) error {
    82  	validatedBandwidths := []int{10, 20, 50, 100, 200, 500, 1000}
    83  	ok, _ := utils.InArray(bandwidth, validatedBandwidths)
    84  	if ok {
    85  		return nil
    86  	}
    87  	return httperrors.NewInputParameterError("require validated qcloud cross region vpcPeering bandwidth values:[10, 20, 50, 100, 200, 500, 1000],unit Mbps")
    88  }
    89  
    90  func (self *SQcloudProviderFactory) GetSupportedDnsZoneTypes() []cloudprovider.TDnsZoneType {
    91  	return []cloudprovider.TDnsZoneType{
    92  		cloudprovider.PublicZone,
    93  	}
    94  }
    95  
    96  func (self *SQcloudProviderFactory) GetSupportedDnsTypes() map[cloudprovider.TDnsZoneType][]cloudprovider.TDnsType {
    97  	return map[cloudprovider.TDnsZoneType][]cloudprovider.TDnsType{
    98  		cloudprovider.PublicZone: []cloudprovider.TDnsType{
    99  			cloudprovider.DnsTypeA,
   100  			cloudprovider.DnsTypeAAAA,
   101  			cloudprovider.DnsTypeCNAME,
   102  			cloudprovider.DnsTypeMX,
   103  			cloudprovider.DnsTypeNS,
   104  			cloudprovider.DnsTypeSRV,
   105  			cloudprovider.DnsTypeTXT,
   106  			cloudprovider.DnsTypePTR,
   107  		},
   108  	}
   109  }
   110  
   111  func (self *SQcloudProviderFactory) GetSupportedDnsPolicyTypes() map[cloudprovider.TDnsZoneType][]cloudprovider.TDnsPolicyType {
   112  	return map[cloudprovider.TDnsZoneType][]cloudprovider.TDnsPolicyType{
   113  		cloudprovider.PublicZone: []cloudprovider.TDnsPolicyType{
   114  			cloudprovider.DnsPolicyTypeSimple,
   115  			cloudprovider.DnsPolicyTypeByCarrier,
   116  			cloudprovider.DnsPolicyTypeByGeoLocation,
   117  			cloudprovider.DnsPolicyTypeBySearchEngine,
   118  			cloudprovider.DnsPolicyTypeWeighted,
   119  		},
   120  	}
   121  }
   122  
   123  func (self *SQcloudProviderFactory) GetSupportedDnsPolicyValues() map[cloudprovider.TDnsPolicyType][]cloudprovider.TDnsPolicyValue {
   124  	return map[cloudprovider.TDnsPolicyType][]cloudprovider.TDnsPolicyValue{
   125  		cloudprovider.DnsPolicyTypeByCarrier: []cloudprovider.TDnsPolicyValue{
   126  			cloudprovider.DnsPolicyValueUnicom,
   127  			cloudprovider.DnsPolicyValueTelecom,
   128  			cloudprovider.DnsPolicyValueChinaMobile,
   129  			cloudprovider.DnsPolicyValueCernet,
   130  		},
   131  		cloudprovider.DnsPolicyTypeByGeoLocation: []cloudprovider.TDnsPolicyValue{
   132  			cloudprovider.DnsPolicyValueOversea,
   133  			cloudprovider.DnsPolicyValueMainland,
   134  		},
   135  		cloudprovider.DnsPolicyTypeBySearchEngine: []cloudprovider.TDnsPolicyValue{
   136  			cloudprovider.DnsPolicyValueBaidu,
   137  			cloudprovider.DnsPolicyValueBing,
   138  			cloudprovider.DnsPolicyValueGoogle,
   139  			cloudprovider.DnsPolicyValueYoudao,
   140  			cloudprovider.DnsPolicyValueSousou,
   141  			cloudprovider.DnsPolicyValueSougou,
   142  			cloudprovider.DnsPolicyValueQihu360,
   143  		},
   144  	}
   145  }
   146  
   147  // https://buy.cloud.tencent.com/cns?from=gobuy&domain=example4.com
   148  func (self *SQcloudProviderFactory) GetTTLRange(zoneType cloudprovider.TDnsZoneType, productType cloudprovider.TDnsProductType) cloudprovider.TTlRange {
   149  	if len(productType) > 0 {
   150  		switch productType {
   151  		case cloudprovider.DnsProductEnterpriseUltimate:
   152  			return cloudprovider.TtlRangeQcloudEnterpriseUltimate
   153  		case cloudprovider.DnsProductEnterpriseStandard:
   154  			return cloudprovider.TtlRangeQcloudEnterpriseStandard
   155  		case cloudprovider.DnsProductEnterpriseBasic:
   156  			return cloudprovider.TtlRangeQcloudEnterpriseBasic
   157  		case cloudprovider.DnsProductPersonalProfessional:
   158  			return cloudprovider.TtlRangeQcloudPersonalProfessional
   159  		case cloudprovider.DnsProductFree:
   160  			return cloudprovider.TtlRangeQcloudFree
   161  		default:
   162  			return cloudprovider.TtlRangeQcloudFree
   163  		}
   164  	}
   165  	return cloudprovider.TtlRangeQcloudFree
   166  }
   167  
   168  func (self *SQcloudProviderFactory) ValidateChangeBandwidth(instanceId string, bandwidth int64) error {
   169  	if len(instanceId) == 0 {
   170  		return fmt.Errorf("Only changes to the binding machine's EIP bandwidth are supported")
   171  	}
   172  	return nil
   173  }
   174  
   175  func (self *SQcloudProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential) (cloudprovider.SCloudaccount, error) {
   176  	output := cloudprovider.SCloudaccount{}
   177  	if len(input.AppId) == 0 {
   178  		return output, errors.Wrap(httperrors.ErrMissingParameter, "app_id")
   179  	}
   180  	if len(input.SecretId) == 0 {
   181  		return output, errors.Wrap(httperrors.ErrMissingParameter, "secret_id")
   182  	}
   183  	if len(input.SecretKey) == 0 {
   184  		return output, errors.Wrap(httperrors.ErrMissingParameter, "secret_key")
   185  	}
   186  	output.Account = fmt.Sprintf("%s/%s", input.SecretId, input.AppId)
   187  	output.Secret = input.SecretKey
   188  	return output, nil
   189  }
   190  
   191  func (self *SQcloudProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, userCred mcclient.TokenCredential, input cloudprovider.SCloudaccountCredential, cloudaccount string) (cloudprovider.SCloudaccount, error) {
   192  	output := cloudprovider.SCloudaccount{}
   193  	if len(input.AppId) == 0 {
   194  		accountInfo := strings.Split(cloudaccount, "/")
   195  		if len(accountInfo) < 2 {
   196  			return output, errors.Wrap(httperrors.ErrMissingParameter, "app_id")
   197  		}
   198  		input.AppId = accountInfo[1]
   199  	}
   200  	if len(input.SecretId) == 0 {
   201  		return output, errors.Wrap(httperrors.ErrMissingParameter, "secret_id")
   202  	}
   203  	if len(input.SecretKey) == 0 {
   204  		return output, errors.Wrap(httperrors.ErrMissingParameter, "secret_key")
   205  	}
   206  	output = cloudprovider.SCloudaccount{
   207  		Account: fmt.Sprintf("%s/%s", input.SecretId, input.AppId),
   208  		Secret:  input.SecretKey,
   209  	}
   210  	return output, nil
   211  }
   212  
   213  func (self *SQcloudProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) {
   214  	secretId := cfg.Account
   215  	appId := ""
   216  	if tmp := strings.Split(cfg.Account, "/"); len(tmp) == 2 {
   217  		secretId = tmp[0]
   218  		appId = tmp[1]
   219  	}
   220  	client, err := qcloud.NewQcloudClient(
   221  		qcloud.NewQcloudClientConfig(
   222  			secretId, cfg.Secret,
   223  		).AppId(appId).CloudproviderConfig(cfg),
   224  	)
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	return &SQcloudProvider{
   229  		SBaseProvider: cloudprovider.NewBaseProvider(self),
   230  		client:        client,
   231  	}, nil
   232  }
   233  
   234  func (self *SQcloudProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) {
   235  	secretId := info.Account
   236  	appId := ""
   237  	if tmp := strings.Split(info.Account, "/"); len(tmp) == 2 {
   238  		secretId = tmp[0]
   239  		appId = tmp[1]
   240  	}
   241  	return map[string]string{
   242  		"QCLOUD_APPID":      appId,
   243  		"QCLOUD_SECRET_ID":  secretId,
   244  		"QCLOUD_SECRET_KEY": info.Secret,
   245  		"QCLOUD_REGION":     qcloud.QCLOUD_DEFAULT_REGION,
   246  	}, nil
   247  }
   248  
   249  func init() {
   250  	factory := SQcloudProviderFactory{}
   251  	cloudprovider.RegisterFactory(&factory)
   252  }
   253  
   254  type SQcloudProvider struct {
   255  	cloudprovider.SBaseProvider
   256  	client *qcloud.SQcloudClient
   257  }
   258  
   259  func (self *SQcloudProvider) GetSysInfo() (jsonutils.JSONObject, error) {
   260  	regions := self.client.GetIRegions()
   261  	info := jsonutils.NewDict()
   262  	info.Add(jsonutils.NewInt(int64(len(regions))), "region_count")
   263  	info.Add(jsonutils.NewString(qcloud.QCLOUD_API_VERSION), "api_version")
   264  	return info, nil
   265  }
   266  
   267  func (self *SQcloudProvider) GetVersion() string {
   268  	return qcloud.QCLOUD_API_VERSION
   269  }
   270  
   271  func (self *SQcloudProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
   272  	return self.client.GetSubAccounts()
   273  }
   274  
   275  func (self *SQcloudProvider) GetAccountId() string {
   276  	return self.client.GetAccountId()
   277  }
   278  
   279  func (self *SQcloudProvider) GetIamLoginUrl() string {
   280  	return self.client.GetIamLoginUrl()
   281  }
   282  
   283  func (self *SQcloudProvider) GetIRegions() []cloudprovider.ICloudRegion {
   284  	return self.client.GetIRegions()
   285  }
   286  
   287  func (self *SQcloudProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
   288  	return self.client.GetIRegionById(id)
   289  }
   290  
   291  func (self *SQcloudProvider) GetBalance() (float64, string, error) {
   292  	balance, err := self.client.QueryAccountBalance()
   293  	if err != nil {
   294  		return 0.0, api.CLOUD_PROVIDER_HEALTH_UNKNOWN, err
   295  	}
   296  	status := api.CLOUD_PROVIDER_HEALTH_NORMAL
   297  	if balance.AvailableAmount < 0.0 {
   298  		status = api.CLOUD_PROVIDER_HEALTH_ARREARS
   299  	}
   300  	return balance.AvailableAmount, status, nil
   301  }
   302  
   303  func (self *SQcloudProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
   304  	return self.client.GetIProjects()
   305  }
   306  
   307  func (self *SQcloudProvider) CreateIProject(name string) (cloudprovider.ICloudProject, error) {
   308  	return self.client.CreateIProject(name)
   309  }
   310  
   311  func (self *SQcloudProvider) GetStorageClasses(regionId string) []string {
   312  	return []string{
   313  		"STANDARD", "STANDARD_IA", "ARCHIVE",
   314  	}
   315  }
   316  
   317  func (self *SQcloudProvider) GetBucketCannedAcls(regionId string) []string {
   318  	return []string{
   319  		string(cloudprovider.ACLPrivate),
   320  		string(cloudprovider.ACLAuthRead),
   321  		string(cloudprovider.ACLPublicRead),
   322  	}
   323  }
   324  
   325  func (self *SQcloudProvider) GetObjectCannedAcls(regionId string) []string {
   326  	return []string{
   327  		string(cloudprovider.ACLPrivate),
   328  		string(cloudprovider.ACLAuthRead),
   329  		string(cloudprovider.ACLPublicRead),
   330  	}
   331  }
   332  
   333  func (self *SQcloudProvider) GetCapabilities() []string {
   334  	return self.client.GetCapabilities()
   335  }
   336  
   337  func (self *SQcloudProvider) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) {
   338  	return self.client.CreateIClouduser(conf)
   339  }
   340  
   341  func (self *SQcloudProvider) GetICloudusers() ([]cloudprovider.IClouduser, error) {
   342  	return self.client.GetICloudusers()
   343  }
   344  
   345  func (self *SQcloudProvider) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) {
   346  	return self.client.GetICloudgroups()
   347  }
   348  
   349  func (self *SQcloudProvider) GetICloudgroupByName(name string) (cloudprovider.ICloudgroup, error) {
   350  	return self.client.GetICloudgroupByName(name)
   351  }
   352  
   353  func (self *SQcloudProvider) CreateICloudgroup(name, desc string) (cloudprovider.ICloudgroup, error) {
   354  	return self.client.CreateICloudgroup(name, desc)
   355  }
   356  
   357  func (self *SQcloudProvider) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
   358  	return self.client.GetISystemCloudpolicies()
   359  }
   360  
   361  func (self *SQcloudProvider) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
   362  	return self.client.GetICustomCloudpolicies()
   363  }
   364  
   365  func (self *SQcloudProvider) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) {
   366  	return self.client.GetIClouduserByName(name)
   367  }
   368  
   369  func (self *SQcloudProvider) CreateICloudpolicy(opts *cloudprovider.SCloudpolicyCreateOptions) (cloudprovider.ICloudpolicy, error) {
   370  	return self.client.CreateICloudpolicy(opts)
   371  }
   372  
   373  func (self *SQcloudProvider) GetSamlEntityId() string {
   374  	return cloudprovider.SAML_ENTITY_ID_QCLOUD
   375  }
   376  
   377  func (self *SQcloudProvider) GetICloudDnsZones() ([]cloudprovider.ICloudDnsZone, error) {
   378  	return self.client.GetICloudDnsZones()
   379  }
   380  
   381  func (self *SQcloudProvider) GetICloudDnsZoneById(id string) (cloudprovider.ICloudDnsZone, error) {
   382  	domain, err := self.client.GetDomain(id)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  	return domain, nil
   387  }
   388  
   389  func (self *SQcloudProvider) CreateICloudDnsZone(opts *cloudprovider.SDnsZoneCreateOptions) (cloudprovider.ICloudDnsZone, error) {
   390  	return self.client.CreateICloudDnsZone(opts)
   391  }
   392  
   393  func (self *SQcloudProvider) CreateICloudSAMLProvider(opts *cloudprovider.SAMLProviderCreateOptions) (cloudprovider.ICloudSAMLProvider, error) {
   394  	saml, err := self.client.CreateSAMLProvider(opts.Name, opts.Metadata.String(), "")
   395  	if err != nil {
   396  		return nil, errors.Wrap(err, "CreateSAMLProvider")
   397  	}
   398  	return saml, nil
   399  }
   400  
   401  func (self *SQcloudProvider) GetICloudSAMLProviders() ([]cloudprovider.ICloudSAMLProvider, error) {
   402  	return self.client.GetICloudSAMLProviders()
   403  }
   404  
   405  func (self *SQcloudProvider) CreateICloudrole(opts *cloudprovider.SRoleCreateOptions) (cloudprovider.ICloudrole, error) {
   406  	if len(opts.SAMLProvider) > 0 {
   407  		document := fmt.Sprintf(`{"version":"2.0","statement":[{"action":"name/sts:AssumeRoleWithSAML","effect":"allow","principal":{"federated":["qcs::cam::uin/%s:saml-provider/%s"]},"condition":{}}]}`, self.client.GetAccountId(), opts.SAMLProvider)
   408  		role, err := self.client.CreateRole(opts.Name, document, opts.Desc)
   409  		if err != nil {
   410  			return nil, errors.Wrapf(err, "CreateRole")
   411  		}
   412  		return role, nil
   413  	}
   414  	role, err := self.client.CreateRole(opts.Name, "", opts.Desc)
   415  	if err != nil {
   416  		return nil, errors.Wrapf(err, "")
   417  	}
   418  	return role, nil
   419  }
   420  
   421  func (self *SQcloudProvider) GetICloudroles() ([]cloudprovider.ICloudrole, error) {
   422  	return self.client.GetICloudroles()
   423  }
   424  
   425  func (self *SQcloudProvider) GetICloudroleByName(name string) (cloudprovider.ICloudrole, error) {
   426  	role, err := self.client.GetRole(name)
   427  	if err != nil {
   428  		return nil, errors.Wrapf(err, "GetRole(%s)", name)
   429  	}
   430  	return role, nil
   431  }
   432  
   433  func (self *SQcloudProvider) GetICloudroleById(id string) (cloudprovider.ICloudrole, error) {
   434  	return self.GetICloudroleByName(id)
   435  }
   436  
   437  func (self *SQcloudProvider) GetICloudInterVpcNetworks() ([]cloudprovider.ICloudInterVpcNetwork, error) {
   438  	return self.client.GetICloudInterVpcNetworks()
   439  }
   440  
   441  func (self *SQcloudProvider) GetICloudInterVpcNetworkById(id string) (cloudprovider.ICloudInterVpcNetwork, error) {
   442  	return self.client.GetICloudInterVpcNetworkById(id)
   443  }
   444  
   445  func (self *SQcloudProvider) CreateICloudInterVpcNetwork(opts *cloudprovider.SInterVpcNetworkCreateOptions) (cloudprovider.ICloudInterVpcNetwork, error) {
   446  	return self.client.CreateICloudInterVpcNetwork(opts)
   447  }
   448  
   449  func (self *SQcloudProvider) GetICloudCDNDomains() ([]cloudprovider.ICloudCDNDomain, error) {
   450  	return self.client.GetICloudCDNDomains()
   451  }
   452  
   453  func (self *SQcloudProvider) GetICloudCDNDomainByName(name string) (cloudprovider.ICloudCDNDomain, error) {
   454  	return self.client.GetICloudCDNDomainByName(name)
   455  }
   456  
   457  func (self *SQcloudProvider) CreateICloudCDNDomain(opts *cloudprovider.CdnCreateOptions) (cloudprovider.ICloudCDNDomain, error) {
   458  	return self.client.CreateCDNDomain(opts)
   459  }
   460  
   461  func (self *SQcloudProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) {
   462  	return self.client.GetMetrics(opts)
   463  }