mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
fix(region): support rockbasecloud (#24978)
This commit is contained in:
@@ -41,6 +41,7 @@ func init() {
|
||||
cmd.CreateWithKeyword("create-hcs", &options.SHCSAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-hcsop", &options.SHcsOpCloudAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-ucloud", &options.SUcloudCloudAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-rockbase", &options.SRockbaseAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-volcengine", &options.SVolcengineCloudAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-zstack", &options.SZStackCloudAccountCreateOptions{})
|
||||
cmd.CreateWithKeyword("create-s3", &options.SS3CloudAccountCreateOptions{})
|
||||
@@ -76,6 +77,7 @@ func init() {
|
||||
cmd.UpdateWithKeyword("update-hcso", &options.SHCSOAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-hcs", &options.SHCSAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-ucloud", &options.SUcloudCloudAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-rockbase", &options.SRockbaseAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-volcengine", &options.SVolcengineCloudAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-zstack", &options.SZStackCloudAccountUpdateOptions{})
|
||||
cmd.UpdateWithKeyword("update-s3", &options.SS3CloudAccountUpdateOptions{})
|
||||
@@ -107,6 +109,7 @@ func init() {
|
||||
cmd.PerformWithKeyword("update-credential-hcso", "update-credential", &options.SHCSOAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-hcs", "update-credential", &options.SHCSOAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-ucloud", "update-credential", &options.SUcloudCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-rockbase", "update-credential", &options.SRockbaseAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-volcengine", "update-credential", &options.SVolcengineCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-zstack", "update-credential", &options.SZStackCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("update-credential-s3", "update-credential", &options.SS3CloudAccountUpdateCredentialOptions{})
|
||||
@@ -132,6 +135,7 @@ func init() {
|
||||
cmd.PerformWithKeyword("test-connectivity-openstack", "test-connectivity", &options.SOpenStackCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-huawei", "test-connectivity", &options.SHuaweiCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-ucloud", "test-connectivity", &options.SUcloudCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-rockbase", "test-connectivity", &options.SRockbaseAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-volcengine", "test-connectivity", &options.SVolcengineCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-zstack", "test-connectivity", &options.SZStackCloudAccountUpdateCredentialOptions{})
|
||||
cmd.PerformWithKeyword("test-connectivity-s3", "test-connectivity", &options.SS3CloudAccountUpdateCredentialOptions{})
|
||||
|
||||
2
go.mod
2
go.mod
@@ -108,7 +108,7 @@ require (
|
||||
k8s.io/cri-api v0.28.15
|
||||
k8s.io/klog/v2 v2.90.1
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084559-539f78289e9a
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260605102752-5312ff154585
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005
|
||||
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1785,8 +1785,8 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084559-539f78289e9a h1:cFTQgCSRc8X0yPvlELifa5zZkcEO7X7RXA002TNrV4E=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084559-539f78289e9a/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260605102752-5312ff154585 h1:4JQZa+RLkT8qut0U4Fa15hhktj01V9q/cqyDST/xqeA=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260605102752-5312ff154585/go.mod h1:TbMuTWxcTdyL2Usn+WQdIw0jdlBYO66SzPRY8LZ3Wj0=
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005 h1:3sWwcjGXGjG9mLBWa7AyLq+QSi0udTAx21pfVQRFMBE=
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
@@ -78,6 +78,7 @@ const (
|
||||
CLOUD_PROVIDER_CLOUDFLARE = compute.CLOUD_PROVIDER_CLOUDFLARE
|
||||
CLOUD_PROVIDER_CNWARE = compute.CLOUD_PROVIDER_CNWARE
|
||||
CLOUD_PROVIDER_OCEANBASE = compute.CLOUD_PROVIDER_OCEANBASE
|
||||
CLOUD_PROVIDER_ROCKBASE = compute.CLOUD_PROVIDER_ROCKBASE
|
||||
|
||||
CLOUD_PROVIDER_GENERICS3 = compute.CLOUD_PROVIDER_GENERICS3
|
||||
CLOUD_PROVIDER_CEPH = compute.CLOUD_PROVIDER_CEPH
|
||||
@@ -147,6 +148,7 @@ var (
|
||||
CLOUD_PROVIDER_VOLCENGINE,
|
||||
CLOUD_PROVIDER_ORACLE,
|
||||
CLOUD_PROVIDER_CLOUDFLARE,
|
||||
CLOUD_PROVIDER_ROCKBASE,
|
||||
}
|
||||
|
||||
CLOUD_PROVIDERS = []string{
|
||||
@@ -188,6 +190,7 @@ var (
|
||||
CLOUD_PROVIDER_CLOUDFLARE,
|
||||
CLOUD_PROVIDER_CNWARE,
|
||||
CLOUD_PROVIDER_OCEANBASE,
|
||||
CLOUD_PROVIDER_ROCKBASE,
|
||||
}
|
||||
|
||||
CLOUD_PROVIDER_HOST_TYPE_MAP = map[string][]string{
|
||||
@@ -301,6 +304,9 @@ var (
|
||||
CLOUD_PROVIDER_CNWARE: {
|
||||
HOST_TYPE_CNWARE,
|
||||
},
|
||||
CLOUD_PROVIDER_ROCKBASE: {
|
||||
HOST_TYPE_ROCKBASE,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -230,6 +230,7 @@ const (
|
||||
HYPERVISOR_UIS = compute.HYPERVISOR_UIS
|
||||
HYPERVISOR_CAS = compute.HYPERVISOR_CAS
|
||||
HYPERVISOR_CNWARE = compute.HYPERVISOR_CNWARE
|
||||
HYPERVISOR_ROCKBASE = compute.HYPERVISOR_ROCKBASE
|
||||
|
||||
// HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
HYPERVISOR_DEFAULT = HYPERVISOR_KVM
|
||||
@@ -319,6 +320,7 @@ var HYPERVISORS = []string{
|
||||
HYPERVISOR_ZETTAKIT,
|
||||
HYPERVISOR_UIS,
|
||||
HYPERVISOR_CNWARE,
|
||||
HYPERVISOR_ROCKBASE,
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -61,6 +61,7 @@ const (
|
||||
HOST_TYPE_UIS = compute.HOST_TYPE_UIS
|
||||
HOST_TYPE_CAS = compute.HOST_TYPE_CAS
|
||||
HOST_TYPE_CNWARE = compute.HOST_TYPE_CNWARE
|
||||
HOST_TYPE_ROCKBASE = compute.HOST_TYPE_ROCKBASE
|
||||
|
||||
HOST_TYPE_DEFAULT = HOST_TYPE_HYPERVISOR
|
||||
|
||||
@@ -167,6 +168,7 @@ var HOST_TYPES = []string{
|
||||
HOST_TYPE_ZETTAKIT,
|
||||
HOST_TYPE_UIS,
|
||||
HOST_TYPE_CNWARE,
|
||||
HOST_TYPE_ROCKBASE,
|
||||
}
|
||||
|
||||
var ALL_NIC_TYPES = []compute.TNicType{NIC_TYPE_IPMI, NIC_TYPE_ADMIN, NIC_TYPE_NORMAL}
|
||||
|
||||
@@ -79,6 +79,7 @@ var (
|
||||
CLOUD_PROVIDER_HCS,
|
||||
CLOUD_PROVIDER_CTYUN,
|
||||
CLOUD_PROVIDER_UCLOUD,
|
||||
CLOUD_PROVIDER_ROCKBASE,
|
||||
CLOUD_PROVIDER_GOOGLE,
|
||||
CLOUD_PROVIDER_OPENSTACK,
|
||||
CLOUD_PROVIDER_JDCLOUD,
|
||||
|
||||
@@ -95,6 +95,13 @@ const (
|
||||
STORAGE_UCLOUD_LOCAL_SSD = compute.STORAGE_UCLOUD_LOCAL_SSD // SSD本地盘
|
||||
STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK = compute.STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK // 独享本地盘
|
||||
|
||||
// RockBase storage type
|
||||
STORAGE_ROCKBASE_CLOUD_NORMAL = compute.STORAGE_ROCKBASE_CLOUD_NORMAL // 普通云盘
|
||||
STORAGE_ROCKBASE_CLOUD_SSD = compute.STORAGE_ROCKBASE_CLOUD_SSD // SSD云盘
|
||||
STORAGE_ROCKBASE_LOCAL_NORMAL = compute.STORAGE_ROCKBASE_LOCAL_NORMAL // 普通本地盘
|
||||
STORAGE_ROCKBASE_LOCAL_SSD = compute.STORAGE_ROCKBASE_LOCAL_SSD // SSD本地盘
|
||||
STORAGE_ROCKBASE_EXCLUSIVE_LOCAL_DISK = compute.STORAGE_ROCKBASE_EXCLUSIVE_LOCAL_DISK // 独享本地盘
|
||||
|
||||
// VolcEngine storage types
|
||||
STORAGE_VOLC_CLOUD_FLEXPL = compute.STORAGE_VOLCENGINE_FlexPL // 极速型SSD云盘, FlexPL规格
|
||||
STORAGE_VOLC_CLOUD_PL0 = compute.STORAGE_VOLCENGINE_PL0 //极速型SSD云盘, PL0规格
|
||||
@@ -184,6 +191,7 @@ var (
|
||||
STORAGE_LOCAL_TYPES = []string{
|
||||
STORAGE_LOCAL, STORAGE_NVME_PT, STORAGE_NVME, STORAGE_LVM,
|
||||
STORAGE_BAREMETAL, STORAGE_UCLOUD_LOCAL_NORMAL, STORAGE_UCLOUD_LOCAL_SSD, STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK,
|
||||
STORAGE_ROCKBASE_LOCAL_NORMAL, STORAGE_ROCKBASE_LOCAL_SSD, STORAGE_ROCKBASE_EXCLUSIVE_LOCAL_DISK,
|
||||
STORAGE_EPHEMERAL_SSD, STORAGE_LOCAL_BASIC, STORAGE_LOCAL_SSD, STORAGE_LOCAL_PRO, STORAGE_OPENSTACK_NOVA,
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE, STORAGE_GOOGLE_LOCAL_SSD,
|
||||
}
|
||||
@@ -203,6 +211,8 @@ var (
|
||||
STORAGE_HUAWEI_SSD, STORAGE_HUAWEI_SAS, STORAGE_HUAWEI_SATA,
|
||||
STORAGE_OPENSTACK_ISCSI, STORAGE_UCLOUD_CLOUD_NORMAL, STORAGE_UCLOUD_CLOUD_SSD,
|
||||
STORAGE_UCLOUD_LOCAL_NORMAL, STORAGE_UCLOUD_LOCAL_SSD, STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK,
|
||||
STORAGE_ROCKBASE_CLOUD_NORMAL, STORAGE_ROCKBASE_CLOUD_SSD,
|
||||
STORAGE_ROCKBASE_LOCAL_NORMAL, STORAGE_ROCKBASE_LOCAL_SSD, STORAGE_ROCKBASE_EXCLUSIVE_LOCAL_DISK,
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE, STORAGE_ZSTACK_CEPH, STORAGE_ZSTACK_LOCAL_STORAGE, STORAGE_GPFS, STORAGE_CIFS,
|
||||
STORAGE_NVME_PT, STORAGE_NVME, STORAGE_LVM, STORAGE_CLVM, STORAGE_SLVM,
|
||||
}
|
||||
|
||||
31
pkg/cloudmon/providerdriver/rockbase.go
Normal file
31
pkg/cloudmon/providerdriver/rockbase.go
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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 providerdriver
|
||||
|
||||
import (
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type RockbaseCollect struct {
|
||||
SBaseCollectDriver
|
||||
}
|
||||
|
||||
func (self *RockbaseCollect) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func init() {
|
||||
Register(&RockbaseCollect{})
|
||||
}
|
||||
136
pkg/compute/guestdrivers/rockbase.go
Normal file
136
pkg/compute/guestdrivers/rockbase.go
Normal file
@@ -0,0 +1,136 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
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/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SRockbaseGuestDriver struct {
|
||||
SManagedVirtualizedGuestDriver
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) 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_ROCKBASE
|
||||
keys.Brand = api.CLOUD_PROVIDER_ROCKBASE
|
||||
keys.Hypervisor = api.HYPERVISOR_ROCKBASE
|
||||
return keys
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetDefaultSysDiskBackend() string {
|
||||
return api.STORAGE_ROCKBASE_CLOUD_SSD
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetDeployStatus() ([]string, error) {
|
||||
return []string{api.VM_READY}, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetMinimalSysDiskSizeGb() int {
|
||||
return 10
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetGuestInitialStateAfterCreate() string {
|
||||
return api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetDetachDiskStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetAttachDiskStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) IsChangeInstanceTypeWhileRunningSupported(guest *models.SGuest) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetRebuildRootStatus() ([]string, error) {
|
||||
return []string{api.VM_READY, api.VM_RUNNING}, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) GetGuestInitialStateAfterRebuild() string {
|
||||
return api.VM_RUNNING
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_START_RESIZE_DISK, api.VM_RESIZE_DISK}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_ROCKBASE_CLOUD_SSD, api.STORAGE_ROCKBASE_CLOUD_NORMAL}) {
|
||||
return fmt.Errorf("Cannot resize disk with unsupported volumes type %s", storage.StorageType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseGuestDriver) 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,
|
||||
},
|
||||
Windows: cloudprovider.SOsDefaultAccount{
|
||||
DefaultAccount: api.VM_DEFAULT_WINDOWS_LOGIN_USER,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SRockbaseGuestDriver{}
|
||||
models.RegisterGuestDriver(&driver)
|
||||
}
|
||||
|
||||
func (rockbase *SRockbaseGuestDriver) ValidateGuestChangeConfigInput(ctx context.Context, guest *models.SGuest, input api.ServerChangeConfigInput) (*api.ServerChangeConfigSettings, error) {
|
||||
confs, err := rockbase.SBaseGuestDriver.ValidateGuestChangeConfigInput(ctx, guest, input)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SBaseGuestDriver.ValidateGuestChangeConfigInput")
|
||||
}
|
||||
|
||||
if len(input.InstanceType) > 0 {
|
||||
if !strings.HasPrefix(guest.InstanceType, confs.InstanceTypeFamily) {
|
||||
return nil, httperrors.NewInputParameterError("Cannot change config with different instance family")
|
||||
}
|
||||
}
|
||||
|
||||
return confs, nil
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func (self *SManagedVirtualizationHostDriver) CheckAndSetCacheImage(ctx context.
|
||||
}
|
||||
|
||||
providerName := storageCache.GetProviderName()
|
||||
if utils.IsInStringArray(providerName, []string{api.CLOUD_PROVIDER_HUAWEI, api.CLOUD_PROVIDER_HCSO, api.CLOUD_PROVIDER_HCS, api.CLOUD_PROVIDER_UCLOUD}) {
|
||||
if utils.IsInStringArray(providerName, []string{api.CLOUD_PROVIDER_HUAWEI, api.CLOUD_PROVIDER_HCSO, api.CLOUD_PROVIDER_HCS, api.CLOUD_PROVIDER_UCLOUD, api.CLOUD_PROVIDER_ROCKBASE}) {
|
||||
image.OsVersion = input.OsFullVersion
|
||||
}
|
||||
|
||||
|
||||
84
pkg/compute/hostdrivers/rockbase.go
Normal file
84
pkg/compute/hostdrivers/rockbase.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// 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 (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SRockbaseHostDriver struct {
|
||||
SManagedVirtualizationHostDriver
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SRockbaseHostDriver{}
|
||||
models.RegisterHostDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SRockbaseHostDriver) GetHostType() string {
|
||||
return api.HOST_TYPE_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseHostDriver) GetHypervisor() string {
|
||||
return api.HYPERVISOR_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseHostDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb int) error {
|
||||
if storage.StorageType == api.STORAGE_ROCKBASE_CLOUD_NORMAL {
|
||||
if sizeGb < 20 || sizeGb > 8000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 20G ~ 8000GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == api.STORAGE_ROCKBASE_CLOUD_SSD {
|
||||
if sizeGb < 20 || sizeGb > 4000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 20G ~ 4000GB", storage.StorageType)
|
||||
}
|
||||
} else if storage.StorageType == api.STORAGE_ROCKBASE_LOCAL_SSD {
|
||||
if sizeGb < 20 || sizeGb > 1000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 20G ~ 1000GB", storage.StorageType)
|
||||
}
|
||||
|
||||
return fmt.Errorf("Not support create/resize %s disk", storage.StorageType)
|
||||
} else if storage.StorageType == api.STORAGE_ROCKBASE_LOCAL_NORMAL {
|
||||
if sizeGb < 20 || sizeGb > 2000 {
|
||||
return fmt.Errorf("The %s disk size must be in the range of 20G ~ 2000GB", storage.StorageType)
|
||||
}
|
||||
|
||||
return fmt.Errorf("Not support create/resize %s disk", storage.StorageType)
|
||||
} else {
|
||||
return fmt.Errorf("Not support create %s disk", storage.StorageType)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseHostDriver) ValidateResetDisk(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, snapshot *models.SSnapshot, guests []models.SGuest, input *api.DiskResetInput) (*api.DiskResetInput, error) {
|
||||
if len(guests) > 0 {
|
||||
return nil, httperrors.NewInputParameterError("RockBase reset disk operation required disk not be attached")
|
||||
}
|
||||
if disk.DiskType != api.DISK_TYPE_DATA {
|
||||
return nil, httperrors.NewInputParameterError("RockBase only support data disk reset operation")
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
@@ -161,6 +161,7 @@ var HypervisorBrandMap = map[string]string{
|
||||
computeapis.HYPERVISOR_HUAWEI: computeapis.CLOUD_PROVIDER_HUAWEI,
|
||||
computeapis.HYPERVISOR_OPENSTACK: computeapis.CLOUD_PROVIDER_OPENSTACK,
|
||||
computeapis.HYPERVISOR_UCLOUD: computeapis.CLOUD_PROVIDER_UCLOUD,
|
||||
computeapis.HYPERVISOR_ROCKBASE: computeapis.CLOUD_PROVIDER_ROCKBASE,
|
||||
computeapis.HYPERVISOR_ZSTACK: computeapis.CLOUD_PROVIDER_ZSTACK,
|
||||
computeapis.HYPERVISOR_GOOGLE: computeapis.CLOUD_PROVIDER_GOOGLE,
|
||||
computeapis.HYPERVISOR_CTYUN: computeapis.CLOUD_PROVIDER_CTYUN,
|
||||
@@ -177,6 +178,7 @@ var BrandHypervisorMap = map[string]string{
|
||||
computeapis.CLOUD_PROVIDER_HUAWEI: computeapis.HYPERVISOR_HUAWEI,
|
||||
computeapis.CLOUD_PROVIDER_OPENSTACK: computeapis.HYPERVISOR_OPENSTACK,
|
||||
computeapis.CLOUD_PROVIDER_UCLOUD: computeapis.HYPERVISOR_UCLOUD,
|
||||
computeapis.CLOUD_PROVIDER_ROCKBASE: computeapis.HYPERVISOR_ROCKBASE,
|
||||
computeapis.CLOUD_PROVIDER_ZSTACK: computeapis.HYPERVISOR_ZSTACK,
|
||||
computeapis.CLOUD_PROVIDER_GOOGLE: computeapis.HYPERVISOR_GOOGLE,
|
||||
computeapis.CLOUD_PROVIDER_CTYUN: computeapis.HYPERVISOR_CTYUN,
|
||||
|
||||
96
pkg/compute/regiondrivers/rockbase.go
Normal file
96
pkg/compute/regiondrivers/rockbase.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// 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"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/validators"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
)
|
||||
|
||||
type SRockbaseRegionDriver struct {
|
||||
SManagedVirtualizationRegionDriver
|
||||
}
|
||||
|
||||
func init() {
|
||||
driver := SRockbaseRegionDriver{}
|
||||
models.RegisterRegionDriver(&driver)
|
||||
}
|
||||
|
||||
func (self *SRockbaseRegionDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, input api.VpcCreateInput) (api.VpcCreateInput, error) {
|
||||
var cidrV = validators.NewIPv4PrefixValidator("cidr_block")
|
||||
if err := cidrV.Validate(ctx, jsonutils.Marshal(input).(*jsonutils.JSONDict)); err != nil {
|
||||
return input, err
|
||||
}
|
||||
err := IsInPrivateIpRange(cidrV.Value.ToIPRange())
|
||||
if err != nil {
|
||||
return input, err
|
||||
}
|
||||
|
||||
if cidrV.Value.MaskLen > 29 {
|
||||
return input, httperrors.NewInputParameterError("%s request the mask range should be less than or equal to 29", self.GetProvider())
|
||||
}
|
||||
return input, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseRegionDriver) ValidateCreateSecurityGroupInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupCreateInput) (*api.SSecgroupCreateInput, error) {
|
||||
for i := range input.Rules {
|
||||
if input.Rules[i].Protocol == secrules.PROTO_ANY {
|
||||
return nil, httperrors.NewNotSupportedError("protocol %s", input.Rules[i].Protocol)
|
||||
}
|
||||
if input.Rules[i].Priority == nil {
|
||||
return nil, httperrors.NewMissingParameterError("priority")
|
||||
}
|
||||
if *input.Rules[i].Priority < 1 || *input.Rules[i].Priority > 3 {
|
||||
return nil, httperrors.NewInputParameterError("invalid priority %d, range 1-3", *input.Rules[i].Priority)
|
||||
}
|
||||
}
|
||||
return self.SManagedVirtualizationRegionDriver.ValidateCreateSecurityGroupInput(ctx, userCred, input)
|
||||
}
|
||||
|
||||
func (self *SRockbaseRegionDriver) ValidateUpdateSecurityGroupRuleInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.SSecgroupRuleUpdateInput) (*api.SSecgroupRuleUpdateInput, error) {
|
||||
if input.Priority != nil && (*input.Priority < 1 || *input.Priority > 3) {
|
||||
return nil, httperrors.NewInputParameterError("invalid priority %d, range 1-3", *input.Priority)
|
||||
}
|
||||
|
||||
if input.Protocol != nil && *input.Protocol == secrules.PROTO_ANY {
|
||||
return nil, httperrors.NewNotSupportedError("protocol %s", *input.Protocol)
|
||||
}
|
||||
|
||||
if input.Ports != nil && strings.Contains(*input.Ports, ",") {
|
||||
return nil, httperrors.NewInputParameterError("invalid ports %s", *input.Ports)
|
||||
}
|
||||
|
||||
return self.SManagedVirtualizationRegionDriver.ValidateUpdateSecurityGroupRuleInput(ctx, userCred, input)
|
||||
}
|
||||
|
||||
func (self *SRockbaseRegionDriver) GetSecurityGroupFilter(vpc *models.SVpc) (func(q *sqlchemy.SQuery) *sqlchemy.SQuery, error) {
|
||||
return func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
|
||||
return q.Equals("cloudregion_id", vpc.CloudregionId).Equals("manager_id", vpc.ManagerId)
|
||||
}, nil
|
||||
}
|
||||
@@ -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|VolcEngine|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud|IncloudSphere|JDcloud|Proxmox|Ceph|CephFS|Ecloud|HCSO|HCS|HCSOP|H3C|S3|RemoteFile|Ksyun|Baidu|QingCloud|OracleCloud|SangFor|ZettaKit|UIS|CNWare" json:"provider,omitempty"`
|
||||
Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Apsara|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|RockBase|VolcEngine|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud|IncloudSphere|JDcloud|Proxmox|Ceph|CephFS|Ecloud|HCSO|HCS|HCSOP|H3C|S3|RemoteFile|Ksyun|Baidu|QingCloud|OracleCloud|SangFor|ZettaKit|UIS|CNWare" 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"`
|
||||
|
||||
@@ -357,6 +357,17 @@ func (opts *SUcloudCloudAccountCreateOptions) Params() (jsonutils.JSONObject, er
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type SRockbaseAccountCreateOptions struct {
|
||||
SCloudAccountCreateBaseOptions
|
||||
SAccessKeyCredential
|
||||
}
|
||||
|
||||
func (opts *SRockbaseAccountCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
params := jsonutils.Marshal(opts)
|
||||
params.(*jsonutils.JSONDict).Add(jsonutils.NewString("RockBase"), "provider")
|
||||
return params, nil
|
||||
}
|
||||
|
||||
type SVolcengineCloudAccountCreateOptions struct {
|
||||
SCloudAccountCreateBaseOptions
|
||||
SAccessKeyCredential
|
||||
@@ -602,6 +613,15 @@ func (opts *SUcloudCloudAccountUpdateCredentialOptions) Params() (jsonutils.JSON
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type SRockbaseAccountUpdateCredentialOptions struct {
|
||||
SCloudAccountIdOptions
|
||||
SAccessKeyCredential
|
||||
}
|
||||
|
||||
func (opts *SRockbaseAccountUpdateCredentialOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type SVolcengineCloudAccountUpdateCredentialOptions struct {
|
||||
SCloudAccountIdOptions
|
||||
SUserPasswordCredential
|
||||
@@ -1033,6 +1053,14 @@ func (opts *SUcloudCloudAccountUpdateOptions) Params() (jsonutils.JSONObject, er
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type SRockbaseAccountUpdateOptions struct {
|
||||
SCloudAccountUpdateBaseOptions
|
||||
}
|
||||
|
||||
func (opts *SRockbaseAccountUpdateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(opts), nil
|
||||
}
|
||||
|
||||
type SVolcengineCloudAccountUpdateOptions struct {
|
||||
SCloudAccountUpdateBaseOptions
|
||||
|
||||
|
||||
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@@ -2603,7 +2603,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.3.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260512084559-539f78289e9a
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260605102752-5312ff154585
|
||||
## explicit; go 1.24
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
@@ -2692,6 +2692,8 @@ yunion.io/x/cloudmux/pkg/multicloud/qingcloud
|
||||
yunion.io/x/cloudmux/pkg/multicloud/qingcloud/provider
|
||||
yunion.io/x/cloudmux/pkg/multicloud/remotefile
|
||||
yunion.io/x/cloudmux/pkg/multicloud/remotefile/provider
|
||||
yunion.io/x/cloudmux/pkg/multicloud/rockbase
|
||||
yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider
|
||||
yunion.io/x/cloudmux/pkg/multicloud/ucloud
|
||||
yunion.io/x/cloudmux/pkg/multicloud/ucloud/provider
|
||||
yunion.io/x/cloudmux/pkg/multicloud/volcengine
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go
generated
vendored
@@ -52,6 +52,7 @@ const (
|
||||
CLOUD_PROVIDER_CAS = "CAS"
|
||||
CLOUD_PROVIDER_CNWARE = "CNware"
|
||||
CLOUD_PROVIDER_OCEANBASE = "OceanBase"
|
||||
CLOUD_PROVIDER_ROCKBASE = "RockBase"
|
||||
|
||||
CLOUD_PROVIDER_GENERICS3 = "S3"
|
||||
CLOUD_PROVIDER_CEPH = "Ceph"
|
||||
|
||||
7
vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudregions_const.go
generated
vendored
7
vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudregions_const.go
generated
vendored
@@ -124,6 +124,7 @@ const (
|
||||
CITY_N_CALIFORNIA = "N. California" //北加州
|
||||
CITY_OREGON = "Oregon" //俄勒冈州
|
||||
CITY_LOS_ANGELES = "Los Angeles" //洛杉矶
|
||||
CITY_DENVER = "Denver" //丹佛
|
||||
CITY_SAN_FRANCISCO = "San Francisco" //旧金山
|
||||
CITY_UTAH = "Utah" //犹他州
|
||||
CITY_WASHINGTON = "Washington" //华盛顿
|
||||
@@ -179,6 +180,7 @@ const (
|
||||
|
||||
// 波兰
|
||||
CITY_WARSAW = "Warsaw" // 华沙
|
||||
CITY_ISTANBUL = "Istanbul" // 伊斯坦布尔
|
||||
|
||||
// 巴西
|
||||
CITY_SAO_PAULO = "Sao Paulo" //圣保罗
|
||||
@@ -229,6 +231,9 @@ const (
|
||||
// 新西兰
|
||||
CITY_NEW_ZEALAND = "New Zealand" // 新西兰
|
||||
|
||||
// 菲律宾
|
||||
CITY_MANILA = "Manila" // 马尼拉
|
||||
|
||||
COUNTRY_CODE_CN = "CN" //中国
|
||||
COUNTRY_CODE_JP = "JP" //日本
|
||||
COUNTRY_CODE_SG = "SG" //新加坡
|
||||
@@ -265,4 +270,6 @@ const (
|
||||
COUNTRY_CODE_ES = "ES" //西班牙
|
||||
COUNTRY_CODE_QA = "QA" //卡塔尔
|
||||
COUNTRY_CODE_NZ = "NZ" //新西兰
|
||||
COUNTRY_CODE_PH = "PH" //菲律宾
|
||||
COUNTRY_CODE_TR = "TR" //土耳其
|
||||
)
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/guest_const.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/guest_const.go
generated
vendored
@@ -84,6 +84,7 @@ const (
|
||||
HYPERVISOR_UIS = "uis"
|
||||
HYPERVISOR_CAS = "cas"
|
||||
HYPERVISOR_CNWARE = "cnware"
|
||||
HYPERVISOR_ROCKBASE = "rockbase"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/host_const.go
generated
vendored
1
vendor/yunion.io/x/cloudmux/pkg/apis/compute/host_const.go
generated
vendored
@@ -53,6 +53,7 @@ const (
|
||||
HOST_TYPE_UIS = "uis"
|
||||
HOST_TYPE_CAS = "cas"
|
||||
HOST_TYPE_CNWARE = "cnware"
|
||||
HOST_TYPE_ROCKBASE = "rockbase"
|
||||
|
||||
// # possible status
|
||||
HOST_ONLINE = "online"
|
||||
|
||||
44
vendor/yunion.io/x/cloudmux/pkg/apis/compute/regiondata.go
generated
vendored
44
vendor/yunion.io/x/cloudmux/pkg/apis/compute/regiondata.go
generated
vendored
@@ -318,8 +318,8 @@ var (
|
||||
CountryCode: COUNTRY_CODE_JP,
|
||||
}
|
||||
RegionSeoul = cloudprovider.SGeographicInfo{
|
||||
Latitude: 34.694,
|
||||
Longitude: 135.502,
|
||||
Latitude: 37.566,
|
||||
Longitude: 126.978,
|
||||
City: CITY_SEOUL,
|
||||
CountryCode: COUNTRY_CODE_KR,
|
||||
}
|
||||
@@ -387,6 +387,18 @@ var (
|
||||
City: CITY_BANGKOK,
|
||||
CountryCode: COUNTRY_CODE_TH,
|
||||
}
|
||||
RegionManila = cloudprovider.SGeographicInfo{
|
||||
Latitude: 14.599,
|
||||
Longitude: 120.984,
|
||||
City: CITY_MANILA,
|
||||
CountryCode: COUNTRY_CODE_PH,
|
||||
}
|
||||
RegionHoChiMinh = cloudprovider.SGeographicInfo{
|
||||
Latitude: 10.823,
|
||||
Longitude: 106.630,
|
||||
City: CITY_HO_CHI_MINH,
|
||||
CountryCode: COUNTRY_CODE_VN,
|
||||
}
|
||||
|
||||
RegionSydney = cloudprovider.SGeographicInfo{
|
||||
Latitude: -33.869,
|
||||
@@ -429,6 +441,12 @@ var (
|
||||
City: CITY_JOHANNESBURG,
|
||||
CountryCode: COUNTRY_CODE_ZA,
|
||||
}
|
||||
RegionLagos = cloudprovider.SGeographicInfo{
|
||||
Latitude: 6.524,
|
||||
Longitude: 3.379,
|
||||
City: CITY_LAGOS,
|
||||
CountryCode: COUNTRY_CODE_NG,
|
||||
}
|
||||
|
||||
// Middleeast
|
||||
RegionBahrain = cloudprovider.SGeographicInfo{
|
||||
@@ -513,6 +531,12 @@ var (
|
||||
City: CITY_WARSAW,
|
||||
CountryCode: COUNTRY_CODE_PL,
|
||||
}
|
||||
RegionIstanbul = cloudprovider.SGeographicInfo{
|
||||
Latitude: 41.008,
|
||||
Longitude: 28.978,
|
||||
City: CITY_ISTANBUL,
|
||||
CountryCode: COUNTRY_CODE_TR,
|
||||
}
|
||||
RegionMadrid = cloudprovider.SGeographicInfo{
|
||||
Latitude: 40.438,
|
||||
Longitude: -3.82,
|
||||
@@ -640,8 +664,8 @@ var (
|
||||
}
|
||||
|
||||
RegionMexico = cloudprovider.SGeographicInfo{
|
||||
Latitude: 55.118,
|
||||
Longitude: 141.038,
|
||||
Latitude: 19.433,
|
||||
Longitude: -99.133,
|
||||
City: CITY_MEXICO,
|
||||
CountryCode: COUNTRY_CODE_MX,
|
||||
}
|
||||
@@ -732,6 +756,18 @@ var (
|
||||
City: CITY_LOS_ANGELES,
|
||||
CountryCode: COUNTRY_CODE_US,
|
||||
}
|
||||
RegionDenver = cloudprovider.SGeographicInfo{
|
||||
Latitude: 39.739,
|
||||
Longitude: -104.990,
|
||||
City: CITY_DENVER,
|
||||
CountryCode: COUNTRY_CODE_US,
|
||||
}
|
||||
RegionWashingtonDC = cloudprovider.SGeographicInfo{
|
||||
Latitude: 38.907,
|
||||
Longitude: -77.037,
|
||||
City: CITY_WASHINGTON,
|
||||
CountryCode: COUNTRY_CODE_US,
|
||||
}
|
||||
RegionSaltLakeCity = cloudprovider.SGeographicInfo{
|
||||
Latitude: 40.777,
|
||||
Longitude: -111.991,
|
||||
|
||||
7
vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go
generated
vendored
7
vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go
generated
vendored
@@ -81,6 +81,13 @@ const (
|
||||
STORAGE_UCLOUD_LOCAL_SSD = "LOCAL_SSD" // SSD本地盘
|
||||
STORAGE_UCLOUD_EXCLUSIVE_LOCAL_DISK = "EXCLUSIVE_LOCAL_DISK" // 独享本地盘
|
||||
|
||||
// RockBase storage type
|
||||
STORAGE_ROCKBASE_CLOUD_NORMAL = "CLOUD_NORMAL" // 普通云盘
|
||||
STORAGE_ROCKBASE_CLOUD_SSD = "CLOUD_SSD" // SSD云盘
|
||||
STORAGE_ROCKBASE_LOCAL_NORMAL = "LOCAL_NORMAL" // 普通本地盘
|
||||
STORAGE_ROCKBASE_LOCAL_SSD = "LOCAL_SSD" // SSD本地盘
|
||||
STORAGE_ROCKBASE_EXCLUSIVE_LOCAL_DISK = "EXCLUSIVE_LOCAL_DISK" // 独享本地盘
|
||||
|
||||
// Zstack storage type
|
||||
STORAGE_ZSTACK_LOCAL_STORAGE = "localstorage"
|
||||
STORAGE_ZSTACK_CEPH = "ceph"
|
||||
|
||||
15
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/cloudprovider.go
generated
vendored
15
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/cloudprovider.go
generated
vendored
@@ -315,6 +315,13 @@ type ICloudProvider interface {
|
||||
GetIAiGateways() ([]IAiGateway, error)
|
||||
GetIAiGatewayById(id string) (IAiGateway, error)
|
||||
CreateIAiGateway(opts *AiGatewayCreateOptions) (IAiGateway, error)
|
||||
|
||||
GetNotices() ([]INotice, error)
|
||||
}
|
||||
|
||||
type INotice interface {
|
||||
GetTitle() string
|
||||
GetContent() string
|
||||
}
|
||||
|
||||
func IsSupportCapability(prod ICloudProvider, capa string) bool {
|
||||
@@ -423,6 +430,10 @@ func RegisterFactory(factory ICloudProviderFactory) {
|
||||
providerTable[factory.GetId()] = factory
|
||||
}
|
||||
|
||||
func RegisterFactoryAlias(alias string, factory ICloudProviderFactory) {
|
||||
providerTable[alias] = factory
|
||||
}
|
||||
|
||||
func GetProviderFactory(provider string) (ICloudProviderFactory, error) {
|
||||
factory, ok := providerTable[provider]
|
||||
if ok {
|
||||
@@ -660,6 +671,10 @@ func (base *SBaseProvider) CreateIAiGateway(opts *AiGatewayCreateOptions) (IAiGa
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "CreateIAiGateway")
|
||||
}
|
||||
|
||||
func (base *SBaseProvider) GetNotices() ([]INotice, error) {
|
||||
return nil, errors.Wrapf(ErrNotImplemented, "GetNotices")
|
||||
}
|
||||
|
||||
func NewBaseProvider(factory ICloudProviderFactory) SBaseProvider {
|
||||
return SBaseProvider{factory: factory}
|
||||
}
|
||||
|
||||
33
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/notice.go
generated
vendored
Normal file
33
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/notice.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// 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 "time"
|
||||
|
||||
// IsNoticePublishedToday reports whether t falls on the current calendar day in Asia/Shanghai.
|
||||
func IsNoticePublishedToday(t time.Time) bool {
|
||||
if t.IsZero() {
|
||||
return false
|
||||
}
|
||||
loc, err := time.LoadLocation("Asia/Shanghai")
|
||||
if err != nil {
|
||||
loc = time.FixedZone("CST", 8*3600)
|
||||
}
|
||||
now := time.Now().In(loc)
|
||||
t = t.In(loc)
|
||||
y1, m1, d1 := now.Date()
|
||||
y2, m2, d2 := t.Date()
|
||||
return y1 == y2 && m1 == m2 && d1 == d2
|
||||
}
|
||||
26
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/latitud_and_longitude.go
generated
vendored
26
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/latitud_and_longitude.go
generated
vendored
@@ -22,28 +22,44 @@ import (
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-qingdao": api.RegionQingdao,
|
||||
"cn-beijing": api.RegionBeijing,
|
||||
"cn-beijing-finance-1": api.RegionBeijing,
|
||||
"cn-zhangjiakou": api.RegionZhangjiakou,
|
||||
"cn-huhehaote": api.RegionHuhehaote,
|
||||
"cn-huhehaote-nebula-1": api.RegionHuhehaote,
|
||||
"cn-wulanchabu": api.RegionWulanchabu,
|
||||
"cn-hangzhou": api.RegionHangzhou,
|
||||
"cn-hangzhou-finance": api.RegionHangzhou,
|
||||
"cn-shanghai": api.RegionShanghai,
|
||||
"cn-shanghai-finance-1": api.RegionShanghai,
|
||||
"cn-nanjing": api.RegionNanjing,
|
||||
"cn-fuzhou": api.RegionFujian,
|
||||
"cn-fujian": api.RegionFujian,
|
||||
"cn-wuhan": api.RegionWuhan,
|
||||
"cn-wuhan-lr": api.RegionWuhan,
|
||||
"cn-shenzhen": api.RegionShenzhen,
|
||||
"cn-shenzhen-finance-1": api.RegionShenzhen,
|
||||
"cn-hongkong": api.RegionHongkong,
|
||||
"cn-chengdu": api.RegionChengdu,
|
||||
"cn-heyuan": api.RegionHeyuan,
|
||||
"cn-guangzhou": api.RegionGuangzhou,
|
||||
"cn-chengdu": api.RegionChengdu,
|
||||
"cn-zhongwei": api.RegionNingxia,
|
||||
"cn-hongkong": api.RegionHongkong,
|
||||
"cn-north-2-gov-1": api.RegionBeijing,
|
||||
"ap-northeast-1": api.RegionTokyo,
|
||||
"ap-northeast-2": api.RegionSeoul,
|
||||
"ap-southeast-1": api.RegionSingapore,
|
||||
"ap-southeast-2": api.RegionSydney,
|
||||
"ap-southeast-3": api.RegionKualaLumpur,
|
||||
"ap-southeast-5": api.RegionJakarta,
|
||||
"ap-southeast-6": api.RegionManila,
|
||||
"ap-southeast-7": api.RegionBangkok,
|
||||
"ap-southeast-8": api.RegionKualaLumpur,
|
||||
"ap-south-1": api.RegionMumbai,
|
||||
"us-east-1": api.RegionVirginia,
|
||||
"us-west-1": api.RegionSiliconValley,
|
||||
"na-south-1": api.RegionMexico,
|
||||
"eu-west-1": api.RegionLondon,
|
||||
"me-east-1": api.RegionDubai,
|
||||
"eu-west-2": api.RegionParis,
|
||||
"eu-central-1": api.RegionFrankfurt,
|
||||
"cn-wulanchabu": api.RegionWulanchabu,
|
||||
"cn-guangzhou": api.RegionGuangzhou,
|
||||
"me-east-1": api.RegionDubai,
|
||||
"me-central-1": api.RegionDubai,
|
||||
}
|
||||
|
||||
152
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/notice.go
generated
vendored
Normal file
152
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/notice.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// 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 aliyun
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const aliyunNoticeRssURL = "https://www.aliyun.com/rss/notice/zh.xml"
|
||||
|
||||
var htmlTagRe = regexp.MustCompile(`<[^>]*>`)
|
||||
|
||||
type SNotice struct {
|
||||
title string
|
||||
content string
|
||||
}
|
||||
|
||||
func (notice *SNotice) GetTitle() string {
|
||||
return notice.title
|
||||
}
|
||||
|
||||
func (notice *SNotice) GetContent() string {
|
||||
return notice.content
|
||||
}
|
||||
|
||||
type sRssFeed struct {
|
||||
Channel sRssChannel `xml:"channel"`
|
||||
}
|
||||
|
||||
type sRssChannel struct {
|
||||
Items []sRssItem `xml:"item"`
|
||||
}
|
||||
|
||||
type sRssItem struct {
|
||||
Title string `xml:"title"`
|
||||
Link string `xml:"link"`
|
||||
Description string `xml:"description"`
|
||||
PubDate string `xml:"pubDate"`
|
||||
ContentEncoded string `xml:"http://purl.org/rss/1.0/modules/content/ encoded"`
|
||||
}
|
||||
|
||||
func (self *SAliyunClient) GetNotices() ([]cloudprovider.INotice, error) {
|
||||
body, err := self.fetchNoticeRss()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
feed := &sRssFeed{}
|
||||
err = xml.Unmarshal(body, feed)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "xml.Unmarshal")
|
||||
}
|
||||
ret := make([]cloudprovider.INotice, 0, len(feed.Channel.Items))
|
||||
for i := range feed.Channel.Items {
|
||||
item := &feed.Channel.Items[i]
|
||||
|
||||
pubAt, err := parseRssPubDate(item.PubDate)
|
||||
if err != nil || !cloudprovider.IsNoticePublishedToday(pubAt) {
|
||||
continue
|
||||
}
|
||||
|
||||
ret = append(ret, &SNotice{
|
||||
title: strings.TrimSpace(item.Title),
|
||||
content: formatRssNoticeContent(item),
|
||||
})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func parseRssPubDate(pubDate string) (time.Time, error) {
|
||||
pubDate = strings.TrimSpace(pubDate)
|
||||
if len(pubDate) == 0 {
|
||||
return time.Time{}, errors.New("empty pubDate")
|
||||
}
|
||||
return http.ParseTime(pubDate)
|
||||
}
|
||||
|
||||
func (self *SAliyunClient) fetchNoticeRss() ([]byte, error) {
|
||||
client := httputils.GetAdaptiveTimeoutClient()
|
||||
httputils.SetClientProxyFunc(client, self.cpcfg.ProxyFunc)
|
||||
resp, err := httputils.Request(client, context.Background(), httputils.GET, aliyunNoticeRssURL, nil, nil, self.debug)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Request")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.Errorf("unexpected status %s", resp.Status)
|
||||
}
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ReadAll")
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func formatRssNoticeContent(item *sRssItem) string {
|
||||
content := stripHTML(item.ContentEncoded)
|
||||
if len(content) == 0 {
|
||||
content = stripHTML(item.Description)
|
||||
}
|
||||
if len(item.Link) > 0 {
|
||||
if len(content) > 0 {
|
||||
content = fmt.Sprintf("%s\n\nLink: %s", content, item.Link)
|
||||
} else {
|
||||
content = item.Link
|
||||
}
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
func stripHTML(s string) string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
s = html.UnescapeString(s)
|
||||
s = htmlTagRe.ReplaceAllString(s, "")
|
||||
s = strings.ReplaceAll(s, "\u00a0", " ")
|
||||
lines := strings.Split(s, "\n")
|
||||
parts := []string{}
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if len(line) > 0 {
|
||||
parts = append(parts, line)
|
||||
}
|
||||
}
|
||||
return strings.Join(parts, "\n")
|
||||
}
|
||||
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/provider/provider.go
generated
vendored
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/provider/provider.go
generated
vendored
@@ -518,3 +518,7 @@ func (self *SAliyunProvider) GetISSLCertificates() ([]cloudprovider.ICloudSSLCer
|
||||
func (self *SAliyunProvider) GetISSLCertificate(certId string) (cloudprovider.ICloudSSLCertificate, error) {
|
||||
return self.client.GetISSLCertificate(certId)
|
||||
}
|
||||
|
||||
func (self *SAliyunProvider) GetNotices() ([]cloudprovider.INotice, error) {
|
||||
return self.client.GetNotices()
|
||||
}
|
||||
|
||||
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws.go
generated
vendored
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/aws.go
generated
vendored
@@ -217,7 +217,7 @@ func (client *SAwsClient) getHttpClient() (*http.Client, error) {
|
||||
|
||||
if client.cpcfg.ReadOnly {
|
||||
if len(action) > 0 {
|
||||
for _, prefix := range []string{"Get", "List", "Describe"} {
|
||||
for _, prefix := range []string{"Get", "List", "Describe", "AssumeRole"} {
|
||||
if strings.HasPrefix(action, prefix) {
|
||||
return respCheck, nil
|
||||
}
|
||||
|
||||
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/latitude_and_longitude.go
generated
vendored
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aws/latitude_and_longitude.go
generated
vendored
@@ -37,12 +37,14 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-north-1": api.RegionBeijing,
|
||||
"cn-northwest-1": api.RegionNingxia,
|
||||
"eu-central-1": api.RegionFrankfurt,
|
||||
"eusc-de-east-1": api.RegionFrankfurt,
|
||||
"eu-west-1": api.RegionIreland,
|
||||
"eu-west-2": api.RegionLondon,
|
||||
"eu-west-3": api.RegionParis,
|
||||
"eu-north-1": api.RegionStockholm,
|
||||
"sa-east-1": api.RegionSaoPaulo,
|
||||
"us-gov-west-1": api.RegionUSGOVWest,
|
||||
"us-gov-east-1": api.RegionNothVirginia,
|
||||
|
||||
"af-south-1": api.RegionCapeTown,
|
||||
"me-south-1": api.RegionBahrain,
|
||||
|
||||
11
vendor/yunion.io/x/cloudmux/pkg/multicloud/azure/geographicinfo.go
generated
vendored
11
vendor/yunion.io/x/cloudmux/pkg/multicloud/azure/geographicinfo.go
generated
vendored
@@ -44,6 +44,8 @@ var AzureGeographicInfo = map[string]cloudprovider.SGeographicInfo{
|
||||
"westus2": api.RegionWashington, //美国 华盛顿
|
||||
"southcentralus": api.RegionTexas, //美国 德克萨斯
|
||||
"brazilsouth": api.RegionSaoPaulo, //巴西 圣保罗
|
||||
"brazilsoutheast": api.RegionRioDeJaneiro, // 里约热内卢
|
||||
"chilecentral": api.RegionSantiago,
|
||||
"koreacentral": api.RegionSeoul, //韩国 汉城 -> 首尔
|
||||
"centralindia": api.RegionMaharashtra, //印度 马哈拉施特拉邦
|
||||
"northcentralus": api.RegionChicago, //美国 芝加哥
|
||||
@@ -61,7 +63,6 @@ var AzureGeographicInfo = map[string]cloudprovider.SGeographicInfo{
|
||||
"germanywestcentral": api.RegionFrankfurt, // 法兰克福
|
||||
"germanynorth": api.RegionDelmenhorst, // 代尔门霍斯特
|
||||
"westus3": api.RegionPhoenix,
|
||||
"brazilsoutheast": api.RegionRioDeJaneiro, // 里约热内卢
|
||||
"jioindiawest": api.RegionJioIndiaWest, // 贾姆讷格尔
|
||||
"jioindiacentral": api.RegionJioIndiaCentral, // 那格浦尔
|
||||
"swedencentral": api.RegionSandviken,
|
||||
@@ -70,6 +71,14 @@ var AzureGeographicInfo = map[string]cloudprovider.SGeographicInfo{
|
||||
"italynorth": api.RegionMilan,
|
||||
"israelcentral": api.RegionTelAviv,
|
||||
"brazilus": api.RegionIndianapolis,
|
||||
"austriaeast": api.RegionFrankfurt,
|
||||
"belgiumcentral": api.RegionBelgium,
|
||||
"denmarkeast": api.RegionOslo,
|
||||
"indonesiacentral": api.RegionJakarta,
|
||||
"malaysiawest": api.RegionKualaLumpur,
|
||||
"mexicocentral": api.RegionMexico,
|
||||
"newzealandnorth": api.RegionNewZealand,
|
||||
"spaincentral": api.RegionMadrid,
|
||||
|
||||
"chinaeast": api.RegionShanghai,
|
||||
"chinaeast2": api.RegionShanghai,
|
||||
|
||||
14
vendor/yunion.io/x/cloudmux/pkg/multicloud/azure/instancenic.go
generated
vendored
14
vendor/yunion.io/x/cloudmux/pkg/multicloud/azure/instancenic.go
generated
vendored
@@ -19,7 +19,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
@@ -168,18 +167,7 @@ func (self *SRegion) CreateNetworkInterface(resourceGroup string, nicName string
|
||||
}
|
||||
|
||||
func (self *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
|
||||
nics, err := self.GetNetworkInterfaces()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetNetworkInterfaces")
|
||||
}
|
||||
ret := []cloudprovider.ICloudNetworkInterface{}
|
||||
for i := range nics {
|
||||
if len(nics[i].Properties.VirtualMachine.ID) > 0 {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, &nics[i])
|
||||
}
|
||||
return ret, nil
|
||||
return []cloudprovider.ICloudNetworkInterface{}, nil
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetAssociateId() string {
|
||||
|
||||
183
vendor/yunion.io/x/cloudmux/pkg/multicloud/ctyun/latitud_and_longitude.go
generated
vendored
183
vendor/yunion.io/x/cloudmux/pkg/multicloud/ctyun/latitud_and_longitude.go
generated
vendored
@@ -19,37 +19,166 @@ import (
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// GetGeographicInfo 使用 RegionCode,无 RegionCode 时使用 RegionId 作为 key
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-beijing-5": api.RegionBeijing,
|
||||
// 北京
|
||||
"cn-beijing-5": api.RegionBeijing,
|
||||
|
||||
// 天津 / 华北
|
||||
"cn-tianjin-2": api.RegionTianjin,
|
||||
"cn-tianjin-01": api.RegionTianjin,
|
||||
"e4874db42e9211ed88f70242ac110002": api.RegionTianjin, // 天津3
|
||||
|
||||
// 河北
|
||||
"cn-he-sjz20-hybrid-ctcloud": api.RegionShijiazhuang,
|
||||
"3ddd0446876d11eaab020242ac110002": api.RegionShijiazhuang, // 石家庄2
|
||||
"529d1808bcf511eb93260242ac110002": api.RegionShijiazhuang, // 石家庄3
|
||||
|
||||
// 内蒙
|
||||
"cn-neimeng-6": api.RegionNeimenggu,
|
||||
"cn-huhehaote-03": api.RegionHuhehaote,
|
||||
"cn-huhehaote-6": api.RegionHuhehaote, // 历史别名
|
||||
|
||||
// 山西
|
||||
"cn-jinzhong-2": api.RegionJinzhong,
|
||||
"cn-taiyuan-04": api.RegionJinzhong,
|
||||
"05f7a93651a211ecbe170242ac110002": api.RegionJinzhong, // 太原2
|
||||
|
||||
// 辽宁
|
||||
"cn-shenyang-08": api.RegionShenyang,
|
||||
"cn-ln-ly1-public-ctcloud": api.RegionShenyang,
|
||||
"172f2480f64b11ea98a40242ac110002": api.RegionShenyang, // 沈阳4
|
||||
"200000001820": api.RegionShenyang, // 辽阳2
|
||||
|
||||
// 黑龙江
|
||||
"cn-haerbin-2": api.RegionHaerbin,
|
||||
|
||||
// 上海 / 华东
|
||||
"cn-shanghai-7": api.RegionShanghai,
|
||||
"cn-shanghai-15": api.RegionShanghai,
|
||||
"cn-shanghai-36": api.RegionShanghai,
|
||||
"cn-huadong-1": api.RegionShanghai,
|
||||
"db0fed10499511eb8a780242ac110002": api.RegionShanghai, // 上海8
|
||||
"01aaa9182e9311edad970242ac110002": api.RegionShanghai, // 上海9
|
||||
|
||||
// 江苏
|
||||
"cn-nanjing-2": api.RegionNanjing,
|
||||
"cn-nanjing-3": api.RegionNanjing,
|
||||
"cn-nanjing-4": api.RegionNanjing,
|
||||
"cn-nanjing-5": api.RegionNanjing,
|
||||
"0e72cfe651a211ecabbe0242ac110002": api.RegionNanjing, // 扬州
|
||||
|
||||
// 浙江
|
||||
"cn-hangzhou-2": api.RegionHangzhou,
|
||||
"cn-nanjing-4": api.RegionNanjing,
|
||||
"cn-wuhan-3": api.RegionWuhan,
|
||||
"cn-yaan-2": api.RegionXian,
|
||||
"cn-wuhu-1": api.RegionWuhu,
|
||||
"cn-kunming-2": api.RegionKunming,
|
||||
"cn-hefei2": api.RegionHefei,
|
||||
"cn-fujian-3": api.RegionFujian,
|
||||
"cn-jinzhong-2": api.RegionJinzhong,
|
||||
"cn-nanjing-5": api.RegionNanning,
|
||||
"cn-huhehaote-6": api.RegionHuhehaote,
|
||||
"cn-nanjing-3": api.RegionNanjing,
|
||||
"cn-haikou-2": api.RegionHaikou,
|
||||
"cn-tianjin-2": api.RegionTianjin,
|
||||
"cn-wuhan-5": api.RegionWuhan,
|
||||
"cn-foshan-3": api.RegionFoshan,
|
||||
"cn-nanning-2": api.RegionNanning,
|
||||
"cn-chenzhou-4": api.RegionChengzhou,
|
||||
"cn-hanzhou-07": api.RegionHangzhou,
|
||||
"200000001856": api.RegionHangzhou, // 浙江金华6
|
||||
|
||||
// 安徽
|
||||
"cn-wuhu-1": api.RegionWuhu,
|
||||
"cn-wuhu-04": api.RegionWuhu,
|
||||
"cn-hefei2": api.RegionHefei,
|
||||
"b02ba000ab1c11ec8c4a0242ac110002": api.RegionHefei, // 合肥
|
||||
"200000003615": api.RegionWuhu, // 芜湖5
|
||||
|
||||
// 福建
|
||||
"cn-fujian-3": api.RegionFujian,
|
||||
"cn-fuzhou-4": api.RegionFujian,
|
||||
"cn-xiamen-3": api.RegionFujian,
|
||||
"cn-fuzhou-25": api.RegionFujian,
|
||||
"4f23b922ab1d11ecaa9f0242ac110002": api.RegionFujian, // 福州5
|
||||
|
||||
// 江西
|
||||
"cn-jiangxi-2": api.RegionJiangxi,
|
||||
"cn-hunan-3": api.RegionChangsha,
|
||||
"cn-nanchang-05": api.RegionJiangxi,
|
||||
"200000001476": api.RegionJiangxi, // 南昌18
|
||||
"200000004030": api.RegionJiangxi, // 南昌4
|
||||
|
||||
// 山东
|
||||
"cn-qingdao-20": api.RegionQingdao,
|
||||
"9395e62eb52511eab9d70242ac110002": api.RegionQingdao, // 青岛3
|
||||
"63daa10af68111ecb89f0242ac110002": api.RegionQingdao, // 青岛4
|
||||
|
||||
// 河南
|
||||
"cn-zhengzhou-2": api.RegionZhengzhou,
|
||||
"cn-zhengzhou-05": api.RegionZhengzhou,
|
||||
"200000004029": api.RegionZhengzhou, // 郑州13
|
||||
|
||||
// 湖北
|
||||
"cn-wuhan-3": api.RegionWuhan,
|
||||
"cn-wuhan-5": api.RegionWuhan,
|
||||
"cn-wuhan-41": api.RegionWuhan,
|
||||
|
||||
// 湖南
|
||||
"cn-hunan-3": api.RegionChangsha,
|
||||
"cn-changsha-42": api.RegionChangsha,
|
||||
"cn-chenzhou-2": api.RegionChengzhou,
|
||||
"cn-chenzhou-4": api.RegionChengzhou, // 历史别名
|
||||
|
||||
// 广东
|
||||
"cn-foshan-3": api.RegionFoshan,
|
||||
"cn-guangzhou-5": api.RegionGuangzhou,
|
||||
"cn-huanan-02": api.RegionGuangzhou,
|
||||
"f4b6680cac0411ecb2da0242ac110002": api.RegionGuangzhou, // 广州5
|
||||
|
||||
// 广西
|
||||
"cn-nanning-2": api.RegionNanning,
|
||||
"cn-nanning-23": api.RegionNanning,
|
||||
"200000001709": api.RegionNanning, // 南宁24
|
||||
|
||||
// 海南
|
||||
"cn-haikou-2": api.RegionHaikou,
|
||||
|
||||
// 重庆
|
||||
"cn-chongqing-2": api.RegionChongqing,
|
||||
"cn-shanghai-7": api.RegionShanghai,
|
||||
"cn-shanxi-2": api.RegionXian,
|
||||
"cn-guiyang-1": api.RegionGuiyang,
|
||||
"cn-haerbin-2": api.RegionHaerbin,
|
||||
"cn-zhengzhou-2": api.RegionZhengzhou,
|
||||
"cn-xian-4": api.RegionXian,
|
||||
"cn-xian-5": api.RegionXian,
|
||||
|
||||
// 四川
|
||||
"cn-yaan-2": api.RegionChengdu,
|
||||
"ab8a29247cc111ec94230242ac110002": api.RegionChengdu, // 成都5
|
||||
"cn-xinan-01": api.RegionChengdu,
|
||||
"cn-lasa-4": api.RegionChengdu, // 拉萨
|
||||
|
||||
// 贵州
|
||||
"cn-guiyang-1": api.RegionGuiyang,
|
||||
"cn-xinan2-gz-01": api.RegionGuiyang,
|
||||
|
||||
// 云南
|
||||
"cn-kunming-2": api.RegionKunming,
|
||||
|
||||
// 陕西
|
||||
"cn-shanxi-2": api.RegionXian,
|
||||
"cn-xian-4": api.RegionXian,
|
||||
"cn-xian-5": api.RegionXian,
|
||||
"cn-xian-07": api.RegionXian,
|
||||
|
||||
// 甘肃
|
||||
"cn-lanzhou-3": api.RegionLanzhou,
|
||||
"cn-nanjing-2": api.RegionNanjing,
|
||||
"cn-qingyang-02": api.RegionQingYang,
|
||||
"05aa842ab38d11eba6640242ac110002": api.RegionLanzhou, // 兰州3
|
||||
"200000003684": api.RegionQingYang, // 庆阳3
|
||||
|
||||
// 青海
|
||||
"cn-xining-2": api.RegionLanzhou,
|
||||
|
||||
// 宁夏
|
||||
"cn-zhongwei-2": api.RegionNingxia,
|
||||
"cn-zhongwei-05": api.RegionNingxia,
|
||||
"200000003576": api.RegionNingxia, // 中卫6
|
||||
|
||||
// 新疆
|
||||
"cn-wlmq-27": api.RegionWulumuqi,
|
||||
"cn-wulumuqi-07": api.RegionWulumuqi,
|
||||
"2d0cadee70d211ea8c4d0242ac110002": api.RegionWulumuqi, // 乌鲁木齐2
|
||||
|
||||
// 港澳及海外
|
||||
"cn-xianggang-1": api.RegionHongkong,
|
||||
"cn-xianggang-02": api.RegionHongkong,
|
||||
"4681b038013011ea9b210242ac110002": api.RegionHongkong, // 香港5
|
||||
"cn-aomen-01": api.RegionHongkong,
|
||||
"cn-xinjiapo-3": api.RegionSingapore,
|
||||
"cn-xinjiapo-04": api.RegionSingapore,
|
||||
"cn-falankefu-1": api.RegionFrankfurt,
|
||||
"cn-shengbaoluo-1": api.RegionSaoPaulo,
|
||||
"cn-dibai-1": api.RegionDubai,
|
||||
"cn-ydnixiya-01": api.RegionJakarta,
|
||||
"cn-badayan-01": api.RegionManila,
|
||||
}
|
||||
|
||||
80
vendor/yunion.io/x/cloudmux/pkg/multicloud/ecloud/latitud_and_longitude.go
generated
vendored
80
vendor/yunion.io/x/cloudmux/pkg/multicloud/ecloud/latitud_and_longitude.go
generated
vendored
@@ -21,31 +21,57 @@ import (
|
||||
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
// 对齐最新 RegionId(cn- 前缀),与 regionIdToPoolId 保持一致;尽量复用 compute.RegionXXX
|
||||
"cn-beijing-1": api.RegionBeijing,
|
||||
"cn-jiangsu-1": api.RegionSuzhou, // 江苏(无锡附近)复用苏州坐标
|
||||
"cn-guangdong-1": api.RegionGuangzhou, // 广东(东莞附近)复用广州坐标
|
||||
"cn-sichuan-1": api.RegionChengdu, // 四川(雅安/成都附近)复用成都坐标
|
||||
"cn-henan-1": api.RegionZhengzhou, // 河南(郑州)
|
||||
"cn-hunan-1": api.RegionChangsha, // 湖南(株洲/长沙)
|
||||
"cn-shandong-1": api.RegionJiNan, // 山东(济南)
|
||||
"cn-shaanxi-1": api.RegionXian, // 陕西(西安)
|
||||
"cn-shanghai-1": api.RegionShanghai, // 上海
|
||||
"cn-chongqing-1": api.RegionChongqing, // 重庆
|
||||
"cn-zhejiang-1": api.RegionHangzhou, // 浙江(宁波/杭州)
|
||||
"cn-tianjin-1": api.RegionTianjin, // 天津
|
||||
"cn-jilin-1": api.RegionChangchun, // 吉林(长春)
|
||||
"cn-hubei-2": api.RegionXiangyang, // 湖北(襄阳)
|
||||
"cn-jiangxi-1": api.RegionJiangxi, // 江西(南昌)
|
||||
"cn-gansu-1": api.RegionLanzhou, // 甘肃(兰州)
|
||||
"cn-shangxi-1": api.RegionJinzhong, // 山西(太原附近),复用晋中
|
||||
"cn-liaoning-1": api.RegionShenyang, // 辽宁(沈阳)
|
||||
"cn-yunnan-1": api.RegionKunming, // 云南(昆明)
|
||||
"cn-hebei-1": api.RegionShijiazhuang, // 河北(石家庄)
|
||||
"cn-fujian-1": api.RegionFujian, // 福建(厦门附近)
|
||||
"cn-guangxi-1": api.RegionNanning, // 广西(南宁)
|
||||
"cn-anhui-1": api.RegionHuainan, // 安徽(淮南)
|
||||
"cn-neimenggu-1": api.RegionHuhehaote, // 内蒙古(呼和浩特)
|
||||
"cn-guzhou-1": api.RegionGuiyang, // 贵州(贵阳)
|
||||
"cn-hainan-1": api.RegionHaikou, // 海南(海口)
|
||||
"cn-xinjiang-1": api.RegionWulumuqi, // 新疆(乌鲁木齐)
|
||||
"cn-beijing-1": api.RegionBeijing,
|
||||
"cn-beijing-11": api.RegionBeijing, // 华北-北京9
|
||||
"cn-neimenggu-1": api.RegionHuhehaote, // 华北-呼和浩特
|
||||
"cn-hebei-1": api.RegionShijiazhuang, // 河北-石家庄
|
||||
"cn-shanxi-1": api.RegionJinzhong, // 山西-太原
|
||||
"cn-shangxi-1": api.RegionJinzhong, // 山西-太原(历史拼写)
|
||||
"cn-tianjin-1": api.RegionTianjin, // 天津-天津
|
||||
"cn-liaoning-1": api.RegionShenyang, // 辽宁-沈阳
|
||||
"cn-jilin-1": api.RegionChangchun, // 吉林-长春
|
||||
"cn-heilongjiang-1": api.RegionHaerbin, // 黑龙江-哈尔滨
|
||||
"cn-heilongjiang-3": api.RegionHaerbin, // 东北-哈尔滨
|
||||
|
||||
"cn-jiangsu-1": api.RegionSuzhou, // 华东-苏州
|
||||
"cn-jiangsu-20": api.RegionNanjing, // 华东-南京
|
||||
"cn-shanghai-1": api.RegionShanghai, // 华东-上海1
|
||||
"cn-shanghai-5": api.RegionShanghai, // 华东-上海5
|
||||
"cn-zhejiang-1": api.RegionHangzhou, // 华东-杭州
|
||||
"cn-zhejiang-6": api.RegionHangzhou, // 华东-杭州4
|
||||
"cn-shandong-1": api.RegionJiNan, // 华东-济南
|
||||
"cn-shandong-14": api.RegionQingdao, // 华东-青岛
|
||||
"cn-anhui-1": api.RegionHuainan, // 安徽-淮南
|
||||
"cn-fujian-1": api.RegionFujian, // 福建-厦门
|
||||
"cn-jiangxi-1": api.RegionJiangxi, // 江西-南昌
|
||||
|
||||
"cn-guangdong-1": api.RegionGuangzhou, // 华南-广州3
|
||||
"cn-guangxi-1": api.RegionNanning, // 广西-南宁3
|
||||
"cn-guangxi-2": api.RegionNanning, // 广西-南宁
|
||||
"cn-hainan-1": api.RegionHaikou, // 海南-海口
|
||||
|
||||
"cn-henan-1": api.RegionZhengzhou, // 华中-郑州
|
||||
"cn-hubei-1": api.RegionWuhan, // 湖北-武汉
|
||||
"cn-hubei-2": api.RegionXiangyang, // 湖北-襄阳
|
||||
"cn-hunan-1": api.RegionChangsha, // 华中-长沙2
|
||||
|
||||
"cn-sichuan-1": api.RegionChengdu, // 西南-成都
|
||||
"cn-sichuan-7": api.RegionChengdu, // 西南-成都4
|
||||
"cn-chongqing-1": api.RegionChongqing, // 西南-重庆
|
||||
"cn-guizhou-1": api.RegionGuiyang, // 西南-贵阳
|
||||
"cn-guzhou-1": api.RegionGuiyang, // 西南-贵阳(历史拼写)
|
||||
"cn-guizhou-5": api.RegionGuiyang, // 西南-贵阳3
|
||||
"cn-yunnan-1": api.RegionKunming, // 云南-昆明2
|
||||
"cn-xizang-1": api.RegionChengdu, // 西藏-拉萨
|
||||
"cn-xizang-2": api.RegionChengdu, // 西藏-拉萨2
|
||||
|
||||
"cn-shaanxi-1": api.RegionXian, // 西北-西安
|
||||
"cn-gansu-1": api.RegionLanzhou, // 甘肃-兰州
|
||||
"cn-qinghai-1": api.RegionLanzhou, // 青海-海东
|
||||
"cn-qinghai-2": api.RegionLanzhou, // 青海-海东2
|
||||
"cn-qinghai-3": api.RegionLanzhou, // 青海-西宁
|
||||
"cn-ningxia-1": api.RegionNingxia, // 宁夏-中卫
|
||||
"cn-ningxia-2": api.RegionNingxia, // 宁夏-中卫2
|
||||
"cn-ningxia-3": api.RegionNingxia, // 西北-中卫
|
||||
"cn-xinjiang-1": api.RegionWulumuqi, // 新疆-昌吉
|
||||
}
|
||||
|
||||
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/latitude_and_longitude.go
generated
vendored
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/latitude_and_longitude.go
generated
vendored
@@ -29,6 +29,7 @@ var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"asia-south2": api.RegionDelhi,
|
||||
"asia-southeast1": api.RegionSingapore,
|
||||
"asia-southeast2": api.RegionJakarta,
|
||||
"asia-southeast3": api.RegionBangkok,
|
||||
"australia-southeast1": api.RegionSydney,
|
||||
"australia-southeast2": api.RegionMelbourne,
|
||||
|
||||
@@ -77,6 +78,7 @@ var RegionNames = map[string]string{
|
||||
"asia-south2": "德里",
|
||||
"asia-southeast1": "新加坡",
|
||||
"asia-southeast2": "雅加达",
|
||||
"asia-southeast3": "曼谷",
|
||||
"australia-southeast1": "悉尼",
|
||||
"australia-southeast2": "墨尔本",
|
||||
|
||||
|
||||
58
vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/latitud_and_longitude.go
generated
vendored
58
vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/latitud_and_longitude.go
generated
vendored
@@ -23,22 +23,54 @@ import (
|
||||
// International: https://developer-intl.huaweicloud.com/endpoint
|
||||
// ref: https://countrycode.org
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-east-2": api.RegionShanghai,
|
||||
"cn-east-3": api.RegionShanghai,
|
||||
"cn-north-1": api.RegionBeijing,
|
||||
"cn-north-4": api.RegionBeijing,
|
||||
"cn-south-1": api.RegionGuangzhou,
|
||||
"cn-south-2": api.RegionGuangzhou,
|
||||
// 华北
|
||||
"cn-north-1": api.RegionBeijing,
|
||||
"cn-north-4": api.RegionBeijing,
|
||||
"cn-north-9": api.RegionNeimenggu,
|
||||
"cn-north-11": api.RegionWulanchabu,
|
||||
"cn-north-12": api.RegionBeijing,
|
||||
"cn-north-219": api.RegionBeijing,
|
||||
|
||||
// 华东
|
||||
"cn-east-2": api.RegionShanghai,
|
||||
"cn-east-3": api.RegionShanghai,
|
||||
"cn-east-4": api.RegionWuhu,
|
||||
"cn-east-5": api.RegionQingdao,
|
||||
|
||||
// 华南
|
||||
"cn-south-1": api.RegionGuangzhou,
|
||||
"cn-south-2": api.RegionGuangzhou,
|
||||
"cn-south-4": api.RegionGuangzhou,
|
||||
|
||||
// 西南 / 东北 / 西北
|
||||
"cn-southwest-2": api.RegionGuiyang,
|
||||
"cn-northeast-1": api.RegionDalian,
|
||||
"cn-northwest-1": api.RegionNingxia,
|
||||
|
||||
// 亚太
|
||||
"ap-southeast-1": api.RegionHongkong,
|
||||
"ap-southeast-2": api.RegionBangkok,
|
||||
"ap-southeast-3": api.RegionSingapore,
|
||||
"eu-west-0": api.RegionParis,
|
||||
"cn-northeast-1": api.RegionDalian,
|
||||
"cn-southwest-2": api.RegionGuiyang,
|
||||
"af-south-1": api.RegionJohannesburg,
|
||||
"sa-brazil-1": api.RegionSaoPaulo,
|
||||
"ap-southeast-4": api.RegionJakarta,
|
||||
"ap-southeast-5": api.RegionManila,
|
||||
|
||||
// 欧洲
|
||||
"eu-west-0": api.RegionParis,
|
||||
"eu-west-1": api.RegionDublin,
|
||||
|
||||
// 中东 / 土耳其
|
||||
"me-east-1": api.RegionDamman,
|
||||
"tr-west-1": api.RegionIstanbul,
|
||||
|
||||
// 非洲
|
||||
"af-south-1": api.RegionJohannesburg,
|
||||
"af-north-1": api.RegionTelAviv,
|
||||
|
||||
// 拉美
|
||||
"na-mexico-1": api.RegionMexico,
|
||||
"la-north-2": api.RegionMexico,
|
||||
"sa-brazil-1": api.RegionSaoPaulo,
|
||||
"la-south-2": api.RegionSantiago,
|
||||
"cn-north-9": api.RegionNeimenggu,
|
||||
"cn-north-219": api.RegionBeijing,
|
||||
"sa-argentina-1": api.RegionSantiago,
|
||||
"sa-peru-1": api.RegionSantiago,
|
||||
}
|
||||
|
||||
26
vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go
generated
vendored
26
vendor/yunion.io/x/cloudmux/pkg/multicloud/ksyun/region.go
generated
vendored
@@ -52,11 +52,31 @@ func (region *SRegion) GetCloudEnv() string {
|
||||
|
||||
func (region *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
|
||||
geo, ok := map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-northwest-1": api.RegionQingYang,
|
||||
"ap-singapore-1": api.RegionSingapore,
|
||||
// 华北
|
||||
"cn-beijing-6": api.RegionBeijing,
|
||||
"cn-guangzhou-1": api.RegionGuangzhou,
|
||||
"cn-beijing-fin": api.RegionBeijing,
|
||||
"cn-north-vip1": api.RegionBeijing,
|
||||
"cn-hohhot-1": api.RegionHuhehaote,
|
||||
|
||||
// 华东
|
||||
"cn-shanghai-2": api.RegionShanghai,
|
||||
"cn-shanghai-fin": api.RegionShanghai,
|
||||
|
||||
// 华南
|
||||
"cn-guangzhou-1": api.RegionGuangzhou,
|
||||
|
||||
// 华中 / 西南
|
||||
"cn-central-1": api.RegionWuhan,
|
||||
"cn-southwest-1": api.RegionChongqing,
|
||||
|
||||
// 西北
|
||||
"cn-northwest-1": api.RegionQingYang,
|
||||
"cn-northwest-3": api.RegionNingxia,
|
||||
"cn-northwest-4": api.RegionLanzhou,
|
||||
|
||||
// 海外
|
||||
"ap-singapore-1": api.RegionSingapore,
|
||||
"eu-east-1": api.RegionMoscow,
|
||||
}[region.Region]
|
||||
if ok {
|
||||
return geo
|
||||
|
||||
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/loader/loader.go
generated
vendored
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/loader/loader.go
generated
vendored
@@ -44,7 +44,8 @@ import (
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/qcloud/provider"
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/qingcloud/provider"
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/remotefile/provider" // private clouds
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/ucloud/provider" // object storages
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider"
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/ucloud/provider" // object storages
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/volcengine/provider"
|
||||
_ "yunion.io/x/cloudmux/pkg/multicloud/zstack/provider" // private clouds
|
||||
)
|
||||
|
||||
124
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/latitude_and_longitude.go
generated
vendored
Normal file
124
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/latitude_and_longitude.go
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
// 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 oracle
|
||||
|
||||
import (
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// ref: https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm
|
||||
// ref: https://github.com/oracle/oci-go-sdk/blob/v65.110.0/common/regions.go
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
// Asia Pacific
|
||||
"ap-batam-1": api.RegionJakarta,
|
||||
"ap-chiyoda-1": api.RegionTokyo,
|
||||
"ap-chuncheon-1": api.RegionSeoul,
|
||||
"ap-chuncheon-2": api.RegionSeoul,
|
||||
"ap-delhi-1": api.RegionDelhi,
|
||||
"ap-hyderabad-1": api.RegionHyderabad,
|
||||
"ap-ibaraki-1": api.RegionTokyo,
|
||||
"ap-kulai-2": api.RegionKualaLumpur,
|
||||
"ap-melbourne-1": api.RegionMelbourne,
|
||||
"ap-mumbai-1": api.RegionMumbai,
|
||||
"ap-osaka-1": api.RegionOsaka,
|
||||
"ap-seoul-1": api.RegionSeoul,
|
||||
"ap-seoul-2": api.RegionSeoul,
|
||||
"ap-singapore-1": api.RegionSingapore,
|
||||
"ap-singapore-2": api.RegionSingapore,
|
||||
"ap-suwon-1": api.RegionSeoul,
|
||||
"ap-sydney-1": api.RegionSydney,
|
||||
"ap-tokyo-1": api.RegionTokyo,
|
||||
"ap-dcc-canberra-1": api.RegionYarralumla,
|
||||
"ap-dcc-gazipur-1": api.RegionMumbai,
|
||||
|
||||
// Canada
|
||||
"ca-montreal-1": api.RegionMontreal,
|
||||
"ca-toronto-1": api.RegionToronto,
|
||||
|
||||
// Europe
|
||||
"eu-amsterdam-1": api.RegionHolland,
|
||||
"eu-budapest-1": api.RegionWarsaw,
|
||||
"eu-crissier-1": api.RegionGeneva,
|
||||
"eu-frankfurt-1": api.RegionFrankfurt,
|
||||
"eu-frankfurt-2": api.RegionFrankfurt,
|
||||
"eu-jovanovac-1": api.RegionWarsaw,
|
||||
"eu-madrid-1": api.RegionMadrid,
|
||||
"eu-madrid-2": api.RegionMadrid,
|
||||
"eu-madrid-3": api.RegionMadrid,
|
||||
"eu-marseille-1": api.RegionParis,
|
||||
"eu-milan-1": api.RegionMilan,
|
||||
"eu-paris-1": api.RegionParis,
|
||||
"eu-stockholm-1": api.RegionStockholm,
|
||||
"eu-turin-1": api.RegionTurin,
|
||||
"eu-zurich-1": api.RegionZurich,
|
||||
"eu-dcc-dublin-1": api.RegionDublin,
|
||||
"eu-dcc-dublin-2": api.RegionDublin,
|
||||
"eu-dcc-milan-1": api.RegionMilan,
|
||||
"eu-dcc-milan-2": api.RegionMilan,
|
||||
"eu-dcc-rating-1": api.RegionFrankfurt,
|
||||
"eu-dcc-rating-2": api.RegionFrankfurt,
|
||||
"eu-dcc-zurich-1": api.RegionZurich,
|
||||
"uk-cardiff-1": api.RegionLondon,
|
||||
"uk-london-1": api.RegionLondon,
|
||||
"uk-gov-cardiff-1": api.RegionLondon,
|
||||
"uk-gov-london-1": api.RegionLondon,
|
||||
|
||||
// Middle East
|
||||
"me-abudhabi-1": api.RegionAbuDhabi,
|
||||
"me-abudhabi-2": api.RegionAbuDhabi,
|
||||
"me-abudhabi-3": api.RegionAbuDhabi,
|
||||
"me-abudhabi-4": api.RegionAbuDhabi,
|
||||
"me-alain-1": api.RegionAbuDhabi,
|
||||
"me-dcc-doha-1": api.RegionDoha,
|
||||
"me-dcc-muscat-1": api.RegionDubai,
|
||||
"me-dubai-1": api.RegionDubai,
|
||||
"me-ibri-1": api.RegionDubai,
|
||||
"me-jeddah-1": api.RegionDamman,
|
||||
"me-riyadh-1": api.RegionDamman,
|
||||
|
||||
// Africa
|
||||
"af-casablanca-1": api.RegionMadrid,
|
||||
"af-johannesburg-1": api.RegionJohannesburg,
|
||||
|
||||
// Israel
|
||||
"il-jerusalem-1": api.RegionTelAviv,
|
||||
|
||||
// North America
|
||||
"us-ashburn-1": api.RegionNothVirginia,
|
||||
"us-ashburn-2": api.RegionNothVirginia,
|
||||
"us-chicago-1": api.RegionChicago,
|
||||
"us-gov-ashburn-1": api.RegionNothVirginia,
|
||||
"us-gov-chicago-1": api.RegionChicago,
|
||||
"us-gov-phoenix-1": api.RegionPhoenix,
|
||||
"us-langley-1": api.RegionVirginia,
|
||||
"us-luke-1": api.RegionPhoenix,
|
||||
"us-newark-1": api.RegionVirginia,
|
||||
"us-phoenix-1": api.RegionPhoenix,
|
||||
"us-saltlake-2": api.RegionSaltLakeCity,
|
||||
"us-sanjose-1": api.RegionSiliconValley,
|
||||
"us-somerset-1": api.RegionVirginia,
|
||||
"us-thames-1": api.RegionVirginia,
|
||||
"mx-monterrey-1": api.RegionMexico,
|
||||
"mx-queretaro-1": api.RegionMexico,
|
||||
|
||||
// South America
|
||||
"sa-bogota-1": api.RegionSaoPaulo,
|
||||
"sa-riodejaneiro-1": api.RegionRioDeJaneiro,
|
||||
"sa-santiago-1": api.RegionSantiago,
|
||||
"sa-saopaulo-1": api.RegionSaoPaulo,
|
||||
"sa-valparaiso-1": api.RegionSantiago,
|
||||
"sa-vinhedo-1": api.RegionSaoPaulo,
|
||||
}
|
||||
201
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/notice.go
generated
vendored
Normal file
201
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/notice.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// 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 oracle
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SAnnouncementSummary struct {
|
||||
Id string `json:"id"`
|
||||
Summary string `json:"summary"`
|
||||
AnnouncementType string `json:"announcementType"`
|
||||
LifecycleState string `json:"lifecycleState"`
|
||||
Services []string `json:"services"`
|
||||
AffectedRegions []string `json:"affectedRegions"`
|
||||
ReferenceTicket string `json:"referenceTicketNumber"`
|
||||
TimeCreated string `json:"timeCreated"`
|
||||
TimeUpdated string `json:"timeUpdated"`
|
||||
}
|
||||
|
||||
type SAnnouncement struct {
|
||||
SAnnouncementSummary
|
||||
Description string `json:"description"`
|
||||
AdditionalInformation string `json:"additionalInformation"`
|
||||
}
|
||||
|
||||
type SNotice struct {
|
||||
title string
|
||||
content string
|
||||
}
|
||||
|
||||
func (notice *SNotice) GetTitle() string {
|
||||
return notice.title
|
||||
}
|
||||
|
||||
func (notice *SNotice) GetContent() string {
|
||||
return notice.content
|
||||
}
|
||||
|
||||
func (self *SOracleClient) GetNotices() ([]cloudprovider.INotice, error) {
|
||||
region, err := self.Region()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summaries, err := self.listAnnouncements(region)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := make([]cloudprovider.INotice, 0, len(summaries))
|
||||
for i := range summaries {
|
||||
if !isAnnouncementPublishedToday(&summaries[i]) {
|
||||
continue
|
||||
}
|
||||
content := self.announcementContent(region, &summaries[i])
|
||||
ret = append(ret, &SNotice{
|
||||
title: summaries[i].Summary,
|
||||
content: content,
|
||||
})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func isAnnouncementPublishedToday(summary *SAnnouncementSummary) bool {
|
||||
ts := summary.TimeCreated
|
||||
if len(ts) == 0 {
|
||||
ts = summary.TimeUpdated
|
||||
}
|
||||
if len(ts) == 0 {
|
||||
return false
|
||||
}
|
||||
t, err := parseAnnouncementTime(ts)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return cloudprovider.IsNoticePublishedToday(t)
|
||||
}
|
||||
|
||||
func parseAnnouncementTime(ts string) (time.Time, error) {
|
||||
layouts := []string{
|
||||
time.RFC3339Nano,
|
||||
time.RFC3339,
|
||||
"2006-01-02T15:04:05.000+0000",
|
||||
}
|
||||
for _, layout := range layouts {
|
||||
if t, err := time.Parse(layout, ts); err == nil {
|
||||
return t, nil
|
||||
}
|
||||
}
|
||||
return time.Time{}, errors.Errorf("parse announcement time %q", ts)
|
||||
}
|
||||
|
||||
func (self *SOracleClient) listAnnouncements(region string) ([]SAnnouncementSummary, error) {
|
||||
query := url.Values{}
|
||||
query.Set("compartmentId", self.tenancyOCID)
|
||||
query.Set("lifecycleState", "ACTIVE")
|
||||
|
||||
ret := []SAnnouncementSummary{}
|
||||
for {
|
||||
resp, token, err := self.request(httputils.GET, SERVICE_ANNOUNCEMENTS, region, "announcements", query, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items, err := resp.GetArray("items")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetArray items")
|
||||
}
|
||||
part := []SAnnouncementSummary{}
|
||||
err = jsonutils.Update(&part, items)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Unmarshal announcement summaries")
|
||||
}
|
||||
ret = append(ret, part...)
|
||||
if len(token) == 0 {
|
||||
break
|
||||
}
|
||||
query.Set("page", token)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SOracleClient) getAnnouncement(region, id string) (*SAnnouncement, error) {
|
||||
resp, err := self.get(SERVICE_ANNOUNCEMENTS, region, "announcements", id, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ann := &SAnnouncement{}
|
||||
err = resp.Unmarshal(ann)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Unmarshal announcement")
|
||||
}
|
||||
return ann, nil
|
||||
}
|
||||
|
||||
func (self *SOracleClient) announcementContent(region string, summary *SAnnouncementSummary) string {
|
||||
ann, err := self.getAnnouncement(region, summary.Id)
|
||||
if err == nil {
|
||||
return formatAnnouncementContent(ann)
|
||||
}
|
||||
return formatAnnouncementSummaryContent(summary)
|
||||
}
|
||||
|
||||
func formatAnnouncementContent(ann *SAnnouncement) string {
|
||||
parts := []string{}
|
||||
if len(ann.Description) > 0 {
|
||||
parts = append(parts, ann.Description)
|
||||
}
|
||||
if len(ann.AdditionalInformation) > 0 {
|
||||
parts = append(parts, ann.AdditionalInformation)
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
return strings.Join(parts, "\n\n")
|
||||
}
|
||||
return formatAnnouncementSummaryContent(&ann.SAnnouncementSummary)
|
||||
}
|
||||
|
||||
func formatAnnouncementSummaryContent(summary *SAnnouncementSummary) string {
|
||||
lines := []string{}
|
||||
if len(summary.AnnouncementType) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Type: %s", summary.AnnouncementType))
|
||||
}
|
||||
if len(summary.Services) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Services: %s", strings.Join(summary.Services, ", ")))
|
||||
}
|
||||
if len(summary.AffectedRegions) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Affected regions: %s", strings.Join(summary.AffectedRegions, ", ")))
|
||||
}
|
||||
if len(summary.ReferenceTicket) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Reference: %s", summary.ReferenceTicket))
|
||||
}
|
||||
if len(summary.TimeCreated) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Created: %s", summary.TimeCreated))
|
||||
}
|
||||
if len(summary.TimeUpdated) > 0 {
|
||||
lines = append(lines, fmt.Sprintf("Updated: %s", summary.TimeUpdated))
|
||||
}
|
||||
if len(lines) == 0 {
|
||||
return summary.Summary
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
10
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/oracle.go
generated
vendored
10
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/oracle.go
generated
vendored
@@ -48,9 +48,11 @@ const (
|
||||
|
||||
NEXT_TOKEN = "opc-next-page"
|
||||
|
||||
SERVICE_IAAS = "iaas"
|
||||
SERVICE_IDENTITY = "identity"
|
||||
SERVICE_TELEMETRY = "telemetry"
|
||||
SERVICE_IAAS = "iaas"
|
||||
SERVICE_IDENTITY = "identity"
|
||||
SERVICE_TELEMETRY = "telemetry"
|
||||
SERVICE_ANNOUNCEMENTS = "announcements"
|
||||
ANNOUNCEMENTS_API_VERSION = "20180904"
|
||||
)
|
||||
|
||||
type OracleClientConfig struct {
|
||||
@@ -199,6 +201,8 @@ func (self *SOracleClient) getUrl(service, regionId, resource string) (string, e
|
||||
return fmt.Sprintf("https://%s.%s.oraclecloud.com/%s/%s", service, regionId, DEFAULT_API_VERSION, strings.TrimPrefix(resource, "/")), nil
|
||||
case SERVICE_TELEMETRY:
|
||||
return fmt.Sprintf("https://%s.%s.oraclecloud.com/%s/%s", service, regionId, MONITORY_API_VERSION, strings.TrimPrefix(resource, "/")), nil
|
||||
case SERVICE_ANNOUNCEMENTS:
|
||||
return fmt.Sprintf("https://%s.%s.oraclecloud.com/%s/%s", service, regionId, ANNOUNCEMENTS_API_VERSION, strings.TrimPrefix(resource, "/")), nil
|
||||
default:
|
||||
return "", errors.Wrapf(cloudprovider.ErrNotSupported, "%s", service)
|
||||
}
|
||||
|
||||
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/provider/provider.go
generated
vendored
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/provider/provider.go
generated
vendored
@@ -228,3 +228,7 @@ func (self *SOracleProvider) GetCloudRegionExternalIdPrefix() string {
|
||||
func (self *SOracleProvider) GetMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) {
|
||||
return self.client.GetMetrics(opts)
|
||||
}
|
||||
|
||||
func (self *SOracleProvider) GetNotices() ([]cloudprovider.INotice, error) {
|
||||
return self.client.GetNotices()
|
||||
}
|
||||
|
||||
7
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/region.go
generated
vendored
7
vendor/yunion.io/x/cloudmux/pkg/multicloud/oracle/region.go
generated
vendored
@@ -54,11 +54,8 @@ func (region *SRegion) GetCloudEnv() string {
|
||||
}
|
||||
|
||||
func (region *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
|
||||
geo, ok := map[string]cloudprovider.SGeographicInfo{
|
||||
"ap-singapore-1": api.RegionSingapore,
|
||||
}[region.RegionName]
|
||||
if ok {
|
||||
return geo
|
||||
if info, ok := LatitudeAndLongitude[region.RegionName]; ok {
|
||||
return info
|
||||
}
|
||||
return cloudprovider.SGeographicInfo{}
|
||||
}
|
||||
|
||||
87
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/latitud_and_longitude.go
generated
vendored
87
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/latitud_and_longitude.go
generated
vendored
@@ -19,25 +19,72 @@ import (
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// ref: https://cloud.tencent.com/document/product/213/6091
|
||||
// ref: https://cloud.tencent.com/developer/article/1930067
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"ap-bangkok": api.RegionBangkok, // 腾讯云 亚太地区(曼谷)
|
||||
"ap-beijing": api.RegionBeijing, // 腾讯云 华北地区(北京)
|
||||
"ap-chengdu": api.RegionChengdu, // 腾讯云 西南地区(成都)
|
||||
"ap-chongqing": api.RegionChongqing, // 腾讯云 西南地区(重庆)
|
||||
"ap-guangzhou": api.RegionGuangzhou, // 腾讯云 华南地区(广州)
|
||||
"ap-guangzhou-open": api.RegionGuangzhou, // 腾讯云 华南地区(广州Open)
|
||||
"ap-hongkong": api.RegionHongkong, // 腾讯云 东南亚地区(香港)
|
||||
"ap-mumbai": api.RegionMumbai, // 腾讯云 亚太地区(孟买)
|
||||
"ap-seoul": api.RegionSeoul, // 腾讯云 东南亚地区(首尔)
|
||||
"ap-shanghai": api.RegionShanghai, // 腾讯云 华东地区(上海)
|
||||
"ap-shanghai-fsi": api.RegionShanghai, // 腾讯云 华东地区(上海金融)
|
||||
"ap-shenzhen-fsi": api.RegionShenzhen, // 腾讯云 华南地区(深圳金融)
|
||||
"ap-singapore": api.RegionSingapore, // 腾讯云 东南亚地区(新加坡)
|
||||
"ap-tokyo": api.RegionTokyo, // 腾讯云 亚太地区(东京)
|
||||
"eu-frankfurt": api.RegionFrankfurt, // 腾讯云 欧洲地区(德国)
|
||||
"eu-moscow": api.RegionMoscow, // 腾讯云 欧洲地区(莫斯科)
|
||||
"na-ashburn": api.RegionVirginia, // 腾讯云 美国东部(弗吉尼亚)
|
||||
"na-siliconvalley": api.RegionSiliconValley, // 腾讯云 美国西部(硅谷)
|
||||
"na-toronto": api.RegionToronto, // 腾讯云 北美地区(多伦多)
|
||||
"ap-nanjing": api.RegionNanjing,
|
||||
// 华北
|
||||
"ap-beijing": api.RegionBeijing,
|
||||
"ap-beijing-fsi": api.RegionBeijing,
|
||||
"ap-tianjin": api.RegionTianjin,
|
||||
"ap-shijiazhuang-ec": api.RegionShijiazhuang,
|
||||
|
||||
// 华东
|
||||
"ap-shanghai": api.RegionShanghai,
|
||||
"ap-shanghai-fsi": api.RegionShanghai,
|
||||
"ap-shanghai-adc": api.RegionShanghai,
|
||||
"ap-nanjing": api.RegionNanjing,
|
||||
"ap-jinan-ec": api.RegionJiNan,
|
||||
"ap-hangzhou-ec": api.RegionHangzhou,
|
||||
"ap-fuzhou-ec": api.RegionFujian,
|
||||
"ap-hefei-ec": api.RegionHefei,
|
||||
|
||||
// 华南
|
||||
"ap-guangzhou": api.RegionGuangzhou,
|
||||
"ap-guangzhou-open": api.RegionGuangzhou,
|
||||
"ap-qingyuan": api.RegionGuangzhou,
|
||||
"ap-qingyuan-xinan": api.RegionGuangzhou,
|
||||
"ap-shenzhen": api.RegionShenzhen,
|
||||
"ap-shenzhen-fsi": api.RegionShenzhen,
|
||||
"ap-shenzhen-sycft": api.RegionShenzhen,
|
||||
|
||||
// 华中
|
||||
"ap-wuhan-ec": api.RegionWuhan,
|
||||
"ap-changsha-ec": api.RegionChangsha,
|
||||
"ap-zhengzhou-ec": api.RegionZhengzhou,
|
||||
|
||||
// 西南 / 西北
|
||||
"ap-chengdu": api.RegionChengdu,
|
||||
"ap-chongqing": api.RegionChongqing,
|
||||
"ap-zhongwei": api.RegionNingxia,
|
||||
"ap-xian-ec": api.RegionXian,
|
||||
"ap-xibei-ec": api.RegionLanzhou,
|
||||
|
||||
// 东北
|
||||
"ap-shenyang-ec": api.RegionShenyang,
|
||||
|
||||
// 港澳台
|
||||
"ap-hongkong": api.RegionHongkong,
|
||||
"ap-taipei": api.RegionTaiwan,
|
||||
|
||||
// 亚太
|
||||
"ap-singapore": api.RegionSingapore,
|
||||
"ap-jakarta": api.RegionJakarta,
|
||||
"ap-seoul": api.RegionSeoul,
|
||||
"ap-tokyo": api.RegionTokyo,
|
||||
"ap-osaka": api.RegionOsaka,
|
||||
"ap-bangkok": api.RegionBangkok,
|
||||
"ap-mumbai": api.RegionMumbai,
|
||||
|
||||
// 中东
|
||||
"me-saudi-arabia": api.RegionDamman,
|
||||
|
||||
// 欧洲
|
||||
"eu-frankfurt": api.RegionFrankfurt,
|
||||
"eu-moscow": api.RegionMoscow,
|
||||
|
||||
// 北美 / 南美
|
||||
"na-ashburn": api.RegionVirginia,
|
||||
"na-siliconvalley": api.RegionSiliconValley,
|
||||
"na-toronto": api.RegionToronto,
|
||||
"sa-saopaulo": api.RegionSaoPaulo,
|
||||
}
|
||||
|
||||
180
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/client.go
generated
vendored
Normal file
180
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/client.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
const ROCKBASE_API_HOST = "https://api.rockbasecloud.com"
|
||||
|
||||
type SParams struct {
|
||||
data jsonutils.JSONDict
|
||||
}
|
||||
|
||||
type SRockbaseError struct {
|
||||
Action string `json:"Action"`
|
||||
Message string `json:"Message"`
|
||||
RetCode int64 `json:"RetCode"`
|
||||
}
|
||||
|
||||
func (self *SRockbaseError) Error() string {
|
||||
return fmt.Sprintf("Do %s failed, code: %d, %s", self.Action, self.RetCode, self.Message)
|
||||
}
|
||||
|
||||
func NewRockbaseParams() SParams {
|
||||
data := jsonutils.NewDict()
|
||||
return SParams{data: *data}
|
||||
}
|
||||
|
||||
func (self *SParams) Set(key string, value interface{}) {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
self.data.Set(key, jsonutils.NewString(v))
|
||||
case int64:
|
||||
self.data.Set(key, jsonutils.NewInt(v))
|
||||
case int:
|
||||
self.data.Set(key, jsonutils.NewInt(int64(v)))
|
||||
case bool:
|
||||
self.data.Set(key, jsonutils.NewBool(v))
|
||||
case float64:
|
||||
self.data.Set(key, jsonutils.NewFloat64(v))
|
||||
case float32:
|
||||
self.data.Set(key, jsonutils.NewFloat32(v))
|
||||
case []string:
|
||||
self.data.Set(key, jsonutils.NewStringArray(v))
|
||||
default:
|
||||
log.Debugf("unsuported params type %T", value)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SParams) SetAction(action string) {
|
||||
self.data.Set("Action", jsonutils.NewString(action))
|
||||
}
|
||||
|
||||
func (self *SParams) SetPagination(limit, offset int) {
|
||||
if limit == 0 {
|
||||
limit = 20
|
||||
}
|
||||
|
||||
self.data.Set("Limit", jsonutils.NewInt(int64(limit)))
|
||||
self.data.Set("Offset", jsonutils.NewInt(int64(offset)))
|
||||
}
|
||||
|
||||
func (self *SParams) String() string {
|
||||
return self.data.String()
|
||||
}
|
||||
|
||||
func (self *SParams) PrettyString() string {
|
||||
return self.data.PrettyString()
|
||||
}
|
||||
|
||||
func (self *SParams) GetParams() jsonutils.JSONDict {
|
||||
return self.data
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/summary/signature
|
||||
func BuildParams(params SParams, privateKey string) jsonutils.JSONObject {
|
||||
data := params.GetParams()
|
||||
// remove old Signature
|
||||
data.Remove("Signature")
|
||||
|
||||
// 排序并计算signture
|
||||
keys := data.SortedKeys()
|
||||
lst := []string{}
|
||||
for _, k := range keys {
|
||||
lst = append(lst, k)
|
||||
v, _ := data.GetString(k)
|
||||
lst = append(lst, v)
|
||||
}
|
||||
|
||||
raw := strings.Join(lst, "") + privateKey
|
||||
signture := fmt.Sprintf("%x", sha1.Sum([]byte(raw)))
|
||||
|
||||
data.Set("Signature", jsonutils.NewString(signture))
|
||||
return &data
|
||||
}
|
||||
|
||||
func GetSignature(params SParams, privateKey string) string {
|
||||
sign, _ := BuildParams(params, privateKey).GetString("Signature")
|
||||
return sign
|
||||
}
|
||||
|
||||
func parseUcloudResponse(params SParams, resp jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
err := &SRockbaseError{}
|
||||
e := resp.Unmarshal(err)
|
||||
if e != nil {
|
||||
return nil, e
|
||||
}
|
||||
|
||||
err.Action, _ = params.data.GetString("Action")
|
||||
|
||||
if err.RetCode > 0 {
|
||||
if err.RetCode == 171 {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrInvalidAccessKey, "%s", err.Error())
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func jsonRequest(client *SRockbaseClient, params SParams) (jsonutils.JSONObject, error) {
|
||||
ctx := context.Background()
|
||||
MAX_RETRY := 3
|
||||
retry := 0
|
||||
var err error
|
||||
var resp jsonutils.JSONObject
|
||||
for retry < MAX_RETRY {
|
||||
_, resp, err = httputils.JSONRequest(
|
||||
client.httpClient,
|
||||
ctx,
|
||||
httputils.POST,
|
||||
ROCKBASE_API_HOST,
|
||||
nil,
|
||||
BuildParams(params, client.accessKeySecret),
|
||||
client.debug)
|
||||
|
||||
if err == nil {
|
||||
return parseUcloudResponse(params, resp)
|
||||
}
|
||||
|
||||
switch e := err.(type) {
|
||||
case *httputils.JSONClientError:
|
||||
if e.Code >= 499 && !strings.Contains(err.Error(), cloudprovider.ErrAccountReadOnly.Error()) {
|
||||
time.Sleep(3 * time.Second)
|
||||
retry += 1
|
||||
continue
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return resp, err
|
||||
}
|
||||
130
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/consts.go
generated
vendored
Normal file
130
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/consts.go
generated
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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 rockbase
|
||||
|
||||
// https://docs.ucloud.cn/api/summary/regionlist
|
||||
var ROCKBASE_REGION_NAMES = map[string]string{
|
||||
"cn-bj1": "北京一",
|
||||
"cn-bj2": "北京二",
|
||||
"cn-sh": "上海金融云",
|
||||
"cn-sh2": "上海二",
|
||||
"cn-gd": "广州",
|
||||
"hk": "香港",
|
||||
"us-ca": "洛杉矶",
|
||||
"us-ws": "华盛顿",
|
||||
"ge-fra": "法兰克福",
|
||||
"th-bkk": "曼谷",
|
||||
"kr-seoul": "首尔",
|
||||
"sg": "新加坡",
|
||||
"tw-tp": "台北",
|
||||
"tw-kh": "高雄",
|
||||
"jpn-tky": "东京",
|
||||
"rus-mosc": "莫斯科",
|
||||
"uae-dubai": "迪拜",
|
||||
"idn-jakarta": "雅加达",
|
||||
"ind-mumbai": "孟买",
|
||||
"bra-saopaulo": "圣保罗",
|
||||
"uk-london": "伦敦",
|
||||
"afr-nigeria": "拉各斯",
|
||||
"vn-sng": "胡志明市",
|
||||
}
|
||||
|
||||
var ROCKBASE_REGION_NAMES_EN = map[string]string{
|
||||
"cn-bj1": "Beijing 1",
|
||||
"cn-bj2": "Beijing 2",
|
||||
"cn-sh": "Shanghai 1",
|
||||
"cn-sh2": "Shanghai 2",
|
||||
"cn-gd": "Guangzhou",
|
||||
"hk": "Hongkong",
|
||||
"us-ca": "Los Angeles",
|
||||
"us-ws": "Washington",
|
||||
"ge-fra": "Frankfurt",
|
||||
"th-bkk": "Bangkok",
|
||||
"kr-seoul": "Seoul",
|
||||
"sg": "Singapore",
|
||||
"tw-tp": "TaiPei",
|
||||
"tw-kh": "Gaoxiong",
|
||||
"jpn-tky": "Tokyo",
|
||||
"rus-mosc": "Moscow",
|
||||
"uae-dubai": "Dubai",
|
||||
"idn-jakarta": "Jakarta",
|
||||
"ind-mumbai": "Mumbai",
|
||||
"bra-saopaulo": "Sao Paulo",
|
||||
"uk-london": "London",
|
||||
"afr-nigeria": "Lagos",
|
||||
"vn-sng": "Ho Chi Min City",
|
||||
}
|
||||
|
||||
var ROCKBASE_ZONE_NAMES = map[string]string{
|
||||
"cn-bj1-01": "北京一可用区A",
|
||||
"cn-bj2-02": "北京二可用区B",
|
||||
"cn-bj2-03": "北京二可用区C",
|
||||
"cn-bj2-04": "北京二可用区D",
|
||||
"cn-bj2-05": "北京二可用区E",
|
||||
"cn-sh-01": "上海一可用区A",
|
||||
"cn-sh2-01": "上海二可用区A",
|
||||
"cn-sh2-02": "上海二可用区B",
|
||||
"cn-gd-02": "广州可用区B",
|
||||
"hk-01": "香港可用区A",
|
||||
"hk-02": "香港可用区B",
|
||||
"us-ca-01": "洛杉矶可用区A",
|
||||
"us-ws-01": "华盛顿可用区A",
|
||||
"ge-fra-01": "法兰克福可用区A",
|
||||
"th-bkk-01": "曼谷可用区A",
|
||||
"kr-seoul-01": "首尔可用区A",
|
||||
"sg-01": "新加坡可用区A",
|
||||
"tw-kh-01": "高雄可用区A",
|
||||
"tw-tp-01": "台北可用区A",
|
||||
"jpn-tky-01": "东京可用区A",
|
||||
"rus-mosc-01": "莫斯科可用区A",
|
||||
"uae-dubai-01": "迪拜可用区A",
|
||||
"idn-jakarta-01": "雅加达可用区A",
|
||||
"ind-mumbai-01": "孟买可用区A",
|
||||
"bra-saopaulo-01": "圣保罗可用区A",
|
||||
"uk-london-01": "伦敦可用区A",
|
||||
"afr-nigeria-01": "拉各斯可用区A",
|
||||
"vn-sng-01": "胡志明市可用区A",
|
||||
}
|
||||
|
||||
var ROCKBASE_ZONE_NAMES_EN = map[string]string{
|
||||
"cn-bj1-01": "Beijing 1 Zone A",
|
||||
"cn-bj2-02": "Beijing 2 Zone B",
|
||||
"cn-bj2-03": "Beijing 2 Zone C",
|
||||
"cn-bj2-04": "Beijing 2 Zone D",
|
||||
"cn-bj2-05": "Beijing 2 Zone E",
|
||||
"cn-sh-01": "Shanghai 1 Zone A",
|
||||
"cn-sh2-01": "Shanghai 2 Zone A",
|
||||
"cn-sh2-02": "Shanghai 2 Zone B",
|
||||
"cn-gd-02": "Guangzhou Zone B",
|
||||
"hk-01": "Hongkong Zone A",
|
||||
"hk-02": "Hongkong Zone B",
|
||||
"us-ca-01": "Los Angeles Zone A",
|
||||
"us-ws-01": "Washington Zone A",
|
||||
"ge-fra-01": "Frankfurt Zone A",
|
||||
"th-bkk-01": "Bangkok Zone A",
|
||||
"kr-seoul-01": "Seoul Zone A",
|
||||
"sg-01": "Singapore Zone A",
|
||||
"tw-kh-01": "Gaoxiong Zone A",
|
||||
"tw-tp-01": "TaiPei Zone A",
|
||||
"jpn-tky-01": "Tokyo Zone A",
|
||||
"rus-mosc-01": "Moscow Zone A",
|
||||
"uae-dubai-01": "Dubai Zone A",
|
||||
"idn-jakarta-01": "Jakarta Zone A",
|
||||
"ind-mumbai-01": "Mumbai Zone A",
|
||||
"bra-saopaulo-01": "Sao Paulo Zone A",
|
||||
"uk-london-01": "London Zone A",
|
||||
"afr-nigeria-01": "Lagos Zone A",
|
||||
"vn-sng-01": "Ho Chi Min City Zone A",
|
||||
}
|
||||
456
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/disk.go
generated
vendored
Normal file
456
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/disk.go
generated
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/describe_udisk
|
||||
type SDisk struct {
|
||||
storage *SStorage
|
||||
multicloud.SDisk
|
||||
RockbaseTags
|
||||
|
||||
Status string `json:"Status"`
|
||||
DeviceName string `json:"DeviceName"`
|
||||
UHostID string `json:"UHostId"`
|
||||
Tag string `json:"Tag"`
|
||||
Version string `json:"Version"`
|
||||
Name string `json:"Name"`
|
||||
Zone string `json:"Zone"`
|
||||
UHostIP string `json:"UHostIP"`
|
||||
DiskType string `json:"DiskType"`
|
||||
UDataArkMode string `json:"UDataArkMode"`
|
||||
SnapshotLimit int `json:"SnapshotLimit"`
|
||||
ExpiredTime int64 `json:"ExpiredTime"`
|
||||
SnapshotCount int `json:"SnapshotCount"`
|
||||
IsExpire string `json:"IsExpire"`
|
||||
UDiskID string `json:"UDiskId"`
|
||||
ChargeType string `json:"ChargeType"`
|
||||
UHostName string `json:"UHostName"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
SizeGB int `json:"Size"`
|
||||
}
|
||||
|
||||
func (self *SDisk) GetProjectId() string {
|
||||
return self.storage.zone.region.client.projectId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetId() string {
|
||||
return self.UDiskID
|
||||
}
|
||||
|
||||
func (self *SDisk) GetName() string {
|
||||
if len(self.Name) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SDisk) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SDisk) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "Available":
|
||||
return api.DISK_READY
|
||||
case "Attaching":
|
||||
return api.DISK_ATTACHING
|
||||
case "InUse":
|
||||
return api.DISK_READY
|
||||
case "Detaching":
|
||||
return api.DISK_DETACHING
|
||||
case "Initializating":
|
||||
return api.DISK_ALLOCATING
|
||||
case "Failed":
|
||||
return api.DISK_ALLOC_FAILED
|
||||
case "Cloning":
|
||||
return api.DISK_CLONING
|
||||
case "Restoring":
|
||||
return api.DISK_RESET
|
||||
case "RestoreFailed":
|
||||
return api.DISK_RESET_FAILED
|
||||
default:
|
||||
return api.DISK_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDisk) Refresh() error {
|
||||
new, err := self.storage.zone.region.GetDisk(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SDisk) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetSysTags() map[string]string {
|
||||
data := map[string]string{}
|
||||
data["hypervisor"] = api.HYPERVISOR_ROCKBASE
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// Year,Month,Dynamic,Trial
|
||||
func (self *SDisk) GetBillingType() string {
|
||||
switch self.ChargeType {
|
||||
case "Year", "Month":
|
||||
return billing_api.BILLING_TYPE_PREPAID
|
||||
default:
|
||||
return billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SDisk) GetCreatedAt() time.Time {
|
||||
return time.Unix(self.CreateTime, 0)
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExpiredAt() time.Time {
|
||||
return time.Unix(self.ExpiredTime, 0)
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
|
||||
return self.storage, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskFormat() string {
|
||||
return "vhd"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskSizeMB() int {
|
||||
return self.SizeGB * 1024
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsAutoDelete() bool {
|
||||
if self.DiskType == "SystemDisk" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetTemplateId() string {
|
||||
if strings.Contains(self.DiskType, "SystemDisk") && len(self.UHostID) > 0 {
|
||||
ins, err := self.storage.zone.region.GetInstanceByID(self.UHostID)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
return ins.ImageID
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskType() string {
|
||||
if strings.Contains(self.DiskType, "SystemDisk") {
|
||||
return api.DISK_TYPE_SYS
|
||||
}
|
||||
|
||||
return api.DISK_TYPE_DATA
|
||||
}
|
||||
|
||||
func (self *SDisk) GetStorageType() string {
|
||||
if self.storage == nil {
|
||||
if strings.Contains(self.DiskType, "SSD") {
|
||||
return api.STORAGE_ROCKBASE_CLOUD_SSD
|
||||
} else {
|
||||
return api.STORAGE_ROCKBASE_CLOUD_NORMAL
|
||||
}
|
||||
}
|
||||
|
||||
return self.storage.storageType
|
||||
}
|
||||
|
||||
func (self *SDisk) GetFsFormat() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsNonPersistent() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDriver() string {
|
||||
return "scsi"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetCacheMode() string {
|
||||
return "none"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetMountpoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetAccessPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) Delete(ctx context.Context) error {
|
||||
return self.storage.zone.region.DeleteDisk(self.Zone, self.GetId())
|
||||
}
|
||||
|
||||
func (self *SDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
snapshot, err := self.storage.zone.region.CreateSnapshot(self.Zone, self.GetId(), name, desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isnapshot, err := self.GetISnapshot(snapshot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatus(isnapshot, api.SNAPSHOT_READY, time.Second*10, time.Second*300)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "CreateISnapshot")
|
||||
}
|
||||
|
||||
return isnapshot, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) getSnapshot(snapshotId string) (*SSnapshot, error) {
|
||||
snapshot, err := self.storage.zone.region.GetSnapshotById(self.Zone, snapshotId)
|
||||
return &snapshot, err
|
||||
}
|
||||
|
||||
func (self *SDisk) GetISnapshot(idStr string) (cloudprovider.ICloudSnapshot, error) {
|
||||
snapshot, err := self.getSnapshot(idStr)
|
||||
return snapshot, err
|
||||
}
|
||||
|
||||
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
snapshots, err := self.storage.zone.region.GetSnapshots("", self.GetId(), "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isnapshots := make([]cloudprovider.ICloudSnapshot, len(snapshots))
|
||||
for i := 0; i < len(snapshots); i++ {
|
||||
isnapshots[i] = &snapshots[i]
|
||||
}
|
||||
return isnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) Resize(ctx context.Context, newSizeMB int64) error {
|
||||
var sizeGB int64
|
||||
// 向上取整
|
||||
if (newSizeMB % 1024) > 0 {
|
||||
sizeGB = newSizeMB/1024 + 1
|
||||
} else {
|
||||
sizeGB = newSizeMB / 1024
|
||||
}
|
||||
|
||||
if self.Status == "InUse" {
|
||||
err := self.storage.zone.region.DetachDisk(self.Zone, self.UHostID, self.UDiskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer self.storage.zone.region.AttachDisk(self.Zone, self.UHostID, self.UDiskID)
|
||||
err = cloudprovider.WaitStatusWithDelay(self, api.DISK_READY, 10*time.Second, 5*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "DiskResize")
|
||||
}
|
||||
|
||||
}
|
||||
return self.storage.zone.region.resizeDisk(self.Zone, self.GetId(), sizeGB)
|
||||
}
|
||||
|
||||
func (self *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
|
||||
err := self.storage.zone.region.resetDisk(self.Zone, self.GetId(), snapshotId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return self.GetId(), nil
|
||||
}
|
||||
|
||||
func (self *SDisk) Rebuild(ctx context.Context) error {
|
||||
return self.storage.zone.region.resetDisk(self.Zone, self.GetId(), "")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetDisk(diskId string) (*SDisk, error) {
|
||||
if len(diskId) == 0 {
|
||||
return nil, fmt.Errorf("GetDisk id should not empty")
|
||||
}
|
||||
|
||||
disks, err := self.GetDisks("", "", []string{diskId})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(disks) == 1 {
|
||||
return &disks[0], nil
|
||||
} else if len(disks) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return nil, fmt.Errorf("GetDisk %s %d found", diskId, len(disks))
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/describe_udisk
|
||||
// diskType DataDisk|SystemDisk (DataDisk表示数据盘,SystemDisk表示系统盘)
|
||||
func (self *SRegion) GetDisks(zoneId string, diskType string, diskIds []string) ([]SDisk, error) {
|
||||
disks := make([]SDisk, 0)
|
||||
params := NewRockbaseParams()
|
||||
if len(zoneId) > 0 {
|
||||
params.Set("Zone", zoneId)
|
||||
}
|
||||
|
||||
if len(diskType) > 0 {
|
||||
params.Set("DiskType", diskType)
|
||||
}
|
||||
|
||||
err := self.DoListAll("DescribeUDisk", params, &disks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(diskIds) > 0 {
|
||||
filtedDisks := make([]SDisk, 0)
|
||||
for i := range disks {
|
||||
if utils.IsInStringArray(disks[i].UDiskID, diskIds) {
|
||||
filtedDisks = append(filtedDisks, disks[i])
|
||||
}
|
||||
}
|
||||
|
||||
return filtedDisks, nil
|
||||
}
|
||||
|
||||
return disks, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/delete_udisk
|
||||
func (self *SRegion) DeleteDisk(zoneId string, diskId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("UDiskId", diskId)
|
||||
|
||||
return self.DoAction("DeleteUDisk", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/create_udisk
|
||||
func (self *SRegion) CreateDisk(zoneId string, category string, opts *cloudprovider.DiskCreateConfig) (string, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("Size", opts.SizeGb)
|
||||
params.Set("Name", opts.Name)
|
||||
params.Set("DiskType", category)
|
||||
|
||||
diskIds := make([]string, 0)
|
||||
err := self.DoAction("CreateUDisk", params, &diskIds)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(diskIds) == 0 {
|
||||
return "", fmt.Errorf("CreateDisk with empty response")
|
||||
}
|
||||
|
||||
return diskIds[0], nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/create_udisk_snapshot
|
||||
func (self *SRegion) CreateSnapshot(zoneId, diskId, name, desc string) (string, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("UDiskId", diskId)
|
||||
params.Set("Name", name)
|
||||
params.Set("Comment", desc)
|
||||
|
||||
snapshotIds := make([]string, 0)
|
||||
err := self.DoAction("CreateUDiskSnapshot", params, &snapshotIds)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(snapshotIds) == 0 {
|
||||
return "", fmt.Errorf("CreateSnapshot with empty response")
|
||||
}
|
||||
|
||||
return snapshotIds[0], nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/resize_udisk
|
||||
func (self *SRegion) resizeDisk(zoneId string, diskId string, sizeGB int64) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("Size", sizeGB)
|
||||
params.Set("UDiskId", diskId)
|
||||
|
||||
return self.DoAction("ResizeUDisk", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/restore_u_disk
|
||||
func (self *SRegion) resetDisk(zoneId, diskId, snapshotId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("UDiskId", diskId)
|
||||
if len(snapshotId) > 0 {
|
||||
params.Set("SnapshotId", snapshotId)
|
||||
}
|
||||
|
||||
return self.DoAction("RestoreUDisk", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/attach_udisk
|
||||
func (self *SRegion) AttachDisk(zoneId string, instanceId string, diskId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("UDiskId", diskId)
|
||||
|
||||
return self.DoAction("AttachUDisk", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/detach_udisk
|
||||
func (self *SRegion) DetachDisk(zoneId string, instanceId string, diskId string) error {
|
||||
idisks, err := self.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if idisks.Status == "Available" {
|
||||
return nil
|
||||
}
|
||||
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("UDiskId", diskId)
|
||||
|
||||
return self.DoAction("DetachUDisk", params, nil)
|
||||
}
|
||||
15
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/doc.go
generated
vendored
Normal file
15
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/doc.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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 rockbase // import "yunion.io/x/cloudmux/pkg/multicloud/rockbase"
|
||||
289
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/eip.go
generated
vendored
Normal file
289
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/eip.go
generated
vendored
Normal file
@@ -0,0 +1,289 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
|
||||
billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
const (
|
||||
EIP_CHARGE_TYPE_BY_TRAFFIC = "traffic"
|
||||
EIP_CHARGE_TYPE_BY_BANDWIDTH = "bandwidth"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/describe_eip
|
||||
type SEip struct {
|
||||
region *SRegion
|
||||
multicloud.SEipBase
|
||||
RockbaseTags
|
||||
|
||||
BandwidthMb int `json:"Bandwidth"`
|
||||
BandwidthType int `json:"BandwidthType"`
|
||||
ChargeType string `json:"ChargeType"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
EIPAddr []EIPAddr `json:"EIPAddr"`
|
||||
EIPID string `json:"EIPId"`
|
||||
Expire bool `json:"Expire"`
|
||||
ExpireTime int64 `json:"ExpireTime"`
|
||||
Name string `json:"Name"`
|
||||
PayMode string `json:"PayMode"`
|
||||
Remark string `json:"Remark"`
|
||||
Resource Resource `json:"Resource"`
|
||||
ShareBandwidthSet ShareBandwidthSet `json:"ShareBandwidthSet"`
|
||||
Status string `json:"Status"`
|
||||
Tag string `json:"Tag"`
|
||||
Weight int `json:"Weight"`
|
||||
}
|
||||
|
||||
func (self *SEip) GetProjectId() string {
|
||||
return self.region.client.projectId
|
||||
}
|
||||
|
||||
type EIPAddr struct {
|
||||
IP string `json:"IP"`
|
||||
OperatorName string `json:"OperatorName"`
|
||||
}
|
||||
|
||||
type Resource struct {
|
||||
ResourceID string `json:"ResourceID"`
|
||||
ResourceName string `json:"ResourceName"`
|
||||
ResourceType string `json:"ResourceType"`
|
||||
Zone string `json:"Zone"`
|
||||
}
|
||||
|
||||
type ShareBandwidthSet struct {
|
||||
ShareBandwidth int `json:"ShareBandwidth"`
|
||||
ShareBandwidthID string `json:"ShareBandwidthId"`
|
||||
ShareBandwidthName string `json:"ShareBandwidthName"`
|
||||
}
|
||||
|
||||
func (self *SEip) GetId() string {
|
||||
return self.EIPID
|
||||
}
|
||||
|
||||
func (self *SEip) GetName() string {
|
||||
if len(self.Name) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SEip) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
// 弹性IP的资源绑定状态, 枚举值为: used: 已绑定, free: 未绑定, freeze: 已冻结
|
||||
func (self *SEip) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "used":
|
||||
return api.EIP_STATUS_ASSOCIATE // ?
|
||||
case "free":
|
||||
return api.EIP_STATUS_READY
|
||||
case "freeze":
|
||||
return api.EIP_STATUS_UNKNOWN
|
||||
default:
|
||||
return api.EIP_STATUS_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEip) Refresh() error {
|
||||
if self.IsEmulated() {
|
||||
return nil
|
||||
}
|
||||
new, err := self.region.GetEipById(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SEip) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// 付费方式, 枚举值为: Year, 按年付费; Month, 按月付费; Dynamic, 按小时付费; Trial, 试用. 按小时付费和试用这两种付费模式需要开通权限.
|
||||
func (self *SEip) GetBillingType() string {
|
||||
switch self.ChargeType {
|
||||
case "Year", "Month":
|
||||
return billing_api.BILLING_TYPE_PREPAID
|
||||
default:
|
||||
return billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEip) GetCreatedAt() time.Time {
|
||||
return time.Unix(self.CreateTime, 0)
|
||||
}
|
||||
|
||||
func (self *SEip) GetExpiredAt() time.Time {
|
||||
return time.Unix(self.ExpireTime, 0)
|
||||
}
|
||||
|
||||
func (self *SEip) GetIpAddr() string {
|
||||
if len(self.EIPAddr) > 1 {
|
||||
log.Warningf("GetIpAddr %d eip addr found", len(self.EIPAddr))
|
||||
} else if len(self.EIPAddr) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return self.EIPAddr[0].IP
|
||||
}
|
||||
|
||||
func (self *SEip) GetMode() string {
|
||||
return api.EIP_MODE_STANDALONE_EIP
|
||||
}
|
||||
|
||||
func (self *SEip) GetAssociationType() string {
|
||||
switch self.Resource.ResourceType {
|
||||
case "uhost":
|
||||
return api.EIP_ASSOCIATE_TYPE_SERVER
|
||||
case "natgw":
|
||||
return api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
|
||||
case "ulb":
|
||||
return api.EIP_ASSOCIATE_TYPE_LOADBALANCER
|
||||
default:
|
||||
return self.Resource.ResourceType
|
||||
}
|
||||
}
|
||||
|
||||
// 已绑定的资源类型, 枚举值为: uhost, 云主机;natgw:NAT网关;ulb:负载均衡器;upm: 物理机; hadoophost: 大数据集群;fortresshost:堡垒机;udockhost:容器;udhost:私有专区主机;vpngw:IPSec VPN;ucdr:云灾备;dbaudit:数据库审计。
|
||||
func (self *SEip) GetAssociationExternalId() string {
|
||||
return self.Resource.ResourceID
|
||||
}
|
||||
|
||||
func (self *SEip) GetBandwidth() int {
|
||||
return self.BandwidthMb
|
||||
}
|
||||
|
||||
func (self *SEip) GetINetworkId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// 弹性IP的计费模式, 枚举值为: "Bandwidth", 带宽计费; "Traffic", 流量计费; "ShareBandwidth",共享带宽模式. 默认为 "Bandwidth".
|
||||
func (self *SEip) GetInternetChargeType() string {
|
||||
switch self.PayMode {
|
||||
case "Bandwidth":
|
||||
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
|
||||
case "Traffic":
|
||||
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
|
||||
default:
|
||||
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SEip) Delete() error {
|
||||
return self.region.DeallocateEIP(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SEip) Associate(conf *cloudprovider.AssociateConfig) error {
|
||||
return self.region.AssociateEip(self.GetId(), conf.InstanceId)
|
||||
}
|
||||
|
||||
func (self *SEip) Dissociate() error {
|
||||
return self.region.DissociateEip(self.GetId(), self.Resource.ResourceID)
|
||||
}
|
||||
|
||||
func (self *SEip) ChangeBandwidth(bw int) error {
|
||||
return self.region.UpdateEipBandwidth(self.GetId(), bw)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/allocate_eip
|
||||
// 增加共享带宽模式ShareBandwidth
|
||||
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
|
||||
if len(eip.BGPType) == 0 {
|
||||
if strings.HasPrefix(self.GetId(), "cn-") {
|
||||
eip.BGPType = "Bgp"
|
||||
} else {
|
||||
eip.BGPType = "International"
|
||||
}
|
||||
}
|
||||
|
||||
params := NewRockbaseParams()
|
||||
params.Set("OperatorName", eip.BGPType)
|
||||
params.Set("Bandwidth", eip.BandwidthMbps)
|
||||
params.Set("Name", eip.Name)
|
||||
var payMode string
|
||||
switch eip.ChargeType {
|
||||
case api.EIP_CHARGE_TYPE_BY_TRAFFIC:
|
||||
payMode = "Traffic"
|
||||
case api.EIP_CHARGE_TYPE_BY_BANDWIDTH:
|
||||
payMode = "Bandwidth"
|
||||
}
|
||||
params.Set("PayMode", payMode)
|
||||
params.Set("ChargeType", "Dynamic") // 按需付费
|
||||
|
||||
eips := make([]SEip, 0)
|
||||
err := self.DoAction("AllocateEIP", params, &eips)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(eips) == 1 {
|
||||
eip := eips[0]
|
||||
eip.region = self
|
||||
eip.Refresh()
|
||||
return &eip, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("CreateEIP %d eip created", len(eips))
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/release_eip
|
||||
func (self *SRegion) DeallocateEIP(eipId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("EIPId", eipId)
|
||||
|
||||
return self.DoAction("ReleaseEIP", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/bind_eip
|
||||
func (self *SRegion) AssociateEip(eipId string, instanceId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("EIPId", eipId)
|
||||
params.Set("ResourceType", "uhost")
|
||||
params.Set("ResourceId", instanceId)
|
||||
|
||||
return self.DoAction("BindEIP", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/unbind_eip
|
||||
func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("EIPId", eipId)
|
||||
params.Set("ResourceType", "uhost")
|
||||
params.Set("ResourceId", instanceId)
|
||||
|
||||
return self.DoAction("UnBindEIP", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/modify_eip_bandwidth
|
||||
func (self *SRegion) UpdateEipBandwidth(eipId string, bw int) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("EIPId", eipId)
|
||||
params.Set("Bandwidth", bw)
|
||||
|
||||
return self.DoAction("ModifyEIPBandwidth", params, nil)
|
||||
}
|
||||
358
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/host.go
generated
vendored
Normal file
358
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/host.go
generated
vendored
Normal file
@@ -0,0 +1,358 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
multicloud.SHostBase
|
||||
zone *SZone
|
||||
|
||||
projectId string
|
||||
}
|
||||
|
||||
func (self *SHost) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SHost) GetName() string {
|
||||
return fmt.Sprintf("%s-%s", self.zone.region.client.cpcfg.Name, self.zone.GetId())
|
||||
}
|
||||
|
||||
func (self *SHost) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SHost) GetStatus() string {
|
||||
return api.HOST_STATUS_RUNNING
|
||||
}
|
||||
|
||||
func (self *SHost) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SHost) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
vms, err := self.zone.GetInstances()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ivms := make([]cloudprovider.ICloudVM, len(vms))
|
||||
for i := 0; i < len(vms); i += 1 {
|
||||
vms[i].host = self
|
||||
ivms[i] = &vms[i]
|
||||
}
|
||||
|
||||
return ivms, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
|
||||
vm, err := self.zone.region.GetInstanceByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm.host = self
|
||||
return &vm, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorages()
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorageById(id)
|
||||
}
|
||||
|
||||
func (self *SHost) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostStatus() string {
|
||||
return api.HOST_ONLINE
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessIp() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessMac() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
|
||||
info := jsonutils.NewDict()
|
||||
info.Add(jsonutils.NewString(CLOUD_PROVIDER_ROCKBASE), "manufacture")
|
||||
return info
|
||||
}
|
||||
|
||||
func (self *SHost) GetSN() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuCount() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetNodeCount() int8 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuDesc() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuMhz() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetMemSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageSizeMB() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageType() string {
|
||||
return api.DISK_TYPE_HYBRID
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostType() string {
|
||||
return api.HOST_TYPE_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SHost) GetIsMaintenance() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SHost) GetVersion() string {
|
||||
return ROCKBASE_API_VERSION
|
||||
}
|
||||
|
||||
// 不支持user data
|
||||
// 不支持指定keypair
|
||||
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
|
||||
vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.ExternalSecgroupIds, desc.BillingCycle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm, err := self.zone.region.GetInstanceByID(vmId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vm.host = self
|
||||
return &vm, err
|
||||
}
|
||||
|
||||
func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
|
||||
wires, err := host.zone.GetIWires()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getIWires")
|
||||
}
|
||||
return cloudprovider.GetHostNetifs(host, wires), nil
|
||||
}
|
||||
|
||||
type SInstanceType struct {
|
||||
UHostType string
|
||||
CPU int
|
||||
MemoryMB int
|
||||
GPU int
|
||||
}
|
||||
|
||||
func ParseInstanceType(instanceType string) (SInstanceType, error) {
|
||||
i := SInstanceType{}
|
||||
segs := strings.Split(instanceType, ".")
|
||||
if len(segs) < 3 {
|
||||
return i, fmt.Errorf("invalid instance type %s", instanceType)
|
||||
} else if len(segs) >= 4 {
|
||||
gpu, err := strconv.Atoi(strings.TrimLeft(segs[3], "g"))
|
||||
if err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
i.GPU = gpu
|
||||
}
|
||||
|
||||
cpu, err := strconv.Atoi(strings.TrimLeft(segs[1], "c"))
|
||||
if err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
mem, err := strconv.Atoi(strings.TrimLeft(segs[2], "m"))
|
||||
if err != nil {
|
||||
return i, err
|
||||
}
|
||||
|
||||
i.UHostType = segs[0]
|
||||
i.CPU = cpu
|
||||
i.MemoryMB = mem * 1024
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (self *SHost) _createVM(name, imgId string, sysDisk cloudprovider.SDiskInfo, cpu, memMB int, instanceType string,
|
||||
networkId, ipAddr, desc, passwd string,
|
||||
dataDisks []cloudprovider.SDiskInfo, secgroupIds []string, bc *billing.SBillingCycle) (string, error) {
|
||||
// 网络配置及安全组绑定
|
||||
net, _ := self.zone.region.getNetwork(networkId)
|
||||
if net == nil {
|
||||
return "", fmt.Errorf("invalid network ID %s", networkId)
|
||||
}
|
||||
|
||||
if net.wire == nil {
|
||||
log.Errorf("network's wire is empty")
|
||||
return "", fmt.Errorf("network's wire is empty")
|
||||
}
|
||||
|
||||
if net.wire.vpc == nil {
|
||||
log.Errorf("wire's vpc is empty")
|
||||
return "", fmt.Errorf("wire's vpc is empty")
|
||||
}
|
||||
|
||||
if len(passwd) == 0 {
|
||||
return "", fmt.Errorf("CreateVM password should not be emtpty")
|
||||
}
|
||||
|
||||
// 镜像及硬盘配置
|
||||
img, err := self.zone.region.GetImage(imgId)
|
||||
if err != nil {
|
||||
log.Errorf("GetImage %s fail %s", imgId, err)
|
||||
return "", err
|
||||
}
|
||||
if img.GetStatus() != api.CACHED_IMAGE_STATUS_ACTIVE {
|
||||
log.Errorf("image %s status %s, expect %s", imgId, img.GetStatus(), api.CACHED_IMAGE_STATUS_ACTIVE)
|
||||
return "", fmt.Errorf("image not ready")
|
||||
}
|
||||
|
||||
disks := make([]SDisk, len(dataDisks)+1)
|
||||
disks[0].SizeGB = int(img.ImageSizeGB)
|
||||
if sysDisk.SizeGB > 0 && sysDisk.SizeGB > int(img.ImageSizeGB) {
|
||||
disks[0].SizeGB = sysDisk.SizeGB
|
||||
}
|
||||
disks[0].DiskType = sysDisk.StorageType
|
||||
|
||||
for i, dataDisk := range dataDisks {
|
||||
disks[i+1].SizeGB = dataDisk.SizeGB
|
||||
disks[i+1].DiskType = dataDisk.StorageType
|
||||
}
|
||||
|
||||
// 创建实例
|
||||
// https://docs.ucloud.cn/api/uhost-api/uhost_type
|
||||
// https://docs.ucloud.cn/compute/uhost/introduction/uhost/type
|
||||
var vmId string
|
||||
i, err := ParseInstanceType(instanceType)
|
||||
if err != nil {
|
||||
if cpu <= 0 || memMB <= 0 {
|
||||
return "", err
|
||||
} else {
|
||||
i.UHostType = "N2"
|
||||
i.CPU = cpu
|
||||
i.MemoryMB = memMB
|
||||
}
|
||||
}
|
||||
|
||||
vmId, err = self.zone.region.CreateInstance(name, imgId, i.UHostType, passwd, net.wire.vpc.GetId(), networkId, secgroupIds, self.zone.ZoneId, desc, ipAddr, i.CPU, i.MemoryMB, i.GPU, disks, bc)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to create: %v", err)
|
||||
}
|
||||
|
||||
return vmId, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/create_uhost_instance
|
||||
// https://docs.ucloud.cn/api/uhost-api/specification
|
||||
// 支持8-30位字符, 不能包含[A-Z],[a-z],[0-9]和[()`~!@#$%^&*-+=_|{}[]:;'<>,.?/]之外的非法字符
|
||||
func (self *SRegion) CreateInstance(name, imageId, hostType, password, vpcId, SubnetId string, securityGroupId []string,
|
||||
zoneId, desc, ipAddr string, cpu, memMB, gpu int, disks []SDisk, bc *billing.SBillingCycle) (string, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Zone", zoneId)
|
||||
params.Set("ImageId", imageId)
|
||||
params.Set("Password", base64.StdEncoding.EncodeToString([]byte(password)))
|
||||
params.Set("LoginMode", "Password")
|
||||
params.Set("Name", name)
|
||||
params.Set("UHostType", hostType)
|
||||
params.Set("CPU", cpu)
|
||||
params.Set("Memory", memMB)
|
||||
params.Set("VPCId", vpcId)
|
||||
params.Set("SubnetId", SubnetId)
|
||||
for _, id := range securityGroupId {
|
||||
params.Set("SecurityGroupId", id)
|
||||
}
|
||||
if gpu > 0 {
|
||||
params.Set("GPU", gpu)
|
||||
}
|
||||
|
||||
if bc != nil && bc.GetMonths() >= 1 && bc.GetMonths() < 10 {
|
||||
params.Set("ChargeType", "Month")
|
||||
params.Set("Quantity", bc.GetMonths())
|
||||
} else if bc != nil && bc.GetMonths() >= 10 && bc.GetMonths() < 12 {
|
||||
params.Set("ChargeType", "Year")
|
||||
params.Set("Quantity", 1)
|
||||
} else if bc != nil && bc.GetYears() >= 1 {
|
||||
params.Set("ChargeType", "Year")
|
||||
params.Set("Quantity", bc.GetYears())
|
||||
} else {
|
||||
params.Set("ChargeType", "Dynamic")
|
||||
}
|
||||
|
||||
// boot disk
|
||||
params.Set("Disks.0.IsBoot", "True")
|
||||
params.Set("Disks.0.Type", disks[0].DiskType)
|
||||
params.Set("Disks.0.Size", disks[0].SizeGB)
|
||||
|
||||
// data disk
|
||||
for i, disk := range disks[1:] {
|
||||
N := i + 1
|
||||
params.Set(fmt.Sprintf("Disks.%d.IsBoot", N), "False")
|
||||
params.Set(fmt.Sprintf("Disks.%d.Type", N), disk.DiskType)
|
||||
params.Set(fmt.Sprintf("Disks.%d.Size", N), disk.SizeGB)
|
||||
}
|
||||
|
||||
type Ret struct {
|
||||
UHostIds []string
|
||||
}
|
||||
|
||||
ret := Ret{}
|
||||
err := self.DoAction("CreateUHostInstance", params, &ret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(ret.UHostIds) == 1 {
|
||||
return ret.UHostIds[0], nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("CreateInstance %d instance created. %s", len(ret.UHostIds), ret.UHostIds)
|
||||
}
|
||||
228
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/image.go
generated
vendored
Normal file
228
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/image.go
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/imagetools"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SImage struct {
|
||||
multicloud.SImageBase
|
||||
RockbaseTags
|
||||
storageCache *SStoragecache
|
||||
|
||||
// normalized image info
|
||||
imgInfo *imagetools.ImageInfo
|
||||
|
||||
Zone string `json:"Zone"`
|
||||
ImageDescription string `json:"ImageDescription"`
|
||||
OSName string `json:"OsName"`
|
||||
ImageID string `json:"ImageId"`
|
||||
State string `json:"State"`
|
||||
ImageName string `json:"ImageName"`
|
||||
OSType string `json:"OsType"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
ImageType string `json:"ImageType"`
|
||||
ImageSizeGB int64 `json:"ImageSize"`
|
||||
}
|
||||
|
||||
func (self *SImage) GetMinRamSizeMb() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SImage) GetId() string {
|
||||
return self.ImageID
|
||||
}
|
||||
|
||||
func (self *SImage) GetName() string {
|
||||
if len(self.ImageName) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
return self.ImageName
|
||||
}
|
||||
|
||||
func (self *SImage) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
// 镜像状态, 可用:Available,制作中:Making, 不可用:Unavailable
|
||||
func (self *SImage) GetStatus() string {
|
||||
switch self.State {
|
||||
case "Available":
|
||||
return api.CACHED_IMAGE_STATUS_ACTIVE
|
||||
case "Making":
|
||||
return api.CACHED_IMAGE_STATUS_CACHING
|
||||
case "Unavailable":
|
||||
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
default:
|
||||
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SImage) Refresh() error {
|
||||
new, err := self.storageCache.region.GetImage(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SImage) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SImage) Delete(ctx context.Context) error {
|
||||
return self.storageCache.region.DeleteImage(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return self.storageCache
|
||||
}
|
||||
|
||||
func (self *SImage) GetSizeByte() int64 {
|
||||
return self.ImageSizeGB * 1024 * 1024 * 1024
|
||||
}
|
||||
|
||||
// 镜像类型。标准镜像:Base,镜像市场:Business, 自定义镜像:Custom,默认返回所有类型
|
||||
func (self *SImage) GetImageType() cloudprovider.TImageType {
|
||||
switch self.ImageType {
|
||||
case "Base":
|
||||
return cloudprovider.ImageTypeSystem
|
||||
case "Custom":
|
||||
return cloudprovider.ImageTypeCustomized
|
||||
case "Business":
|
||||
return cloudprovider.ImageTypeShared
|
||||
default:
|
||||
return cloudprovider.ImageTypeCustomized
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SImage) GetImageStatus() string {
|
||||
switch self.State {
|
||||
case "Available":
|
||||
return cloudprovider.IMAGE_STATUS_ACTIVE
|
||||
case "Making":
|
||||
return cloudprovider.IMAGE_STATUS_QUEUED
|
||||
case "Unavailable":
|
||||
return cloudprovider.IMAGE_STATUS_KILLED
|
||||
default:
|
||||
return cloudprovider.IMAGE_STATUS_KILLED
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SImage) getNormalizedImageInfo() *imagetools.ImageInfo {
|
||||
if self.imgInfo == nil {
|
||||
imgInfo := imagetools.NormalizeImageInfo(self.ImageName, "", "", "", "")
|
||||
self.imgInfo = &imgInfo
|
||||
}
|
||||
|
||||
return self.imgInfo
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsType() cloudprovider.TOsType {
|
||||
return cloudprovider.TOsType(self.getNormalizedImageInfo().OsType)
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsDist() string {
|
||||
return self.getNormalizedImageInfo().OsDistro
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsVersion() string {
|
||||
return self.getNormalizedImageInfo().OsVersion
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsArch() string {
|
||||
return self.getNormalizedImageInfo().OsArch
|
||||
}
|
||||
|
||||
func (img *SImage) GetOsLang() string {
|
||||
return img.getNormalizedImageInfo().OsLang
|
||||
}
|
||||
|
||||
func (img *SImage) GetBios() cloudprovider.TBiosType {
|
||||
return cloudprovider.ToBiosType(img.getNormalizedImageInfo().OsBios)
|
||||
}
|
||||
|
||||
func (img *SImage) GetFullOsName() string {
|
||||
return img.ImageName
|
||||
}
|
||||
|
||||
func (self *SImage) GetMinOsDiskSizeGb() int {
|
||||
return int(self.ImageSizeGB)
|
||||
}
|
||||
|
||||
func (self *SImage) GetImageFormat() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SImage) GetCreatedAt() time.Time {
|
||||
return time.Unix(self.CreateTime, 0)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/describe_image
|
||||
func (self *SRegion) GetImage(imageId string) (SImage, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("ImageId", imageId)
|
||||
|
||||
images := make([]SImage, 0)
|
||||
err := self.DoListAll("DescribeImage", params, &images)
|
||||
if err != nil {
|
||||
return SImage{}, err
|
||||
}
|
||||
|
||||
if len(images) == 1 {
|
||||
return images[0], nil
|
||||
} else if len(images) == 0 {
|
||||
return SImage{}, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return SImage{}, fmt.Errorf("GetImage %s %d found.", imageId, len(images))
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/describe_image
|
||||
// ImageType 标准镜像:Base,镜像市场:Business, 自定义镜像:Custom,默认返回所有类型
|
||||
func (self *SRegion) GetImages(imageType string, imageId string) ([]SImage, error) {
|
||||
params := NewRockbaseParams()
|
||||
|
||||
if len(imageId) > 0 {
|
||||
params.Set("ImageId", imageId)
|
||||
}
|
||||
|
||||
if len(imageType) > 0 {
|
||||
params.Set("ImageType", imageType)
|
||||
}
|
||||
|
||||
images := make([]SImage, 0)
|
||||
err := self.DoListAll("DescribeImage", params, &images)
|
||||
return images, err
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/terminate_custom_image
|
||||
func (self *SRegion) DeleteImage(imageId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("ImageId", imageId)
|
||||
|
||||
return self.DoAction("TerminateCustomImage", params, nil)
|
||||
}
|
||||
679
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/instance.go
generated
vendored
Normal file
679
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/instance.go
generated
vendored
Normal file
@@ -0,0 +1,679 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/billing"
|
||||
"yunion.io/x/pkg/util/imagetools"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SInstance struct {
|
||||
multicloud.SInstanceBase
|
||||
RockbaseTags
|
||||
|
||||
host *SHost
|
||||
|
||||
osInfo *imagetools.ImageInfo
|
||||
|
||||
UHostID string `json:"UHostId"`
|
||||
Zone string `json:"Zone"`
|
||||
LifeCycle string `json:"LifeCycle"`
|
||||
OSName string `json:"OsName"`
|
||||
ImageID string `json:"ImageId"`
|
||||
BasicImageID string `json:"BasicImageId"`
|
||||
BasicImageName string `json:"BasicImageName"`
|
||||
Tag string `json:"Tag"`
|
||||
Name string `json:"Name"`
|
||||
Remark string `json:"Remark"`
|
||||
State string `json:"State"`
|
||||
NetworkState string `json:"NetworkState"`
|
||||
HostType string `json:"HostType"`
|
||||
StorageType string `json:"StorageType"`
|
||||
TotalDiskSpace int `json:"TotalDiskSpace"`
|
||||
DiskSet []DiskSet `json:"DiskSet"`
|
||||
NetCapability string `json:"NetCapability"`
|
||||
IPSet []IPSet `json:"IPSet"`
|
||||
SubnetType string `json:"SubnetType"`
|
||||
ChargeType string `json:"ChargeType"`
|
||||
ExpireTime int64 `json:"ExpireTime"`
|
||||
AutoRenew string `json:"AutoRenew"`
|
||||
IsExpire string `json:"IsExpire"`
|
||||
UHostType string `json:"UHostType"`
|
||||
OSType string `json:"OsType"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
CPU int `json:"CPU"`
|
||||
GPU int `json:"GPU"`
|
||||
MemoryMB int `json:"Memory"`
|
||||
TimemachineFeature string `json:"TimemachineFeature"`
|
||||
HotplugFeature bool `json:"HotplugFeature"`
|
||||
NetCapFeature bool `json:"NetCapFeature"`
|
||||
BootDiskState string `json:"BootDiskState"`
|
||||
}
|
||||
|
||||
func (self *SInstance) GetSecurityGroupIds() ([]string, error) {
|
||||
secgroups, err := self.GetSecurityGroups()
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
secgroupIds := make([]string, 0)
|
||||
for _, secgroup := range secgroups {
|
||||
secgroupIds = append(secgroupIds, secgroup.GetId())
|
||||
}
|
||||
|
||||
return secgroupIds, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetProjectId() string {
|
||||
return self.host.zone.region.client.projectId
|
||||
}
|
||||
|
||||
func (self *SInstance) GetError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DiskSet struct {
|
||||
DiskID string `json:"DiskId"`
|
||||
DiskType string `json:"DiskType"`
|
||||
Drive string `json:"Drive"`
|
||||
IsBoot bool `json:"IsBoot"`
|
||||
Size int `json:"Size"`
|
||||
Encrypted string `json:"Encrypted"`
|
||||
Type string `json:"Type"`
|
||||
}
|
||||
|
||||
type IPSet struct {
|
||||
Type string `json:"Type"`
|
||||
IP string `json:"IP"`
|
||||
IPId string `json:"IPId"` // IP资源ID (内网IP无对应的资源ID)
|
||||
MAC string `json:"Mac"`
|
||||
VpcId string `json:"VPCId"`
|
||||
SubnetID string `json:"SubnetId"`
|
||||
}
|
||||
|
||||
type SVncInfo struct {
|
||||
VNCIP string `json:"VncIP"`
|
||||
VNCPassword string `json:"VncPassword"`
|
||||
UHostID string `json:"UHostId"`
|
||||
Action string `json:"Action"`
|
||||
VNCPort int64 `json:"VncPort"`
|
||||
}
|
||||
|
||||
func (self *SInstance) GetId() string {
|
||||
return self.UHostID
|
||||
}
|
||||
|
||||
func (self *SInstance) GetName() string {
|
||||
if len(self.Name) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SInstance) GetHostname() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
// 实例状态,枚举值:
|
||||
// >初始化: Initializing;
|
||||
// >启动中: Starting;
|
||||
// > 运行中: Running;
|
||||
// > 关机中: Stopping;
|
||||
// >关机: Stopped
|
||||
// >安装失败: Install Fail;
|
||||
// >重启中: Rebooting
|
||||
func (self *SInstance) GetStatus() string {
|
||||
switch self.State {
|
||||
case "Running":
|
||||
return api.VM_RUNNING
|
||||
case "Stopped":
|
||||
return api.VM_READY
|
||||
case "Rebooting":
|
||||
return api.VM_STOPPING
|
||||
case "Initializing":
|
||||
return api.VM_INIT
|
||||
case "Starting":
|
||||
return api.VM_STARTING
|
||||
case "Stopping":
|
||||
return api.VM_STOPPING
|
||||
case "Install Fail":
|
||||
return api.VM_CREATE_FAILED
|
||||
default:
|
||||
return api.VM_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) Refresh() error {
|
||||
new, err := self.host.zone.region.GetInstanceByID(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
new.host = self.host
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
// 计费模式,枚举值为: Year,按年付费; Month,按月付费; Dynamic,按需付费(需开启权限);
|
||||
func (self *SInstance) GetBillingType() string {
|
||||
switch self.ChargeType {
|
||||
case "Year", "Month":
|
||||
return billing_api.BILLING_TYPE_PREPAID
|
||||
default:
|
||||
return billing_api.BILLING_TYPE_POSTPAID
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) GetCreatedAt() time.Time {
|
||||
return time.Unix(self.CreateTime, 0)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetExpiredAt() time.Time {
|
||||
if self.AutoRenew != "Yes" {
|
||||
return time.Unix(self.ExpireTime, 0)
|
||||
}
|
||||
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SInstance) GetLocalDisk(diskId, storageType string, sizeGB int, isBoot bool) SDisk {
|
||||
diskType := ""
|
||||
if isBoot {
|
||||
diskType = "SystemDisk"
|
||||
}
|
||||
|
||||
disk := SDisk{
|
||||
SDisk: multicloud.SDisk{},
|
||||
Status: "Available",
|
||||
UHostID: self.GetId(),
|
||||
Name: diskId,
|
||||
Zone: self.host.zone.GetId(),
|
||||
DiskType: diskType,
|
||||
UDiskID: diskId,
|
||||
UHostName: self.GetName(),
|
||||
CreateTime: self.CreateTime,
|
||||
SizeGB: sizeGB,
|
||||
}
|
||||
|
||||
disk.storage = &SStorage{zone: self.host.zone, storageType: storageType}
|
||||
return disk
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
localDisks := make([]SDisk, 0)
|
||||
diskIds := make([]string, 0)
|
||||
for _, disk := range self.DiskSet {
|
||||
if utils.IsInStringArray(disk.DiskType, []string{api.STORAGE_ROCKBASE_LOCAL_NORMAL, api.STORAGE_ROCKBASE_LOCAL_SSD}) {
|
||||
localDisks = append(localDisks, self.GetLocalDisk(disk.DiskID, disk.DiskType, disk.Size, disk.IsBoot))
|
||||
} else {
|
||||
diskIds = append(diskIds, disk.DiskID)
|
||||
}
|
||||
}
|
||||
|
||||
disks := []SDisk{}
|
||||
var err error
|
||||
if len(diskIds) > 0 {
|
||||
disks, err = self.host.zone.region.GetDisks("", "", diskIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
disks = append(disks, localDisks...)
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(disks))
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
if disks[i].storage == nil {
|
||||
var category string
|
||||
if strings.Contains(disks[i].DiskType, "SSD") {
|
||||
category = api.STORAGE_ROCKBASE_CLOUD_SSD
|
||||
} else {
|
||||
category = api.STORAGE_ROCKBASE_CLOUD_NORMAL
|
||||
}
|
||||
storage, err := self.host.zone.getStorageByCategory(category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disks[i].storage = storage
|
||||
}
|
||||
idisks[i] = &disks[i]
|
||||
// 将系统盘放到第0个位置
|
||||
if disks[i].GetDiskType() == api.DISK_TYPE_SYS {
|
||||
idisks[0], idisks[i] = idisks[i], idisks[0]
|
||||
}
|
||||
}
|
||||
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
nics := make([]cloudprovider.ICloudNic, 0)
|
||||
|
||||
for _, ip := range self.IPSet {
|
||||
if len(ip.SubnetID) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
nic := SInstanceNic{
|
||||
instance: self,
|
||||
ipAddr: ip.IP,
|
||||
macAddr: ip.MAC,
|
||||
}
|
||||
nics = append(nics, &nic)
|
||||
}
|
||||
|
||||
return nics, nil
|
||||
}
|
||||
|
||||
// 国际: Internation,BGP: BGP,内网: Private
|
||||
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
for _, ip := range self.IPSet {
|
||||
if len(ip.IPId) > 0 {
|
||||
eip, err := self.host.zone.region.GetEipById(ip.IPId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &eip, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVcpuCount() int {
|
||||
return self.CPU
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVmemSizeMB() int {
|
||||
return self.MemoryMB
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBootOrder() string {
|
||||
return "dcn"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVga() string {
|
||||
return "std"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVdi() string {
|
||||
return "vnc"
|
||||
}
|
||||
|
||||
func (ins *SInstance) getNormalizedOsInfo() *imagetools.ImageInfo {
|
||||
if ins.osInfo == nil {
|
||||
osInfo := imagetools.NormalizeImageInfo(ins.OSName, "", ins.OSType, "", "")
|
||||
ins.osInfo = &osInfo
|
||||
}
|
||||
return ins.osInfo
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetOsType() cloudprovider.TOsType {
|
||||
return cloudprovider.TOsType(ins.getNormalizedOsInfo().OsType)
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetFullOsName() string {
|
||||
return ins.OSName
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetBios() cloudprovider.TBiosType {
|
||||
return cloudprovider.ToBiosType(ins.getNormalizedOsInfo().OsBios)
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetOsArch() string {
|
||||
return ins.getNormalizedOsInfo().OsArch
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetOsDist() string {
|
||||
return ins.getNormalizedOsInfo().OsDistro
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetOsVersion() string {
|
||||
return ins.getNormalizedOsInfo().OsVersion
|
||||
}
|
||||
|
||||
func (ins *SInstance) GetOsLang() string {
|
||||
return ins.getNormalizedOsInfo().OsLang
|
||||
}
|
||||
|
||||
func (self *SInstance) GetMachine() string {
|
||||
return "pc"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetInstanceType() string {
|
||||
// C1.c8.m24
|
||||
if strings.HasPrefix(self.HostType, "G") {
|
||||
return fmt.Sprintf("%s.c%d.m%d.g%d", self.HostType, self.CPU, self.MemoryMB/1014, self.GPU)
|
||||
} else {
|
||||
return fmt.Sprintf("%s.c%d.m%d", self.HostType, self.CPU, self.MemoryMB/1014)
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/grant_firewall
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
if len(secgroupIds) == 0 {
|
||||
return fmt.Errorf("SetSecurityGroups secgroup id should not be empty")
|
||||
} else if len(secgroupIds) > 1 {
|
||||
return fmt.Errorf("SetSecurityGroups only allowed to assign one secgroup id. %d given", len(secgroupIds))
|
||||
}
|
||||
|
||||
return self.host.zone.region.assignSecurityGroups(self.GetId(), secgroupIds[0])
|
||||
}
|
||||
|
||||
func (self *SInstance) GetHypervisor() string {
|
||||
return api.HYPERVISOR_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SInstance) StartVM(ctx context.Context) error {
|
||||
err := self.host.zone.region.StartVM(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatusWithDelay(self, api.VM_RUNNING, 10*time.Second, 10*time.Second, 600*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "StartVM")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
|
||||
err := self.host.zone.region.StopVM(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cloudprovider.WaitStatusWithDelay(self, api.VM_READY, 10*time.Second, 10*time.Second, 600*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "StopVM")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return self.host.zone.region.DeleteVM(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateVM(ctx context.Context, input cloudprovider.SInstanceUpdateOptions) error {
|
||||
return self.host.zone.region.UpdateVM(self.GetId(), input.NAME)
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateUserData(userData string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/reinstall_uhost_instance
|
||||
// 1.请确认在重新安装之前,该实例已被关闭;
|
||||
// 2.请确认该实例未挂载UDisk;
|
||||
// todo:// 3.将原系统重装为不同类型的系统时(Linux->Windows),不可选择保留数据盘;
|
||||
// 4.重装不同版本的系统时(CentOS6->CentOS7),若选择保留数据盘,请注意数据盘的文件系统格式;
|
||||
// 5.若主机CPU低于2核,不可重装为Windows系统。
|
||||
func (self *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
|
||||
if len(desc.PublicKey) > 0 {
|
||||
return "", fmt.Errorf("DeployVM not support assign ssh keypair")
|
||||
}
|
||||
|
||||
if self.GetStatus() != api.VM_READY {
|
||||
return "", fmt.Errorf("DeployVM instance status %s , expected %s.", self.GetStatus(), api.VM_READY)
|
||||
}
|
||||
|
||||
if len(self.DiskSet) > 1 {
|
||||
for _, disk := range self.DiskSet {
|
||||
if disk.Type == "Data" {
|
||||
err := self.host.zone.region.DetachDisk(self.host.zone.GetId(), self.GetId(), disk.DiskID)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("RebuildRoot detach disk %s", err)
|
||||
}
|
||||
|
||||
defer self.host.zone.region.AttachDisk(self.host.zone.GetId(), self.GetId(), disk.DiskID)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
err := self.host.zone.region.RebuildRoot(self.GetId(), desc.ImageId, desc.Password)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = cloudprovider.WaitStatusWithDelay(self, api.VM_RUNNING, 10*time.Second, 15*time.Second, 300*time.Second)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "RebuildRoot")
|
||||
}
|
||||
|
||||
disks, err := self.GetIDisks()
|
||||
if len(disks) > 0 {
|
||||
return disks[0].GetId(), nil
|
||||
} else {
|
||||
return "", fmt.Errorf("RebuildRoot %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
|
||||
if len(opts.PublicKey) > 0 {
|
||||
return fmt.Errorf("DeployVM not support assign ssh keypair")
|
||||
}
|
||||
|
||||
if opts.DeleteKeypair {
|
||||
return fmt.Errorf("DeployVM not support delete ssh keypair")
|
||||
}
|
||||
|
||||
if self.GetStatus() != api.VM_READY {
|
||||
return fmt.Errorf("DeployVM instance status %s , expected %s.", self.GetStatus(), api.VM_READY)
|
||||
}
|
||||
|
||||
if len(opts.Password) > 0 {
|
||||
err := self.host.zone.region.ResetVMPasswd(self.GetId(), opts.Password)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err := cloudprovider.WaitStatus(self, api.VM_READY, 10*time.Second, 300*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "DeployVM")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
|
||||
if len(config.InstanceType) > 0 {
|
||||
return self.ChangeConfig2(ctx, config.InstanceType)
|
||||
}
|
||||
return self.host.zone.region.ResizeVM(self.GetId(), config.Cpu, config.MemoryMB)
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error {
|
||||
i, err := ParseInstanceType(instanceType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return self.host.zone.region.ResizeVM(self.GetId(), i.CPU, i.MemoryMB)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
|
||||
return self.host.zone.region.GetInstanceVNCUrl(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
||||
return self.host.zone.region.AttachDisk(self.host.zone.GetId(), self.GetId(), diskId)
|
||||
}
|
||||
|
||||
func (self *SInstance) DetachDisk(ctx context.Context, diskId string) error {
|
||||
err := self.host.zone.region.DetachDisk(self.host.zone.GetId(), self.GetId(), diskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
disk, err := self.host.zone.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
disk.storage = &SStorage{zone: self.host.zone, storageType: disk.GetStorageType()}
|
||||
err = cloudprovider.WaitStatusWithDelay(disk, api.DISK_READY, 10*time.Second, 10*time.Second, 60*time.Second)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "DetachDisk")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) Renew(bc billing.SBillingCycle) error {
|
||||
// return self.host.zone.region
|
||||
return self.host.zone.region.RenewInstance(self.GetId(), bc)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetSecurityGroups() ([]SSecurityGroup, error) {
|
||||
return self.host.zone.region.GetSecurityGroups("", self.GetId(), "")
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/get_uhost_instance_vnc_info
|
||||
func (self *SRegion) GetInstanceVNCUrl(instanceId string) (*cloudprovider.ServerVncOutput, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
vnc := SVncInfo{}
|
||||
err := self.DoAction("GetUHostInstanceVncInfo", params, &vnc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &cloudprovider.ServerVncOutput{
|
||||
Host: vnc.VNCIP,
|
||||
Port: vnc.VNCPort,
|
||||
Password: vnc.VNCPassword,
|
||||
Hypervisor: api.HYPERVISOR_ROCKBASE,
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/grant_firewall
|
||||
func (self *SRegion) assignSecurityGroups(instanceId string, secgroupId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("FWId", secgroupId)
|
||||
params.Set("ResourceType", "uhost")
|
||||
params.Set("ResourceId", instanceId)
|
||||
|
||||
return self.DoAction("GrantFirewall", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/start_uhost_instance
|
||||
func (self *SRegion) StartVM(instanceId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
|
||||
return self.DoAction("StartUHostInstance", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/stop_uhost_instance
|
||||
func (self *SRegion) StopVM(instanceId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
|
||||
return self.DoAction("StopUHostInstance", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/terminate_uhost_instance
|
||||
func (self *SRegion) DeleteVM(instanceId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("Destroy", 1) // 跳过回收站,直接删除
|
||||
|
||||
return self.DoAction("TerminateUHostInstance", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/modify_uhost_instance_name
|
||||
func (self *SRegion) UpdateVM(instanceId, name string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("Name", name)
|
||||
|
||||
return self.DoAction("ModifyUHostInstanceName", params, nil)
|
||||
}
|
||||
|
||||
// ChargeType : Dynamic(按需)/Month(按月)/Year(按年)
|
||||
func (self *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("ResourceId", instanceId)
|
||||
params.Set("ResourceType", "Host")
|
||||
|
||||
if bc.GetMonths() >= 10 && bc.GetMonths() < 12 {
|
||||
params.Set("ChargeType", "Year")
|
||||
params.Set("Quantity", 1)
|
||||
} else if bc.GetYears() >= 1 {
|
||||
params.Set("ChargeType", "Year")
|
||||
params.Set("Quantity", bc.GetYears())
|
||||
} else {
|
||||
params.Set("ChargeType", "Month")
|
||||
params.Set("Quantity", bc.GetMonths())
|
||||
}
|
||||
|
||||
return self.DoAction("CreateRenew", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/reset_uhost_instance_password
|
||||
// 该操作需要UHost实例处于关闭状态。
|
||||
func (self *SRegion) ResetVMPasswd(instanceId, password string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("Password", base64.StdEncoding.EncodeToString([]byte(password)))
|
||||
|
||||
return self.DoAction("ResetUHostInstancePassword", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/reinstall_uhost_instance
|
||||
// (密码格式使用BASE64编码;LoginMode不可变更)
|
||||
func (self *SRegion) RebuildRoot(instanceId, imageId, password string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("Password", base64.StdEncoding.EncodeToString([]byte(password)))
|
||||
params.Set("ImageId", imageId)
|
||||
|
||||
return self.DoAction("ReinstallUHostInstance", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/resize_uhost_instance
|
||||
func (self *SRegion) ResizeVM(instanceId string, cpu, memoryMB int) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostId", instanceId)
|
||||
params.Set("CPU", cpu)
|
||||
params.Set("Memory", memoryMB)
|
||||
|
||||
return self.DoAction("ResizeUHostInstance", params, nil)
|
||||
}
|
||||
56
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/instancenic.go
generated
vendored
Normal file
56
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/instancenic.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type SInstanceNic struct {
|
||||
instance *SInstance
|
||||
ipAddr string
|
||||
macAddr string
|
||||
|
||||
cloudprovider.DummyICloudNic
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetIP() string {
|
||||
return self.ipAddr
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetMAC() string {
|
||||
return self.macAddr
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetDriver() string {
|
||||
return "virtio"
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) InClassicNetwork() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetINetworkId() string {
|
||||
for _, ip := range self.instance.IPSet {
|
||||
if ip.IP == self.ipAddr {
|
||||
return ip.SubnetID
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
41
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/latitud_and_longitude.go
generated
vendored
Normal file
41
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/latitud_and_longitude.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"hk": api.RegionHongkong,
|
||||
"tw-tp": api.RegionTaipei,
|
||||
"sg": api.RegionSingapore,
|
||||
"jpn-tky": api.RegionTokyo,
|
||||
"kr-seoul": api.RegionSeoul,
|
||||
"th-bkk": api.RegionBangkok,
|
||||
"idn-jakarta": api.RegionJakarta,
|
||||
"vn-sng": api.RegionHoChiMinh,
|
||||
"ph-mnl": api.RegionManila,
|
||||
"ind-mumbai": api.RegionMumbai,
|
||||
"us-den": api.RegionDenver,
|
||||
"us-ca": api.RegionLosAngeles,
|
||||
"us-ws": api.RegionWashingtonDC,
|
||||
"bra-saopaulo": api.RegionSaoPaulo,
|
||||
"ge-fra": api.RegionFrankfurt,
|
||||
"uk-london": api.RegionLondon,
|
||||
"uae-dubai": api.RegionDubai,
|
||||
"afr-nigeria": api.RegionLagos,
|
||||
}
|
||||
205
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/network.go
generated
vendored
Normal file
205
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/network.go
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
"yunion.io/x/pkg/util/rbacscope"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/describe_subnet
|
||||
type SNetwork struct {
|
||||
multicloud.SNetworkBase
|
||||
RockbaseTags
|
||||
wire *SWire
|
||||
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
Gateway string `json:"Gateway"`
|
||||
HasNATGW bool `json:"HasNATGW"`
|
||||
Name string `json:"Name"`
|
||||
Netmask string `json:"Netmask"`
|
||||
Remark string `json:"Remark"`
|
||||
RouteTableID string `json:"RouteTableId"`
|
||||
Subnet string `json:"Subnet"`
|
||||
SubnetID string `json:"SubnetId"`
|
||||
SubnetName string `json:"SubnetName"`
|
||||
SubnetType int `json:"SubnetType"`
|
||||
Tag string `json:"Tag"`
|
||||
VpcId string `json:"VPCId"`
|
||||
VPCName string `json:"VPCName"`
|
||||
VRouterID string `json:"VRouterId"`
|
||||
Zone string `json:"Zone"`
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetProjectId() string {
|
||||
return self.wire.vpc.region.client.projectId
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetId() string {
|
||||
return self.SubnetID
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetName() string {
|
||||
if len(self.SubnetName) > 0 {
|
||||
return self.SubnetName
|
||||
}
|
||||
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetStatus() string {
|
||||
return api.NETWORK_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SNetwork) Refresh() error {
|
||||
log.Debugf("network refresh %s", self.GetId())
|
||||
new, err := self.wire.vpc.region.getNetwork(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SNetwork) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIWire() cloudprovider.ICloudWire {
|
||||
return self.wire
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpStart() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.Subnet + "/" + self.Netmask)
|
||||
startIp := pref.Address.NetAddr(pref.MaskLen) // 0
|
||||
startIp = startIp.StepUp() // 1 gateway
|
||||
startIp = startIp.StepUp() // 2
|
||||
return startIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpEnd() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.Subnet + "/" + self.Netmask)
|
||||
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
|
||||
endIp = endIp.StepDown() // 254
|
||||
return endIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpMask() int8 {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.Subnet + "/" + self.Netmask)
|
||||
return pref.MaskLen
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGateway() string {
|
||||
return self.Gateway
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetServerType() string {
|
||||
return api.NETWORK_TYPE_GUEST
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIsPublic() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetPublicScope() rbacscope.TRbacScope {
|
||||
return rbacscope.ScopeDomain
|
||||
}
|
||||
|
||||
func (self *SNetwork) Delete() error {
|
||||
return self.wire.vpc.region.DeleteNetwork(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetAllocTimeoutSeconds() int {
|
||||
return 120 // 2 minutes
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/describe_subnet
|
||||
func (self *SRegion) GetNetwork(networkId string) (*SNetwork, error) {
|
||||
return self.getNetwork(networkId)
|
||||
}
|
||||
|
||||
func (self *SRegion) getNetwork(networkId string) (*SNetwork, error) {
|
||||
if len(networkId) == 0 {
|
||||
return nil, fmt.Errorf("getNetwork network id should not be empty")
|
||||
}
|
||||
networks := make([]SNetwork, 0)
|
||||
|
||||
params := NewRockbaseParams()
|
||||
params.Set("SubnetId", networkId)
|
||||
err := self.DoListAll("DescribeSubnet", params, &networks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(networks) == 1 {
|
||||
network := networks[0]
|
||||
vpc, err := self.GetVpc(network.VpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
network.wire = &SWire{vpc: vpc}
|
||||
return &network, nil
|
||||
} else if len(networks) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return nil, fmt.Errorf("getNetwork %s %d found", networkId, len(networks))
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/delete_subnet
|
||||
func (self *SRegion) DeleteNetwork(networkId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("SubnetId", networkId)
|
||||
|
||||
return self.DoAction("DeleteSubnet", params, nil)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/create_subnet
|
||||
func (self *SRegion) CreateNetwork(vpcId string, name string, cidr string, desc string) (*SNetwork, error) {
|
||||
ip, mask, err := netutils.ParsePrefix(cidr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("CreateINetwork invalid cidr %s", cidr)
|
||||
}
|
||||
|
||||
params := NewRockbaseParams()
|
||||
params.Set("VPCId", vpcId)
|
||||
params.Set("Subnet", ip.String())
|
||||
params.Set("Netmask", int(mask))
|
||||
params.Set("SubnetName", name)
|
||||
params.Set("Remark", desc)
|
||||
|
||||
type SNet struct {
|
||||
SubnetId string
|
||||
}
|
||||
|
||||
net := SNet{}
|
||||
err = self.DoAction("CreateSubnet", params, &net)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.getNetwork(net.SubnetId)
|
||||
}
|
||||
64
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/project.go
generated
vendored
Normal file
64
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/project.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/summary/get_project_list
|
||||
type SProject struct {
|
||||
multicloud.SProjectBase
|
||||
RockbaseTags
|
||||
ProjectID string `json:"ProjectId"`
|
||||
ProjectName string `json:"ProjectName"`
|
||||
ParentID string `json:"ParentId"`
|
||||
ParentName string `json:"ParentName"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
IsDefault bool `json:"IsDefault"`
|
||||
MemberCount int64 `json:"MemberCount"`
|
||||
ResourceCount int64 `json:"ResourceCount"`
|
||||
}
|
||||
|
||||
func (self *SProject) GetId() string {
|
||||
return self.ProjectID
|
||||
}
|
||||
|
||||
func (self *SProject) GetName() string {
|
||||
return self.ProjectName
|
||||
}
|
||||
|
||||
func (self *SProject) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SProject) GetStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SProject) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SProject) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) FetchProjects() ([]SProject, error) {
|
||||
params := NewRockbaseParams()
|
||||
projects := make([]SProject, 0)
|
||||
err := self.DoListAll("GetProjectList", params, &projects)
|
||||
return projects, err
|
||||
}
|
||||
15
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider/doc.go
generated
vendored
Normal file
15
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider/doc.go
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// 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 "yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider"
|
||||
195
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider/provider.go
generated
vendored
Normal file
195
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/provider/provider.go
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// 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"
|
||||
"strings"
|
||||
|
||||
"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/rockbase"
|
||||
)
|
||||
|
||||
// tag:finished
|
||||
type SRockbaseProviderFactory struct {
|
||||
cloudprovider.SPublicCloudBaseProviderFactory
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) GetId() string {
|
||||
return rockbase.CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) GetName() string {
|
||||
return rockbase.CLOUD_PROVIDER_ROCKBASE_CN
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) 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.Account = input.AccessKeyId
|
||||
output.Secret = input.AccessKeySecret
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) 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 parseAccount(account string) (accessKey string, projectId string) {
|
||||
segs := strings.Split(account, "::")
|
||||
if len(segs) == 2 {
|
||||
accessKey = segs[0]
|
||||
projectId = segs[1]
|
||||
} else {
|
||||
accessKey = account
|
||||
projectId = ""
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) {
|
||||
accessKey, projectId := parseAccount(cfg.Account)
|
||||
client, err := rockbase.NewRockbaseClient(
|
||||
rockbase.NewRockbaseClientConfig(
|
||||
accessKey, cfg.Secret,
|
||||
).ProjectId(projectId).CloudproviderConfig(cfg),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &SRockbaseProvider{
|
||||
SBaseProvider: cloudprovider.NewBaseProvider(self),
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) {
|
||||
accessKey, projectId := parseAccount(info.Account)
|
||||
return map[string]string{
|
||||
"ROCKBASE_ACCESS_KEY_ID": accessKey,
|
||||
"ROCKBASE_ACCESS_KEY_SECRET": info.Secret,
|
||||
"ROCKBASE_REGION_ID": rockbase.ROCKBASE_DEFAULT_REGION,
|
||||
"ROCKBASE_PROJECT_ID": projectId,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
factory := SRockbaseProviderFactory{}
|
||||
cloudprovider.RegisterFactory(&factory)
|
||||
}
|
||||
|
||||
type SRockbaseProvider struct {
|
||||
cloudprovider.SBaseProvider
|
||||
client *rockbase.SRockbaseClient
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
|
||||
projects, err := self.client.FetchProjects()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
iprojects := make([]cloudprovider.ICloudProject, len(projects))
|
||||
for i := range projects {
|
||||
iprojects[i] = &projects[i]
|
||||
}
|
||||
|
||||
return iprojects, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetSysInfo() (jsonutils.JSONObject, error) {
|
||||
regions, _ := self.client.GetIRegions()
|
||||
info := jsonutils.NewDict()
|
||||
info.Add(jsonutils.NewInt(int64(len(regions))), "region_count")
|
||||
info.Add(jsonutils.NewString(rockbase.ROCKBASE_API_VERSION), "api_version")
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetVersion() string {
|
||||
return rockbase.ROCKBASE_API_VERSION
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
return self.client.GetSubAccounts()
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetAccountId() string {
|
||||
return self.client.GetAccountId()
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
|
||||
return self.client.GetIRegions()
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetIRegionById(extId string) (cloudprovider.ICloudRegion, error) {
|
||||
return self.client.GetIRegionById(extId)
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetBalance() (*cloudprovider.SBalanceInfo, error) {
|
||||
return &cloudprovider.SBalanceInfo{
|
||||
Amount: 0.0,
|
||||
Currency: "CNY",
|
||||
Status: api.CLOUD_PROVIDER_HEALTH_NORMAL,
|
||||
}, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetOnPremiseIRegion() (cloudprovider.ICloudRegion, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetStorageClasses(regionId string) []string {
|
||||
return []string{
|
||||
"STANDARD", "IA", "ARCHIVE",
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetBucketCannedAcls(regionId string) []string {
|
||||
return []string{
|
||||
string(cloudprovider.ACLPrivate),
|
||||
string(cloudprovider.ACLPublicRead),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetObjectCannedAcls(regionId string) []string {
|
||||
return []string{
|
||||
string(cloudprovider.ACLPrivate),
|
||||
string(cloudprovider.ACLPublicRead),
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRockbaseProvider) GetCapabilities() []string {
|
||||
return self.client.GetCapabilities()
|
||||
}
|
||||
504
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/region.go
generated
vendored
Normal file
504
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/region.go
generated
vendored
Normal file
@@ -0,0 +1,504 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type SRegion struct {
|
||||
multicloud.SRegion
|
||||
multicloud.SNoLbRegion
|
||||
client *SRockbaseClient
|
||||
|
||||
RegionID string `json:"Region"`
|
||||
LocalName string `json:"LocalName"`
|
||||
CountryCode string `json:"CountryCode"`
|
||||
Category string `json:"Category"`
|
||||
|
||||
storageCache *SStoragecache
|
||||
}
|
||||
|
||||
func (self *SRegion) GetId() string {
|
||||
return self.RegionID
|
||||
}
|
||||
|
||||
func (self *SRegion) GetName() string {
|
||||
return self.LocalName
|
||||
}
|
||||
|
||||
func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
|
||||
table := cloudprovider.SModelI18nTable{}
|
||||
return table
|
||||
}
|
||||
|
||||
func (self *SRegion) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_ROCKBASE, self.GetId())
|
||||
}
|
||||
|
||||
func (self *SRegion) GetStatus() string {
|
||||
return api.CLOUD_REGION_STATUS_INSERVER
|
||||
}
|
||||
|
||||
func (self *SRegion) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
|
||||
if info, ok := LatitudeAndLongitude[self.GetId()]; ok {
|
||||
return info
|
||||
}
|
||||
return cloudprovider.SGeographicInfo{}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
|
||||
instance, err := self.GetInstanceByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &instance, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
|
||||
return self.GetDisk(id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
|
||||
zones, err := self.GetZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudZone{}
|
||||
for i := range zones {
|
||||
zones[i].region = self
|
||||
ret = append(ret, &zones[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
|
||||
vpcs, err := self.GetVpcs("")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetVpcs")
|
||||
}
|
||||
ret := []cloudprovider.ICloudVpc{}
|
||||
for i := range vpcs {
|
||||
vpcs[i].region = self
|
||||
ret = append(ret, &vpcs[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/describe_eip
|
||||
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
|
||||
params := NewRockbaseParams()
|
||||
eips := make([]SEip, 0)
|
||||
err := self.DoListAll("DescribeEIP", params, &eips)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ieips := []cloudprovider.ICloudEIP{}
|
||||
for i := range eips {
|
||||
eip := eips[i]
|
||||
eip.region = self
|
||||
ieips = append(ieips, &eip)
|
||||
}
|
||||
|
||||
return ieips, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
return self.GetVpc(id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
if izones[i].GetGlobalId() == id {
|
||||
return izones[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetEipById(eipId string) (SEip, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("EIPIds.0", eipId)
|
||||
eips := make([]SEip, 0)
|
||||
err := self.DoListAll("DescribeEIP", params, &eips)
|
||||
if err != nil {
|
||||
return SEip{}, err
|
||||
}
|
||||
|
||||
if len(eips) == 1 {
|
||||
eip := eips[0]
|
||||
eip.region = self
|
||||
return eip, nil
|
||||
} else if len(eips) == 0 {
|
||||
return SEip{}, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return SEip{}, fmt.Errorf("GetEipById %d eip found", len(eips))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
|
||||
eip, err := self.GetEipById(id)
|
||||
return &eip, err
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/delete_firewall
|
||||
func (self *SRegion) DeleteSecurityGroup(secgroupId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("FWId", secgroupId)
|
||||
return self.DoAction("DeleteFirewall", params, nil)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
|
||||
secgroups, err := self.GetSecurityGroups("", "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := []cloudprovider.ICloudSecurityGroup{}
|
||||
for i := 0; i < len(secgroups); i++ {
|
||||
secgroups[i].region = self
|
||||
ret = append(ret, &secgroups[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISecurityGroupById(secgroupId string) (cloudprovider.ICloudSecurityGroup, error) {
|
||||
return self.GetSecurityGroup(secgroupId)
|
||||
}
|
||||
|
||||
func (self *SRegion) CreateISecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
|
||||
externalId, err := self.CreateSecurityGroup(opts.Name, opts.Desc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return self.GetISecurityGroupById(externalId)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/describe_firewall
|
||||
// 绑定防火墙组的资源类型,默认为全部资源类型。枚举值为:"unatgw",NAT网关; "uhost",云主机; "upm",物理云主机; "hadoophost",hadoop节点; "fortresshost",堡垒机; "udhost",私有专区主机;"udockhost",容器;"dbaudit",数据库审计.
|
||||
// todo: 是否需要过滤出仅绑定云主机的安全组?
|
||||
|
||||
func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Name", opts.NAME)
|
||||
params.Set("Remark", opts.Desc)
|
||||
for i, cidr := range strings.Split(opts.CIDR, ",") {
|
||||
params.Set(fmt.Sprintf("Network.%d", i), cidr)
|
||||
}
|
||||
|
||||
vpcId := ""
|
||||
err := self.DoAction("CreateVPC", params, &vpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return self.GetIVpcById(vpcId)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/describe_udisk_snapshot
|
||||
func (self *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
params := NewRockbaseParams()
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
err := self.DoListAll("DescribeUDiskSnapshot", params, &snapshots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
isnapshots := make([]cloudprovider.ICloudSnapshot, 0)
|
||||
for i := range snapshots {
|
||||
snapshots[i].region = self
|
||||
isnapshots = append(isnapshots, &snapshots[i])
|
||||
}
|
||||
|
||||
return isnapshots, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISnapshotById(snapshotId string) (cloudprovider.ICloudSnapshot, error) {
|
||||
if len(snapshotId) == 0 {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
params := NewRockbaseParams()
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
err := self.DoListAll("DescribeUDiskSnapshot", params, &snapshots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range snapshots {
|
||||
if snapshots[i].SnapshotID == snapshotId {
|
||||
snapshot := snapshots[i]
|
||||
snapshot.region = self
|
||||
return &snapshot, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
iHosts := make([]cloudprovider.ICloudHost, 0)
|
||||
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
iZoneHost, err := izones[i].GetIHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iHosts = append(iHosts, iZoneHost...)
|
||||
}
|
||||
return iHosts, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
ihost, err := izones[i].GetIHostById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
iStores := make([]cloudprovider.ICloudStorage, 0)
|
||||
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
iZoneStores, err := izones[i].GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iStores = append(iStores, iZoneStores...)
|
||||
}
|
||||
return iStores, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
izones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(izones); i += 1 {
|
||||
istore, err := izones[i].GetIStorageById(id)
|
||||
if err == nil {
|
||||
return istore, nil
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) getStoragecache() *SStoragecache {
|
||||
if self.storageCache == nil {
|
||||
self.storageCache = &SStoragecache{region: self}
|
||||
}
|
||||
return self.storageCache
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
|
||||
storageCache := self.getStoragecache()
|
||||
return []cloudprovider.ICloudStoragecache{storageCache}, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
storageCache := self.getStoragecache()
|
||||
if storageCache.GetGlobalId() == id {
|
||||
return storageCache, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSkus(zoneId string) ([]cloudprovider.ICloudSku, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SRegion) GetProvider() string {
|
||||
return CLOUD_PROVIDER_ROCKBASE
|
||||
}
|
||||
|
||||
func (self *SRegion) GetCloudEnv() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRegion) DoListAll(action string, params SParams, result interface{}) error {
|
||||
params.Set("Region", self.GetId())
|
||||
return self.client.DoListAll(action, params, result)
|
||||
}
|
||||
|
||||
// return total,lenght,error
|
||||
func (self *SRegion) DoListPart(action string, limit int, offset int, params SParams, result interface{}) (int, int, error) {
|
||||
params.Set("Region", self.GetId())
|
||||
return self.client.DoListPart(action, limit, offset, params, result)
|
||||
}
|
||||
|
||||
func (self *SRegion) DoAction(action string, params SParams, result interface{}) error {
|
||||
params.Set("Region", self.GetId())
|
||||
return self.client.DoAction(action, params, result)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetZones() ([]SZone, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Region", self.GetId())
|
||||
zones := make([]SZone, 0)
|
||||
err := self.client.DoListAll("ListZones", params, &zones)
|
||||
return zones, err
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceByID(instanceId string) (SInstance, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("UHostIds.0", instanceId)
|
||||
instances := make([]SInstance, 0)
|
||||
err := self.DoAction("DescribeUHostInstance", params, &instances)
|
||||
if err != nil {
|
||||
return SInstance{}, err
|
||||
}
|
||||
|
||||
if len(instances) == 1 {
|
||||
return instances[0], nil
|
||||
} else if len(instances) == 0 {
|
||||
return SInstance{}, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return SInstance{}, fmt.Errorf("GetInstanceByID %s %d found.", instanceId, len(instances))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetClient() *SRockbaseClient {
|
||||
return self.client
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/ufile-api/describe_bucket
|
||||
func (client *SRockbaseClient) listBuckets(name string, offset int, limit int) ([]SBucket, error) {
|
||||
params := NewRockbaseParams()
|
||||
if len(name) > 0 {
|
||||
params.Set("BucketName", name)
|
||||
} else {
|
||||
params.Set("Limit", limit)
|
||||
params.Set("Offset", offset)
|
||||
}
|
||||
buckets := make([]SBucket, 0)
|
||||
// request without RegionId
|
||||
err := client.DoAction("DescribeBucket", params, &buckets)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "DoAction DescribeBucket")
|
||||
}
|
||||
return buckets, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/ufile-api/update_bucket
|
||||
func (region *SRegion) updateBucket(name string, aclType string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("BucketName", name)
|
||||
params.Set("ProjectId", region.client.projectId)
|
||||
params.Set("Type", aclType)
|
||||
return region.client.DoAction("UpdateBucket", params, nil)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
iBuckets, err := region.client.getIBuckets()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getIBuckets")
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, 0)
|
||||
for i := range iBuckets {
|
||||
if iBuckets[i].GetLocation() != region.GetId() {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, iBuckets[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr string) error {
|
||||
if aclStr != "private" && aclStr != "public" {
|
||||
return errors.Error("invalid acl")
|
||||
}
|
||||
return region.CreateBucket(name, aclStr)
|
||||
}
|
||||
|
||||
func (region *SRegion) DeleteIBucket(name string) error {
|
||||
err := region.DeleteBucket(name)
|
||||
if err != nil {
|
||||
if strings.Index(err.Error(), "bucket not found") >= 0 {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "region.DeleteBucket")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (region *SRegion) IBucketExist(name string) (bool, error) {
|
||||
parts, err := region.client.listBuckets(name, 0, 1)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "region.listBuckets")
|
||||
}
|
||||
if len(parts) == 0 {
|
||||
return false, cloudprovider.ErrNotFound
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketById(bucketId string) (cloudprovider.ICloudBucket, error) {
|
||||
return cloudprovider.GetIBucketById(region, bucketId)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIBucketByName(name string) (cloudprovider.ICloudBucket, error) {
|
||||
return region.GetIBucketByName(name)
|
||||
}
|
||||
|
||||
func (region *SRegion) GetCapabilities() []string {
|
||||
return region.client.GetCapabilities()
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
vms, err := region.GetInstances("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudVM{}
|
||||
for i := range vms {
|
||||
ret = append(ret, &vms[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
389
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/rockbase.go
generated
vendored
Normal file
389
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/rockbase.go
generated
vendored
Normal file
@@ -0,0 +1,389 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
/*
|
||||
UCLOUD 项目:https://docs.ucloud.cn/management_monitor/uproject/projects
|
||||
项目可认为是云账户下承载资源的容器,当您注册一个UCloud云账户后,系统会默认创建一个项目,您属于的资源都落在此项目下。如您有新的业务要使用云服务,可创建一个新项目,并将新业务部署在新项目下,实现业务之间的网络与逻辑隔离。
|
||||
|
||||
1、项目之间默认网络与逻辑隔离,即项目A的主机无法绑定项目B的EIP,默认也无法与项目B的主机内网通信。但联通项目后,uhost、udb、umem可实现内网通信。
|
||||
|
||||
2、资源不能在项目间迁移,即项目A内的主机无法迁移至项目B,因其不在一个基础网络内,且逻辑上也是隔离的。但诸如自主镜像等静态资源,您可以提交工单申请迁移至其他项目。
|
||||
|
||||
3、只有云账户本身,才能删除项目,且必须是项目被没有资源、没有任何子成员、未与其他项目联通的情况下才可删除。
|
||||
|
||||
|
||||
UCloud DiskType貌似也是一个奇葩的存在
|
||||
// https://docs.ucloud.cn/api/uhost-api/disk_type
|
||||
1.在主机创建查询接口中 DISK type 对应 CLOUD_SSD|CLOUD_NORMAL|...
|
||||
2.在数据盘创建中对应 DataDisk|SSDDataDisk
|
||||
3.在数据盘查询接口请求中对应 DataDisk|SystemDisk 。在结果中对应DataDisk|SSDDataDisk|SSDSystemDisk|SystemDisk
|
||||
|
||||
目前存在的问题:
|
||||
1.很多国外区域都需要单独申请开通权限才能使用。onecloud有可能调度到未开通权限区域导致失败。
|
||||
*/
|
||||
|
||||
const (
|
||||
CLOUD_PROVIDER_ROCKBASE = api.CLOUD_PROVIDER_ROCKBASE
|
||||
CLOUD_PROVIDER_ROCKBASE_CN = "RockBase"
|
||||
|
||||
ROCKBASE_DEFAULT_REGION = "hk"
|
||||
|
||||
ROCKBASE_API_VERSION = "2019-02-28"
|
||||
)
|
||||
|
||||
type RockbaseClientConfig struct {
|
||||
cpcfg cloudprovider.ProviderConfig
|
||||
|
||||
accessKeyId string
|
||||
accessKeySecret string
|
||||
projectId string
|
||||
|
||||
debug bool
|
||||
}
|
||||
|
||||
func NewRockbaseClientConfig(accessKeyId, accessKeySecret string) *RockbaseClientConfig {
|
||||
cfg := &RockbaseClientConfig{
|
||||
accessKeyId: accessKeyId,
|
||||
accessKeySecret: accessKeySecret,
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (cfg *RockbaseClientConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *RockbaseClientConfig {
|
||||
cfg.cpcfg = cpcfg
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (cfg *RockbaseClientConfig) ProjectId(projectId string) *RockbaseClientConfig {
|
||||
cfg.projectId = projectId
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (cfg *RockbaseClientConfig) Debug(debug bool) *RockbaseClientConfig {
|
||||
cfg.debug = debug
|
||||
return cfg
|
||||
}
|
||||
|
||||
type SRockbaseClient struct {
|
||||
*RockbaseClientConfig
|
||||
|
||||
iregions []cloudprovider.ICloudRegion
|
||||
iBuckets []cloudprovider.ICloudBucket
|
||||
|
||||
httpClient *http.Client
|
||||
}
|
||||
|
||||
// 进行资源操作时参数account 对应数据库cloudprovider表中的account字段,由accessKey和projectID两部分组成,通过"/"分割。
|
||||
// 初次导入Subaccount时,参数account对应cloudaccounts表中的account字段,即accesskey。此时projectID为空,只能进行同步子账号(项目)、查询region列表等projectId无关的操作。
|
||||
func NewRockbaseClient(cfg *RockbaseClientConfig) (*SRockbaseClient, error) {
|
||||
httpClient := cfg.cpcfg.AdaptiveTimeoutHttpClient()
|
||||
ts, _ := httpClient.Transport.(*http.Transport)
|
||||
httpClient.Transport = cloudprovider.GetCheckTransport(ts, func(req *http.Request) (func(resp *http.Response) error, error) {
|
||||
if cfg.cpcfg.ReadOnly {
|
||||
if req.ContentLength > 0 {
|
||||
body, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ioutil.ReadAll")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
|
||||
obj, err := jsonutils.Parse(body)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Parse request body")
|
||||
}
|
||||
action, err := obj.GetString("Action")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Get request action")
|
||||
}
|
||||
for _, prefix := range []string{"Get", "Describe", "List"} {
|
||||
if strings.HasPrefix(action, prefix) {
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrAccountReadOnly, "%s %s", req.Method, req.URL.Path)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
})
|
||||
client := SRockbaseClient{
|
||||
RockbaseClientConfig: cfg,
|
||||
httpClient: httpClient,
|
||||
}
|
||||
|
||||
err := client.fetchRegions()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = client.fetchBuckets()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &client, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) UpdateAccount(accessKey, secret string) error {
|
||||
if self.accessKeyId != accessKey || self.accessKeySecret != secret {
|
||||
self.accessKeyId = accessKey
|
||||
self.accessKeySecret = secret
|
||||
return self.fetchRegions()
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) commonParams(params SParams) SParams {
|
||||
if len(self.projectId) > 0 {
|
||||
params.Set("ProjectId", self.projectId)
|
||||
}
|
||||
params.Set("PublicKey", self.accessKeyId)
|
||||
return params
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) DoListAll(action string, params SParams, result interface{}) error {
|
||||
params = self.commonParams(params)
|
||||
return DoListAll(self, action, params, result)
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) DoListPart(action string, limit int, offset int, params SParams, result interface{}) (int, int, error) {
|
||||
params = self.commonParams(params)
|
||||
params.SetPagination(limit, offset)
|
||||
return doListPart(self, action, params, result)
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) DoAction(action string, params SParams, result interface{}) error {
|
||||
params = self.commonParams(params)
|
||||
err := DoAction(self, action, params, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) fetchRegions() error {
|
||||
params := NewRockbaseParams()
|
||||
sregions := make([]SRegion, 0)
|
||||
err := self.DoListAll("ListRegions", params, &sregions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
self.iregions = make([]cloudprovider.ICloudRegion, len(sregions))
|
||||
for i := range sregions {
|
||||
sregions[i].client = self
|
||||
self.iregions[i] = &sregions[i]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (client *SRockbaseClient) invalidateIBuckets() {
|
||||
client.iBuckets = nil
|
||||
}
|
||||
|
||||
func (client *SRockbaseClient) getIBuckets() ([]cloudprovider.ICloudBucket, error) {
|
||||
if client.iBuckets == nil {
|
||||
err := client.fetchBuckets()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetchBuckets")
|
||||
}
|
||||
}
|
||||
return client.iBuckets, nil
|
||||
}
|
||||
|
||||
func (client *SRockbaseClient) fetchBuckets() error {
|
||||
buckets := make([]SBucket, 0)
|
||||
offset := 0
|
||||
limit := 50
|
||||
for {
|
||||
parts, err := client.listBuckets("", offset, limit)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "client.listBuckets")
|
||||
}
|
||||
if len(parts) > 0 {
|
||||
buckets = append(buckets, parts...)
|
||||
}
|
||||
if len(parts) < limit {
|
||||
break
|
||||
} else {
|
||||
offset += limit
|
||||
}
|
||||
}
|
||||
ret := make([]cloudprovider.ICloudBucket, 0)
|
||||
for i := range buckets {
|
||||
region, err := client.getIRegionByRegionId(buckets[i].Region)
|
||||
if err != nil {
|
||||
log.Errorf("fail to find iregion %s", buckets[i].Region)
|
||||
continue
|
||||
}
|
||||
buckets[i].region = region.(*SRegion)
|
||||
ret = append(ret, &buckets[i])
|
||||
}
|
||||
|
||||
client.iBuckets = ret
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetRegions() []SRegion {
|
||||
regions := make([]SRegion, len(self.iregions))
|
||||
for i := 0; i < len(regions); i += 1 {
|
||||
region := self.iregions[i].(*SRegion)
|
||||
regions[i] = *region
|
||||
}
|
||||
return regions
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
projects, err := self.FetchProjects()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subAccounts := make([]cloudprovider.SSubAccount, 0)
|
||||
for _, project := range projects {
|
||||
subAccount := cloudprovider.SSubAccount{}
|
||||
subAccount.Id = project.ProjectID
|
||||
subAccount.Name = fmt.Sprintf("%s-%s", self.cpcfg.Name, project.ProjectName)
|
||||
// ucloud账号ID中可能包含/。因此使用::作为分割符号
|
||||
subAccount.Account = fmt.Sprintf("%s::%s", self.accessKeyId, project.ProjectID)
|
||||
subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL
|
||||
|
||||
subAccounts = append(subAccounts, subAccount)
|
||||
}
|
||||
|
||||
return subAccounts, nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetAccountId() string {
|
||||
return "" // no account ID found for ucloud
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetIRegions() ([]cloudprovider.ICloudRegion, error) {
|
||||
return self.iregions, nil
|
||||
}
|
||||
|
||||
func removeDigit(idstr string) string {
|
||||
for len(idstr) > 0 && idstr[len(idstr)-1] >= '0' && idstr[len(idstr)-1] <= '9' {
|
||||
idstr = idstr[:len(idstr)-1]
|
||||
}
|
||||
return idstr
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) getIRegionByRegionId(id string) (cloudprovider.ICloudRegion, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
if self.iregions[i].GetId() == id {
|
||||
return self.iregions[i], nil
|
||||
}
|
||||
}
|
||||
// retry
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
rid := removeDigit(self.iregions[i].GetId())
|
||||
rid2 := removeDigit(id)
|
||||
if rid == rid2 {
|
||||
return self.iregions[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
if self.iregions[i].GetGlobalId() == id {
|
||||
return self.iregions[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetRegion(regionId string) *SRegion {
|
||||
if len(regionId) == 0 {
|
||||
regionId = ROCKBASE_DEFAULT_REGION
|
||||
}
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
if self.iregions[i].GetId() == regionId {
|
||||
return self.iregions[i].(*SRegion)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIHostById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIVpcById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
for i := 0; i < len(self.iregions); i += 1 {
|
||||
ihost, err := self.iregions[i].GetIStorageById(id)
|
||||
if err == nil {
|
||||
return ihost, nil
|
||||
} else if errors.Cause(err) != cloudprovider.ErrNotFound {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRockbaseClient) GetCapabilities() []string {
|
||||
caps := []string{
|
||||
// cloudprovider.CLOUD_CAPABILITY_PROJECT,
|
||||
cloudprovider.CLOUD_CAPABILITY_COMPUTE,
|
||||
cloudprovider.CLOUD_CAPABILITY_NETWORK,
|
||||
cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
|
||||
cloudprovider.CLOUD_CAPABILITY_EIP,
|
||||
// cloudprovider.CLOUD_CAPABILITY_LOADBALANCER,
|
||||
// cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
|
||||
// cloudprovider.CLOUD_CAPABILITY_RDS,
|
||||
// cloudprovider.CLOUD_CAPABILITY_CACHE,
|
||||
// cloudprovider.CLOUD_CAPABILITY_EVENT,
|
||||
}
|
||||
return caps
|
||||
}
|
||||
99
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/secgrouprules.go
generated
vendored
Normal file
99
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/secgrouprules.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
)
|
||||
|
||||
type SecurityGroupRule struct {
|
||||
secgroup *SSecurityGroup
|
||||
|
||||
DstPort string `json:"DstPort"`
|
||||
Priority string `json:"Priority"`
|
||||
ProtocolType string `json:"ProtocolType"`
|
||||
RuleAction string `json:"RuleAction"`
|
||||
SrcIP string `json:"SrcIP"`
|
||||
Remark string
|
||||
}
|
||||
|
||||
func (self SecurityGroupRule) String() string {
|
||||
return fmt.Sprintf("%s|%s|%s|%s|%s|%s", self.ProtocolType, self.DstPort, self.SrcIP, self.RuleAction, self.Priority, self.Remark)
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s|%s|%s|%s|%s", self.Priority, self.RuleAction, self.SrcIP, self.DstPort, self.ProtocolType)
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetAction() secrules.TSecurityRuleAction {
|
||||
if self.RuleAction == "ACCEPT" {
|
||||
return secrules.SecurityRuleAllow
|
||||
}
|
||||
return secrules.SecurityRuleDeny
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetDescription() string {
|
||||
return self.Remark
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetDirection() secrules.TSecurityRuleDirection {
|
||||
return secrules.DIR_IN
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetCIDRs() []string {
|
||||
return []string{self.SrcIP}
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetProtocol() string {
|
||||
return strings.ToLower(self.ProtocolType)
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetPorts() string {
|
||||
return self.DstPort
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) GetPriority() int {
|
||||
switch self.Priority {
|
||||
case "HIGH":
|
||||
return 1
|
||||
case "MEDIUM":
|
||||
return 2
|
||||
case "LOW":
|
||||
return 3
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) Delete() error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("FWId", self.secgroup.FWID)
|
||||
idx := 0
|
||||
for _, rule := range self.secgroup.Rule {
|
||||
if rule.GetGlobalId() == self.GetGlobalId() {
|
||||
continue
|
||||
}
|
||||
params.Set(fmt.Sprintf("Rule.%d", idx), rule.String())
|
||||
idx++
|
||||
}
|
||||
return self.secgroup.region.DoAction("UpdateFirewall", params, nil)
|
||||
}
|
||||
|
||||
func (self *SecurityGroupRule) Update(opts *cloudprovider.SecurityGroupRuleUpdateOptions) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
214
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/securitygroup.go
generated
vendored
Normal file
214
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/securitygroup.go
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/describe_firewall
|
||||
type SSecurityGroup struct {
|
||||
multicloud.SSecurityGroup
|
||||
RockbaseTags
|
||||
region *SRegion
|
||||
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
FWID string `json:"FWId"`
|
||||
GroupID string `json:"GroupId"`
|
||||
Name string `json:"Name"`
|
||||
Remark string `json:"Remark"`
|
||||
ResourceCount int `json:"ResourceCount"`
|
||||
Rule []SecurityGroupRule `json:"Rule"`
|
||||
Tag string `json:"Tag"`
|
||||
Type string `json:"Type"`
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetProjectId() string {
|
||||
return self.region.client.projectId
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetId() string {
|
||||
return self.FWID
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetName() string {
|
||||
if len(self.Name) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetStatus() string {
|
||||
return api.SECGROUP_STATUS_READY
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) Refresh() error {
|
||||
group, err := self.region.GetSecurityGroup(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, group)
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetDescription() string {
|
||||
return self.Remark
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
|
||||
ret := []cloudprovider.ISecurityGroupRule{}
|
||||
for i := range self.Rule {
|
||||
self.Rule[i].secgroup = self
|
||||
ret = append(ret, &self.Rule[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetVpcId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSecurityGroup(secGroupId string) (*SSecurityGroup, error) {
|
||||
secgroups, err := self.GetSecurityGroups(secGroupId, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range secgroups {
|
||||
secgroups[i].region = self
|
||||
if secgroups[i].GetGlobalId() == secGroupId {
|
||||
return &secgroups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", secGroupId)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/unet-api/create_firewall
|
||||
func (self *SRegion) CreateSecurityGroup(name, description string) (string, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("Name", name)
|
||||
params.Set("Remark", description)
|
||||
|
||||
rules := []string{"TCP|22|0.0.0.0/0|ACCEPT|LOW", "TCP|3389|0.0.0.0/0|ACCEPT|LOW", "ICMP||0.0.0.0/0|ACCEPT|LOW"}
|
||||
for i, rule := range rules {
|
||||
params.Set(fmt.Sprintf("Rule.%d", i), rule)
|
||||
}
|
||||
|
||||
type Firewall struct {
|
||||
FWId string
|
||||
}
|
||||
|
||||
firewall := Firewall{}
|
||||
err := self.DoAction("CreateFirewall", params, &firewall)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return firewall.FWId, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("FWId", self.FWID)
|
||||
idx := 0
|
||||
for _, rule := range self.Rule {
|
||||
params.Set(fmt.Sprintf("Rule.%d", idx), rule.String())
|
||||
idx++
|
||||
}
|
||||
if len(opts.Ports) == 0 {
|
||||
opts.Ports = "1-65535"
|
||||
}
|
||||
if opts.Protocol == secrules.PROTO_ICMP || opts.Protocol == "gre" {
|
||||
opts.Ports = ""
|
||||
}
|
||||
if opts.Protocol == secrules.PROTO_ANY {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotSupported, "protocol any")
|
||||
}
|
||||
action := "DROP"
|
||||
if opts.Action == secrules.SecurityRuleAllow {
|
||||
action = "ACCEPT"
|
||||
}
|
||||
priority := "LOW"
|
||||
if opts.Priority == 1 {
|
||||
priority = "HIGH"
|
||||
} else if opts.Priority == 2 {
|
||||
priority = "MEDIUM"
|
||||
}
|
||||
rule := fmt.Sprintf("%s|%s|%s|%s|%s|%s", strings.ToUpper(opts.Protocol), opts.Ports, opts.CIDR, action, priority, opts.Desc)
|
||||
params.Set(fmt.Sprintf("Rule.%d", idx), rule)
|
||||
err := self.region.DoAction("UpdateFirewall", params, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = self.Refresh()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range self.Rule {
|
||||
if self.Rule[i].String() == rule {
|
||||
self.Rule[i].secgroup = self
|
||||
return &self.Rule[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSecurityGroups(secGroupId string, resourceId string, name string) ([]SSecurityGroup, error) {
|
||||
secgroups := make([]SSecurityGroup, 0)
|
||||
|
||||
params := NewRockbaseParams()
|
||||
if len(secGroupId) > 0 {
|
||||
params.Set("FWId", secGroupId)
|
||||
}
|
||||
|
||||
if len(resourceId) > 0 {
|
||||
params.Set("ResourceId", resourceId)
|
||||
params.Set("ResourceType", "uhost") // 默认只支持"uhost",云主机
|
||||
}
|
||||
err := self.DoListAll("DescribeFirewall", params, &secgroups)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "not exist") {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := []SSecurityGroup{}
|
||||
|
||||
for i := range secgroups {
|
||||
if len(name) == 0 || secgroups[i].Name == name {
|
||||
secgroups[i].region = self
|
||||
result = append(result, secgroups[i])
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) Delete() error {
|
||||
return self.region.DeleteSecurityGroup(self.FWID)
|
||||
}
|
||||
207
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/snapshot.go
generated
vendored
Normal file
207
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/snapshot.go
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/describe_udisk_snapshot
|
||||
type SSnapshot struct {
|
||||
multicloud.SResourceBase
|
||||
RockbaseTags
|
||||
region *SRegion
|
||||
|
||||
Comment string `json:"Comment"`
|
||||
ChargeType string `json:"ChargeType"`
|
||||
Name string `json:"Name"`
|
||||
UDiskName string `json:"UDiskName"`
|
||||
ExpiredTime int64 `json:"ExpiredTime"`
|
||||
UDiskID string `json:"UDiskId"`
|
||||
SnapshotID string `json:"SnapshotId"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
SizeGB int32 `json:"Size"`
|
||||
Status string `json:"Status"`
|
||||
IsUDiskAvailable bool `json:"IsUDiskAvailable"`
|
||||
Version string `json:"Version"`
|
||||
DiskType int `json:"DiskType"`
|
||||
UHostID string `json:"UHostId"`
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetProjectId() string {
|
||||
return self.region.client.projectId
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetId() string {
|
||||
return self.SnapshotID
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetName() string {
|
||||
if len(self.Name) == 0 {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
// 快照状态,Normal:正常,Failed:失败,Creating:制作中
|
||||
func (self *SSnapshot) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "Normal":
|
||||
return api.SNAPSHOT_READY
|
||||
case "Failed":
|
||||
return api.SNAPSHOT_FAILED
|
||||
case "Creating":
|
||||
return api.SNAPSHOT_CREATING
|
||||
default:
|
||||
return api.SNAPSHOT_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SSnapshot) Refresh() error {
|
||||
disk, err := self.region.GetDisk(self.UDiskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
snapshot, err := self.region.GetSnapshotById(disk.Zone, self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := jsonutils.Update(self, snapshot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SSnapshot) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetSizeMb() int32 {
|
||||
return self.SizeGB * 1024
|
||||
}
|
||||
|
||||
func (self *SSnapshot) GetDiskId() string {
|
||||
return self.UDiskID
|
||||
}
|
||||
|
||||
// 磁盘类型,0:数据盘,1:系统盘
|
||||
func (self *SSnapshot) GetDiskType() string {
|
||||
if self.DiskType == 1 {
|
||||
return api.DISK_TYPE_SYS
|
||||
} else {
|
||||
return api.DISK_TYPE_DATA
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/delete_udisk_snapshot
|
||||
func (self *SSnapshot) Delete() error {
|
||||
zoneId := ""
|
||||
idisk, err := self.region.GetDisk(self.UDiskID)
|
||||
if err == nil {
|
||||
zoneId = idisk.Zone
|
||||
} else if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
zones, err := self.region.GetIZones()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "snapshot.Delete GetIZones")
|
||||
}
|
||||
|
||||
for _, zone := range zones {
|
||||
if _, err := self.region.GetSnapshotById(zone.GetId(), self.GetId()); err == nil {
|
||||
zoneId = zone.GetId()
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return errors.Wrap(err, "snapshot.Delete")
|
||||
}
|
||||
|
||||
if len(zoneId) == 0 {
|
||||
return fmt.Errorf("snapshot.Delete can not found snapshot %s zone id", self.GetId())
|
||||
}
|
||||
|
||||
return self.region.DeleteSnapshot(self.GetId(), zoneId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshotById(zoneId string, snapshotId string) (SSnapshot, error) {
|
||||
snapshots, err := self.GetSnapshots(zoneId, "", snapshotId)
|
||||
if err != nil {
|
||||
return SSnapshot{}, err
|
||||
}
|
||||
|
||||
if len(snapshots) == 1 {
|
||||
return snapshots[0], nil
|
||||
} else if len(snapshots) == 0 {
|
||||
return SSnapshot{}, cloudprovider.ErrNotFound
|
||||
} else {
|
||||
return SSnapshot{}, fmt.Errorf("GetSnapshotById %s %d found", snapshotId, len(snapshots))
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSnapshots(zoneId string, diskId string, snapshotId string) ([]SSnapshot, error) {
|
||||
params := NewRockbaseParams()
|
||||
if len(diskId) > 0 {
|
||||
disk, err := self.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params.Set("UDiskId", diskId)
|
||||
params.Set("Zone", disk.Zone)
|
||||
}
|
||||
|
||||
if len(zoneId) > 0 {
|
||||
params.Set("Zone", zoneId)
|
||||
}
|
||||
|
||||
if len(snapshotId) > 0 {
|
||||
params.Set("SnapshotId", snapshotId)
|
||||
}
|
||||
|
||||
snapshots := make([]SSnapshot, 0)
|
||||
err := self.DoAction("DescribeUDiskSnapshot", params, &snapshots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range snapshots {
|
||||
snapshots[i].region = self
|
||||
}
|
||||
|
||||
return snapshots, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/delete_udisk_snapshot
|
||||
func (self *SRegion) DeleteSnapshot(snapshotId string, zoneId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("SnapshotId", snapshotId)
|
||||
params.Set("Zone", zoneId)
|
||||
|
||||
return self.DoAction("DeleteUDiskSnapshot", params, nil)
|
||||
}
|
||||
157
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/storage.go
generated
vendored
Normal file
157
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/storage.go
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SStorage struct {
|
||||
multicloud.SStorageBase
|
||||
RockbaseTags
|
||||
zone *SZone
|
||||
storageType string
|
||||
}
|
||||
|
||||
func (self *SStorage) GetId() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetName() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.cpcfg.Name, self.zone.GetId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetGlobalId(), self.storageType)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStatus() string {
|
||||
return api.STORAGE_ONLINE
|
||||
}
|
||||
|
||||
func (self *SStorage) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStorage) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return self.zone.region.getStoragecache()
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return self.zone
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
disks, err := self.zone.region.GetDisks(self.zone.GetId(), "", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
filtedDisks := make([]SDisk, 0)
|
||||
for _, disk := range disks {
|
||||
// ssd 盘
|
||||
if self.storageType == api.STORAGE_ROCKBASE_CLOUD_SSD && strings.Contains(disk.DiskType, "SSD") {
|
||||
filtedDisks = append(filtedDisks, disk)
|
||||
}
|
||||
|
||||
// 普通盘
|
||||
if self.storageType == api.STORAGE_ROCKBASE_CLOUD_NORMAL && !strings.Contains(disk.DiskType, "SSD") {
|
||||
filtedDisks = append(filtedDisks, disk)
|
||||
}
|
||||
}
|
||||
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(filtedDisks))
|
||||
for i := 0; i < len(filtedDisks); i += 1 {
|
||||
filtedDisks[i].storage = self
|
||||
idisks[i] = &filtedDisks[i]
|
||||
}
|
||||
return idisks, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageType() string {
|
||||
return self.storageType
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMediumType() string {
|
||||
if self.storageType == api.STORAGE_ROCKBASE_CLOUD_SSD {
|
||||
return api.DISK_TYPE_SSD
|
||||
} else {
|
||||
return api.DISK_TYPE_ROTATE
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SStorage) GetCapacityMB() int64 {
|
||||
return 0 // unlimited
|
||||
}
|
||||
|
||||
func (self *SStorage) GetCapacityUsedMB() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
return jsonutils.NewDict()
|
||||
}
|
||||
|
||||
func (self *SStorage) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SStorage) CreateIDisk(opts *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) {
|
||||
diskType := "DataDisk"
|
||||
switch self.storageType {
|
||||
case api.STORAGE_ROCKBASE_CLOUD_SSD:
|
||||
diskType = "SSDDataDisk"
|
||||
}
|
||||
diskId, err := self.zone.region.CreateDisk(self.zone.GetId(), diskType, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disk, err := self.zone.region.GetDisk(diskId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
disk.storage = self
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) {
|
||||
if disk, err := self.zone.region.GetDisk(idStr); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
disk.storage = self
|
||||
return disk, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMountPoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SStorage) IsSysDiskStore() bool {
|
||||
return true
|
||||
}
|
||||
376
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/storagecache.go
generated
vendored
Normal file
376
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/storagecache.go
generated
vendored
Normal file
@@ -0,0 +1,376 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/qemuimgfmt"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SStoragecache struct {
|
||||
multicloud.SResourceBase
|
||||
RockbaseTags
|
||||
region *SRegion
|
||||
}
|
||||
|
||||
func GetBucketName(regionId string, imageId string) string {
|
||||
return fmt.Sprintf("imgcache-%s-%s", strings.ToLower(regionId), strings.ToLower(imageId))
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.cpcfg.Id, self.region.GetId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetName() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.cpcfg.Name, self.region.GetId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.client.cpcfg.Id, self.region.GetGlobalId())
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetStatus() string {
|
||||
return "available"
|
||||
}
|
||||
|
||||
func (self *SStoragecache) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetICloudImages() ([]cloudprovider.ICloudImage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetICustomizedCloudImages() ([]cloudprovider.ICloudImage, error) {
|
||||
images, err := self.region.GetImages("", "Custom")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetImages")
|
||||
}
|
||||
ret := []cloudprovider.ICloudImage{}
|
||||
for i := range images {
|
||||
images[i].storageCache = self
|
||||
ret = append(ret, &images[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) {
|
||||
image, err := self.region.GetImage(extId)
|
||||
image.storageCache = self
|
||||
return &image, err
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/import_custom_image
|
||||
func (self *SStoragecache) UploadImage(ctx context.Context, image *cloudprovider.SImageCreateOption, callback func(progress float32)) (string, error) {
|
||||
return self.uploadImage(ctx, image, callback)
|
||||
}
|
||||
|
||||
func (self *SStoragecache) uploadImage(ctx context.Context, image *cloudprovider.SImageCreateOption, callback func(progress float32)) (string, error) {
|
||||
if len(image.OsVersion) == 0 {
|
||||
return "", fmt.Errorf("uploadImage os version is empty")
|
||||
}
|
||||
|
||||
bucketName := GetBucketName(self.region.GetId(), image.ImageId)
|
||||
|
||||
// create bucket
|
||||
exist, err := self.region.IBucketExist(bucketName)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "self.region.IBucketExist")
|
||||
}
|
||||
if !exist {
|
||||
err = self.region.CreateBucket(bucketName, "private")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "CreateBucket")
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
e := self.region.DeleteBucket(bucketName)
|
||||
if e != nil {
|
||||
log.Errorf("uploadImage delete bucket %s", e.Error())
|
||||
}
|
||||
}()
|
||||
|
||||
reader, size, err := image.GetReader(image.ImageId, string(qemuimgfmt.VMDK))
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "GetReader")
|
||||
}
|
||||
|
||||
minDiskGB := int64(math.Ceil(float64(image.MinDiskMb) / 1024))
|
||||
|
||||
if minDiskGB < 40 {
|
||||
minDiskGB = 40
|
||||
} else if minDiskGB > 1024 {
|
||||
minDiskGB = 1024
|
||||
}
|
||||
md5 := image.Checksum
|
||||
diskFormat := string(qemuimgfmt.QCOW2)
|
||||
// upload to ucloud
|
||||
bucket, err := self.region.GetIBucketById(bucketName)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "GetIBucketByName")
|
||||
}
|
||||
file := SFile{
|
||||
bucket: bucket.(*SBucket),
|
||||
file: multicloud.NewProgress(size, 98, reader, callback),
|
||||
|
||||
Size: size,
|
||||
FileName: image.ImageId,
|
||||
Hash: md5,
|
||||
}
|
||||
|
||||
err = file.Upload()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
e := file.Delete()
|
||||
if e != nil {
|
||||
log.Errorf("uploadImage delete object %s", e.Error())
|
||||
}
|
||||
}() // remove object
|
||||
|
||||
// check image name, avoid name conflict
|
||||
imageBaseName := image.ImageId
|
||||
if imageBaseName[0] >= '0' && imageBaseName[0] <= '9' {
|
||||
imageBaseName = fmt.Sprintf("img%s", image.ImageId)
|
||||
}
|
||||
imageName := imageBaseName
|
||||
nameIdx := 1
|
||||
|
||||
for {
|
||||
_, err = self.region.GetImageByName(imageName)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == cloudprovider.ErrNotFound {
|
||||
break
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
imageName = fmt.Sprintf("%s-%d", imageBaseName, nameIdx)
|
||||
nameIdx += 1
|
||||
log.Debugf("uploadImage Match remote name %s", imageName)
|
||||
}
|
||||
|
||||
imgId, err := self.region.ImportImage(imageName, file.FetchFileUrl(), image.OsDistribution, image.OsVersion, diskFormat)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("ImportImage error %s %s", file.FetchFileUrl(), err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
// timeout: 1hour = 3600 seconds
|
||||
err = cloudprovider.WaitCreated(60*time.Second, 3600*time.Second, func() bool {
|
||||
image, err := self.region.GetImage(imgId)
|
||||
if err == nil && image.State == "Available" {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "UploadImage")
|
||||
}
|
||||
if callback != nil {
|
||||
callback(100)
|
||||
}
|
||||
return imgId, err
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/create_custom_image
|
||||
func (self *SRegion) createIImage(snapshotId, imageName, imageDesc string) (string, error) {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
/*func (self *SRegion) GetBucketDomain(name string) (string, error) {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("BucketName", name)
|
||||
|
||||
res := make([]SBucket, 0)
|
||||
err := self.client.DoListAll("DescribeBucket", params, &res)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if len(res) == 1 && len(res[0].Domain.Src) >= 1 {
|
||||
return res[0].Domain.Src[0], nil
|
||||
} else {
|
||||
return "", fmt.Errorf("GetBucketDomain failed. %v", res)
|
||||
}
|
||||
}*/
|
||||
|
||||
// https://docs.ucloud.cn/api/ufile-api/create_bucket
|
||||
func (self *SRegion) CreateBucket(name, bucketType string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("BucketName", name)
|
||||
params.Set("Type", bucketType)
|
||||
err := self.DoAction("CreateBucket", params, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.client.invalidateIBuckets()
|
||||
return nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/ufile-api/delete_bucket
|
||||
func (self *SRegion) DeleteBucket(name string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("BucketName", name)
|
||||
err := self.DoAction("DeleteBucket", params, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
self.client.invalidateIBuckets()
|
||||
return nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/ufile-api/put_file
|
||||
func (self *SRegion) uploadObj(name string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("BucketName", name)
|
||||
return self.DoAction("PutFile", params, nil)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImageByName(name string) (*SImage, error) {
|
||||
images, err := self.GetImages("Custom", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range images {
|
||||
if images[i].GetName() == name {
|
||||
return &images[i], nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func normalizeOsType(osType string) string {
|
||||
switch strings.ToLower(osType) {
|
||||
case "centos":
|
||||
return "CentOS"
|
||||
case "ubuntu":
|
||||
return "Ubuntu"
|
||||
case "windows":
|
||||
return "Windows"
|
||||
case "redHat":
|
||||
return "RedHat"
|
||||
case "debian":
|
||||
return "Debian"
|
||||
default:
|
||||
return "Other"
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeOsName(normalizeOsType string, fullVersion string) string {
|
||||
if utils.IsInStringArray(normalizeOsType, []string{"CentOS", "RedHat", "Debian"}) {
|
||||
if len(fullVersion) >= 3 {
|
||||
return fmt.Sprintf("%s %s 64位", normalizeOsType, fullVersion[0:3])
|
||||
} else {
|
||||
return fmt.Sprintf("%s %s.0 64位", normalizeOsType, fullVersion[0:1])
|
||||
}
|
||||
}
|
||||
|
||||
if normalizeOsType == "Ubuntu" {
|
||||
if len(fullVersion) >= 5 {
|
||||
return fmt.Sprintf("Ubuntu %s 64位", fullVersion[0:5])
|
||||
} else if len(fullVersion) >= 2 {
|
||||
return fmt.Sprintf("Ubuntu %s.04 64位", fullVersion[0:2])
|
||||
} else {
|
||||
// 默认猜一个?
|
||||
return "Ubuntu 14.04 64位"
|
||||
}
|
||||
}
|
||||
|
||||
if normalizeOsType == "Windows" {
|
||||
if len(fullVersion) >= 4 {
|
||||
return fmt.Sprintf("Windows %s 64位", fullVersion[0:4])
|
||||
} else {
|
||||
// 默认猜一个?
|
||||
return "Windows 2016 64位"
|
||||
}
|
||||
}
|
||||
|
||||
return "Other"
|
||||
}
|
||||
|
||||
func normalizeDiskFormat(diskFormat string) (string, error) {
|
||||
switch strings.ToLower(diskFormat) {
|
||||
case "raw":
|
||||
return "RAW", nil
|
||||
case "vhd":
|
||||
return "VHD", nil
|
||||
case "vmdk":
|
||||
return "VMDK", nil
|
||||
case "qcow2":
|
||||
return "qcow2", nil
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported image format %s", diskFormat)
|
||||
}
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/import_custom_image
|
||||
func (self *SRegion) ImportImage(name string, ufileUrl string, osType string, osVersion string, diskFormat string) (string, error) {
|
||||
format, err := normalizeDiskFormat(diskFormat)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
nOsType := normalizeOsType(osType)
|
||||
|
||||
params := NewRockbaseParams()
|
||||
params.Set("ImageName", name)
|
||||
params.Set("UFileUrl", ufileUrl)
|
||||
// 操作系统平台,比如CentOS、Ubuntu、Windows、RedHat等,请参考控制台的镜像版本;若导入控制台上没有的操作系统,参数为Other
|
||||
params.Set("OsType", nOsType)
|
||||
// 操作系统详细版本,请参考控制台的镜像版本;OsType为Other时,输入参数为Other
|
||||
params.Set("OsName", normalizeOsName(nOsType, osVersion))
|
||||
params.Set("Format", format)
|
||||
params.Set("Auth", "True")
|
||||
params.Set("ImageDescription", osVersion)
|
||||
|
||||
type SImageId struct {
|
||||
ImageId string
|
||||
}
|
||||
|
||||
ret := SImageId{}
|
||||
log.Debugf("ImportImage with params %s", params.String())
|
||||
err = self.DoAction("ImportCustomImage", params, &ret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return ret.ImageId, nil
|
||||
}
|
||||
36
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/tag_base.go
generated
vendored
Normal file
36
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/tag_base.go
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
type RockbaseTags struct {
|
||||
}
|
||||
|
||||
func (self *RockbaseTags) GetTags() (map[string]string, error) {
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "GetTags")
|
||||
}
|
||||
|
||||
func (self *RockbaseTags) GetSysTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *RockbaseTags) SetTags(tags map[string]string, replace bool) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags")
|
||||
}
|
||||
394
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/ufile.go
generated
vendored
Normal file
394
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/ufile.go
generated
vendored
Normal file
@@ -0,0 +1,394 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/httputils"
|
||||
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SBucket struct {
|
||||
multicloud.SBaseBucket
|
||||
RockbaseTags
|
||||
|
||||
region *SRegion
|
||||
|
||||
// projectId string
|
||||
|
||||
Domain Domain `json:"Domain"`
|
||||
BucketID string `json:"BucketId"`
|
||||
Region string `json:"Region"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
Biz string `json:"Biz"`
|
||||
BucketName string `json:"BucketName"`
|
||||
ModifyTime int64 `json:"ModifyTime"`
|
||||
Type string `json:"Type"`
|
||||
Tag string `json:"Tag"`
|
||||
HasUserDomain int64 `json:"HasUserDomain"`
|
||||
CDNDomainID []string `json:"CdnDomainId"`
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
Src []string `json:"Src"`
|
||||
CDN []string `json:"Cdn"`
|
||||
CustomCDN []interface{} `json:"CustomCdn"`
|
||||
CustomSrc []interface{} `json:"CustomSrc"`
|
||||
}
|
||||
|
||||
type SFile struct {
|
||||
bucket *SBucket
|
||||
|
||||
BucketName string `json:"BucketName"`
|
||||
FileName string `json:"FileName"`
|
||||
Size int64 `json:"Size"`
|
||||
Hash string `json:"Hash"`
|
||||
MimeType string `json:"MimeType"`
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
ModifyTime int64 `json:"ModifyTime"`
|
||||
StorageClass string `json:"StorageClass"`
|
||||
|
||||
file io.Reader
|
||||
}
|
||||
|
||||
func (client *SRockbaseClient) signHeader(httpMethod string, path string, md5 string) string {
|
||||
contentType := ""
|
||||
if httpMethod == http.MethodPut {
|
||||
contentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
data := httpMethod + "\n"
|
||||
data += md5 + "\n"
|
||||
data += contentType + "\n"
|
||||
data += "\n"
|
||||
data += path
|
||||
|
||||
log.Debugf("sign %s", data)
|
||||
h := hmac.New(sha1.New, []byte(client.accessKeySecret))
|
||||
h.Write([]byte(data))
|
||||
return base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func (self *SFile) signHeader(httpMethod string) string {
|
||||
return self.bucket.region.client.signHeader(httpMethod, "/"+self.bucket.BucketName+"/"+self.FileName, self.Hash)
|
||||
}
|
||||
|
||||
func (self *SFile) auth(httpMethod string) string {
|
||||
return "UCloud" + " " + self.bucket.region.client.accessKeyId + ":" + self.signHeader(httpMethod)
|
||||
}
|
||||
|
||||
func (self *SFile) GetHost() string {
|
||||
return self.bucket.Domain.Src[0]
|
||||
}
|
||||
|
||||
func (self *SFile) GetUrl() string {
|
||||
return fmt.Sprintf("http://%s/%s", self.GetHost(), self.FileName)
|
||||
}
|
||||
|
||||
// https://github.com/ufilesdk-dev/ufile-gosdk/blob/master/auth.go
|
||||
func (self *SFile) FetchFileUrl() string {
|
||||
expired := strconv.FormatInt(time.Now().Add(6*time.Hour).Unix(), 10)
|
||||
// sign
|
||||
data := "GET\n\n\n" + expired + "\n"
|
||||
data += "/" + self.bucket.BucketName + "/" + self.FileName
|
||||
h := hmac.New(sha1.New, []byte(self.bucket.region.client.accessKeySecret))
|
||||
h.Write([]byte(data))
|
||||
sign := base64.StdEncoding.EncodeToString(h.Sum(nil))
|
||||
|
||||
urlEncoder := url.Values{}
|
||||
urlEncoder.Add("UCloudPublicKey", self.bucket.region.client.accessKeyId)
|
||||
urlEncoder.Add("Signature", sign)
|
||||
urlEncoder.Add("Expires", expired)
|
||||
querys := urlEncoder.Encode()
|
||||
return fmt.Sprintf("%s?%s", self.GetUrl(), querys)
|
||||
}
|
||||
|
||||
func (self *SFile) Upload() error {
|
||||
req, _ := http.NewRequest(http.MethodPut, self.GetUrl(), self.file)
|
||||
req.Header.Add("Authorization", self.auth(http.MethodPut))
|
||||
req.Header.Add("Content-MD5", self.Hash)
|
||||
req.Header.Add("Content-Type", "application/octet-stream")
|
||||
req.Header.Add("Content-Length", strconv.FormatInt(self.Size, 10))
|
||||
_, err := doRequest(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SFile) Delete() error {
|
||||
req, _ := http.NewRequest(http.MethodDelete, self.GetUrl(), nil)
|
||||
req.Header.Add("Authorization", self.auth(http.MethodDelete))
|
||||
_, err := doRequest(req)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SFile) GetIBucket() cloudprovider.ICloudBucket {
|
||||
return self.bucket
|
||||
}
|
||||
|
||||
func (self *SFile) GetKey() string {
|
||||
return self.FileName
|
||||
}
|
||||
|
||||
func (self *SFile) GetSizeBytes() int64 {
|
||||
return self.Size
|
||||
}
|
||||
|
||||
func (self *SFile) GetLastModified() time.Time {
|
||||
return time.Unix(self.ModifyTime, 0)
|
||||
}
|
||||
|
||||
func (self *SFile) GetStorageClass() string {
|
||||
return self.StorageClass
|
||||
}
|
||||
|
||||
func (self *SFile) GetETag() string {
|
||||
return self.Hash
|
||||
}
|
||||
|
||||
func (self *SFile) GetContentType() string {
|
||||
return self.MimeType
|
||||
}
|
||||
|
||||
func (self *SFile) GetAcl() cloudprovider.TBucketACLType {
|
||||
return self.bucket.GetAcl()
|
||||
}
|
||||
|
||||
func (self *SFile) SetAcl(cloudprovider.TBucketACLType) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SFile) GetMeta() http.Header {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SFile) SetMeta(ctx context.Context, meta http.Header) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func doRequest(req *http.Request) (jsonutils.JSONObject, error) {
|
||||
// ufile request use no timeout client so as to download/upload large files
|
||||
res, err := httputils.GetAdaptiveTimeoutClient().Do(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "httpclient Do")
|
||||
}
|
||||
_, body, err := httputils.ParseJSONResponse("", res, err, false)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ParseJSONResponse")
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type sPrefixFileListOutput struct {
|
||||
BucketName string
|
||||
BucketId string
|
||||
NextMarker string
|
||||
DataSet []SFile
|
||||
}
|
||||
|
||||
func (b *SBucket) doPrefixFileList(prefix string, marker string, limit int) (*sPrefixFileListOutput, error) {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(""), "list")
|
||||
if len(prefix) > 0 {
|
||||
params.Add(jsonutils.NewString(prefix), "prefix")
|
||||
}
|
||||
if len(marker) > 0 {
|
||||
params.Add(jsonutils.NewString(marker), "marker")
|
||||
}
|
||||
if limit > 0 {
|
||||
params.Add(jsonutils.NewInt(int64(limit)), "limit")
|
||||
}
|
||||
host := fmt.Sprintf("https://%s.ufile.ucloud.cn", b.BucketName)
|
||||
path := fmt.Sprintf("/?%s", params.QueryString())
|
||||
|
||||
log.Debugf("Request %s%s", host, path)
|
||||
|
||||
req, _ := http.NewRequest(http.MethodGet, host+path, nil)
|
||||
|
||||
sign := b.region.client.signHeader(http.MethodGet, path, "")
|
||||
auth := "UCloud" + " " + b.region.client.accessKeyId + ":" + sign
|
||||
|
||||
req.Header.Add("Authorization", auth)
|
||||
|
||||
output := sPrefixFileListOutput{}
|
||||
|
||||
body, err := doRequest(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "doRequest")
|
||||
}
|
||||
err = body.Unmarshal(&output)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "body.Unmarshal")
|
||||
}
|
||||
|
||||
return &output, nil
|
||||
}
|
||||
|
||||
func (b *SBucket) GetProjectId() string {
|
||||
return b.region.client.projectId
|
||||
}
|
||||
|
||||
func (b *SBucket) GetGlobalId() string {
|
||||
return b.BucketID
|
||||
}
|
||||
|
||||
func (b *SBucket) GetName() string {
|
||||
return b.BucketName
|
||||
}
|
||||
|
||||
func (b *SBucket) GetLocation() string {
|
||||
return b.region.GetId()
|
||||
}
|
||||
|
||||
func (b *SBucket) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return b.region
|
||||
}
|
||||
|
||||
func (b *SBucket) GetCreatedAt() time.Time {
|
||||
return time.Unix(b.CreateTime, 0)
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStorageClass() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAcl() cloudprovider.TBucketACLType {
|
||||
switch b.Type {
|
||||
case "public":
|
||||
return cloudprovider.ACLPublicRead
|
||||
default:
|
||||
return cloudprovider.ACLPrivate
|
||||
}
|
||||
}
|
||||
|
||||
func (b *SBucket) SetAcl(aclStr cloudprovider.TBucketACLType) error {
|
||||
aclType := "private"
|
||||
if aclStr == cloudprovider.ACLPublicRead || aclStr == cloudprovider.ACLPublicReadWrite {
|
||||
aclType = "public"
|
||||
}
|
||||
return b.region.updateBucket(b.BucketName, aclType)
|
||||
}
|
||||
|
||||
func (b *SBucket) getSrcUrl() string {
|
||||
if len(b.Domain.Src) > 0 {
|
||||
return b.Domain.Src[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *SBucket) GetAccessUrls() []cloudprovider.SBucketAccessUrl {
|
||||
ret := make([]cloudprovider.SBucketAccessUrl, 0)
|
||||
for i, u := range b.Domain.Src {
|
||||
primary := false
|
||||
if i == 0 {
|
||||
primary = true
|
||||
}
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: u,
|
||||
Description: fmt.Sprintf("src%d", i),
|
||||
Primary: primary,
|
||||
})
|
||||
}
|
||||
for i, u := range b.Domain.CDN {
|
||||
ret = append(ret, cloudprovider.SBucketAccessUrl{
|
||||
Url: u,
|
||||
Description: fmt.Sprintf("cdn%d", i),
|
||||
})
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *SBucket) GetStats() cloudprovider.SBucketStats {
|
||||
stats, _ := cloudprovider.GetIBucketStats(b)
|
||||
return stats
|
||||
}
|
||||
|
||||
func (b *SBucket) ListObjects(prefix string, marker string, delimiter string, maxCount int) (cloudprovider.SListObjectResult, error) {
|
||||
result := cloudprovider.SListObjectResult{}
|
||||
|
||||
output, err := b.doPrefixFileList(prefix, marker, maxCount)
|
||||
if err != nil {
|
||||
return result, errors.Wrap(err, "b.doPrefixFileList")
|
||||
}
|
||||
|
||||
if len(output.NextMarker) > 0 {
|
||||
result.NextMarker = output.NextMarker
|
||||
result.IsTruncated = true
|
||||
}
|
||||
|
||||
result.Objects = make([]cloudprovider.ICloudObject, len(output.DataSet))
|
||||
for i := range output.DataSet {
|
||||
result.Objects[i] = &output.DataSet[i]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (b *SBucket) PutObject(ctx context.Context, key string, input io.Reader, sizeBytes int64, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) NewMultipartUpload(ctx context.Context, key string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) (string, error) {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) UploadPart(ctx context.Context, key string, uploadId string, partIndex int, input io.Reader, partSize int64, offset, totalSize int64) (string, error) {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) CompleteMultipartUpload(ctx context.Context, key string, uploadId string, partEtags []string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) AbortMultipartUpload(ctx context.Context, key string, uploadId string) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) DeleteObject(ctx context.Context, key string) error {
|
||||
file := SFile{
|
||||
bucket: b,
|
||||
FileName: key,
|
||||
}
|
||||
return file.Delete()
|
||||
}
|
||||
|
||||
func (b *SBucket) GetTempUrl(method string, key string, expire time.Duration) (string, error) {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) CopyObject(ctx context.Context, destKey string, srcBucket, srcKey string, cannedAcl cloudprovider.TBucketACLType, storageClassStr string, meta http.Header) error {
|
||||
return cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) GetObject(ctx context.Context, key string, rangeOpt *cloudprovider.SGetObjectRange) (io.ReadCloser, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (b *SBucket) CopyPart(ctx context.Context, key string, uploadId string, partIndex int, srcBucketName string, srcKey string, srcOffset int64, srcLength int64) (string, error) {
|
||||
return "", cloudprovider.ErrNotSupported
|
||||
}
|
||||
180
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/utils.go
generated
vendored
Normal file
180
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/utils.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
)
|
||||
|
||||
var responseMetaKeys = map[string]bool{
|
||||
"RetCode": true,
|
||||
"Message": true,
|
||||
"Action": true,
|
||||
"TotalCount": true,
|
||||
}
|
||||
|
||||
func detectResultKey(resp jsonutils.JSONObject, result interface{}) string {
|
||||
if result == nil {
|
||||
return ""
|
||||
}
|
||||
rt := reflect.TypeOf(result)
|
||||
if rt.Kind() != reflect.Ptr {
|
||||
return ""
|
||||
}
|
||||
et := rt.Elem()
|
||||
switch et.Kind() {
|
||||
case reflect.Slice:
|
||||
if et.Elem().Kind() == reflect.String {
|
||||
return detectStringResultKey(resp)
|
||||
}
|
||||
return detectArrayResultKey(resp)
|
||||
case reflect.String:
|
||||
return detectStringResultKey(resp)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func detectStringResultKey(resp jsonutils.JSONObject) string {
|
||||
dict, ok := resp.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
for _, key := range dict.SortedKeys() {
|
||||
if responseMetaKeys[key] {
|
||||
continue
|
||||
}
|
||||
if strings.HasSuffix(key, "Id") || strings.HasSuffix(key, "Ids") {
|
||||
return key
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func detectArrayResultKey(resp jsonutils.JSONObject) string {
|
||||
dict, ok := resp.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
candidates := []string{}
|
||||
for _, key := range dict.SortedKeys() {
|
||||
if responseMetaKeys[key] {
|
||||
continue
|
||||
}
|
||||
val, _ := dict.Get(key)
|
||||
if val == nil {
|
||||
continue
|
||||
}
|
||||
if _, ok := val.(*jsonutils.JSONArray); ok {
|
||||
candidates = append(candidates, key)
|
||||
}
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
return ""
|
||||
}
|
||||
if len(candidates) == 1 {
|
||||
return candidates[0]
|
||||
}
|
||||
for _, key := range candidates {
|
||||
if strings.HasSuffix(key, "Set") {
|
||||
return key
|
||||
}
|
||||
}
|
||||
return candidates[0]
|
||||
}
|
||||
|
||||
func unmarshalResult(resp jsonutils.JSONObject, respErr error, result interface{}) error {
|
||||
if respErr != nil {
|
||||
return respErr
|
||||
}
|
||||
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
resultKey := detectResultKey(resp, result)
|
||||
if len(resultKey) > 0 {
|
||||
respErr = resp.Unmarshal(result, resultKey)
|
||||
} else {
|
||||
respErr = resp.Unmarshal(result)
|
||||
}
|
||||
|
||||
if respErr != nil {
|
||||
log.Errorf("unmarshal json error %s", respErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func doListPart(client *SRockbaseClient, action string, params SParams, result interface{}) (int, int, error) {
|
||||
params.SetAction(action)
|
||||
ret, err := jsonRequest(client, params)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
total, _ := ret.Int("TotalCount")
|
||||
|
||||
resultKey := detectResultKey(ret, result)
|
||||
lst, err := ret.GetArray(resultKey)
|
||||
if err != nil {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
||||
resultValue := reflect.Indirect(reflect.ValueOf(result))
|
||||
elemType := resultValue.Type().Elem()
|
||||
for i := range lst {
|
||||
elemPtr := reflect.New(elemType)
|
||||
err = lst[i].Unmarshal(elemPtr.Interface())
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
resultValue.Set(reflect.Append(resultValue, elemPtr.Elem()))
|
||||
}
|
||||
return int(total), len(lst), nil
|
||||
}
|
||||
|
||||
// 执行操作
|
||||
func DoAction(client *SRockbaseClient, action string, params SParams, result interface{}) error {
|
||||
params.SetAction(action)
|
||||
resp, err := jsonRequest(client, params)
|
||||
return unmarshalResult(resp, err, result)
|
||||
}
|
||||
|
||||
// 遍历所有结果
|
||||
func DoListAll(client *SRockbaseClient, action string, params SParams, result interface{}) error {
|
||||
pageLimit := 100
|
||||
offset := 0
|
||||
|
||||
resultValue := reflect.Indirect(reflect.ValueOf(result))
|
||||
params.SetPagination(pageLimit, offset)
|
||||
for {
|
||||
total, part, err := doListPart(client, action, params, result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// total 大于零的情况下通过total字段判断列表是否遍历完成。total不存在或者为0的情况下,通过返回列表的长度判断是否遍历完成
|
||||
if (total > 0 && resultValue.Len() >= total) || (total == 0 && pageLimit > part) {
|
||||
break
|
||||
}
|
||||
|
||||
params.SetPagination(pageLimit, offset+resultValue.Len())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
119
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/vip.go
generated
vendored
Normal file
119
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/vip.go
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SVipAddr struct {
|
||||
VIP string
|
||||
SubnetId string
|
||||
}
|
||||
|
||||
func (ip *SVipAddr) GetIP() string {
|
||||
return ip.VIP
|
||||
}
|
||||
|
||||
func (ip *SVipAddr) GetINetworkId() string {
|
||||
return ip.SubnetId
|
||||
}
|
||||
|
||||
func (ip *SVipAddr) IsPrimary() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (ip *SVipAddr) GetGlobalId() string {
|
||||
return ip.VIP
|
||||
}
|
||||
|
||||
type SVip struct {
|
||||
multicloud.SNetworkInterfaceBase
|
||||
RockbaseTags
|
||||
region *SRegion
|
||||
CreateTime int64
|
||||
Name string
|
||||
RealIp string
|
||||
Remark string
|
||||
SubnetId string
|
||||
Tag string
|
||||
VIP string
|
||||
VIPId string
|
||||
VPCId string
|
||||
Zone string
|
||||
}
|
||||
|
||||
func (vip *SVip) GetName() string {
|
||||
if len(vip.Name) > 0 {
|
||||
return vip.Name
|
||||
}
|
||||
return vip.VIPId
|
||||
}
|
||||
|
||||
func (vip *SVip) GetId() string {
|
||||
return vip.VIPId
|
||||
}
|
||||
|
||||
func (vip *SVip) GetGlobalId() string {
|
||||
return vip.VIPId
|
||||
}
|
||||
|
||||
func (vip *SVip) GetMacAddress() string {
|
||||
ip, _ := netutils.NewIPV4Addr(vip.VIP)
|
||||
return ip.ToMac("00:16:")
|
||||
}
|
||||
|
||||
func (vip *SVip) GetAssociateType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (vip *SVip) GetAssociateId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (vip *SVip) GetStatus() string {
|
||||
return api.NETWORK_INTERFACE_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (vip *SVip) GetICloudInterfaceAddresses() ([]cloudprovider.ICloudInterfaceAddress, error) {
|
||||
ip := &SVipAddr{VIP: vip.VIP, SubnetId: vip.SubnetId}
|
||||
return []cloudprovider.ICloudInterfaceAddress{ip}, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) GetINetworkInterfaces() ([]cloudprovider.ICloudNetworkInterface, error) {
|
||||
vips, err := region.GetVips()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "region.GetVips")
|
||||
}
|
||||
ret := []cloudprovider.ICloudNetworkInterface{}
|
||||
for i := 0; i < len(vips); i++ {
|
||||
vips[i].region = region
|
||||
ret = append(ret, &vips[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetVips() ([]SVip, error) {
|
||||
vips := []SVip{}
|
||||
params := NewRockbaseParams()
|
||||
|
||||
err := self.DoListAll("DescribeVIP", params, &vips)
|
||||
return vips, err
|
||||
}
|
||||
173
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/vpc.go
generated
vendored
Normal file
173
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/vpc.go
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
type SVPC struct {
|
||||
multicloud.SVpc
|
||||
RockbaseTags
|
||||
|
||||
region *SRegion
|
||||
|
||||
CreateTime int64 `json:"CreateTime"`
|
||||
Name string `json:"Name"`
|
||||
Network []string `json:"Network"`
|
||||
NetworkInfo []NetworkInfo `json:"NetworkInfo"`
|
||||
SubnetCount int `json:"SubnetCount"`
|
||||
Tag string `json:"Tag"`
|
||||
UpdateTime int64 `json:"UpdateTime"`
|
||||
VpcId string `json:"VPCId"`
|
||||
}
|
||||
|
||||
type NetworkInfo struct {
|
||||
Network string `json:"Network"`
|
||||
SubnetCount int `json:"SubnetCount"`
|
||||
}
|
||||
|
||||
func (self *SVPC) GetId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVPC) GetName() string {
|
||||
if len(self.Name) > 0 {
|
||||
return self.Name
|
||||
}
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVPC) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SVPC) GetStatus() string {
|
||||
return api.VPC_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SVPC) Refresh() error {
|
||||
new, err := self.region.GetVpc(self.GetId())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return jsonutils.Update(self, new)
|
||||
}
|
||||
|
||||
func (self *SVPC) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SVPC) GetRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SVPC) GetIsDefault() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SVPC) GetCidrBlock() string {
|
||||
return strings.Join(self.Network, ",")
|
||||
}
|
||||
|
||||
func (self *SVPC) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
return []cloudprovider.ICloudWire{&SWire{vpc: self}}, nil
|
||||
}
|
||||
|
||||
// 由于Ucloud 安全组和vpc没有直接关联,这里是返回同一个项目下的防火墙列表,会导致重复同步的问题。
|
||||
// https://docs.ucloud.cn/api/unet-api/grant_firewall
|
||||
func (self *SVPC) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
|
||||
return []cloudprovider.ICloudSecurityGroup{}, nil
|
||||
}
|
||||
|
||||
func (self *SVPC) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
|
||||
rts := []cloudprovider.ICloudRouteTable{}
|
||||
return rts, nil
|
||||
}
|
||||
|
||||
func (self *SVPC) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRouteTable, error) {
|
||||
return nil, cloudprovider.ErrNotSupported
|
||||
}
|
||||
|
||||
func (self *SVPC) Delete() error {
|
||||
return self.region.DeleteVpc(self.GetId())
|
||||
}
|
||||
|
||||
func (self *SVPC) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
|
||||
wires, err := self.GetIWires()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(wires); i += 1 {
|
||||
if wires[i].GetGlobalId() == wireId {
|
||||
return wires[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SRegion) GetVpc(vpcId string) (*SVPC, error) {
|
||||
if len(vpcId) == 0 {
|
||||
return nil, errors.Wrap(cloudprovider.ErrNotFound, "empty vpc id")
|
||||
}
|
||||
vpcs, err := self.GetVpcs(vpcId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetVpcs")
|
||||
}
|
||||
for i := range vpcs {
|
||||
if vpcs[i].VpcId == vpcId {
|
||||
vpcs[i].region = self
|
||||
return &vpcs[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", vpcId)
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/delete_vpc
|
||||
func (self *SRegion) DeleteVpc(vpcId string) error {
|
||||
params := NewRockbaseParams()
|
||||
params.Set("VPCId", vpcId)
|
||||
return self.DoAction("DeleteVPC", params, nil)
|
||||
}
|
||||
|
||||
// https://support.huaweicloud.com/api-vpc/zh-cn_topic_0020090625.html
|
||||
func (self *SRegion) GetVpcs(vpcId string) ([]SVPC, error) {
|
||||
vpcs := make([]SVPC, 0)
|
||||
params := NewRockbaseParams()
|
||||
if len(vpcId) > 0 {
|
||||
params.Set("VPCIds.0", vpcId)
|
||||
}
|
||||
|
||||
err := self.DoListAll("DescribeVPC", params, &vpcs)
|
||||
return vpcs, err
|
||||
}
|
||||
|
||||
func (self *SRegion) GetNetworks(vpcId string) ([]SNetwork, error) {
|
||||
params := NewRockbaseParams()
|
||||
if len(vpcId) > 0 {
|
||||
params.Set("VPCId", vpcId)
|
||||
}
|
||||
|
||||
networks := make([]SNetwork, 0)
|
||||
err := self.DoAction("DescribeSubnet", params, &networks)
|
||||
return networks, err
|
||||
}
|
||||
97
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/wire.go
generated
vendored
Normal file
97
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/wire.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// 子网在整个region可用
|
||||
type SWire struct {
|
||||
multicloud.SResourceBase
|
||||
RockbaseTags
|
||||
vpc *SVPC
|
||||
}
|
||||
|
||||
func (self *SWire) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.vpc.GetId(), self.vpc.region.GetId())
|
||||
}
|
||||
|
||||
func (self *SWire) GetName() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SWire) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s-%s", self.vpc.GetGlobalId(), self.vpc.region.GetGlobalId())
|
||||
}
|
||||
|
||||
func (self *SWire) GetStatus() string {
|
||||
return api.WIRE_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SWire) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SWire) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SWire) GetIVpc() cloudprovider.ICloudVpc {
|
||||
return self.vpc
|
||||
}
|
||||
|
||||
func (self *SWire) GetIZone() cloudprovider.ICloudZone {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
|
||||
networks, err := self.vpc.region.GetNetworks(self.vpc.GetId())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudNetwork{}
|
||||
for i := range networks {
|
||||
networks[i].wire = self
|
||||
ret = append(ret, &networks[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SWire) GetBandwidth() int {
|
||||
return 10000
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {
|
||||
networks, err := self.GetINetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(networks); i += 1 {
|
||||
if networks[i].GetGlobalId() == netid {
|
||||
return networks[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/vpc2.0-api/create_subnet
|
||||
func (self *SWire) CreateINetwork(opts *cloudprovider.SNetworkCreateOptions) (cloudprovider.ICloudNetwork, error) {
|
||||
return self.vpc.region.CreateNetwork(self.vpc.GetId(), opts.Name, opts.Cidr, opts.Desc)
|
||||
}
|
||||
184
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/zone.go
generated
vendored
Normal file
184
vendor/yunion.io/x/cloudmux/pkg/multicloud/rockbase/zone.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
// 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 rockbase
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
api "yunion.io/x/cloudmux/pkg/apis/compute"
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
"yunion.io/x/cloudmux/pkg/multicloud"
|
||||
)
|
||||
|
||||
// https://docs.ucloud.cn/api/udisk-api/create_udisk
|
||||
// UDisk 类型: DataDisk(普通数据盘),SSDDataDisk(SSD数据盘),默认值(DataDisk)
|
||||
var StorageTypes = []string{
|
||||
api.STORAGE_ROCKBASE_CLOUD_NORMAL,
|
||||
api.STORAGE_ROCKBASE_CLOUD_SSD,
|
||||
api.STORAGE_ROCKBASE_LOCAL_NORMAL, // 本地盘
|
||||
api.STORAGE_ROCKBASE_LOCAL_SSD, // 本地SSD盘
|
||||
}
|
||||
|
||||
type SZone struct {
|
||||
multicloud.SResourceBase
|
||||
RockbaseTags
|
||||
region *SRegion
|
||||
host *SHost
|
||||
|
||||
RegionId string `json:"Region"`
|
||||
ZoneId string `json:"Zone"`
|
||||
LocalName string `json:"LocalName"`
|
||||
Default bool `json:"Default"`
|
||||
Permission string `json:"Permission"`
|
||||
}
|
||||
|
||||
func (self *SZone) getHost() *SHost {
|
||||
if self.host == nil {
|
||||
self.host = &SHost{zone: self, projectId: self.region.client.projectId}
|
||||
}
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SZone) GetId() string {
|
||||
return self.ZoneId
|
||||
}
|
||||
|
||||
func (self *SZone) GetName() string {
|
||||
if len(self.LocalName) > 0 {
|
||||
return self.LocalName
|
||||
}
|
||||
if name, exists := ROCKBASE_ZONE_NAMES[self.GetId()]; exists {
|
||||
return name
|
||||
}
|
||||
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SZone) GetI18n() cloudprovider.SModelI18nTable {
|
||||
var en string
|
||||
if len(self.LocalName) > 0 {
|
||||
en = self.LocalName
|
||||
} else if name, exists := ROCKBASE_ZONE_NAMES_EN[self.GetId()]; exists {
|
||||
en = name
|
||||
} else {
|
||||
en = self.GetId()
|
||||
}
|
||||
|
||||
table := cloudprovider.SModelI18nTable{}
|
||||
table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en)
|
||||
return table
|
||||
}
|
||||
|
||||
func (self *SZone) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", self.region.GetGlobalId(), self.GetId())
|
||||
}
|
||||
|
||||
func (self *SZone) GetStatus() string {
|
||||
return api.ZONE_ENABLE
|
||||
}
|
||||
|
||||
func (self *SZone) Refresh() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SZone) IsEmulated() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SZone) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
return []cloudprovider.ICloudHost{self.getHost()}, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
host := self.getHost()
|
||||
if host.GetGlobalId() == id {
|
||||
return host, nil
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
ret := make([]cloudprovider.ICloudStorage, len(StorageTypes))
|
||||
for i, sc := range StorageTypes {
|
||||
ret[i] = &SStorage{zone: self, storageType: sc}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
storages, err := self.GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range storages {
|
||||
if storages[i].GetGlobalId() == id {
|
||||
return storages[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/describe_uhost_instance
|
||||
func (self *SZone) GetInstances() ([]SInstance, error) {
|
||||
return self.region.GetInstances(self.GetId(), "")
|
||||
}
|
||||
|
||||
func (self *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
vpcs, err := self.region.GetVpcs("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudWire{}
|
||||
for i := range vpcs {
|
||||
vpcs[i].region = self.region
|
||||
ret = append(ret, &SWire{vpc: &vpcs[i]})
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// https://docs.ucloud.cn/api/uhost-api/describe_uhost_instance
|
||||
func (self *SRegion) GetInstances(zoneId string, instanceId string) ([]SInstance, error) {
|
||||
instances := make([]SInstance, 0)
|
||||
|
||||
params := NewRockbaseParams()
|
||||
if len(zoneId) > 0 {
|
||||
params.Set("Zone", zoneId)
|
||||
}
|
||||
|
||||
if len(instanceId) > 0 {
|
||||
params.Set("UHostIds.0", instanceId)
|
||||
}
|
||||
|
||||
err := self.DoListAll("DescribeUHostInstance", params, &instances)
|
||||
return instances, err
|
||||
}
|
||||
|
||||
func (self *SZone) getStorageByCategory(category string) (*SStorage, error) {
|
||||
storages, err := self.GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < len(storages); i += 1 {
|
||||
storage := storages[i].(*SStorage)
|
||||
if storage.storageType == category {
|
||||
return storage, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("No such storage %s", category)
|
||||
}
|
||||
19
vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/latitude_and_longitude.go
generated
vendored
19
vendor/yunion.io/x/cloudmux/pkg/multicloud/volcengine/latitude_and_longitude.go
generated
vendored
@@ -19,8 +19,23 @@ import (
|
||||
"yunion.io/x/cloudmux/pkg/cloudprovider"
|
||||
)
|
||||
|
||||
// ref: https://www.volcengine.com/docs/6534/1131814
|
||||
var LatitudeAndLongitude = map[string]cloudprovider.SGeographicInfo{
|
||||
"cn-guangzhou": api.RegionGuangzhou,
|
||||
"cn-beijing": api.RegionBeijing,
|
||||
// 华北
|
||||
"cn-beijing": api.RegionBeijing,
|
||||
"cn-beijing2": api.RegionBeijing,
|
||||
"cn-datong": api.RegionJinzhong,
|
||||
"cn-wulanchabu": api.RegionWulanchabu,
|
||||
|
||||
// 华东 / 华南
|
||||
"cn-shanghai": api.RegionShanghai,
|
||||
"cn-guangzhou": api.RegionGuangzhou,
|
||||
|
||||
// 港澳台
|
||||
"cn-hongkong": api.RegionHongkong,
|
||||
"cn-hongkong-pop": api.RegionHongkong,
|
||||
|
||||
// 亚太
|
||||
"ap-southeast-1": api.RegionKualaLumpur,
|
||||
"ap-southeast-3": api.RegionJakarta,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user