feat(region): support baidu cloud

This commit is contained in:
ioito
2023-08-07 20:36:13 +08:00
parent 591bac5f5a
commit f5e83b7667
25 changed files with 1016 additions and 10 deletions
+3
View File
@@ -56,6 +56,7 @@ func init() {
cmd.CreateWithKeyword("create-proxmox", &options.SProxmoxAccountCreateOptions{})
cmd.CreateWithKeyword("create-remotefile", &options.SRemoteFileAccountCreateOptions{})
cmd.CreateWithKeyword("create-ksyun", &options.SKsyunCloudAccountCreateOptions{})
cmd.CreateWithKeyword("create-baidu", &options.SBaiduCloudAccountCreateOptions{})
cmd.UpdateWithKeyword("update-vmware", &options.SVMwareCloudAccountUpdateOptions{})
cmd.UpdateWithKeyword("update-aliyun", &options.SAliyunCloudAccountUpdateOptions{})
@@ -78,6 +79,7 @@ func init() {
cmd.UpdateWithKeyword("update-incloudsphere", &options.SInCloudSphereAccountUpdateOptions{})
cmd.UpdateWithKeyword("update-proxmox", &options.SProxmoxAccountUpdateOptions{})
cmd.UpdateWithKeyword("update-ksyun", &options.SKsyunCloudAccountUpdateOptions{})
cmd.UpdateWithKeyword("update-baidu", &options.SBaiduCloudAccountUpdateOptions{})
cmd.Perform("update-credential", &options.CloudaccountUpdateCredentialOptions{})
@@ -103,6 +105,7 @@ func init() {
cmd.PerformWithKeyword("update-credential-incloudsphere", "update-credential", &options.SInCloudSphereAccountUpdateCredentialOptions{})
cmd.PerformWithKeyword("update-credential-proxmox", "update-credential", &options.SProxmoxAccountUpdateCredentialOptions{})
cmd.PerformWithKeyword("update-credential-ksyun", "update-credential", &options.SKsyunCloudAccountUpdateCredentialOptions{})
cmd.PerformWithKeyword("update-credential-baidu", "update-credential", &options.SBaiduCloudAccountUpdateCredentialOptions{})
cmd.PerformWithKeyword("test-connectivity-google", "test-connectivity", &options.SGoogleCloudAccountUpdateCredentialOptions{})
cmd.PerformWithKeyword("test-connectivity-vmware", "test-connectivity", &options.SVMwareCloudAccountUpdateCredentialOptions{})
+1
View File
@@ -63,6 +63,7 @@ func init() {
"monitor",
"bingocloud",
"ksyun",
"baidu",
}
const (
+1 -1
View File
@@ -83,7 +83,7 @@ require (
k8s.io/client-go v0.19.3
k8s.io/cluster-bootstrap v0.19.3
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807074306-1afe20f5d67a
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807123447-600aceed37b6
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32
yunion.io/x/jsonutils v1.0.1-0.20230613121553-0f3b41e2ef19
yunion.io/x/log v1.0.1-0.20230411060016-feb3f46ab361
+2 -2
View File
@@ -1174,8 +1174,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807074306-1afe20f5d67a h1:AwlwxsGXNxk80dri0FBlDb5oWSOnq5lXHeke6icd0pA=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807074306-1afe20f5d67a/go.mod h1:2sgCN7nRPQL3woLfdgqLDd92vwAHqtlz3KKiHxC5BAw=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807123447-600aceed37b6 h1:YZ2vDD4g6VqaLI43Ubi6DpsiJFDztfDAXgRRStqMiW8=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807123447-600aceed37b6/go.mod h1:2sgCN7nRPQL3woLfdgqLDd92vwAHqtlz3KKiHxC5BAw=
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 h1:v7POYkQwo1XzOxBoIoRVr/k0V9Y5JyjpshlIFa9raug=
yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
+5
View File
@@ -66,6 +66,7 @@ const (
CLOUD_PROVIDER_REMOTEFILE = compute.CLOUD_PROVIDER_REMOTEFILE
CLOUD_PROVIDER_H3C = compute.CLOUD_PROVIDER_H3C
CLOUD_PROVIDER_KSYUN = compute.CLOUD_PROVIDER_KSYUN
CLOUD_PROVIDER_BAIDU = compute.CLOUD_PROVIDER_BAIDU
CLOUD_PROVIDER_GENERICS3 = compute.CLOUD_PROVIDER_GENERICS3
CLOUD_PROVIDER_CEPH = compute.CLOUD_PROVIDER_CEPH
@@ -144,6 +145,7 @@ var (
CLOUD_PROVIDER_REMOTEFILE,
CLOUD_PROVIDER_H3C,
CLOUD_PROVIDER_KSYUN,
CLOUD_PROVIDER_BAIDU,
}
CLOUD_PROVIDER_HOST_TYPE_MAP = map[string][]string{
@@ -227,6 +229,9 @@ var (
CLOUD_PROVIDER_KSYUN: {
HOST_TYPE_KSYUN,
},
CLOUD_PROVIDER_BAIDU: {
HOST_TYPE_BAIDU,
},
}
)
+5
View File
@@ -198,6 +198,7 @@ const (
HYPERVISOR_REMOTEFILE = compute.HYPERVISOR_REMOTEFILE
HYPERVISOR_H3C = compute.HYPERVISOR_H3C
HYPERVISOR_KSYUN = compute.HYPERVISOR_KSYUN
HYPERVISOR_BAIDU = compute.HYPERVISOR_BAIDU
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
@@ -272,6 +273,7 @@ var HYPERVISORS = []string{
HYPERVISOR_REMOTEFILE,
HYPERVISOR_H3C,
HYPERVISOR_KSYUN,
HYPERVISOR_BAIDU,
}
var ONECLOUD_HYPERVISORS = []string{
@@ -292,6 +294,7 @@ var PUBLIC_CLOUD_HYPERVISORS = []string{
HYPERVISOR_ECLOUD,
HYPERVISOR_JDCLOUD,
HYPERVISOR_KSYUN,
HYPERVISOR_BAIDU,
}
var PRIVATE_CLOUD_HYPERVISORS = []string{
@@ -341,6 +344,7 @@ var HYPERVISOR_HOSTTYPE = map[string]string{
HYPERVISOR_REMOTEFILE: HOST_TYPE_REMOTEFILE,
HYPERVISOR_H3C: HOST_TYPE_H3C,
HYPERVISOR_KSYUN: HOST_TYPE_KSYUN,
HYPERVISOR_BAIDU: HOST_TYPE_BAIDU,
}
var HOSTTYPE_HYPERVISOR = map[string]string{
@@ -372,6 +376,7 @@ var HOSTTYPE_HYPERVISOR = map[string]string{
HOST_TYPE_REMOTEFILE: HYPERVISOR_REMOTEFILE,
HOST_TYPE_H3C: HYPERVISOR_H3C,
HOST_TYPE_KSYUN: HYPERVISOR_KSYUN,
HOST_TYPE_BAIDU: HYPERVISOR_BAIDU,
}
const (
+2
View File
@@ -51,6 +51,7 @@ const (
HOST_TYPE_REMOTEFILE = compute.HOST_TYPE_REMOTEFILE
HOST_TYPE_H3C = compute.HOST_TYPE_H3C
HOST_TYPE_KSYUN = compute.HOST_TYPE_KSYUN
HOST_TYPE_BAIDU = compute.HOST_TYPE_BAIDU
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
@@ -142,6 +143,7 @@ var HOST_TYPES = []string{
HOST_TYPE_REMOTEFILE,
HOST_TYPE_H3C,
HOST_TYPE_KSYUN,
HOST_TYPE_BAIDU,
}
var ALL_NIC_TYPES = []compute.TNicType{NIC_TYPE_IPMI, NIC_TYPE_ADMIN, NIC_TYPE_NORMAL}
+104
View File
@@ -0,0 +1,104 @@
// 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 guestdrivers
import (
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/rbacscope"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SBaiduGuestDriver struct {
SManagedVirtualizedGuestDriver
}
func init() {
driver := SBaiduGuestDriver{}
models.RegisterGuestDriver(&driver)
}
func (self *SBaiduGuestDriver) DoScheduleSKUFilter() bool { return false }
func (self *SBaiduGuestDriver) GetHypervisor() string {
return api.HYPERVISOR_BAIDU
}
func (self *SBaiduGuestDriver) GetProvider() string {
return api.CLOUD_PROVIDER_BAIDU
}
func (self *SBaiduGuestDriver) GetDefaultSysDiskBackend() string {
return ""
}
func (self *SBaiduGuestDriver) GetMinimalSysDiskSizeGb() int {
return 20
}
func (self *SBaiduGuestDriver) GetComputeQuotaKeys(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseProjectQuotaKeys = quotas.OwnerIdProjectQuotaKeys(scope, ownerId)
keys.CloudEnv = api.CLOUD_ENV_PUBLIC_CLOUD
keys.Provider = api.CLOUD_PROVIDER_BAIDU
keys.Brand = api.CLOUD_PROVIDER_BAIDU
keys.Hypervisor = api.HYPERVISOR_BAIDU
return keys
}
func (self *SBaiduGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCapability {
return cloudprovider.SInstanceCapability{
Hypervisor: self.GetHypervisor(),
Provider: self.GetProvider(),
DefaultAccount: cloudprovider.SDefaultAccount{
Linux: cloudprovider.SOsDefaultAccount{
DefaultAccount: api.VM_DEFAULT_LINUX_LOGIN_USER,
Changeable: false,
},
Windows: cloudprovider.SOsDefaultAccount{
DefaultAccount: api.VM_DEFAULT_WINDOWS_LOGIN_USER,
Changeable: false,
},
},
}
}
func (self *SBaiduGuestDriver) GetGuestInitialStateAfterCreate() string {
return api.VM_READY
}
func (self *SBaiduGuestDriver) GetGuestInitialStateAfterRebuild() string {
return api.VM_READY
}
func (self *SBaiduGuestDriver) AllowReconfigGuest() bool {
return true
}
func (self *SBaiduGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
return false
}
func (self *SBaiduGuestDriver) IsSupportPublicipToEip() bool {
return false
}
func (self *SBaiduGuestDriver) IsSupportSetAutoRenew() bool {
return false
}
+37
View File
@@ -0,0 +1,37 @@
// 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 hostdrivers
import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
)
type SBaiduHostDriver struct {
SManagedVirtualizationHostDriver
}
func init() {
driver := SBaiduHostDriver{}
models.RegisterHostDriver(&driver)
}
func (self *SBaiduHostDriver) GetHostType() string {
return api.HOST_TYPE_BAIDU
}
func (self *SBaiduHostDriver) GetHypervisor() string {
return api.HYPERVISOR_BAIDU
}
+52
View File
@@ -0,0 +1,52 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package regiondrivers
import (
"context"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
)
type SBaiduRegionDriver struct {
SManagedVirtualizationRegionDriver
}
func init() {
driver := SBaiduRegionDriver{}
models.RegisterRegionDriver(&driver)
}
func (self *SBaiduRegionDriver) GetProvider() string {
return api.CLOUD_PROVIDER_BAIDU
}
func (self *SBaiduRegionDriver) IsAllowSecurityGroupNameRepeat() bool {
return true
}
func (self *SBaiduRegionDriver) GenerateSecurityGroupName(name string) string {
return name
}
func (self *SBaiduRegionDriver) IsSecurityGroupBelongVpc() bool {
return true
}
func (self *SBaiduRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error {
return nil
}
+1 -1
View File
@@ -245,7 +245,7 @@ type BaseListOptions struct {
Manager []string `help:"List objects belonging to the cloud provider" json:"manager,omitempty"`
Account string `help:"List objects belonging to the cloud account" json:"account,omitempty"`
Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Apsara|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud|IncloudSphere|JDcloud|Proxmox|Ceph|Ecloud|HCSO|HCS|HCSOP|H3C|S3|RemoteFile|Ksyun" json:"provider,omitempty"`
Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Apsara|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud|IncloudSphere|JDcloud|Proxmox|Ceph|Ecloud|HCSO|HCS|HCSOP|H3C|S3|RemoteFile|Ksyun|Baidu" json:"provider,omitempty"`
Brand []string `help:"List objects belonging to a special brand"`
CloudEnv string `help:"Cloud environment" choices:"public|private|onpremise|private_or_onpremise" json:"cloud_env,omitempty"`
PublicCloud *bool `help:"List objects belonging to public cloud" json:"public_cloud"`
+30
View File
@@ -1308,3 +1308,33 @@ type SKsyunCloudAccountUpdateCredentialOptions struct {
func (opts *SKsyunCloudAccountUpdateCredentialOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(opts), nil
}
type SBaiduCloudAccountCreateOptions struct {
SCloudAccountCreateBaseOptions
SAccessKeyCredential
}
func (opts *SBaiduCloudAccountCreateOptions) Params() (jsonutils.JSONObject, error) {
params := jsonutils.Marshal(opts)
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Baidu"), "provider")
return params, nil
}
type SBaiduCloudAccountUpdateOptions struct {
SCloudAccountUpdateBaseOptions
}
func (opts *SBaiduCloudAccountUpdateOptions) Params() (jsonutils.JSONObject, error) {
params := jsonutils.Marshal(opts).(*jsonutils.JSONDict)
return params, nil
}
type SBaiduCloudAccountUpdateCredentialOptions struct {
SCloudAccountIdOptions
SAccessKeyCredential
}
func (opts *SBaiduCloudAccountUpdateCredentialOptions) Params() (jsonutils.JSONObject, error) {
return jsonutils.Marshal(opts), nil
}
+1 -1
View File
@@ -44,7 +44,7 @@ type ServerListOptions struct {
Gpu *bool `help:"Show gpu servers"`
Secgroup string `help:"Secgroup ID or Name"`
AdminSecgroup string `help:"AdminSecgroup ID or Name"`
Hypervisor string `help:"Show server of hypervisor" choices:"kvm|esxi|container|baremetal|aliyun|azure|aws|huawei|ucloud|zstack|openstack|google|ctyun|incloudsphere|nutanix|bingocloud|cloudpods|ecloud|jdcloud|remotefile|h3c|hcs|hcso|hcsop|proxmox|ksyun"`
Hypervisor string `help:"Show server of hypervisor" choices:"kvm|esxi|container|baremetal|aliyun|azure|aws|huawei|ucloud|zstack|openstack|google|ctyun|incloudsphere|nutanix|bingocloud|cloudpods|ecloud|jdcloud|remotefile|h3c|hcs|hcso|hcsop|proxmox|ksyun|baidu"`
Region string `help:"Show servers in cloudregion"`
WithEip *bool `help:"Show Servers with EIP"`
WithoutEip *bool `help:"Show Servers without EIP"`
+3 -1
View File
@@ -1438,7 +1438,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807074306-1afe20f5d67a
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20230807123447-600aceed37b6
## explicit; go 1.18
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
@@ -1456,6 +1456,8 @@ yunion.io/x/cloudmux/pkg/multicloud/azure
yunion.io/x/cloudmux/pkg/multicloud/azure/concurrent
yunion.io/x/cloudmux/pkg/multicloud/azure/progress
yunion.io/x/cloudmux/pkg/multicloud/azure/provider
yunion.io/x/cloudmux/pkg/multicloud/baidu
yunion.io/x/cloudmux/pkg/multicloud/baidu/provider
yunion.io/x/cloudmux/pkg/multicloud/bingocloud
yunion.io/x/cloudmux/pkg/multicloud/bingocloud/provider
yunion.io/x/cloudmux/pkg/multicloud/ctyun
+1
View File
@@ -41,6 +41,7 @@ const (
CLOUD_PROVIDER_REMOTEFILE = "RemoteFile"
CLOUD_PROVIDER_H3C = "H3C"
CLOUD_PROVIDER_KSYUN = "Ksyun"
CLOUD_PROVIDER_BAIDU = "Baidu"
CLOUD_PROVIDER_GENERICS3 = "S3"
CLOUD_PROVIDER_CEPH = "Ceph"
+1
View File
@@ -74,6 +74,7 @@ const (
HYPERVISOR_REMOTEFILE = "remotefile"
HYPERVISOR_H3C = "h3c"
HYPERVISOR_KSYUN = "ksyun"
HYPERVISOR_BAIDU = "baidu"
)
const (
+1
View File
@@ -43,6 +43,7 @@ const (
HOST_TYPE_REMOTEFILE = "remotefile"
HOST_TYPE_H3C = "h3c"
HOST_TYPE_KSYUN = "ksyun"
HOST_TYPE_BAIDU = "baidu"
// # possible status
HOST_ONLINE = "online"
+18
View File
@@ -50,6 +50,12 @@ var (
City: CITY_GUANG_ZHOU,
CountryCode: COUNTRY_CODE_CN,
}
RegionSuzhou = cloudprovider.SGeographicInfo{
Latitude: 31.328,
Longitude: 120.479,
City: CITY_SU_ZHOU,
CountryCode: COUNTRY_CODE_CN,
}
RegionDalian = cloudprovider.SGeographicInfo{
Latitude: 38.91400300000001,
Longitude: 121.614682,
@@ -74,6 +80,12 @@ var (
City: CITY_QING_DAO,
CountryCode: COUNTRY_CODE_CN,
}
RegionBaoDing = cloudprovider.SGeographicInfo{
Latitude: 38.871,
Longitude: 115.393,
City: CITY_BAO_DING,
CountryCode: COUNTRY_CODE_CN,
}
RegionZhangjiakou = cloudprovider.SGeographicInfo{
Latitude: 40.767544,
Longitude: 114.886337,
@@ -92,6 +104,12 @@ var (
City: CITY_HANG_ZHOU,
CountryCode: COUNTRY_CODE_CN,
}
RegionWuhan = cloudprovider.SGeographicInfo{
Latitude: 30.568,
Longitude: 114.136,
City: CITY_WU_HAN,
CountryCode: COUNTRY_CODE_CN,
}
RegionShenzhen = cloudprovider.SGeographicInfo{
Latitude: 22.543097,
Longitude: 114.057861,
+261
View File
@@ -0,0 +1,261 @@
// 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 baidu
import (
"context"
"crypto/tls"
"fmt"
"net/http"
"net/url"
"strings"
"sync"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/pkg/util/httputils"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
)
const (
CLOUD_PROVIDER_BAIDU_CN = "百度云"
BAIDU_DEFAULT_REGION = "bj"
ISO8601 = "2006-01-02T15:04:05Z"
)
type BaiduClientConfig struct {
cpcfg cloudprovider.ProviderConfig
accessKeyId string
accessKeySecret string
debug bool
}
type SBaiduClient struct {
*BaiduClientConfig
client *http.Client
lock sync.Mutex
ctx context.Context
ownerId string
}
func NewBaiduClientConfig(accessKeyId, accessKeySecret string) *BaiduClientConfig {
cfg := &BaiduClientConfig{
accessKeyId: accessKeyId,
accessKeySecret: accessKeySecret,
}
return cfg
}
func (self *BaiduClientConfig) Debug(debug bool) *BaiduClientConfig {
self.debug = debug
return self
}
func (self *BaiduClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *BaiduClientConfig {
self.cpcfg = cpcfg
return self
}
func NewBaiduClient(cfg *BaiduClientConfig) (*SBaiduClient, error) {
client := &SBaiduClient{
BaiduClientConfig: cfg,
ctx: context.Background(),
}
client.ctx = context.WithValue(client.ctx, "time", time.Now())
_, err := client.getOwnerId()
return client, err
}
func (self *SBaiduClient) GetRegions() []SRegion {
ret := []SRegion{}
for k, v := range regions {
ret = append(ret, SRegion{
client: self,
Region: k,
RegionName: v,
})
}
return ret
}
func (self *SBaiduClient) GetRegion(id string) (*SRegion, error) {
regions := self.GetRegions()
for i := range regions {
if regions[i].Region == id {
regions[i].client = self
return &regions[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (self *SBaiduClient) getUrl(service, regionId, resource string) (string, error) {
if len(regionId) == 0 {
regionId = BAIDU_DEFAULT_REGION
}
switch service {
case "bbc":
return fmt.Sprintf("https://bbc.%s.baidubce.com/%s", regionId, strings.TrimPrefix(resource, "/")), nil
case "bos":
return fmt.Sprintf("https://%s.bcebos.com", regionId), nil
case "billing":
return fmt.Sprintf("https://billing.baidubce.com/%s", strings.TrimPrefix(resource, "/")), nil
default:
return "", errors.Wrapf(cloudprovider.ErrNotSupported, service)
}
}
func (cli *SBaiduClient) getDefaultClient() *http.Client {
cli.lock.Lock()
defer cli.lock.Unlock()
if !gotypes.IsNil(cli.client) {
return cli.client
}
cli.client = httputils.GetAdaptiveTimeoutClient()
httputils.SetClientProxyFunc(cli.client, cli.cpcfg.ProxyFunc)
ts, _ := cli.client.Transport.(*http.Transport)
ts.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
cli.client.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response), error) {
if cli.cpcfg.ReadOnly {
if req.Method == "GET" {
return nil, nil
}
return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path)
}
return nil, nil
})
return cli.client
}
type sBaiduError struct {
StatusCode int `json:"statusCode"`
RequestId string `json:"requestId"`
Code string
Message string
}
func (self *sBaiduError) Error() string {
return jsonutils.Marshal(self).String()
}
func (self *sBaiduError) ParseErrorFromJsonResponse(statusCode int, status string, body jsonutils.JSONObject) error {
if body != nil {
body.Unmarshal(self)
}
self.StatusCode = statusCode
return self
}
func (self *SBaiduClient) Do(req *http.Request) (*http.Response, error) {
client := self.getDefaultClient()
req.Header.Set("Content-Type", "application/json; charset=utf-8")
req.Header.Set("x-bce-date", time.Now().UTC().Format(ISO8601))
req.Header.Set("host", req.Host)
signature, err := self.sign(req)
if err != nil {
return nil, errors.Wrapf(err, "sign")
}
req.Header.Set("Authorization", signature)
return client.Do(req)
}
func (self *SBaiduClient) list(service, regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.request(httputils.GET, service, regionId, resource, params)
}
func (self *SBaiduClient) post(service, regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
return self.request(httputils.POST, service, regionId, resource, params)
}
func (self *SBaiduClient) request(method httputils.THttpMethod, service, regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri, err := self.getUrl(service, regionId, resource)
if err != nil {
return nil, err
}
if params == nil {
params = map[string]interface{}{}
}
values := url.Values{}
if method == httputils.GET && len(params) > 0 {
for k, v := range params {
values.Set(k, v.(string))
}
uri = fmt.Sprintf("%s?%s", uri, values.Encode())
}
req := httputils.NewJsonRequest(method, uri, params)
bErr := &sBaiduError{}
client := httputils.NewJsonClient(self)
_, resp, err := client.Send(self.ctx, req, bErr, self.debug)
return resp, err
}
func (self *SBaiduClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
subAccount := cloudprovider.SSubAccount{}
subAccount.Name = self.cpcfg.Name
subAccount.Account = self.accessKeyId
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
return []cloudprovider.SSubAccount{subAccount}, nil
}
func (self *SBaiduClient) getOwnerId() (string, error) {
if len(self.ownerId) > 0 {
return self.ownerId, nil
}
resp, err := self.list("bos", "bj", "/", nil)
if err != nil {
return "", err
}
self.ownerId, err = resp.GetString("owner", "id")
return self.ownerId, err
}
func (self *SBaiduClient) GetAccountId() string {
ownerId, _ := self.getOwnerId()
return ownerId
}
type CashBalance struct {
CashBalance float64
}
func (self *SBaiduClient) QueryBalance() (*CashBalance, error) {
resp, err := self.post("billing", "", "/v1/finance/cash/balance", nil)
if err != nil {
return nil, err
}
ret := &CashBalance{}
err = resp.Unmarshal(ret)
if err != nil {
return nil, errors.Wrapf(err, "resp.Unmarshal")
}
return ret, nil
}
func (self *SBaiduClient) GetCapabilities() []string {
caps := []string{
cloudprovider.CLOUD_CAPABILITY_COMPUTE + cloudprovider.READ_ONLY_SUFFIX,
}
return caps
}
+200
View File
@@ -0,0 +1,200 @@
// 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 provider
import (
"context"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud/baidu"
)
type SBaiduProviderFactory struct {
cloudprovider.SPublicCloudBaseProviderFactory
}
func (self *SBaiduProviderFactory) GetId() string {
return api.CLOUD_PROVIDER_BAIDU
}
func (self *SBaiduProviderFactory) GetName() string {
return baidu.CLOUD_PROVIDER_BAIDU_CN
}
func (self *SBaiduProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, input cloudprovider.SCloudaccountCredential) (cloudprovider.SCloudaccount, error) {
output := cloudprovider.SCloudaccount{}
if len(input.AccessKeyId) == 0 {
return output, errors.Wrap(cloudprovider.ErrMissingParameter, "access_key_id")
}
if len(input.AccessKeySecret) == 0 {
return output, errors.Wrap(cloudprovider.ErrMissingParameter, "access_key_secret")
}
output.AccessUrl = input.Environment
output.Account = input.AccessKeyId
output.Secret = input.AccessKeySecret
return output, nil
}
func (self *SBaiduProviderFactory) ValidateUpdateCloudaccountCredential(ctx context.Context, input cloudprovider.SCloudaccountCredential, cloudaccount string) (cloudprovider.SCloudaccount, error) {
output := cloudprovider.SCloudaccount{}
if len(input.AccessKeyId) == 0 {
return output, errors.Wrap(cloudprovider.ErrMissingParameter, "access_key_id")
}
if len(input.AccessKeySecret) == 0 {
return output, errors.Wrap(cloudprovider.ErrMissingParameter, "access_key_secret")
}
output = cloudprovider.SCloudaccount{
Account: input.AccessKeyId,
Secret: input.AccessKeySecret,
}
return output, nil
}
func (self *SBaiduProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) {
client, err := baidu.NewBaiduClient(
baidu.NewBaiduClientConfig(
cfg.Account,
cfg.Secret,
).CloudproviderConfig(cfg),
)
if err != nil {
return nil, err
}
return &SBaiduProvider{
SBaseProvider: cloudprovider.NewBaseProvider(self),
client: client,
}, nil
}
func (self *SBaiduProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) {
return map[string]string{
"BAIDU_ACCESS_KEY_ID": info.Account,
"BAIDU_ACCESS_KEY_SECRET": info.Secret,
"BAIDU_REGION_ID": baidu.BAIDU_DEFAULT_REGION,
}, nil
}
func init() {
factory := SBaiduProviderFactory{}
cloudprovider.RegisterFactory(&factory)
}
type SBaiduProvider struct {
cloudprovider.SBaseProvider
client *baidu.SBaiduClient
}
func (self *SBaiduProvider) GetSysInfo() (jsonutils.JSONObject, error) {
regions := self.client.GetRegions()
info := jsonutils.NewDict()
info.Add(jsonutils.NewInt(int64(len(regions))), "region_count")
return info, nil
}
func (self *SBaiduProvider) GetVersion() string {
return ""
}
func (self *SBaiduProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
return self.client.GetSubAccounts()
}
func (self *SBaiduProvider) GetAccountId() string {
return self.client.GetAccountId()
}
func (self *SBaiduProvider) GetIRegions() []cloudprovider.ICloudRegion {
regions := self.client.GetRegions()
ret := []cloudprovider.ICloudRegion{}
for i := range regions {
ret = append(ret, &regions[i])
}
return ret
}
func (self *SBaiduProvider) GetIRegionById(extId string) (cloudprovider.ICloudRegion, error) {
region, err := self.client.GetRegion(extId)
if err != nil {
return nil, err
}
return region, nil
}
func (self *SBaiduProvider) GetBalance() (*cloudprovider.SBalanceInfo, error) {
ret := &cloudprovider.SBalanceInfo{Currency: "CNY", Status: api.CLOUD_PROVIDER_HEALTH_UNKNOWN}
balance, err := self.client.QueryBalance()
if err != nil {
return ret, err
}
ret.Status = api.CLOUD_PROVIDER_HEALTH_NORMAL
if balance.CashBalance <= 0 {
if balance.CashBalance < 0 {
ret.Status = api.CLOUD_PROVIDER_HEALTH_ARREARS
} else if balance.CashBalance < 100 {
ret.Status = api.CLOUD_PROVIDER_HEALTH_INSUFFICIENT
}
}
ret.Amount = balance.CashBalance
return ret, nil
}
func (self *SBaiduProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
return []cloudprovider.ICloudProject{}, nil
}
func (self *SBaiduProvider) CreateIProject(name string) (cloudprovider.ICloudProject, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SBaiduProvider) GetStorageClasses(regionId string) []string {
return []string{}
}
func (self *SBaiduProvider) GetBucketCannedAcls(regionId string) []string {
return []string{
string(cloudprovider.ACLPrivate),
string(cloudprovider.ACLPublicRead),
string(cloudprovider.ACLPublicReadWrite),
}
}
func (self *SBaiduProvider) GetObjectCannedAcls(regionId string) []string {
return []string{
string(cloudprovider.ACLPrivate),
string(cloudprovider.ACLPublicRead),
string(cloudprovider.ACLPublicReadWrite),
}
}
func (self *SBaiduProvider) GetCapabilities() []string {
return self.client.GetCapabilities()
}
func (self *SBaiduProvider) GetIamLoginUrl() string {
return ""
}
func (self *SBaiduProvider) GetCloudRegionExternalIdPrefix() string {
return api.CLOUD_PROVIDER_BAIDU + "/"
}
func (self *SBaiduProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) {
return nil, cloudprovider.ErrNotImplemented
}
+143
View File
@@ -0,0 +1,143 @@
// 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 baidu
import (
"fmt"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
)
var regions = map[string]string{
"bj": "北京",
"gz": "广州",
"su": "苏州",
"hkg": "香港",
"fwh": "武汉",
"bd": "保定",
"sin": "新加坡",
"fsh": "上海",
}
type SRegion struct {
multicloud.SRegion
multicloud.SNoObjectStorageRegion
multicloud.SNoLbRegion
client *SBaiduClient
Region string
RegionName string
}
func (self *SRegion) GetId() string {
return self.Region
}
func (self *SRegion) GetGlobalId() string {
return fmt.Sprintf("%s/%s", api.CLOUD_PROVIDER_BAIDU, self.Region)
}
func (self *SRegion) GetProvider() string {
return api.CLOUD_PROVIDER_BAIDU
}
func (self *SRegion) GetCloudEnv() string {
return api.CLOUD_PROVIDER_BAIDU
}
func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
geo, ok := map[string]cloudprovider.SGeographicInfo{
"bj": api.RegionBeijing,
"gz": api.RegionGuangzhou,
"su": api.RegionSuzhou,
"hkg": api.RegionHongkong,
"fwh": api.RegionHangzhou,
"bd": api.RegionBaoDing,
"sin": api.RegionSingapore,
"fsh": api.RegionShanghai,
}[self.Region]
if ok {
return geo
}
return cloudprovider.SGeographicInfo{}
}
func (self *SRegion) GetName() string {
return self.RegionName
}
func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
table := cloudprovider.SModelI18nTable{}
table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(self.Region)
return table
}
func (self *SRegion) GetStatus() string {
return api.CLOUD_REGION_STATUS_INSERVER
}
func (self *SRegion) GetClient() *SBaiduClient {
return self.client
}
func (self *SRegion) CreateEIP(opts *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (region *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (region *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (region *SRegion) GetCapabilities() []string {
return region.client.GetCapabilities()
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
return nil, cloudprovider.ErrNotImplemented
}
+139
View File
@@ -0,0 +1,139 @@
// 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 baidu
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"net/http"
"net/url"
"sort"
"strings"
"time"
"yunion.io/x/pkg/errors"
)
func uriEncode(uri string, encodeSlash bool) string {
var byte_buf bytes.Buffer
for _, b := range []byte(uri) {
if (b >= 'A' && b <= 'Z') || (b >= 'a' && b <= 'z') || (b >= '0' && b <= '9') ||
b == '-' || b == '_' || b == '.' || b == '~' || (b == '/' && !encodeSlash) {
byte_buf.WriteByte(b)
} else {
byte_buf.WriteString(fmt.Sprintf("%%%02X", b))
}
}
return byte_buf.String()
}
func getCanonicalURIPath(path string) string {
if len(path) == 0 {
return "/"
}
canonical_path := path
if strings.HasPrefix(path, "/") {
canonical_path = path[1:]
}
canonical_path = uriEncode(canonical_path, false)
return "/" + canonical_path
}
func getCanonicalQueryString(params url.Values) string {
if len(params) == 0 {
return ""
}
result := make([]string, 0, len(params))
for k, v := range params {
if strings.ToLower(k) == strings.ToLower("authorization") {
continue
}
item := ""
if len(v) == 0 {
item = fmt.Sprintf("%s=", uriEncode(k, true))
} else {
item = fmt.Sprintf("%s=%s", uriEncode(k, true), uriEncode(params.Get(k), true))
}
result = append(result, item)
}
sort.Strings(result)
return strings.Join(result, "&")
}
func getCanonicalHeaders(headers http.Header,
headersToSign map[string]bool) (string, []string) {
canonicalHeaders := make([]string, 0, len(headers))
signHeaders := make([]string, 0, len(headersToSign))
for k := range headers {
headKey := strings.ToLower(k)
if headKey == strings.ToLower("authorization") {
continue
}
_, headExists := headersToSign[headKey]
if headExists ||
(strings.HasPrefix(headKey, "x-bce-") &&
(headKey != "x-bce-request-id")) {
headVal := strings.TrimSpace(headers.Get(k))
encoded := uriEncode(headKey, true) + ":" + uriEncode(headVal, true)
canonicalHeaders = append(canonicalHeaders, encoded)
signHeaders = append(signHeaders, headKey)
}
}
sort.Strings(canonicalHeaders)
sort.Strings(signHeaders)
return strings.Join(canonicalHeaders, "\n"), signHeaders
}
func (self *SBaiduClient) sign(req *http.Request) (string, error) {
signKeyInfo := fmt.Sprintf("%s/%s/%s/%d",
"bce-auth-v1",
self.accessKeyId,
time.Now().UTC().Format(ISO8601),
1800)
hasher := hmac.New(sha256.New, []byte(self.accessKeySecret))
hasher.Write([]byte(signKeyInfo))
signKey := hex.EncodeToString(hasher.Sum(nil))
canonicalUri := getCanonicalURIPath(req.URL.Path)
params, err := url.ParseQuery(req.URL.RawQuery)
if err != nil {
return "", errors.Wrapf(err, "ParseQuery")
}
canonicalQueryString := getCanonicalQueryString(params)
canonicalHeaders, signedHeadersArr := getCanonicalHeaders(req.Header, map[string]bool{
"host": true,
"Content-Length": true,
"Content-Type": true,
"Content-Md5": true,
})
signedHeaders := ""
if len(signedHeadersArr) > 0 {
sort.Strings(signedHeadersArr)
signedHeaders = strings.Join(signedHeadersArr, ";")
}
canonicalParts := []string{req.Method, canonicalUri, canonicalQueryString, canonicalHeaders}
canonicalReq := strings.Join(canonicalParts, "\n")
hasher = hmac.New(sha256.New, []byte(signKey))
hasher.Write([]byte(canonicalReq))
signature := hex.EncodeToString(hasher.Sum(nil))
return signKeyInfo + "/" + signedHeaders + "/" + signature, nil
}
+3 -3
View File
@@ -40,17 +40,17 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"cn-nmhh1": {Latitude: 40.842358, Longitude: 111.749992, City: api.CITY_HU_HE_HAO_TE, CountryCode: api.COUNTRY_CODE_CN},
"cn-shanghai2": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-snxy1": {Latitude: 34.3412614674, Longitude: 108.9398165260, City: api.CITY_XI_AN, CountryCode: api.COUNTRY_CODE_CN},
"cn-hbwh1": {Latitude: 30.5927599029, Longitude: 114.3052387810, City: api.CITY_WU_HAN, CountryCode: api.COUNTRY_CODE_CN},
"cn-hbwh1": api.RegionWuhan,
"cn-hncs1": {Latitude: 28.2277765095, Longitude: 112.9388453666, City: api.CITY_CHANG_SHA, CountryCode: api.COUNTRY_CODE_CN},
"cn-guangzhou2": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-guizhou2": {Latitude: 26.6470035286, Longitude: 106.6302113880, City: api.CITY_GUI_YANG, CountryCode: api.COUNTRY_CODE_CN},
"cn-jssz1": {Latitude: 31.2983479333, Longitude: 120.5831894861, City: api.CITY_SU_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-jssz1": api.RegionSuzhou,
"cn-sccd1": {Latitude: 30.572815, Longitude: 104.066803, City: api.CITY_CHENG_DU, CountryCode: api.COUNTRY_CODE_CN},
"cn-guangzhou3": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-shanghai3": {Latitude: 31.210344, Longitude: 121.455364, City: api.CITY_SHANG_HAI, CountryCode: api.COUNTRY_CODE_CN},
"cn-neimeng4": {Latitude: 40.842358, Longitude: 111.749992, City: api.CITY_HU_HE_HAO_TE, CountryCode: api.COUNTRY_CODE_CN},
"cn-beijing3": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-baoding1": {Latitude: 38.8739745619, Longitude: 115.4646082830, City: api.CITY_BAO_DING, CountryCode: api.COUNTRY_CODE_CN},
"cn-baoding1": api.RegionBaoDing,
"cn-nj2": {Latitude: 32.0584065670, Longitude: 118.7964897811, City: api.CITY_NAN_JING, CountryCode: api.COUNTRY_CODE_CN},
"cn-gdgz1": {Latitude: 23.12911, Longitude: 113.264385, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"cn-bj1": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
@@ -24,7 +24,7 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
"beijing-1": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
"hunan-1": {Latitude: 28.2277765095, Longitude: 112.9388453666, City: api.CITY_CHANG_SHA, CountryCode: api.COUNTRY_CODE_CN},
"wuxi-1": {Latitude: 31.2983479333, Longitude: 120.5831894861, City: api.CITY_SU_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"dongguan-1": {Latitude: 23.129110, Longitude: 113.264381, City: api.CITY_GUANG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"dongguan-1": api.RegionSuzhou,
"yaan-1": {Latitude: 30.572815, Longitude: 104.066803, City: api.CITY_CHENG_DU, CountryCode: api.COUNTRY_CODE_CN},
"zhengzhou-1": {Latitude: 34.7533581487, Longitude: 113.6313915479, City: api.CITY_ZHENG_ZHOU, CountryCode: api.COUNTRY_CODE_CN},
"beijing-2": {Latitude: 39.904202, Longitude: 116.407394, City: api.CITY_BEI_JING, CountryCode: api.COUNTRY_CODE_CN},
+1
View File
@@ -21,6 +21,7 @@ import (
_ "yunion.io/x/cloudmux/pkg/multicloud/apsara/provider" // aliyun apsara stack
_ "yunion.io/x/cloudmux/pkg/multicloud/aws/provider"
_ "yunion.io/x/cloudmux/pkg/multicloud/azure/provider"
_ "yunion.io/x/cloudmux/pkg/multicloud/baidu/provider"
_ "yunion.io/x/cloudmux/pkg/multicloud/bingocloud/provider" // private clouds
_ "yunion.io/x/cloudmux/pkg/multicloud/ctyun/provider"
_ "yunion.io/x/cloudmux/pkg/multicloud/ecloud/provider" // public clouds