diff --git a/go.mod b/go.mod index e6c4c74ac0..43f696091a 100644 --- a/go.mod +++ b/go.mod @@ -88,7 +88,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.20231227025516-4b8aef06c15e + yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231227060638-40a1db02d028 yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 yunion.io/x/jsonutils v1.0.1-0.20230613121553-0f3b41e2ef19 yunion.io/x/log v1.0.1-0.20230411060016-feb3f46ab361 diff --git a/go.sum b/go.sum index 92c1c51c07..5f5982948c 100644 --- a/go.sum +++ b/go.sum @@ -1201,8 +1201,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.20231227025516-4b8aef06c15e h1:MMvjpuPn5uTynnWZfX5nE2+DYpyri8SVPgVQLKMVk8c= -yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231227025516-4b8aef06c15e/go.mod h1:aj1gR9PPb6eqqKOwvANe26CoZFY8ydmXy0fuvgKYXH0= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231227060638-40a1db02d028 h1:Q04t1Xfw9uqR7ba1AJm4tERJ2qwPLysaz9Iekrb0f8U= +yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231227060638-40a1db02d028/go.mod h1:aj1gR9PPb6eqqKOwvANe26CoZFY8ydmXy0fuvgKYXH0= yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32 h1:v7POYkQwo1XzOxBoIoRVr/k0V9Y5JyjpshlIFa9raug= yunion.io/x/executor v0.0.0-20230705125604-c5ac3141db32/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws= yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634= diff --git a/pkg/apis/compute/cloudaccount_const.go b/pkg/apis/compute/cloudaccount_const.go index 7829c21175..b190fdc837 100644 --- a/pkg/apis/compute/cloudaccount_const.go +++ b/pkg/apis/compute/cloudaccount_const.go @@ -104,8 +104,6 @@ const ( CLOUD_ACCESS_ENV_AZURE_GERMAN = compute.CLOUD_ACCESS_ENV_AZURE_GERMAN CLOUD_ACCESS_ENV_AZURE_US_GOVERNMENT = compute.CLOUD_ACCESS_ENV_AZURE_US_GOVERNMENT CLOUD_ACCESS_ENV_AZURE_CHINA = compute.CLOUD_ACCESS_ENV_AZURE_CHINA - CLOUD_ACCESS_ENV_HUAWEI_GLOBAL = compute.CLOUD_ACCESS_ENV_HUAWEI_GLOBAL - CLOUD_ACCESS_ENV_HUAWEI_CHINA = compute.CLOUD_ACCESS_ENV_HUAWEI_CHINA CLOUD_ACCESS_ENV_ALIYUN_GLOBAL = compute.CLOUD_ACCESS_ENV_ALIYUN_GLOBAL CLOUD_ACCESS_ENV_ALIYUN_FINANCE = compute.CLOUD_ACCESS_ENV_ALIYUN_FINANCE CLOUD_ACCESS_ENV_CTYUN_CHINA = compute.CLOUD_ACCESS_ENV_CTYUN_CHINA @@ -287,10 +285,6 @@ var ( "InternationalCloud": CLOUD_ACCESS_ENV_AWS_GLOBAL, "ChinaCloud": CLOUD_ACCESS_ENV_AWS_CHINA, }, - CLOUD_PROVIDER_HUAWEI: { - "InternationalCloud": CLOUD_ACCESS_ENV_HUAWEI_GLOBAL, - "ChinaCloud": CLOUD_ACCESS_ENV_HUAWEI_CHINA, - }, CLOUD_PROVIDER_ALIYUN: { "InternationalCloud": CLOUD_PROVIDER_ALIYUN, "FinanceCloud": CLOUD_ACCESS_ENV_ALIYUN_FINANCE, diff --git a/pkg/compute/models/cloudimages.go b/pkg/compute/models/cloudimages.go index 50cee1d211..0624ec3ee0 100644 --- a/pkg/compute/models/cloudimages.go +++ b/pkg/compute/models/cloudimages.go @@ -17,7 +17,6 @@ package models import ( "context" "database/sql" - "fmt" "yunion.io/x/log" "yunion.io/x/pkg/errors" @@ -150,7 +149,7 @@ func (self *SCloudimage) syncWithImage(ctx context.Context, userCred mcclient.To return err } - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.ImageBase, region.ExternalId, image.GetGlobalId()) + skuUrl := region.getMetaUrl(meta.ImageBase, image.GetGlobalId()) obj, err := db.FetchByExternalId(CachedimageManager, image.GetGlobalId()) if err != nil { diff --git a/pkg/compute/models/cloudregions.go b/pkg/compute/models/cloudregions.go index a03e11ca32..83b4b09078 100644 --- a/pkg/compute/models/cloudregions.go +++ b/pkg/compute/models/cloudregions.go @@ -17,7 +17,6 @@ package models import ( "context" "database/sql" - "fmt" "strings" "time" @@ -1275,7 +1274,7 @@ func (self *SCloudregion) newCloudimage(ctx context.Context, userCred mcclient.T return err } - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.ImageBase, self.ExternalId, iImage.GetGlobalId()) + skuUrl := self.getMetaUrl(meta.ImageBase, iImage.GetGlobalId()) err = meta.Get(skuUrl, image) if err != nil { return errors.Wrapf(err, "Get") diff --git a/pkg/compute/models/dbinstance_skus.go b/pkg/compute/models/dbinstance_skus.go index 0e3a4a1428..b19447bd8c 100644 --- a/pkg/compute/models/dbinstance_skus.go +++ b/pkg/compute/models/dbinstance_skus.go @@ -587,7 +587,7 @@ func (self *SCloudregion) newDBInstanceSkuFromCloudSku(ctx context.Context, user sku := &SDBInstanceSku{} sku.SetModelManager(DBInstanceSkuManager, sku) - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.DBInstanceBase, self.ExternalId, externalId) + skuUrl := self.getMetaUrl(meta.DBInstanceBase, externalId) err = meta.Get(skuUrl, sku) if err != nil { return errors.Wrapf(err, "Get") diff --git a/pkg/compute/models/elasticcache_skus.go b/pkg/compute/models/elasticcache_skus.go index cae58d05ca..977e1ac64f 100644 --- a/pkg/compute/models/elasticcache_skus.go +++ b/pkg/compute/models/elasticcache_skus.go @@ -474,7 +474,7 @@ func (self *SCloudregion) newFromPublicCloudSku(ctx context.Context, userCred mc zoneMaps[zone.ExternalId] = zone.Id } - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.ElasticCacheBase, self.ExternalId, externalId) + skuUrl := self.getMetaUrl(meta.ElasticCacheBase, externalId) sku := &SElasticcacheSku{} sku.SetModelManager(ElasticcacheSkuManager, sku) err = meta.Get(skuUrl, sku) diff --git a/pkg/compute/models/nas_skus.go b/pkg/compute/models/nas_skus.go index 27603fc269..89f5673898 100644 --- a/pkg/compute/models/nas_skus.go +++ b/pkg/compute/models/nas_skus.go @@ -289,7 +289,7 @@ func (self *SCloudregion) newFromCloudNasSku(ctx context.Context, userCred mccli sku := &SNasSku{} sku.SetModelManager(NasSkuManager, sku) - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.NasBase, self.ExternalId, isku.GetGlobalId()) + skuUrl := self.getMetaUrl(meta.NasBase, isku.GetGlobalId()) err = meta.Get(skuUrl, sku) if err != nil { return errors.Wrapf(err, "Get") diff --git a/pkg/compute/models/nat_skus.go b/pkg/compute/models/nat_skus.go index ffde8fa9a6..e56cea3c04 100644 --- a/pkg/compute/models/nat_skus.go +++ b/pkg/compute/models/nat_skus.go @@ -293,7 +293,7 @@ func (self *SCloudregion) newFromCloudNatSku(ctx context.Context, userCred mccli sku := &SNatSku{} sku.SetModelManager(NatSkuManager, sku) - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.NatBase, self.ExternalId, isku.GetGlobalId()) + skuUrl := self.getMetaUrl(meta.NatBase, isku.GetGlobalId()) err = meta.Get(skuUrl, sku) if err != nil { return errors.Wrapf(err, "Get") diff --git a/pkg/compute/models/server_skus.go b/pkg/compute/models/server_skus.go index 61f790d0ec..6ded020d5f 100644 --- a/pkg/compute/models/server_skus.go +++ b/pkg/compute/models/server_skus.go @@ -1162,6 +1162,14 @@ func (self *SServerSku) setPrepaidPostpaidStatus(userCred mcclient.TokenCredenti return nil } +func (region *SCloudregion) getMetaUrl(base string, externalId string) string { + if region.Provider == api.CLOUD_PROVIDER_HUAWEI && strings.Contains(region.ExternalId, "_") { + idx := strings.Index(region.ExternalId, "_") + return fmt.Sprintf("%s/%s/%s.json", base, region.ExternalId[:idx], externalId) + } + return fmt.Sprintf("%s/%s/%s.json", base, region.ExternalId, externalId) +} + func (region *SCloudregion) newPublicCloudSku(ctx context.Context, userCred mcclient.TokenCredential, extSku SServerSku) error { meta, err := yunionmeta.FetchYunionmeta(ctx) if err != nil { @@ -1179,7 +1187,7 @@ func (region *SCloudregion) newPublicCloudSku(ctx context.Context, userCred mccl sku := &SServerSku{} sku.SetModelManager(ServerSkuManager, sku) - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.ServerBase, region.ExternalId, extSku.ExternalId) + skuUrl := region.getMetaUrl(meta.ServerBase, extSku.ExternalId) err = meta.Get(skuUrl, sku) if err != nil { return errors.Wrapf(err, "Get") @@ -1227,7 +1235,7 @@ func (self *SServerSku) syncWithCloudSku(ctx context.Context, userCred mcclient. } sku := &SServerSku{} - skuUrl := fmt.Sprintf("%s/%s/%s.json", meta.ServerBase, region.ExternalId, extSku.ExternalId) + skuUrl := region.getMetaUrl(meta.ServerBase, extSku.ExternalId) err = meta.Get(skuUrl, sku) if err != nil { return errors.Wrapf(err, "Get") diff --git a/pkg/mcclient/options/cloudaccounts.go b/pkg/mcclient/options/cloudaccounts.go index 984b224833..2c76df36de 100644 --- a/pkg/mcclient/options/cloudaccounts.go +++ b/pkg/mcclient/options/cloudaccounts.go @@ -300,7 +300,7 @@ func (opts *SOpenStackCloudAccountCreateOptions) Params() (jsonutils.JSONObject, type SHuaweiCloudAccountCreateOptions struct { SCloudAccountCreateBaseOptions - SAccessKeyCredentialWithEnvironment + SAccessKeyCredential } func (opts *SHuaweiCloudAccountCreateOptions) Params() (jsonutils.JSONObject, error) { diff --git a/pkg/util/yunionmeta/meta.go b/pkg/util/yunionmeta/meta.go index 2a17dc3f19..7d35c0f9bb 100644 --- a/pkg/util/yunionmeta/meta.go +++ b/pkg/util/yunionmeta/meta.go @@ -28,7 +28,8 @@ import ( "yunion.io/x/pkg/util/httputils" "yunion.io/x/pkg/util/version" - "yunion.io/x/onecloud/pkg/esxi/options" + api "yunion.io/x/onecloud/pkg/apis/compute" + "yunion.io/x/onecloud/pkg/compute/options" "yunion.io/x/onecloud/pkg/mcclient/auth" "yunion.io/x/onecloud/pkg/mcclient/modules/compute" ) @@ -152,6 +153,10 @@ func (self *SSkuResourcesMeta) Index(resType string) (map[string]string, error) } func (self *SSkuResourcesMeta) List(resType string, regionId string, retVal interface{}) error { + if strings.HasPrefix(regionId, api.CLOUD_PROVIDER_HUAWEI) && strings.Contains(regionId, "_") { + idx := strings.Index(regionId, "_") + regionId = regionId[:idx] + } var url string switch resType { case "dbinstance_sku": diff --git a/scripts/upgrade_3_11.sh b/scripts/upgrade_3_11.sh new file mode 100755 index 0000000000..087d4cf7bd --- /dev/null +++ b/scripts/upgrade_3_11.sh @@ -0,0 +1,168 @@ +#!/usr/bin/env bash + +# 登录cloudpods控制节点获取mysql账号密码信息,填写到下面变量 +# kubectl get oc -n onecloud default -o yaml | grep -A 4 mysql +# +# 升级到3.11版本之后,等待所有华为云账号同步完成后,执行此升级脚本 +# 脚本原理如下: +# 脚本会检索1天内deleted=1的华为云资源,通过external_id反查当前数据库中对应external_id相同且deleted=0的资源 +# 先会将deleted=1的资源id设为id=id-old, 再将deleted=0的资源id变更到deleted=1的资源id +# +HOST='127.0.0.1' +USERNAME='root' +PASSWORD='' +DATETIME='' +if ["$(uname)"=="Darwin"]; then + DATETIME=$(date -v-1d -u "+%Y-%m-%dT%H:%M%SZ") +else + DATETIME=$(date -d "1 day ago" -u "+%Y-%m-%dT%H:%M%SZ") +if + +function exec_sql_with_db() { + export MYSQL_PWD=$PASSWORD + local db=$1 + local sql=$2 + echo $(mysql -u"$USERNAME" -h "$HOST" -D"$db" -s -e "$sql") +} + +function get_relation_tables() { + local field=$1 + exec_sql_with_db "information_schema" "select table_name from columns where column_name='$field' and table_schema='yunioncloud'" +} + +function exec_sql() { + exec_sql_with_db "yunioncloud" "$1" +} + +function uuid() { + echo $1 | awk -F '-' '{print $1"-"$2"-"$3"-"$4"-"$5}' +} + +function change_uuid() { + local table=$1 + local target_id=$2 + + uid=$(uuid $target_id) + if [ "$uid" != "$target_id" ]; then + target_id=$uid + else + exec_sql "update $table set id='$target_id-old' where id='$target_id'" + fi + echo $target_id +} + + +echo "upgrade guests_tbl" +exec_sql "select name, id, external_id from guests_tbl where deleted=1 and length(external_id) > 0 and host_id in (select id from hosts_tbl where deleted=1 and manager_id in (select id from cloudproviders_tbl where deleted=1 and provider='Huawei' and deleted_at > '$DATETIME'))" | while read -r line; do + info=($(echo $line | tr " ", "\n")) + name=${info[0]} + target_id=${info[1]} + external_id=${info[2]} + id=$(exec_sql "select id from guests_tbl where deleted=0 and external_id='$external_id' and host_id in (select id from hosts_tbl where deleted=0 and manager_id in (select id from cloudproviders_tbl where deleted=0 and provider='Huawei'))") + if [ -n "$id" ]; then + target_id=$(change_uuid "guests_tbl" $target_id) + echo "change server $name id from $id => $target_id" + + exec_sql "update guests_tbl set id='$target_id' where id='$id' and deleted=0" + + tables=$(get_relation_tables "guest_id") + for table in $tables; do + exec_sql "update $table set guest_id='$target_id' where guest_id='$id' and deleted=0" + done + + fi + +done + +echo "upgrade disks_tbl" +exec_sql "select name, id, external_id from disks_tbl where deleted=1 and length(external_id) > 0 and storage_id in (select id from storages_tbl where deleted=1 and manager_id in (select id from cloudproviders_tbl where deleted=1 and provider='Huawei' and deleted_at > '$DATETIME'))" | while read -r line; do + info=($(echo $line | tr " ", "\n")) + name=${info[0]} + target_id=${info[1]} + external_id=${info[2]} + id=$(exec_sql "select id from disks_tbl where deleted=0 and external_id='$external_id' and storage_id in (select id from storages_tbl where deleted=0 and manager_id in (select id from cloudproviders_tbl where deleted=0 and provider='Huawei'))") + if [ -n "$id" ]; then + target_id=$(change_uuid "disks_tbl" $target_id) + echo "change disk $name id from $id => $target_id" + + exec_sql "update disks_tbl set id='$target_id' where id='$id' and deleted=0" + + tables=$(get_relation_tables "disk_id") + for table in $tables; do + exec_sql "update $table set disk_id='$target_id' where disk_id='$id' and deleted=0" + done + + fi + +done + + + +echo "upgrade networks_tbl" +exec_sql "select name, id, external_id from networks_tbl where deleted=1 and length(external_id) > 0 and wire_id in (select id from wires_tbl where deleted=1 and vpc_id in (select id from vpcs_tbl where deleted=1 and manager_id in (select id from cloudproviders_tbl where deleted=1 and provider='Huawei' and deleted_at > '$DATETIME')))" | while read -r line; do + info=($(echo $line | tr " ", "\n")) + name=${info[0]} + target_id=${info[1]} + external_id=${info[2]} + id=$(exec_sql "select id from networks_tbl where deleted=0 and external_id='$external_id' and wire_id in (select id from wires_tbl where deleted=0 and vpc_id in (select id from vpcs_tbl where deleted=0 and manager_id in (select id from cloudproviders_tbl where deleted=0 and provider='Huawei')))") + if [ -n "$id" ]; then + target_id=$(change_uuid "networks_tbl" $target_id) + echo "change network $name id from $id => $target_id" + + exec_sql "update networks_tbl set id='$target_id' where id='$id' and deleted=0" + + tables=$(get_relation_tables "network_id") + for table in $tables; do + if [ "$table" == "network_additional_wire_tbl" ]; then + exec_sql "update $table set network_id='$target_id' where network_id='$id'" + else + exec_sql "update $table set network_id='$target_id' where network_id='$id' and deleted=0" + fi + done + + fi +done + + +function upgrade_managed_resources_table() { + local res_type=$1 + local table_name=$2 + local field=$3 + + echo "upgrade $table_name" + exec_sql "select name, id, external_id from $table_name where deleted=1 and length(external_id) > 0 and manager_id in (select id from cloudproviders_tbl where deleted=1 and provider='Huawei' and deleted_at > '$DATETIME')" | while read -r line; do + info=($(echo $line | tr " ", "\n")) + name=${info[0]} + target_id=${info[1]} + external_id=${info[2]} + id=$(exec_sql "select id from $table_name where deleted=0 and external_id='$external_id' and manager_id in (select id from cloudproviders_tbl where deleted=0 and provider='Huawei')") + if [ -n "$id" ]; then + target_id=$(change_uuid $table_name $target_id) + echo "change $res_type $name id from $id => $target_id" + + exec_sql "update $table_name set id='$target_id' where id='$id' and deleted=0" + + tables=$(get_relation_tables $field) + for table in $tables; do + exec_sql "update $table set $field='$target_id' where $field='$id' and deleted=0" + done + fi + done +} + + +upgrade_managed_resources_table "elasticcacheinstance" "elasticcacheinstances_tbl" "elasticcache_id" +upgrade_managed_resources_table "dbinstance" "dbinstances_tbl" "dbinstance_id" +upgrade_managed_resources_table "bucket" "buckets_tbl" "bucket_id" +upgrade_managed_resources_table "vpc" "vpcs_tbl" "vpc_id" +upgrade_managed_resources_table "cdn" "cdn_domains_tbl" "cdn_domain_id" +upgrade_managed_resources_table "dns" "dnszones_tbl" "dns_zone_id" +upgrade_managed_resources_table "elastic_search" "elastic_searchs_tbl" "elastic_search_id" +upgrade_managed_resources_table "eip" "elasticips_tbl" "eip_id" +upgrade_managed_resources_table "inter_vpc_network" "inter_vpc_networks_tbl" "inter_vpc_network_id" +upgrade_managed_resources_table "kafka" "kafkas_tbl" "kafka_id" +upgrade_managed_resources_table "loadbalancer" "loadbalancers_tbl" "loadbalancer_id" +upgrade_managed_resources_table "snapshot" "snapshots_tbl" "snapshot_id" +upgrade_managed_resources_table "sslcertificate" "sslcertificates_tbl" "sslcertificate_id" + + diff --git a/vendor/modules.txt b/vendor/modules.txt index de45b22dc1..4dd3095b6b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1465,7 +1465,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.20231227025516-4b8aef06c15e +# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20231227060638-40a1db02d028 ## explicit; go 1.18 yunion.io/x/cloudmux/pkg/apis yunion.io/x/cloudmux/pkg/apis/billing diff --git a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go index 21a5ab697c..7b8e35a8a4 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go +++ b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/cloudaccount_const.go @@ -68,8 +68,6 @@ const ( CLOUD_ACCESS_ENV_AZURE_GERMAN = CLOUD_PROVIDER_AZURE + "-de" CLOUD_ACCESS_ENV_AZURE_US_GOVERNMENT = CLOUD_PROVIDER_AZURE + "-us-gov" CLOUD_ACCESS_ENV_AZURE_CHINA = CLOUD_PROVIDER_AZURE - CLOUD_ACCESS_ENV_HUAWEI_GLOBAL = CLOUD_PROVIDER_HUAWEI + "-int" - CLOUD_ACCESS_ENV_HUAWEI_CHINA = CLOUD_PROVIDER_HUAWEI CLOUD_ACCESS_ENV_ALIYUN_GLOBAL = CLOUD_PROVIDER_ALIYUN CLOUD_ACCESS_ENV_ALIYUN_FINANCE = CLOUD_PROVIDER_ALIYUN + "-fin" CLOUD_ACCESS_ENV_CTYUN_CHINA = CLOUD_PROVIDER_CTYUN diff --git a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go index 7f90041ab0..9687ec2e5b 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go +++ b/vendor/yunion.io/x/cloudmux/pkg/apis/compute/storage_const.go @@ -60,11 +60,12 @@ const ( STORAGE_CLOUD_HSSD = "cloud_hssd" //增强型SSD云硬盘 // huawei storage type - STORAGE_HUAWEI_SSD = "SSD" // 超高IO云硬盘 - STORAGE_HUAWEI_SAS = "SAS" // 高IO云硬盘 - STORAGE_HUAWEI_SATA = "SATA" // 普通IO云硬盘 - STORAGE_HUAWEI_GPSSD = "GPSSD" // 通用型SSD - STORAGE_HUAWEI_ESSD = "ESSD" // 急速型SSD + STORAGE_HUAWEI_SSD = "SSD" // 超高IO云硬盘 + STORAGE_HUAWEI_SAS = "SAS" // 高IO云硬盘 + STORAGE_HUAWEI_SATA = "SATA" // 普通IO云硬盘 + STORAGE_HUAWEI_GPSSD = "GPSSD" // 通用型SSD + STORAGE_HUAWEI_GPSSD2 = "GPSSD2" // 通用型SSD V2 + STORAGE_HUAWEI_ESSD = "ESSD" // 急速型SSD // openstack STORAGE_OPENSTACK_ISCSI = "iscsi" diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go index 58ac37e4f9..92c02094db 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/hcso/modelarts.go @@ -292,10 +292,6 @@ type ModelartsStatistics struct { Value float64 } -func (self *SHuaweiClient) GetPoolNetworks(poolName string) (jsonutils.JSONObject, error) { - return self.modelartsPoolNetworkList(nil) -} - func (self *SHuaweiClient) CreatePoolNetworks(cidr string) (jsonutils.JSONObject, error) { params := map[string]interface{}{ "apiVersion": "v1", diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/cloudgroup.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/cloudgroup.go index e6c42119c5..fe208d4614 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/cloudgroup.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/cloudgroup.go @@ -340,7 +340,7 @@ func (self *SHuaweiClient) DetachGroupRole(groupId, roleId string) error { return errors.Wrapf(err, "GetProjects") } for _, project := range projects { - err := self.KeystoneRemoveProjectPermissionFromGroup(project.ID, groupId, role.Id) + err := self.KeystoneRemoveProjectPermissionFromGroup(project.Id, groupId, role.Id) if err != nil { return errors.Wrapf(err, "remove project role ") } @@ -400,7 +400,7 @@ func (self *SHuaweiClient) AttachGroupRole(groupId, roleId string) error { return errors.Wrapf(err, "GetProjects") } for _, project := range projects { - err := self.KeystoneAssociateGroupWithProjectPermission(project.ID, groupId, role.Id) + err := self.KeystoneAssociateGroupWithProjectPermission(project.Id, groupId, role.Id) if err != nil { return errors.Wrapf(err, "add project role ") } @@ -432,7 +432,7 @@ func (self *SHuaweiClient) AttachGroupCustomRole(groupId, roleId string) error { return errors.Wrapf(err, "GetProjects") } for _, project := range projects { - err := self.KeystoneAssociateGroupWithProjectPermission(project.ID, groupId, role.Id) + err := self.KeystoneAssociateGroupWithProjectPermission(project.Id, groupId, role.Id) if err != nil { return errors.Wrapf(err, "add project role ") } @@ -464,7 +464,7 @@ func (self *SHuaweiClient) DetachGroupCustomRole(groupId, roleId string) error { return errors.Wrapf(err, "GetProjects") } for _, project := range projects { - err := self.KeystoneRemoveProjectPermissionFromGroup(project.ID, groupId, role.Id) + err := self.KeystoneRemoveProjectPermissionFromGroup(project.Id, groupId, role.Id) if err != nil { return errors.Wrapf(err, "remove project role ") } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance.go index d991ef930a..9ba432eced 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance.go @@ -474,8 +474,7 @@ func (region *SRegion) CreateIDBInstance(desc *cloudprovider.SManagedDBInstanceC } params := map[string]interface{}{ - "region": region.ID, - "name": desc.Name, + "name": desc.Name, "datastore": map[string]string{ "type": desc.Engine, "version": desc.EngineVersion, diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance_account.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance_account.go index df46042bcd..80c116e882 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance_account.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/dbinstance_account.go @@ -131,11 +131,11 @@ func (region *SRegion) RevokeDBInstancePrivilege(instanceId string, account, dat }, } resource := fmt.Sprintf("instances/%s/db_privilege", instanceId) - url, err := region.client.getUrl(SERVICE_RDS, region.ID, resource, httputils.DELETE, nil) + url, err := region.client.getUrl(SERVICE_RDS, region.Id, resource, httputils.DELETE, nil) if err != nil { return err } - _, err = region.client.request(httputils.DELETE, url, nil, params) + _, err = region.client.request(httputils.DELETE, region.Id, url, nil, params) return err } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disk.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disk.go index 8cde29c94d..97f4259f1e 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disk.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disk.go @@ -406,12 +406,15 @@ func (self *SRegion) GetDisk(diskId string) (*SDisk, error) { } // https://console.huaweicloud.com/apiexplorer/#/openapi/EVS/doc?api=ListVolumes -func (self *SRegion) GetDisks(zoneId string) ([]SDisk, error) { +func (self *SRegion) GetDisks(zoneId, storageTypeId string) ([]SDisk, error) { ret := []SDisk{} query := url.Values{} if len(zoneId) > 0 { query.Set("availability_zone", zoneId) } + if len(storageTypeId) > 0 { + query.Set("volume_type_id", storageTypeId) + } for { resp, err := self.list(SERVICE_EVS, "cloudvolumes/detail", query) if err != nil { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disktype.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disktype.go index 9329a461ce..18364ed4fd 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disktype.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/disktype.go @@ -14,13 +14,11 @@ package huawei -import "strings" - type SDiskType struct { ExtraSpecs ExtraSpecs `json:"extra_specs"` Name string `json:"name"` QosSpecsID string `json:"qos_specs_id"` - ID string `json:"id"` + Id string `json:"id"` IsPublic bool `json:"is_public"` } @@ -30,11 +28,3 @@ type ExtraSpecs struct { RESKEYAvailabilityZones string `json:"RESKEY:availability_zones"` OSVendorExtendedSoldOutAvailabilityZones string `json:"os-vendor-extended:sold_out_availability_zones"` } - -func (self *SDiskType) IsAvaliableInZone(zoneId string) bool { - if len(self.QosSpecsID) > 0 && strings.Contains(self.ExtraSpecs.RESKEYAvailabilityZones, zoneId) && !strings.Contains(self.ExtraSpecs.OSVendorExtendedSoldOutAvailabilityZones, zoneId) { - return true - } - - return false -} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/eip.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/eip.go index d412d6015b..bb4a3b7238 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/eip.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/eip.go @@ -391,14 +391,14 @@ func (self *SRegion) setEipTags(id string, existedTags, tags map[string]string, } if len(deleteTagsKey) > 0 { for _, k := range deleteTagsKey { - err := self.DeletePublicipTag(self.ID, k) + err := self.DeletePublicipTag(id, k) if err != nil { return errors.Wrapf(err, "remove tags") } } } if len(tags) > 0 { - err := self.CreatePublicipTag(self.ID, tags) + err := self.CreatePublicipTag(id, tags) if err != nil { return errors.Wrapf(err, "add tags") } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/host.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/host.go index 5028d9d73a..0a0570c44c 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/host.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/host.go @@ -30,8 +30,6 @@ import ( type SHost struct { multicloud.SHostBase zone *SZone - - projectId string } func (self *SHost) GetId() string { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/huawei.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/huawei.go index f1160dadaf..f141c80173 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/huawei.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/huawei.go @@ -20,7 +20,6 @@ import ( "net/http" "net/url" "strings" - "sync" "time" "github.com/huaweicloud/huaweicloud-sdk-go/auth/aksk" @@ -28,6 +27,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/util/httputils" "yunion.io/x/pkg/util/timeutils" @@ -41,12 +41,8 @@ const ( CLOUD_PROVIDER_HUAWEI_CN = "华为云" CLOUD_PROVIDER_HUAWEI_EN = "Huawei" - HUAWEI_INTERNATIONAL_CLOUDENV = "InternationalCloud" - HUAWEI_CHINA_CLOUDENV = "ChinaCloud" - - HUAWEI_DEFAULT_REGION = "cn-north-1" - HUAWEI_CERT_DEFAULT_REGION = "cn-north-4" - HUAWEI_API_VERSION = "2018-12-25" + HUAWEI_DEFAULT_REGION = "cn-north-4" + HUAWEI_API_VERSION = "2018-12-25" SERVICE_IAM = "iam" SERVICE_IAM_V3 = "iam_v3" @@ -85,27 +81,17 @@ const ( SERVICE_FUNCTIONGRAPH = "functiongraph" ) -var HUAWEI_REGION_CACHES sync.Map - -type userRegionsCache struct { - UserId string - ExpireAt time.Time - Regions []SRegion -} - type HuaweiClientConfig struct { cpcfg cloudprovider.ProviderConfig - projectId string // 华为云项目ID. accessKey string accessSecret string debug bool } -func NewHuaweiClientConfig(accessKey, accessSecret, projectId string) *HuaweiClientConfig { +func NewHuaweiClientConfig(accessKey, accessSecret string) *HuaweiClientConfig { cfg := &HuaweiClientConfig{ - projectId: projectId, accessKey: accessKey, accessSecret: accessSecret, } @@ -125,33 +111,26 @@ func (cfg *HuaweiClientConfig) Debug(debug bool) *HuaweiClientConfig { type SHuaweiClient struct { *HuaweiClientConfig - isMainProject bool // whether the project is the main project in the region - isDefaultProject bool // whether the project is the default region project - clientRegion string - userId string ownerId string ownerName string ownerCreateTime time.Time - iregions []cloudprovider.ICloudRegion iBuckets []cloudprovider.ICloudBucket - projects []SProject - regions []SRegion + projects map[string]SProject + regions map[string]SRegion httpClient *http.Client orders map[string]SOrderResource } -// 进行资源操作时参数account 对应数据库cloudprovider表中的account字段,由accessKey和projectID两部分组成,通过"/"分割。 -// 初次导入Subaccount时,参数account对应cloudaccounts表中的account字段,即accesskey。此时projectID为空, -// 只能进行同步子账号、查询region列表等projectId无关的操作。 -// todo: 通过accessurl支持国际站。目前暂时未支持国际站 func NewHuaweiClient(cfg *HuaweiClientConfig) (*SHuaweiClient, error) { client := SHuaweiClient{ HuaweiClientConfig: cfg, + regions: map[string]SRegion{}, + projects: map[string]SProject{}, } err := client.init() if err != nil { @@ -161,16 +140,13 @@ func NewHuaweiClient(cfg *HuaweiClientConfig) (*SHuaweiClient, error) { } func (self *SHuaweiClient) init() error { - err := self.fetchRegions() + _, err := self.getRegions() if err != nil { - return err + return errors.Wrapf(err, "GetRegions") } - err = self.initOwner() + _, err = self.GetProjects() if err != nil { - return errors.Wrap(err, "fetchOwner") - } - if self.debug { - log.Debugf("OwnerId: %s name: %s", self.ownerId, self.ownerName) + return errors.Wrapf(err, "GetProjects") } return nil } @@ -234,7 +210,7 @@ func (self *SHuaweiClient) getAkClient() *akClient { } } -func (self *SHuaweiClient) request(method httputils.THttpMethod, url string, query url.Values, params map[string]interface{}) (jsonutils.JSONObject, error) { +func (self *SHuaweiClient) request(method httputils.THttpMethod, regionId, url string, query url.Values, params map[string]interface{}) (jsonutils.JSONObject, error) { client := self.getAkClient() if len(query) > 0 { url = fmt.Sprintf("%s?%s", url, query.Encode()) @@ -244,8 +220,11 @@ func (self *SHuaweiClient) request(method httputils.THttpMethod, url string, que body = jsonutils.Marshal(params) } header := http.Header{} - if len(self.projectId) > 0 && !strings.Contains(url, "eps") { - header.Set("X-Project-Id", self.projectId) + + if project, ok := self.projects[regionId]; ok { + if len(project.Id) > 0 && !strings.Contains(url, "eps") { + header.Set("X-Project-Id", project.Id) + } } if (strings.Contains(url, "/OS-CREDENTIAL/") || strings.Contains(url, "/users") || @@ -264,64 +243,30 @@ func (self *SHuaweiClient) request(method httputils.THttpMethod, url string, que } // https://console.huaweicloud.com/apiexplorer/#/openapi/IAM/doc?api=KeystoneListRegions -func (self *SHuaweiClient) fetchRegions() error { - if self.regions == nil { - userId, err := self.GetUserId() - if err != nil { - return errors.Wrap(err, "GetUserId") - } - - if regionsCache, ok := HUAWEI_REGION_CACHES.Load(userId); !ok || regionsCache.(*userRegionsCache).ExpireAt.Sub(time.Now()).Seconds() > 0 { - resp, err := self.list(SERVICE_IAM_V3, "", "regions", nil) - if err != nil { - return errors.Wrapf(err, "list regions") - } - regions := make([]SRegion, 0) - err = resp.Unmarshal(®ions, "regions") - if err != nil { - return errors.Wrapf(err, "Unmarshal") - } - HUAWEI_REGION_CACHES.Store(userId, &userRegionsCache{ExpireAt: time.Now().Add(24 * time.Hour), UserId: userId, Regions: regions}) - } - - if regionsCache, ok := HUAWEI_REGION_CACHES.Load(userId); ok { - self.regions = regionsCache.(*userRegionsCache).Regions - } - } - - filtedRegions := make([]SRegion, 0) - if len(self.projectId) > 0 { - project, err := self.GetProjectById(self.projectId) - if err != nil { - return err - } - +func (self *SHuaweiClient) getRegions() ([]SRegion, error) { + if len(self.regions) > 0 { + ret := []SRegion{} for _, region := range self.regions { - if strings.Count(project.Name, region.ID) >= 1 { - self.clientRegion = region.ID - filtedRegions = append(filtedRegions, region) - } - if project.Name == region.ID { - self.isMainProject = true - } + ret = append(ret, region) } - if project.Name == HUAWEI_CERT_DEFAULT_REGION { - self.isDefaultProject = true - } - } else { - filtedRegions = self.regions + return ret, nil + } + resp, err := self.list(SERVICE_IAM_V3, "", "regions", nil) + if err != nil { + return nil, errors.Wrapf(err, "list regions") } - if len(filtedRegions) == 0 { - return errors.Wrapf(cloudprovider.ErrNotFound, "empty regions") + self.regions = map[string]SRegion{} + regions := make([]SRegion, 0) + err = resp.Unmarshal(®ions, "regions") + if err != nil { + return nil, errors.Wrapf(err, "Unmarshal") } - - self.iregions = make([]cloudprovider.ICloudRegion, len(filtedRegions)) - for i := 0; i < len(filtedRegions); i += 1 { - filtedRegions[i].client = self - self.iregions[i] = &filtedRegions[i] + for _, region := range regions { + region.client = self + self.regions[region.Id] = region } - return nil + return regions, nil } func (self *SHuaweiClient) invalidateIBuckets() { @@ -387,13 +332,13 @@ func (self *SHuaweiClient) fetchBuckets() error { ret := make([]cloudprovider.ICloudBucket, 0) for i := range output.Buckets { bInfo := output.Buckets[i] - region, err := self.getIRegionByRegionId(bInfo.Location) - if err != nil { + region := self.GetRegion(bInfo.Location) + if gotypes.IsNil(region) { log.Errorf("fail to find region %s", bInfo.Location) continue } b := SBucket{ - region: region.(*SRegion), + region: region, Name: bInfo.Name, Location: bInfo.Location, @@ -405,153 +350,81 @@ func (self *SHuaweiClient) fetchBuckets() error { return nil } -func (self *SHuaweiClient) GetCloudRegionExternalIdPrefix() string { - if len(self.projectId) > 0 { - return self.iregions[0].GetGlobalId() - } else { - return CLOUD_PROVIDER_HUAWEI - } -} - -func (self *SHuaweiClient) 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 *SHuaweiClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) { - projects, err := self.fetchProjects() - if err != nil { - return nil, err - } - - // https://support.huaweicloud.com/api-iam/zh-cn_topic_0074171149.html - subAccounts := make([]cloudprovider.SSubAccount, 0) - for i := range projects { - project := projects[i] - - find := false - for j := range self.iregions { - region := self.iregions[j].(*SRegion) - if strings.Contains(project.Name, region.ID) { - find = true - break - } - } - if !find { - // name 为MOS的project是华为云内部的一个特殊project。不需要同步到本地 - // skip invalid project - continue - } - // https://www.huaweicloud.com/notice/2018/20190618171312411.html - // expiredAt, _ := timeutils.ParseTimeStr("2020-09-16 00:00:00") - // if !self.ownerCreateTime.IsZero() && self.ownerCreateTime.After(expiredAt) && strings.ToLower(project.Name) == "cn-north-1" { - // continue - // } - s := cloudprovider.SSubAccount{ - Id: project.ID, - Name: fmt.Sprintf("%s-%s", self.cpcfg.Name, project.Name), - Account: fmt.Sprintf("%s/%s", self.accessKey, project.ID), - HealthStatus: project.GetHealthStatus(), - DefaultProjectId: "0", - Desc: project.GetDescription(), - } - for j := range self.iregions { - region := self.iregions[j].(*SRegion) - if strings.Contains(project.Name, region.ID) { - s.Desc = region.Locales.ZhCN - break - } - } - - subAccounts = append(subAccounts, s) - } - - return subAccounts, nil + subAccount := cloudprovider.SSubAccount{} + subAccount.Id = self.GetAccountId() + subAccount.Name = self.cpcfg.Name + subAccount.Account = self.accessKey + subAccount.HealthStatus = api.CLOUD_PROVIDER_HEALTH_NORMAL + subAccount.DefaultProjectId = "0" + return []cloudprovider.SSubAccount{subAccount}, nil } func (client *SHuaweiClient) GetAccountId() string { - return client.ownerId + ownerId, _ := client.GetOwnerId() + return ownerId } func (client *SHuaweiClient) GetIamLoginUrl() string { return fmt.Sprintf("https://auth.huaweicloud.com/authui/login.html?account=%s#/login", client.ownerName) } -func (self *SHuaweiClient) GetIRegions() []cloudprovider.ICloudRegion { - return self.iregions -} - -func (self *SHuaweiClient) getIRegionByRegionId(id string) (cloudprovider.ICloudRegion, error) { - for i := 0; i < len(self.iregions); i += 1 { - log.Debugf("%d ID: %s", i, self.iregions[i].GetId()) - if self.iregions[i].GetId() == id { - return self.iregions[i], nil +func (self *SHuaweiClient) GetRegions() []SRegion { + ret := []SRegion{} + for id := range self.regions { + if _, ok := self.projects[id]; !ok { + continue + } + region := self.regions[id] + region.client = self + ret = append(ret, region) + } + for id := range self.projects { + project := self.projects[id] + if strings.Contains(project.Name, "_") { + regionId := project.GetRegionId() + if region, ok := self.regions[regionId]; ok { + region.Id = project.Name + region.client = self + ret = append(ret, region) + } } } - return nil, cloudprovider.ErrNotFound + return ret +} + +func (self *SHuaweiClient) GetIRegions() []cloudprovider.ICloudRegion { + regions := self.GetRegions() + ret := []cloudprovider.ICloudRegion{} + for i := range regions { + ret = append(ret, ®ions[i]) + } + return ret } func (self *SHuaweiClient) 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 + regions := self.GetIRegions() + for i := range regions { + if regions[i].GetId() == id || regions[i].GetGlobalId() == id { + return regions[i], nil } } - return nil, cloudprovider.ErrNotFound + return nil, errors.Wrapf(cloudprovider.ErrNotFound, id) } func (self *SHuaweiClient) GetRegion(regionId string) *SRegion { if len(regionId) == 0 { regionId = HUAWEI_DEFAULT_REGION } - for i := 0; i < len(self.iregions); i += 1 { - if self.iregions[i].GetId() == regionId { - return self.iregions[i].(*SRegion) + regions := self.GetRegions() + for i := range regions { + if regions[i].Id == regionId { + return ®ions[i] } } return nil } -func (self *SHuaweiClient) 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 *SHuaweiClient) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { - for i := 0; i < len(self.iregions); i += 1 { - ivpc, err := self.iregions[i].GetIVpcById(id) - if err == nil { - return ivpc, nil - } else if errors.Cause(err) != cloudprovider.ErrNotFound { - return nil, err - } - } - return nil, cloudprovider.ErrNotFound -} - -func (self *SHuaweiClient) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { - for i := 0; i < len(self.iregions); i += 1 { - istorage, err := self.iregions[i].GetIStorageById(id) - if err == nil { - return istorage, nil - } else if errors.Cause(err) != cloudprovider.ErrNotFound { - return nil, err - } - } - return nil, cloudprovider.ErrNotFound -} - type SBalance struct { Amount float64 `json:"amount"` Currency string `json:"currency"` @@ -616,7 +489,7 @@ func (self *SHuaweiClient) GetCapabilities() []string { cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP, cloudprovider.CLOUD_CAPABILITY_EIP, cloudprovider.CLOUD_CAPABILITY_LOADBALANCER, - // cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE, + cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE, cloudprovider.CLOUD_CAPABILITY_RDS, cloudprovider.CLOUD_CAPABILITY_CACHE, cloudprovider.CLOUD_CAPABILITY_EVENT, @@ -627,16 +500,8 @@ func (self *SHuaweiClient) GetCapabilities() []string { cloudprovider.CLOUD_CAPABILITY_QUOTA + cloudprovider.READ_ONLY_SUFFIX, cloudprovider.CLOUD_CAPABILITY_MODELARTES, cloudprovider.CLOUD_CAPABILITY_VPC_PEER, - } - // huawei objectstore is shared across projects(subscriptions) - // to avoid multiple project access the same bucket - // only main project is allow to access objectstore bucket - if self.isMainProject { - caps = append(caps, cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE) - } - if self.isDefaultProject { - caps = append(caps, cloudprovider.CLOUD_CAPABILITY_CERT) - caps = append(caps, cloudprovider.CLOUD_CAPABILITY_CDN+cloudprovider.READ_ONLY_SUFFIX) + cloudprovider.CLOUD_CAPABILITY_CERT, + cloudprovider.CLOUD_CAPABILITY_CDN + cloudprovider.READ_ONLY_SUFFIX, } return caps } @@ -698,20 +563,12 @@ func (self *SHuaweiClient) GetOwnerId() (string, error) { return self.ownerId, nil } -func (self *SHuaweiClient) initOwner() error { - _, err := self.GetOwnerId() - if err != nil { - return errors.Wrap(err, "SHuaweiClient.initOwner") - } - return nil -} - func (self *SHuaweiClient) list(service, regionId, resource string, query url.Values) (jsonutils.JSONObject, error) { url, err := self.getUrl(service, regionId, resource, httputils.GET, nil) if err != nil { return nil, err } - return self.request(httputils.GET, url, query, nil) + return self.request(httputils.GET, regionId, url, query, nil) } func (self *SHuaweiClient) delete(service, regionId, resource string) (jsonutils.JSONObject, error) { @@ -719,12 +576,21 @@ func (self *SHuaweiClient) delete(service, regionId, resource string) (jsonutils if err != nil { return nil, err } - return self.request(httputils.DELETE, url, nil, nil) + return self.request(httputils.DELETE, regionId, url, nil, nil) } func (self *SHuaweiClient) getUrl(service, regionId, resource string, method httputils.THttpMethod, params map[string]interface{}) (string, error) { url := "" resource = strings.TrimPrefix(resource, "/") + if len(regionId) == 0 { + regionId = HUAWEI_DEFAULT_REGION + } + projectId := "" + project, ok := self.projects[regionId] + if ok { + regionId = project.GetRegionId() + projectId = project.Id + } switch service { case SERVICE_IAM: url = fmt.Sprintf("https://iam.myhuaweicloud.com/v3.0/%s", resource) @@ -733,60 +599,60 @@ func (self *SHuaweiClient) getUrl(service, regionId, resource string, method htt case SERVICE_IAM_V3_EXT: url = fmt.Sprintf("https://iam.myhuaweicloud.com/v3-ext/%s", resource) case SERVICE_ELB: - url = fmt.Sprintf("https://elb.%s.myhuaweicloud.com/v3/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://elb.%s.myhuaweicloud.com/v3/%s/%s", regionId, projectId, resource) case SERVICE_VPC: - url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v1/%s/%s", regionId, projectId, resource) case SERVICE_VPC_V2_0: - url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v2.0/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v2.0/%s/%s", regionId, projectId, resource) if strings.Contains(resource, "/peerings") { url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v2.0/%s", regionId, resource) } case SERVICE_VPC_V3: - url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v3/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://vpc.%s.myhuaweicloud.com/v3/%s/%s", regionId, projectId, resource) case SERVICE_CES: - url = fmt.Sprintf("https://ces.%s.myhuaweicloud.com/v1.0/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://ces.%s.myhuaweicloud.com/v1.0/%s/%s", regionId, projectId, resource) case SERVICE_MODELARTS: - url = fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v2/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v2/%s/%s", regionId, projectId, resource) case SERVICE_MODELARTS_V1: - url = fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v1/%s/%s", regionId, projectId, resource) case SERVICE_RDS: - url = fmt.Sprintf("https://rds.%s.myhuaweicloud.com/v3/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://rds.%s.myhuaweicloud.com/v3/%s/%s", regionId, projectId, resource) case SERVICE_ECS: - url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v1/%s/%s", regionId, projectId, resource) case SERVICE_ECS_V1_1: - url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v1.1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v1.1/%s/%s", regionId, projectId, resource) case SERVICE_ECS_V2_1: - url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v2.1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://ecs.%s.myhuaweicloud.com/v2.1/%s/%s", regionId, projectId, resource) case SERVICE_EPS: url = fmt.Sprintf("https://eps.myhuaweicloud.com/v1.0/%s", resource) case SERVICE_EVS_V1: - url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v1/%s/%s", regionId, projectId, resource) case SERVICE_EVS: - url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v2/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v2/%s/%s", regionId, projectId, resource) case SERVICE_EVS_V2_1: - url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v2.1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://evs.%s.myhuaweicloud.com/v2.1/%s/%s", regionId, projectId, resource) case SERVICE_BSS: url = fmt.Sprintf("https://bss.myhuaweicloud.com/v2/%s", resource) case SERVICE_SFS: - url = fmt.Sprintf("https://sfs-turbo.%s.myhuaweicloud.com/v1/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://sfs-turbo.%s.myhuaweicloud.com/v1/%s/%s", regionId, projectId, resource) case SERVICE_IMS: url = fmt.Sprintf("https://ims.%s.myhuaweicloud.com/v2/%s", regionId, resource) case SERVICE_IMS_V1: url = fmt.Sprintf("https://ims.%s.myhuaweicloud.com/v1/%s", regionId, resource) case SERVICE_DCS: - url = fmt.Sprintf("https://dcs.%s.myhuaweicloud.com/v2/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://dcs.%s.myhuaweicloud.com/v2/%s/%s", regionId, projectId, resource) case SERVICE_CTS: - url = fmt.Sprintf("https://cts.%s.myhuaweicloud.com/v3/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://cts.%s.myhuaweicloud.com/v3/%s/%s", regionId, projectId, resource) case SERVICE_NAT: - url = fmt.Sprintf("https://nat.%s.myhuaweicloud.com/v3/%s/%s", regionId, self.projectId, resource) + url = fmt.Sprintf("https://nat.%s.myhuaweicloud.com/v3/%s/%s", regionId, projectId, resource) case SERVICE_SCM: url = fmt.Sprintf("https://scm.cn-north-4.myhuaweicloud.com/v3/%s", resource) case SERVICE_CDN: url = fmt.Sprintf("https://cdn.myhuaweicloud.com/v1.0/%s", resource) case SERVICE_GAUSSDB, SERVICE_GAUSSDB_NOSQL: - url = fmt.Sprintf("https://%s.%s.myhuaweicloud.com/v3/%s/%s", service, regionId, self.projectId, resource) + url = fmt.Sprintf("https://%s.%s.myhuaweicloud.com/v3/%s/%s", service, regionId, projectId, resource) case SERVICE_FUNCTIONGRAPH: - url = fmt.Sprintf("https://%s.%s.myhuaweicloud.com/v2/%s/%s", service, regionId, self.projectId, resource) + url = fmt.Sprintf("https://%s.%s.myhuaweicloud.com/v2/%s/%s", service, regionId, projectId, resource) default: return "", fmt.Errorf("invalid service %s", service) } @@ -798,7 +664,7 @@ func (self *SHuaweiClient) post(service, regionId, resource string, params map[s if err != nil { return nil, err } - return self.request(httputils.POST, url, nil, params) + return self.request(httputils.POST, regionId, url, nil, params) } func (self *SHuaweiClient) patch(service, regionId, resource string, query url.Values, params map[string]interface{}) (jsonutils.JSONObject, error) { @@ -806,7 +672,7 @@ func (self *SHuaweiClient) patch(service, regionId, resource string, query url.V if err != nil { return nil, err } - return self.request(httputils.PATCH, url, query, params) + return self.request(httputils.PATCH, regionId, url, query, params) } func (self *SHuaweiClient) put(service, regionId, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) { @@ -814,5 +680,5 @@ func (self *SHuaweiClient) put(service, regionId, resource string, params map[st if err != nil { return nil, err } - return self.request(httputils.PUT, url, nil, params) + return self.request(httputils.PUT, regionId, url, nil, params) } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/instance.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/instance.go index a475c0e3a9..4f9c344a5c 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/instance.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/instance.go @@ -761,7 +761,7 @@ func (self *SRegion) CreateInstance(keypair, zoneId string, opts *cloudprovider. }) } extendparam := map[string]interface{}{ - "regionID": self.GetId(), + "regionID": self.getId(), "chargingMode": POST_PAID, } if len(opts.ProjectId) > 0 { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/loadbalancer.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/loadbalancer.go index 689ab9006b..ea302ad153 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/loadbalancer.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/loadbalancer.go @@ -559,6 +559,11 @@ func (self *SRegion) CreateLoadBalancer(opts *cloudprovider.SLoadbalancerCreateO return nil, errors.Wrap(err, "getNetwork") } + projectId := "" + project, ok := self.client.projects[self.Id] + if ok { + projectId = project.Id + } params := map[string]interface{}{ "name": opts.Name, "description": opts.Desc, @@ -566,7 +571,7 @@ func (self *SRegion) CreateLoadBalancer(opts *cloudprovider.SLoadbalancerCreateO "provider": "vlb", "admin_state_up": true, "guaranteed": true, - "project_id": self.client.projectId, + "project_id": projectId, "charge_mode": "lcu", } if len(opts.ProjectId) > 0 { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go index 5b9aa64017..014b4be60d 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/modelarts_pool.go @@ -150,9 +150,9 @@ func (self *SRegion) CreateIModelartsPool(args *cloudprovider.ModelartsPoolCreat } if len(netId) == 0 { - createNetObj, err := self.client.CreatePoolNetworks(args.Cidr) + createNetObj, err := self.CreatePoolNetworks(args.Cidr) if err != nil { - return nil, errors.Wrap(err, "SHuaweiClient.CreatePoolNetworks") + return nil, errors.Wrap(err, "CreatePoolNetworks") } netId, _ = createNetObj.GetString("metadata", "name") for i := 0; i < 10; i++ { @@ -290,11 +290,7 @@ type ModelartsStatistics struct { Value float64 } -func (self *SHuaweiClient) GetPoolNetworks(poolName string) (jsonutils.JSONObject, error) { - return self.list(SERVICE_MODELARTS_V1, self.clientRegion, "networks", nil) -} - -func (self *SHuaweiClient) CreatePoolNetworks(cidr string) (jsonutils.JSONObject, error) { +func (self *SRegion) CreatePoolNetworks(cidr string) (jsonutils.JSONObject, error) { params := map[string]interface{}{ "apiVersion": "v1", "kind": "Network", @@ -308,7 +304,7 @@ func (self *SHuaweiClient) CreatePoolNetworks(cidr string) (jsonutils.JSONObject "cidr": cidr, }, } - return self.post(SERVICE_MODELARTS_V1, self.clientRegion, "networks", params) + return self.post(SERVICE_MODELARTS_V1, "networks", params) } func (self *SModelartsPool) GetCreatedAt() time.Time { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/monitor.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/monitor.go index 3560c31dbd..46bbb10979 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/monitor.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/monitor.go @@ -73,7 +73,7 @@ func (self *SHuaweiClient) getServerMetrics(opts *cloudprovider.MetricListOption }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -155,7 +155,7 @@ func (self *SHuaweiClient) getServerAgentMetrics(opts *cloudprovider.MetricListO }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -226,7 +226,7 @@ func (self *SHuaweiClient) getRedisMetrics(opts *cloudprovider.MetricListOptions }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -322,7 +322,7 @@ func (self *SHuaweiClient) getRdsMetrics(opts *cloudprovider.MetricListOptions) }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -411,7 +411,7 @@ func (self *SHuaweiClient) getBucketMetrics(opts *cloudprovider.MetricListOption }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -492,7 +492,7 @@ func (self *SHuaweiClient) getLoadbalancerMetrics(opts *cloudprovider.MetricList }) } params["metrics"] = metrics - resp, err := self.post(SERVICE_CES, self.clientRegion, "batch-query-metric-data", params) + resp, err := self.post(SERVICE_CES, opts.RegionExtId, "batch-query-metric-data", params) if err != nil { return nil, err } @@ -545,7 +545,7 @@ func (self *SHuaweiClient) getLoadbalancerMetrics(opts *cloudprovider.MetricList func (self *SHuaweiClient) getModelartsPoolMetrics(opts *cloudprovider.MetricListOptions) ([]cloudprovider.MetricValues, error) { resource := fmt.Sprintf("pools/%s/monitor", opts.ResourceId) - resp, err := self.list(SERVICE_MODELARTS, self.clientRegion, resource, nil) + resp, err := self.list(SERVICE_MODELARTS, opts.RegionExtId, resource, nil) if err != nil { return nil, err } diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/project.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/project.go index 3e08aec480..ef3b7e3b5d 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/project.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/project.go @@ -18,43 +18,34 @@ import ( "fmt" "strings" - api "yunion.io/x/cloudmux/pkg/apis/compute" "yunion.io/x/pkg/errors" ) -// https://support.huaweicloud.com/api-iam/zh-cn_topic_0057845625.html type SProject struct { client *SHuaweiClient - IsDomain bool `json:"is_domain"` - Description string `json:"description"` - Enabled bool `json:"enabled"` - ID string `json:"id"` - ParentID string `json:"parent_id"` - DomainID string `json:"domain_id"` - Name string `json:"name"` + IsDomain bool + Description string + Enabled bool + Id string + ParentId string + DomainId string + Name string } -func (self *SProject) GetRegionID() string { +func (self *SProject) GetRegionId() string { return strings.Split(self.Name, "_")[0] } -func (self *SProject) GetDescription() string { - return self.Description -} - -func (self *SProject) GetHealthStatus() string { - if self.Enabled { - return api.CLOUD_PROVIDER_HEALTH_NORMAL - } - - return api.CLOUD_PROVIDER_HEALTH_SUSPENDED -} - -func (self *SHuaweiClient) fetchProjects() ([]SProject, error) { +func (self *SHuaweiClient) GetProjects() ([]SProject, error) { if len(self.projects) > 0 { - return self.projects, nil + ret := []SProject{} + for _, project := range self.projects { + ret = append(ret, project) + } + return ret, nil } + self.projects = map[string]SProject{} projects := []SProject{} resp, err := self.list(SERVICE_IAM_V3, "", "auth/projects", nil) if err != nil { @@ -64,8 +55,10 @@ func (self *SHuaweiClient) fetchProjects() ([]SProject, error) { if err != nil { return nil, errors.Wrapf(err, "Unmarshal") } - self.projects = projects - return self.projects, nil + for _, project := range projects { + self.projects[project.Name] = project + } + return projects, nil } // obs 权限必须赋予到mos project之上 @@ -76,26 +69,22 @@ func (self *SHuaweiClient) GetMosProjectId() string { } for i := range projects { if strings.ToLower(projects[i].Name) == "mos" { - return projects[i].ID + return projects[i].Id } } return "" } func (self *SHuaweiClient) GetProjectById(projectId string) (SProject, error) { - projects, err := self.fetchProjects() + projects, err := self.GetProjects() if err != nil { return SProject{}, err } for _, project := range projects { - if project.ID == projectId { + if project.Id == projectId { return project, nil } } return SProject{}, fmt.Errorf("project %s not found", projectId) } - -func (self *SHuaweiClient) GetProjects() ([]SProject, error) { - return self.fetchProjects() -} diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/provider/provider.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/provider/provider.go index 882df2b297..ef3b314602 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/provider/provider.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/provider/provider.go @@ -16,7 +16,6 @@ package provider import ( "context" - "strings" "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" @@ -111,24 +110,10 @@ func (self *SHuaweiProviderFactory) ValidateUpdateCloudaccountCredential(ctx con 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 *SHuaweiProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig) (cloudprovider.ICloudProvider, error) { - accessKey, projectId := parseAccount(cfg.Account) client, err := huawei.NewHuaweiClient( huawei.NewHuaweiClientConfig( - accessKey, cfg.Secret, projectId, + cfg.Account, cfg.Secret, ).CloudproviderConfig(cfg), ) if err != nil { @@ -141,16 +126,10 @@ func (self *SHuaweiProviderFactory) GetProvider(cfg cloudprovider.ProviderConfig } func (self *SHuaweiProviderFactory) GetClientRC(info cloudprovider.SProviderInfo) (map[string]string, error) { - accessKey, projectId := parseAccount(info.Account) - data := strings.Split(info.Name, "-") - if len(info.Region) == 0 && len(data) >= 3 { - info.Region = strings.Join(data[len(data)-3:], "-") - } return map[string]string{ - "HUAWEI_ACCESS_KEY": accessKey, + "HUAWEI_ACCESS_KEY": info.Account, "HUAWEI_SECRET": info.Secret, - "HUAWEI_REGION": info.Region, - "HUAWEI_PROJECT": projectId, + "HUAWEI_REGION": huawei.HUAWEI_DEFAULT_REGION, }, nil } @@ -211,7 +190,7 @@ func (self *SHuaweiProvider) GetIamLoginUrl() string { } func (self *SHuaweiProvider) GetCloudRegionExternalIdPrefix() string { - return self.client.GetCloudRegionExternalIdPrefix() + return api.CLOUD_PROVIDER_HUAWEI + "/" } func (self *SHuaweiProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/region.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/region.go index e24e8ee5df..427c271122 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/region.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/region.go @@ -35,18 +35,17 @@ type Locales struct { ZhCN string `json:"zh-cn"` } -// https://support.huaweicloud.com/api-iam/zh-cn_topic_0067148043.html type SRegion struct { multicloud.SRegion client *SHuaweiClient obsClient *obs.ObsClient // 对象存储client.请勿直接引用。 - Description string `json:"description"` - ID string `json:"id"` - Locales Locales `json:"locales"` - ParentRegionID string `json:"parent_region_id"` - Type string `json:"type"` + Description string + Id string + Locales Locales + ParentRegionId string + Type string storageCache *SStoragecache } @@ -56,32 +55,32 @@ func (self *SRegion) GetClient() *SHuaweiClient { } func (self *SRegion) list(service, resource string, query url.Values) (jsonutils.JSONObject, error) { - return self.client.list(service, self.ID, resource, query) + return self.client.list(service, self.Id, resource, query) } func (self *SRegion) delete(service, resource string) (jsonutils.JSONObject, error) { - return self.client.delete(service, self.ID, resource) + return self.client.delete(service, self.Id, resource) } func (self *SRegion) put(service, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) { - return self.client.put(service, self.ID, resource, params) + return self.client.put(service, self.Id, resource, params) } func (self *SRegion) post(service, resource string, params map[string]interface{}) (jsonutils.JSONObject, error) { - return self.client.post(service, self.ID, resource, params) + return self.client.post(service, self.Id, resource, params) } func (self *SRegion) patch(service, resource string, query url.Values, params map[string]interface{}) (jsonutils.JSONObject, error) { - return self.client.patch(service, self.ID, resource, query, params) + return self.client.patch(service, self.Id, resource, query, params) } func (self *SRegion) getOBSEndpoint() string { - return getOBSEndpoint(self.GetId()) + return getOBSEndpoint(self.getId()) } func (self *SRegion) getOBSClient(signType obs.SignatureType) (*obs.ObsClient, error) { if self.obsClient == nil { - obsClient, err := self.client.getOBSClient(self.GetId(), signType) + obsClient, err := self.client.getOBSClient(self.getId(), signType) if err != nil { return nil, err } @@ -119,7 +118,7 @@ func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { } func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { - if info, ok := LatitudeAndLongitude[self.ID]; ok { + if info, ok := LatitudeAndLongitude[self.getId()]; ok { return info } return cloudprovider.SGeographicInfo{} @@ -206,24 +205,49 @@ func (self *SRegion) GetILoadBalancerCertificates() ([]cloudprovider.ICloudLoadb return iret, nil } -// https://support.huaweicloud.com/api-iam/zh-cn_topic_0057845622.html func (self *SRegion) GetId() string { - return self.ID + return self.Id } func (self *SRegion) GetName() string { - return fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_CN, self.Locales.ZhCN) + name := self.Locales.ZhCN + suffix := self.getSuffix() + if len(suffix) > 0 { + name = fmt.Sprintf("%s-%s", name, suffix) + } + return fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_CN, name) +} + +func (self *SRegion) getId() string { + idx := strings.Index(self.Id, "_") + if idx > 0 { + return self.Id[:idx] + } + return self.Id +} + +func (self *SRegion) getSuffix() string { + idx := strings.Index(self.Id, "_") + if idx > 0 { + return self.Id[idx+1:] + } + return "" } func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable { - en := fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_EN, self.Locales.EnUs) + en := self.Locales.EnUs + suffix := self.getSuffix() + if len(suffix) > 0 { + en = fmt.Sprintf("%s-%s", en, suffix) + } + en = fmt.Sprintf("%s %s", CLOUD_PROVIDER_HUAWEI_EN, en) table := cloudprovider.SModelI18nTable{} table["name"] = cloudprovider.NewSModelI18nEntry(self.GetName()).CN(self.GetName()).EN(en) return table } func (self *SRegion) GetGlobalId() string { - return fmt.Sprintf("%s/%s", api.CLOUD_PROVIDER_HUAWEI, self.ID) + return fmt.Sprintf("%s/%s", api.CLOUD_PROVIDER_HUAWEI, self.Id) } func (self *SRegion) GetStatus() string { @@ -234,24 +258,6 @@ func (self *SRegion) Refresh() error { return nil } -func (self *SRegion) IsEmulated() bool { - return false -} - -func (self *SRegion) GetLatitude() float32 { - if locationInfo, ok := LatitudeAndLongitude[self.ID]; ok { - return locationInfo.Latitude - } - return 0.0 -} - -func (self *SRegion) GetLongitude() float32 { - if locationInfo, ok := LatitudeAndLongitude[self.ID]; ok { - return locationInfo.Longitude - } - return 0.0 -} - func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) { zones, err := self.GetZones() if err != nil { @@ -494,7 +500,10 @@ func (self *SRegion) CreateSecurityGroup(opts *cloudprovider.SecurityGroupCreate params := map[string]interface{}{ "name": opts.Name, "description": opts.Desc, - "enterprise_project_id": opts.ProjectId, + "enterprise_project_id": "0", + } + if len(opts.ProjectId) > 0 { + params["enterprise_project_id"] = opts.ProjectId } resp, err := self.post(SERVICE_VPC_V3, "vpc/security-groups", map[string]interface{}{"security_group": params}) if err != nil { @@ -556,7 +565,7 @@ func (region *SRegion) CreateIBucket(name string, storageClassStr string, aclStr } input := &obs.CreateBucketInput{} input.Bucket = name - input.Location = region.GetId() + input.Location = region.getId() if len(aclStr) > 0 { if strings.EqualFold(aclStr, string(obs.AclPrivate)) { input.ACL = obs.AclPrivate @@ -673,22 +682,6 @@ func (self *SRegion) GetDiskTypes() ([]SDiskType, error) { return ret, nil } -func (self *SRegion) GetZoneSupportedDiskTypes(zoneId string) ([]string, error) { - dts, err := self.GetDiskTypes() - if err != nil { - return nil, errors.Wrap(err, "GetDiskTypes") - } - - ret := []string{} - for i := range dts { - if dts[i].IsAvaliableInZone(zoneId) { - ret = append(ret, dts[i].Name) - } - } - - return ret, nil -} - func (region *SRegion) GetIVMs() ([]cloudprovider.ICloudVM, error) { vms, err := region.GetInstances("") if err != nil { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/storage.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/storage.go index 82e3f14727..636be58daa 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/storage.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/storage.go @@ -30,19 +30,20 @@ type SStorage struct { zone *SZone multicloud.SStorageBase HuaweiTags - storageType string // volume_type 目前支持“SSD”,“SAS”和“SATA”三种 + storageType string + volumeTypeId string } func (self *SStorage) GetId() string { - return fmt.Sprintf("%s-%s-%s", self.zone.region.client.cpcfg.Id, self.zone.GetId(), self.storageType) + return fmt.Sprintf("%s-%s-%s-%s", self.zone.region.client.cpcfg.Id, self.zone.region.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) + return fmt.Sprintf("%s-%s-%s-%s", self.zone.region.client.cpcfg.Name, self.zone.region.Id, 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) + return fmt.Sprintf("%s-%s-%s-%s", self.zone.region.client.cpcfg.Id, self.zone.region.Id, self.zone.GetGlobalId(), self.storageType) } func (self *SStorage) GetStatus() string { @@ -66,26 +67,16 @@ func (self *SStorage) GetIZone() cloudprovider.ICloudZone { } func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) { - disks, err := self.zone.region.GetDisks(self.zone.GetId()) + disks, err := self.zone.region.GetDisks(self.zone.ZoneName, self.volumeTypeId) if err != nil { return nil, err } - - // 按storage type 过滤出disk - filtedDisks := make([]SDisk, 0) - for i := range disks { - disk := disks[i] - if disk.VolumeType == self.storageType { - filtedDisks = append(filtedDisks, disk) - } + ret := []cloudprovider.ICloudDisk{} + for i := 0; i < len(disks); i += 1 { + disks[i].storage = self + ret = append(ret, &disks[i]) } - - 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 + return ret, nil } func (self *SStorage) GetStorageType() string { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/traces.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/traces.go index 24ee2aa2a5..e3ee625bff 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/traces.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/traces.go @@ -98,7 +98,7 @@ func (event *SEvent) GetCreatedAt() time.Time { } func (self *SRegion) GetICloudEvents(start time.Time, end time.Time, withReadEvent bool) ([]cloudprovider.ICloudEvent, error) { - if !self.client.isMainProject { + if self.Id != HUAWEI_DEFAULT_REGION { return nil, cloudprovider.ErrNotSupported } events, err := self.GetEvents(start, end) diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc.go index e73d2a4ec0..9b8c41c238 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc.go @@ -197,7 +197,11 @@ func (self *SVpc) AcceptICloudVpcPeeringConnection(id string) error { } func (self *SVpc) GetAuthorityOwnerId() string { - return self.region.client.projectId + project, ok := self.region.client.projects[self.region.Id] + if ok { + return project.Id + } + return "" } func (self *SVpc) getVpcPeeringConnections() ([]SVpcPeering, error) { diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc_peering.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc_peering.go index 9c89ff374a..ff660b8fed 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc_peering.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/vpc_peering.go @@ -88,13 +88,17 @@ func (self *SRegion) GetVpcPeering(id string) (*SVpcPeering, error) { // https://console.huaweicloud.com/apiexplorer/#/openapi/VPC/doc?version=v2&api=CreateVpcPeering func (self *SRegion) CreateVpcPeering(vpcId string, opts *cloudprovider.VpcPeeringConnectionCreateOptions) (*SVpcPeering, error) { + projectId := "" + if project, ok := self.client.projects[self.Id]; ok { + projectId = project.Id + } params := map[string]interface{}{ "peering": map[string]interface{}{ "name": opts.Name, "description": opts.Desc, "request_vpc_info": map[string]interface{}{ "vpc_id": vpcId, - "tenant_id": self.client.projectId, + "tenant_id": projectId, }, "accept_vpc_info": map[string]interface{}{ "vpc_id": opts.PeerVpcId, diff --git a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/zone.go b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/zone.go index 83a5fc11a5..b282ffae69 100644 --- a/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/zone.go +++ b/vendor/yunion.io/x/cloudmux/pkg/multicloud/huawei/zone.go @@ -16,8 +16,8 @@ package huawei import ( "fmt" + "strings" - "yunion.io/x/log" "yunion.io/x/pkg/errors" api "yunion.io/x/cloudmux/pkg/apis/compute" @@ -25,57 +25,23 @@ import ( "yunion.io/x/cloudmux/pkg/multicloud" ) -var StorageTypes = []string{ - api.STORAGE_HUAWEI_SAS, - api.STORAGE_HUAWEI_SATA, - api.STORAGE_HUAWEI_SSD, -} - type ZoneState struct { Available bool `json:"available"` } -// https://support.huaweicloud.com/api-ecs/zh-cn_topic_0065817728.html type SZone struct { multicloud.SResourceBase HuaweiTags region *SRegion host *SHost - istorages []cloudprovider.ICloudStorage - ZoneState ZoneState `json:"zoneState"` ZoneName string `json:"zoneName"` - - /* 支持的磁盘种类集合 */ - storageTypes []string -} - -func (self *SZone) getStorageType() { - if len(self.storageTypes) == 0 { - if sts, err := self.region.GetZoneSupportedDiskTypes(self.GetId()); err == nil { - self.storageTypes = sts - } else { - log.Errorf("GetZoneSupportedDiskTypes %s %s", self.GetId(), err) - self.storageTypes = StorageTypes - } - } -} - -func (self *SZone) fetchStorages() error { - self.getStorageType() - self.istorages = make([]cloudprovider.ICloudStorage, len(self.storageTypes)) - - for i, sc := range self.storageTypes { - storage := SStorage{zone: self, storageType: sc} - self.istorages[i] = &storage - } - return nil } func (self *SZone) getHost() *SHost { if self.host == nil { - self.host = &SHost{zone: self, projectId: self.region.client.projectId} + self.host = &SHost{zone: self} } return self.host } @@ -96,7 +62,7 @@ func (self *SZone) GetI18n() cloudprovider.SModelI18nTable { } func (self *SZone) GetGlobalId() string { - return fmt.Sprintf("%s/%s", self.region.GetGlobalId(), self.ZoneName) + return fmt.Sprintf("%s/%s/%s", api.CLOUD_PROVIDER_HUAWEI, self.region.getId(), self.ZoneName) } func (self *SZone) GetStatus() string { @@ -128,28 +94,34 @@ func (self *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) { } func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) { - if self.istorages == nil { - err := self.fetchStorages() - if err != nil { - return nil, errors.Wrapf(err, "fetchStorages") + storageTypes, err := self.region.GetDiskTypes() + if err != nil { + return nil, err + } + ret := []cloudprovider.ICloudStorage{} + for _, storageType := range storageTypes { + if strings.Contains(storageType.ExtraSpecs.RESKEYAvailabilityZones, self.ZoneName) { + ret = append(ret, &SStorage{ + zone: self, + storageType: storageType.Name, + volumeTypeId: storageType.Id, + }) } } - return self.istorages, nil + return ret, nil } func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { - if self.istorages == nil { - err := self.fetchStorages() - if err != nil { - return nil, errors.Wrapf(err, "fetchStorages") + storages, err := self.GetIStorages() + if err != nil { + return nil, err + } + for i := range storages { + if storages[i].GetGlobalId() == id { + return storages[i], nil } } - for i := 0; i < len(self.istorages); i += 1 { - if self.istorages[i].GetGlobalId() == id { - return self.istorages[i], nil - } - } - return nil, cloudprovider.ErrNotFound + return nil, errors.Wrapf(cloudprovider.ErrNotFound, id) } func (self *SZone) GetIWires() ([]cloudprovider.ICloudWire, error) { @@ -180,14 +152,15 @@ func (self *SZone) getStorageByCategory(category string) (*SStorage, error) { } func (self *SRegion) getZoneById(id string) (*SZone, error) { - izones, err := self.GetIZones() + zones, err := self.GetZones() if err != nil { return nil, err } - for i := 0; i < len(izones); i += 1 { - zone := izones[i].(*SZone) + for i := 0; i < len(zones); i += 1 { + zones[i].region = self + zone := zones[i] if zone.GetId() == id { - return zone, nil + return &zone, nil } } return nil, fmt.Errorf("no such zone %s", id)