mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 16:13:56 +08:00
fix(region): support hyperdisk for gcp (#23270)
This commit is contained in:
2
go.mod
2
go.mod
@@ -87,7 +87,7 @@ require (
|
||||
k8s.io/client-go v0.19.3
|
||||
k8s.io/cluster-bootstrap v0.19.3
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250910065040-559381eb6587
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
|
||||
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
@@ -1271,8 +1271,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e h1:NkyXNnsky4PIW4CdsuISwDzB6DAO1dF+x8MmkFA+98w=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250910065040-559381eb6587 h1:x/9hAt/1iJ2ow2KgA8iSFO6KA0boXyVS+m9w4acNaJs=
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250910065040-559381eb6587/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
|
||||
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
|
||||
@@ -106,10 +106,15 @@ const (
|
||||
STORAGE_ZSTACK_SHARED_BLOCK = compute.STORAGE_ZSTACK_SHARED_BLOCK
|
||||
|
||||
// Google storage type
|
||||
STORAGE_GOOGLE_LOCAL_SSD = compute.STORAGE_GOOGLE_LOCAL_SSD //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = compute.STORAGE_GOOGLE_PD_STANDARD //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = compute.STORAGE_GOOGLE_PD_SSD //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = compute.STORAGE_GOOGLE_PD_BALANCED //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_LOCAL_SSD = compute.STORAGE_GOOGLE_LOCAL_SSD //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = compute.STORAGE_GOOGLE_PD_STANDARD //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = compute.STORAGE_GOOGLE_PD_SSD //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = compute.STORAGE_GOOGLE_PD_BALANCED //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_PD_EXTREME = compute.STORAGE_GOOGLE_PD_EXTREME //极端永久性磁盘
|
||||
STORAGE_GOOGLE_HYPERDISK_BALANCED = compute.STORAGE_GOOGLE_HYPERDISK_BALANCED //平衡 Hyperdisk
|
||||
STORAGE_GOOGLE_HYPERDISK_EXTREME = compute.STORAGE_GOOGLE_HYPERDISK_EXTREME //Hyperdisk Extreme
|
||||
STORAGE_GOOGLE_HYPERDISK_THROUGHPUT = compute.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT //Hyperdisk Throughput
|
||||
STORAGE_GOOGLE_HYPERDISK_ML = compute.STORAGE_GOOGLE_HYPERDISK_ML //Hyperdisk ML
|
||||
|
||||
// ctyun storage type
|
||||
STORAGE_CTYUN_SSD = compute.STORAGE_CTYUN_SSD // 超高IO云硬盘
|
||||
|
||||
@@ -79,14 +79,25 @@ func (self *SGoogleGuestDriver) GetInstanceCapability() cloudprovider.SInstanceC
|
||||
},
|
||||
Storages: cloudprovider.Storage{
|
||||
DataDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_EXTREME, MaxSizeGb: 65536, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_LOCAL_SSD, MaxSizeGb: 375, MinSizeGb: 375, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_BALANCED, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_EXTREME, MaxSizeGb: 65536, MinSizeGb: 64, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, MaxSizeGb: 32768, MinSizeGb: 2048, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_ML, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
},
|
||||
SysDisk: []cloudprovider.StorageInfo{
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
cloudprovider.StorageInfo{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_SSD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_STANDARD, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_BALANCED, MaxSizeGb: 65536, MinSizeGb: 10, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_PD_EXTREME, MaxSizeGb: 65536, MinSizeGb: 500, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_BALANCED, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_EXTREME, MaxSizeGb: 65536, MinSizeGb: 64, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, MaxSizeGb: 32768, MinSizeGb: 2048, StepSizeGb: 1, Resizable: false},
|
||||
{StorageType: api.STORAGE_GOOGLE_HYPERDISK_ML, MaxSizeGb: 65536, MinSizeGb: 4, StepSizeGb: 1, Resizable: false},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -105,7 +116,12 @@ func (self *SGoogleGuestDriver) GetStorageTypes() []string {
|
||||
api.STORAGE_GOOGLE_PD_SSD,
|
||||
api.STORAGE_GOOGLE_PD_STANDARD,
|
||||
api.STORAGE_GOOGLE_PD_BALANCED,
|
||||
api.STORAGE_GOOGLE_PD_EXTREME,
|
||||
api.STORAGE_GOOGLE_LOCAL_SSD,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_BALANCED,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_ML,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +157,12 @@ func (self *SGoogleGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *m
|
||||
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
|
||||
}
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED}) {
|
||||
if !utils.IsInStringArray(storage.StorageType, []string{
|
||||
api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD,
|
||||
api.STORAGE_GOOGLE_PD_BALANCED, api.STORAGE_GOOGLE_PD_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, api.STORAGE_GOOGLE_HYPERDISK_ML,
|
||||
}) {
|
||||
return fmt.Errorf("Cannot resize %s disk", storage.StorageType)
|
||||
}
|
||||
return nil
|
||||
@@ -163,10 +184,22 @@ func (self *SGoogleGuestDriver) ValidateCreateData(ctx context.Context, userCred
|
||||
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
|
||||
minGB = 10
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_PD_EXTREME:
|
||||
minGB = 500
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_LOCAL_SSD:
|
||||
minGB = 375
|
||||
maxGB = 375
|
||||
localDisk++
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_ML:
|
||||
minGB = 4
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT:
|
||||
minGB = 2048
|
||||
maxGB = 32768
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_EXTREME:
|
||||
minGB = 64
|
||||
maxGB = 65536
|
||||
default:
|
||||
return nil, httperrors.NewInputParameterError("Unknown google storage type %s", disk.Backend)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,18 @@ func (self *SGoogleHostDriver) ValidateDiskSize(storage *models.SStorage, sizeGb
|
||||
switch storage.StorageType {
|
||||
case api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_BALANCED:
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_PD_EXTREME:
|
||||
minGB = 500
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_ML:
|
||||
minGB = 4
|
||||
maxGB = 65536
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT:
|
||||
minGB = 2048
|
||||
maxGB = 32768
|
||||
case api.STORAGE_GOOGLE_HYPERDISK_EXTREME:
|
||||
minGB = 64
|
||||
maxGB = 65536
|
||||
default:
|
||||
return fmt.Errorf("Not support resize %s disk", storage.StorageType)
|
||||
}
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -1576,7 +1576,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
|
||||
# sigs.k8s.io/yaml v1.2.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250902072442-5c3779f6481e
|
||||
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250910065040-559381eb6587
|
||||
## explicit; go 1.21
|
||||
yunion.io/x/cloudmux/pkg/apis
|
||||
yunion.io/x/cloudmux/pkg/apis/billing
|
||||
|
||||
13
vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go
generated
vendored
13
vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go
generated
vendored
@@ -87,10 +87,15 @@ const (
|
||||
STORAGE_ZSTACK_SHARED_BLOCK = "sharedblock"
|
||||
|
||||
// Google storage type
|
||||
STORAGE_GOOGLE_LOCAL_SSD = "local-ssd" //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = "pd-standard" //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = "pd-ssd" //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = "pd-balanced" //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_LOCAL_SSD = "local-ssd" //本地SSD暂存盘 (最多8个)
|
||||
STORAGE_GOOGLE_PD_STANDARD = "pd-standard" //标准永久性磁盘
|
||||
STORAGE_GOOGLE_PD_SSD = "pd-ssd" //SSD永久性磁盘
|
||||
STORAGE_GOOGLE_PD_BALANCED = "pd-balanced" //平衡永久性磁盘
|
||||
STORAGE_GOOGLE_PD_EXTREME = "pd-extreme" //极端永久性磁盘
|
||||
STORAGE_GOOGLE_HYPERDISK_THROUGHPUT = "hyperdisk-throughput" //Hyperdisk Throughput
|
||||
STORAGE_GOOGLE_HYPERDISK_ML = "hyperdisk-ml" //Hyperdisk ML
|
||||
STORAGE_GOOGLE_HYPERDISK_BALANCED = "hyperdisk-balanced" //平衡 Hyperdisk
|
||||
STORAGE_GOOGLE_HYPERDISK_EXTREME = "hyperdisk-extreme" //Hyperdisk Extreme
|
||||
|
||||
// ctyun storage type
|
||||
STORAGE_CTYUN_SSD = "SSD" // 超高IO云硬盘
|
||||
|
||||
2
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/metrics.go
generated
vendored
2
vendor/yunion.io/x/cloudmux/pkg/cloudprovider/metrics.go
generated
vendored
@@ -127,7 +127,7 @@ const (
|
||||
// 支持平台: kvm, aliyun, apsara, azure, esxi, bingocloud, jdcloud, ecloud, qcloud, volcengine
|
||||
VM_METRIC_TYPE_MEM_USAGE TMetricType = "vm_mem.used_percent"
|
||||
// 虚拟机磁盘使用率
|
||||
// 支持平台: aliyun, apsara, jdcloud, azure
|
||||
// 支持平台: aliyun, apsara, jdcloud, azure, baidu, ctyun, huawei, hcso, volcengine, qcloud
|
||||
// 支持按盘符(group_by=device)平台: aliyun, apsara
|
||||
VM_METRIC_TYPE_DISK_USAGE TMetricType = "vm_disk.used_percent"
|
||||
|
||||
|
||||
122
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/elastic_search_instance_types.go
generated
vendored
122
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/elastic_search_instance_types.go
generated
vendored
@@ -14,36 +14,116 @@
|
||||
|
||||
package aliyun
|
||||
|
||||
// https://help.aliyun.com/document_detail/132255.html
|
||||
// https://help.aliyun.com/zh/es/product-overview/node-specifications
|
||||
var esSpec = map[string]struct {
|
||||
VcpuCount int
|
||||
VmemSizeGb int
|
||||
}{
|
||||
"elasticsearch.ic5.2xlarge": {VcpuCount: 8, VmemSizeGb: 8},
|
||||
"elasticsearch.ic5.3xlarge": {VcpuCount: 12, VmemSizeGb: 12},
|
||||
"elasticsearch.ic5.4xlarge": {VcpuCount: 16, VmemSizeGb: 16},
|
||||
"elasticsearch.ic5.large": {VcpuCount: 16, VmemSizeGb: 16},
|
||||
"elasticsearch.ic5.xlarge": {VcpuCount: 4, VmemSizeGb: 4},
|
||||
// 开发测试型规格
|
||||
"elasticsearch.t6.large": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
|
||||
// 云盘型(1:1规格族)
|
||||
"elasticsearch.ic5.large": {VcpuCount: 2, VmemSizeGb: 2},
|
||||
"elasticsearch.ic5.xlarge": {VcpuCount: 4, VmemSizeGb: 4},
|
||||
"elasticsearch.ic5.2xlarge": {VcpuCount: 8, VmemSizeGb: 8},
|
||||
"elasticsearch.ic5.3xlarge": {VcpuCount: 12, VmemSizeGb: 12},
|
||||
"elasticsearch.ic5.4xlarge": {VcpuCount: 16, VmemSizeGb: 16},
|
||||
|
||||
// 云盘型(1:2规格族)
|
||||
"elasticsearch.n4.small": {VcpuCount: 1, VmemSizeGb: 2},
|
||||
"elasticsearch.sn1ne.large": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
"elasticsearch.sn1ne.xlarge": {VcpuCount: 4, VmemSizeGb: 8},
|
||||
"elasticsearch.sn1ne.2xlarge": {VcpuCount: 8, VmemSizeGb: 16},
|
||||
"elasticsearch.sn1ne.4xlarge": {VcpuCount: 16, VmemSizeGb: 32},
|
||||
"elasticsearch.sn1ne.8xlarge": {VcpuCount: 32, VmemSizeGb: 64},
|
||||
"elasticsearch.sn1ne.large": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
"elasticsearch.sn1ne.xlarge": {VcpuCount: 4, VmemSizeGb: 8},
|
||||
|
||||
// 云盘型(1:4规格族)
|
||||
"elasticsearch.sn2ne.large": {VcpuCount: 2, VmemSizeGb: 8},
|
||||
"elasticsearch.sn2ne.xlarge": {VcpuCount: 4, VmemSizeGb: 16},
|
||||
"elasticsearch.sn2ne.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.sn2ne.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.sn2ne.8xlarge": {VcpuCount: 32, VmemSizeGb: 128},
|
||||
"elasticsearch.sn2ne.large": {VcpuCount: 2, VmemSizeGb: 8},
|
||||
"elasticsearch.sn2ne.xlarge": {VcpuCount: 4, VmemSizeGb: 16},
|
||||
"elasticsearch.r6.8xlarge": {VcpuCount: 32, VmemSizeGb: 256},
|
||||
"elasticsearch.r6.4xlarge": {VcpuCount: 16, VmemSizeGb: 128},
|
||||
"elasticsearch.r5.2xlarge": {VcpuCount: 8, VmemSizeGb: 64},
|
||||
"elasticsearch.r5.large": {VcpuCount: 2, VmemSizeGb: 16},
|
||||
"elasticsearch.r5.xlarge": {VcpuCount: 4, VmemSizeGb: 32},
|
||||
"elasticsearch.d1.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.d1.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.i2g.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.i2g.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.i2g.8xlarge": {VcpuCount: 32, VmemSizeGb: 128},
|
||||
"elasticsearch.d2s.5xlarge": {VcpuCount: 20, VmemSizeGb: 88},
|
||||
|
||||
// 云盘型(1:8规格族)
|
||||
"elasticsearch.r5.large": {VcpuCount: 2, VmemSizeGb: 16},
|
||||
"elasticsearch.r5.xlarge": {VcpuCount: 4, VmemSizeGb: 32},
|
||||
"elasticsearch.r5.2xlarge": {VcpuCount: 8, VmemSizeGb: 64},
|
||||
"elasticsearch.r6.4xlarge": {VcpuCount: 16, VmemSizeGb: 128},
|
||||
"elasticsearch.r6.8xlarge": {VcpuCount: 32, VmemSizeGb: 256},
|
||||
|
||||
// 大数据型
|
||||
"elasticsearch.c6.13xlarge": {VcpuCount: 52, VmemSizeGb: 96},
|
||||
|
||||
// 新一代云盘型(1:2规格族)
|
||||
"elasticsearch.sn1ne.large.new": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
"elasticsearch.sn1ne.xlarge.new": {VcpuCount: 4, VmemSizeGb: 8},
|
||||
"elasticsearch.sn1ne.2xlarge.new": {VcpuCount: 8, VmemSizeGb: 16},
|
||||
"elasticsearch.sn1ne.4xlarge.new": {VcpuCount: 16, VmemSizeGb: 32},
|
||||
"elasticsearch.sn1ne.8xlarge.new": {VcpuCount: 32, VmemSizeGb: 64},
|
||||
|
||||
// 新一代云盘型(1:4规格族)
|
||||
"elasticsearch.sn2ne.large.new": {VcpuCount: 2, VmemSizeGb: 8},
|
||||
"elasticsearch.sn2ne.xlarge.new": {VcpuCount: 4, VmemSizeGb: 16},
|
||||
"elasticsearch.sn2ne.2xlarge.new": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.sn2ne.4xlarge.new": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
|
||||
// 本地SSD盘型
|
||||
"elasticsearch.i2g.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.i2g.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.i2.4xlarge": {VcpuCount: 16, VmemSizeGb: 128},
|
||||
"elasticsearch.i2g.8xlarge": {VcpuCount: 32, VmemSizeGb: 128},
|
||||
|
||||
// 大数据本地SATA盘型
|
||||
"elasticsearch.d1.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.d1.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
|
||||
// OpenStore存储型(存算分离型)
|
||||
"openstore.hybrid.i2.2xlarge": {VcpuCount: 8, VmemSizeGb: 64},
|
||||
"openstore.hybrid.i2g.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
|
||||
// AMD处理器 - 新一代云盘型(1:2规格族)
|
||||
"elasticsearch.c7a.large": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
"elasticsearch.c7a.xlarge": {VcpuCount: 4, VmemSizeGb: 8},
|
||||
"elasticsearch.c7a.2xlarge": {VcpuCount: 8, VmemSizeGb: 16},
|
||||
"elasticsearch.c7a.4xlarge": {VcpuCount: 16, VmemSizeGb: 32},
|
||||
"elasticsearch.c7a.8xlarge": {VcpuCount: 32, VmemSizeGb: 64},
|
||||
|
||||
// AMD处理器 - 新一代云盘型(1:4规格族)
|
||||
"elasticsearch.g7a.large": {VcpuCount: 2, VmemSizeGb: 8},
|
||||
"elasticsearch.g7a.xlarge": {VcpuCount: 4, VmemSizeGb: 16},
|
||||
"elasticsearch.g7a.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.g7a.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.g7a.8xlarge": {VcpuCount: 32, VmemSizeGb: 128},
|
||||
|
||||
// AMD处理器 - 新一代云盘型(1:8规格族)
|
||||
"elasticsearch.r7a.large": {VcpuCount: 2, VmemSizeGb: 16},
|
||||
"elasticsearch.r7a.xlarge": {VcpuCount: 4, VmemSizeGb: 32},
|
||||
"elasticsearch.r7a.2xlarge": {VcpuCount: 8, VmemSizeGb: 64},
|
||||
"elasticsearch.r7a.4xlarge": {VcpuCount: 16, VmemSizeGb: 128},
|
||||
"elasticsearch.r7a.8xlarge": {VcpuCount: 32, VmemSizeGb: 256},
|
||||
|
||||
// 新一代云盘型(1:2计算型-Turbo-1)
|
||||
"elasticsearch.turbo1.ca.large": {VcpuCount: 2, VmemSizeGb: 4},
|
||||
"elasticsearch.turbo1.ca.xlarge": {VcpuCount: 4, VmemSizeGb: 8},
|
||||
"elasticsearch.turbo1.ca.2xlarge": {VcpuCount: 8, VmemSizeGb: 16},
|
||||
"elasticsearch.turbo1.ca.4xlarge": {VcpuCount: 16, VmemSizeGb: 32},
|
||||
"elasticsearch.turbo1.ca.8xlarge": {VcpuCount: 32, VmemSizeGb: 64},
|
||||
"elasticsearch.turbo1.ca.16xlarge": {VcpuCount: 64, VmemSizeGb: 128},
|
||||
|
||||
// 新一代云盘型(1:4通用型-Turbo-1)
|
||||
"elasticsearch.turbo1.ga.large": {VcpuCount: 2, VmemSizeGb: 8},
|
||||
"elasticsearch.turbo1.ga.xlarge": {VcpuCount: 4, VmemSizeGb: 16},
|
||||
"elasticsearch.turbo1.ga.2xlarge": {VcpuCount: 8, VmemSizeGb: 32},
|
||||
"elasticsearch.turbo1.ga.4xlarge": {VcpuCount: 16, VmemSizeGb: 64},
|
||||
"elasticsearch.turbo1.ga.8xlarge": {VcpuCount: 32, VmemSizeGb: 128},
|
||||
|
||||
// 新一代云盘型(1:8内存型-Turbo-1)
|
||||
"elasticsearch.turbo1.ra.large": {VcpuCount: 2, VmemSizeGb: 16},
|
||||
"elasticsearch.turbo1.ra.xlarge": {VcpuCount: 4, VmemSizeGb: 32},
|
||||
"elasticsearch.turbo1.ra.2xlarge": {VcpuCount: 8, VmemSizeGb: 64},
|
||||
"elasticsearch.turbo1.ra.4xlarge": {VcpuCount: 16, VmemSizeGb: 128},
|
||||
"elasticsearch.turbo1.ra.8xlarge": {VcpuCount: 32, VmemSizeGb: 256},
|
||||
|
||||
// 保留原有的d2s规格(如果仍在使用)
|
||||
"elasticsearch.d2s.5xlarge": {VcpuCount: 20, VmemSizeGb: 88},
|
||||
}
|
||||
|
||||
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/instance.go
generated
vendored
2
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/instance.go
generated
vendored
@@ -253,8 +253,6 @@ func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
|
||||
sort.Sort(byAttachedTime(disks))
|
||||
|
||||
log.Debugf("%s", jsonutils.Marshal(&disks))
|
||||
|
||||
idisks := make([]cloudprovider.ICloudDisk, len(disks))
|
||||
for i := 0; i < len(disks); i += 1 {
|
||||
store, err := self.host.zone.getStorageByCategory(disks[i].Category)
|
||||
|
||||
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/mongodb.go
generated
vendored
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/aliyun/mongodb.go
generated
vendored
@@ -233,6 +233,9 @@ func (self *SMongoDB) GetPort() int {
|
||||
}
|
||||
|
||||
func (self *SMongoDB) GetReplicationNum() int {
|
||||
if self.DBInstanceType == "sharding" {
|
||||
return len(self.ShardList.ShardAttribute)
|
||||
}
|
||||
if len(self.ReplicationFactor) == 0 {
|
||||
self.Refresh()
|
||||
}
|
||||
|
||||
43
vendor/yunion.io/x/cloudmux/pkg/multicloud/esxi/virtualmachine.go
generated
vendored
43
vendor/yunion.io/x/cloudmux/pkg/multicloud/esxi/virtualmachine.go
generated
vendored
@@ -1201,28 +1201,31 @@ func (svm *SVirtualMachine) getDatastoreAndRootImagePath() (string, *SDatastore,
|
||||
if layoutEx == nil || len(layoutEx.File) == 0 {
|
||||
return "", nil, fmt.Errorf("invalid LayoutEx")
|
||||
}
|
||||
file := layoutEx.File[0].Name
|
||||
// find stroage
|
||||
host := svm.GetIHost()
|
||||
storages, err := host.GetIStorages()
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrap(err, "host.GetIStorages")
|
||||
}
|
||||
var datastore *SDatastore
|
||||
for i := range storages {
|
||||
ds := storages[i].(*SDatastore)
|
||||
if ds.HasFile(file) {
|
||||
datastore = ds
|
||||
break
|
||||
for _, f := range layoutEx.File {
|
||||
if !strings.HasSuffix(f.Name, ".vmdk") {
|
||||
continue
|
||||
}
|
||||
file := f.Name
|
||||
// find stroage
|
||||
host := svm.GetIHost()
|
||||
storages, err := host.GetIStorages()
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrap(err, "host.GetIStorages")
|
||||
}
|
||||
var datastore *SDatastore
|
||||
for i := range storages {
|
||||
ds := storages[i].(*SDatastore)
|
||||
if ds.HasFile(file) {
|
||||
datastore = ds
|
||||
break
|
||||
}
|
||||
}
|
||||
if datastore == nil {
|
||||
return "", nil, fmt.Errorf("can't find storage associated with vm %q", svm.GetName())
|
||||
}
|
||||
return datastore.getPathString(datastore.cleanPath(file)), datastore, nil
|
||||
}
|
||||
if datastore == nil {
|
||||
return "", nil, fmt.Errorf("can't find storage associated with vm %q", svm.GetName())
|
||||
}
|
||||
path := datastore.cleanPath(file)
|
||||
vmDir := strings.Split(path, "/")[0]
|
||||
// TODO find a non-conflicting path
|
||||
return datastore.getPathString(fmt.Sprintf("%s/%s.vmdk", vmDir, vmDir)), datastore, nil
|
||||
return "", nil, fmt.Errorf("can't find root image path")
|
||||
}
|
||||
|
||||
func (svm *SVirtualMachine) GetRootImagePath() (string, error) {
|
||||
|
||||
34
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/dbinstance.go
generated
vendored
34
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/dbinstance.go
generated
vendored
@@ -35,13 +35,18 @@ import (
|
||||
|
||||
var (
|
||||
EngineVersions = map[string]GoogleSQLVersion{
|
||||
"MYSQL_5_5": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.5"},
|
||||
"MYSQL_5_6": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.6"},
|
||||
"MYSQL_5_7": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.7"},
|
||||
"POSTGRES_9_6": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "9.6"},
|
||||
"POSTGRES_10": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "10"},
|
||||
"POSTGRES_11": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "11"},
|
||||
"POSTGRES_12": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "12"},
|
||||
"MYSQL_5_5": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.5"},
|
||||
"MYSQL_5_6": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.6"},
|
||||
"MYSQL_5_7": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "5.7"},
|
||||
"MYSQL_8_0_41": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "8.0"},
|
||||
"MYSQL_8_0_40": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_MYSQL, Version: "8.0"},
|
||||
|
||||
"POSTGRES_9_6": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "9.6"},
|
||||
"POSTGRES_10": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "10"},
|
||||
"POSTGRES_11": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "11"},
|
||||
"POSTGRES_12": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "12"},
|
||||
"POSTGRES_14": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_POSTGRESQL, Version: "14"},
|
||||
|
||||
"SQLSERVER_2017_STANDARD": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_SQLSERVER, Version: "2017 Standard"},
|
||||
"SQLSERVER_2017_ENTERPRISE": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_SQLSERVER, Version: "2017 Enterprise"},
|
||||
"SQLSERVER_2017_EXPRESS": GoogleSQLVersion{Engine: api.DBINSTANCE_TYPE_SQLSERVER, Version: "2017 Express"},
|
||||
@@ -265,6 +270,15 @@ func (rds *SDBInstance) GetEngine() string {
|
||||
if e, ok := EngineVersions[rds.DatabaseVersion]; ok {
|
||||
return e.Engine
|
||||
}
|
||||
if strings.Contains(rds.DatabaseVersion, "MYSQL") {
|
||||
return api.DBINSTANCE_TYPE_MYSQL
|
||||
}
|
||||
if strings.Contains(rds.DatabaseVersion, "POSTGRES") {
|
||||
return api.DBINSTANCE_TYPE_POSTGRESQL
|
||||
}
|
||||
if strings.Contains(rds.DatabaseVersion, "SQLSERVER") {
|
||||
return api.DBINSTANCE_TYPE_SQLSERVER
|
||||
}
|
||||
return rds.DatabaseVersion
|
||||
}
|
||||
|
||||
@@ -272,7 +286,11 @@ func (rds *SDBInstance) GetEngineVersion() string {
|
||||
if e, ok := EngineVersions[rds.DatabaseVersion]; ok {
|
||||
return e.Version
|
||||
}
|
||||
return rds.DatabaseVersion
|
||||
version := strings.TrimPrefix(rds.DatabaseVersion, "MYSQL_")
|
||||
version = strings.TrimPrefix(version, "POSTGRES_")
|
||||
version = strings.TrimPrefix(version, "SQLSERVER_")
|
||||
version = strings.ReplaceAll(version, "_", ".")
|
||||
return version
|
||||
}
|
||||
|
||||
func (rds *SDBInstance) GetInstanceType() string {
|
||||
|
||||
25
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go
generated
vendored
25
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/instance.go
generated
vendored
@@ -28,6 +28,7 @@ import (
|
||||
"yunion.io/x/pkg/util/encode"
|
||||
"yunion.io/x/pkg/util/fileutils"
|
||||
"yunion.io/x/pkg/util/imagetools"
|
||||
"yunion.io/x/pkg/util/stringutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
|
||||
@@ -384,6 +385,12 @@ func (instance *SInstance) StopVM(ctx context.Context, opts *cloudprovider.Serve
|
||||
}
|
||||
|
||||
func (instance *SInstance) DeleteVM(ctx context.Context) error {
|
||||
if instance.DeletionProtection {
|
||||
err := instance.host.zone.region.DisableDeletionProtection(instance.SelfLink)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "DisableDeletionProtection(%s)", instance.Name)
|
||||
}
|
||||
}
|
||||
return instance.host.zone.region.Delete(instance.SelfLink)
|
||||
}
|
||||
|
||||
@@ -500,7 +507,9 @@ func getDiskInfo(disk string) (cloudprovider.SDiskInfo, error) {
|
||||
result := cloudprovider.SDiskInfo{}
|
||||
diskInfo := strings.Split(disk, ":")
|
||||
for _, d := range diskInfo {
|
||||
if utils.IsInStringArray(d, []string{api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_LOCAL_SSD, api.STORAGE_GOOGLE_PD_BALANCED}) {
|
||||
if utils.IsInStringArray(d, []string{
|
||||
api.STORAGE_GOOGLE_PD_STANDARD, api.STORAGE_GOOGLE_PD_SSD, api.STORAGE_GOOGLE_LOCAL_SSD, api.STORAGE_GOOGLE_PD_BALANCED, api.STORAGE_GOOGLE_PD_EXTREME,
|
||||
api.STORAGE_GOOGLE_HYPERDISK_THROUGHPUT, api.STORAGE_GOOGLE_HYPERDISK_ML, api.STORAGE_GOOGLE_HYPERDISK_BALANCED, api.STORAGE_GOOGLE_HYPERDISK_EXTREME}) {
|
||||
result.StorageType = d
|
||||
} else if memSize, err := fileutils.GetSizeMb(d, 'M', 1024); err == nil {
|
||||
result.SizeGB = memSize >> 10
|
||||
@@ -513,17 +522,17 @@ func getDiskInfo(disk string) (cloudprovider.SDiskInfo, error) {
|
||||
}
|
||||
|
||||
if result.SizeGB == 0 {
|
||||
return result, fmt.Errorf("Missing disk size")
|
||||
return result, fmt.Errorf("missing disk size")
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (region *SRegion) CreateInstance(zone, name, desc, instanceType string, cpu, memoryMb int, networkId string, ipAddr, imageId string, disks []string) (*SInstance, error) {
|
||||
if len(instanceType) == 0 && (cpu == 0 || memoryMb == 0) {
|
||||
return nil, fmt.Errorf("Missing instanceType or cpu &memory info")
|
||||
return nil, fmt.Errorf("missing instanceType or cpu &memory info")
|
||||
}
|
||||
if len(disks) == 0 {
|
||||
return nil, fmt.Errorf("Missing disk info")
|
||||
return nil, fmt.Errorf("missing disk info")
|
||||
}
|
||||
sysDisk, err := getDiskInfo(disks[0])
|
||||
if err != nil {
|
||||
@@ -664,6 +673,14 @@ func (region *SRegion) ResetInstance(id string) error {
|
||||
return region.Do(id, "reset", nil, jsonutils.Marshal(params))
|
||||
}
|
||||
|
||||
func (region *SRegion) DisableDeletionProtection(id string) error {
|
||||
params := map[string]string{
|
||||
"requestId": stringutils.UUID4(),
|
||||
"deletionProtection": "false",
|
||||
}
|
||||
return region.Do(id, "setDeletionProtection", params, nil)
|
||||
}
|
||||
|
||||
func (region *SRegion) DetachDisk(instanceId, deviceName string) error {
|
||||
body := map[string]string{}
|
||||
params := map[string]string{"deviceName": deviceName}
|
||||
|
||||
23
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/region.go
generated
vendored
23
vendor/yunion.io/x/cloudmux/pkg/multicloud/google/region.go
generated
vendored
@@ -848,13 +848,26 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC
|
||||
}
|
||||
|
||||
func (region *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
instances, err := region.GetInstances("", 0, "")
|
||||
if utils.IsInStringArray(region.Name, MultiRegions) || utils.IsInStringArray(region.Name, DualRegions) {
|
||||
return []cloudprovider.ICloudVM{}, nil
|
||||
}
|
||||
zones, err := region.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iVMs := []cloudprovider.ICloudVM{}
|
||||
for i := range instances {
|
||||
iVMs = append(iVMs, &instances[i])
|
||||
ret := []cloudprovider.ICloudVM{}
|
||||
for i := range zones {
|
||||
hosts, err := zones[i].GetIHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for j := range hosts {
|
||||
instances, err := hosts[j].GetIVMs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, instances...)
|
||||
}
|
||||
}
|
||||
return iVMs, nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go
generated
vendored
3
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/monitor.go
generated
vendored
@@ -151,6 +151,9 @@ func (self *SQcloudClient) GetEcsMetrics(opts *cloudprovider.MetricListOptions)
|
||||
cloudprovider.VM_METRIC_TYPE_MEM_USAGE: {
|
||||
"MemUsage": "",
|
||||
},
|
||||
cloudprovider.VM_METRIC_TYPE_DISK_USAGE: {
|
||||
"CvmDiskUsage": "",
|
||||
},
|
||||
cloudprovider.VM_METRIC_TYPE_NET_BPS_TX: {
|
||||
"lanOuttraffic": cloudprovider.METRIC_TAG_NET_TYPE + ":" + cloudprovider.METRIC_TAG_NET_TYPE_INTRANET,
|
||||
"WanOuttraffic": cloudprovider.METRIC_TAG_NET_TYPE + ":" + cloudprovider.METRIC_TAG_NET_TYPE_INTERNET,
|
||||
|
||||
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_mysql.go
generated
vendored
4
vendor/yunion.io/x/cloudmux/pkg/multicloud/qcloud/rds_mysql.go
generated
vendored
@@ -154,6 +154,7 @@ type SMySQLInstance struct {
|
||||
VpcId int
|
||||
Vport int
|
||||
WanDomain string
|
||||
DiskType string
|
||||
WanPort int
|
||||
WanStatus int
|
||||
Zone string
|
||||
@@ -354,6 +355,9 @@ func (self *SMySQLInstance) GetCategory() string {
|
||||
}
|
||||
|
||||
func (self *SMySQLInstance) GetStorageType() string {
|
||||
if len(self.DiskType) > 0 {
|
||||
return strings.ToLower(self.DiskType)
|
||||
}
|
||||
switch self.DeviceType {
|
||||
case "BASIC":
|
||||
return api.QCLOUD_DBINSTANCE_STORAGE_TYPE_CLOUD_SSD
|
||||
|
||||
Reference in New Issue
Block a user