add hcso modelarts

This commit is contained in:
mhf
2022-09-21 13:56:46 +08:00
parent c2c9ce8ccf
commit bac407a65c
6 changed files with 681 additions and 0 deletions
+2
View File
@@ -81,6 +81,8 @@ type SHCSOEndpoints struct {
Eps string `default:"$HUAWEI_EPS_ENDPOINT"`
// 文件系统
SfsTurbo string `default:"$HUAWEI_SFS_TURBO_ENDPOINT"`
// Modelarts
Modelarts string `default:"$HUAWEI_MODELARTS_ENDPOINT"`
}
func (self *SHCSOEndpoints) GetEndpoint(defaultRegion, serviceName string, region string) string {
+82
View File
@@ -19,12 +19,14 @@ import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"github.com/huaweicloud/huaweicloud-sdk-go/auth/aksk"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/gotypes"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/httputils"
@@ -122,3 +124,83 @@ func (self *SHuaweiClient) deleteAKSK(accessKey string) (jsonutils.JSONObject, e
uri := fmt.Sprintf("https://%s/v3.0/OS-CREDENTIAL/credentials/%s", self.endpoints.Iam, accessKey)
return self.request(httputils.POST, uri, nil, nil)
}
func (self *SHuaweiClient) modelartsPoolNetworkList(params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v1/%s/networks", self.endpoints.Modelarts, self.projectId)
return self.request(httputils.GET, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolNetworkCreate(params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v1/%s/networks", self.endpoints.Modelarts, self.projectId)
return self.request(httputils.POST, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolById(poolName string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v2/%s/pools/%s", self.endpoints.Modelarts, self.projectId, poolName)
return self.request(httputils.GET, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolList(params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v2/%s/pools", self.endpoints.Modelarts, self.projectId)
return self.request(httputils.GET, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolCreate(params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v2/%s/pools", self.endpoints.Modelarts, self.projectId)
return self.request(httputils.POST, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolDelete(poolName string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v2/%s/pools/%s", self.endpoints.Modelarts, self.projectId, poolName)
return self.request(httputils.DELETE, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsPoolUpdate(poolName string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v2/%s/pools/%s", self.endpoints.Modelarts, self.projectId, poolName)
urlValue := url.Values{}
urlValue.Add("time_range", "")
urlValue.Add("statistics", "")
urlValue.Add("period", "")
return self.patchRequest(httputils.PATCH, uri, urlValue, params)
}
func (self *SHuaweiClient) modelartsPoolMonitor(poolName string, params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://modelarts.%s.myhuaweicloud.com/v2/%s/pools/%s/monitor", self.endpoints.Modelarts, self.projectId, poolName)
return self.request(httputils.GET, uri, url.Values{}, params)
}
func (self *SHuaweiClient) modelartsResourceflavors(params map[string]interface{}) (jsonutils.JSONObject, error) {
uri := fmt.Sprintf("https://%s/v1/%s/resourceflavors", self.endpoints.Modelarts, self.projectId)
return self.request(httputils.GET, uri, url.Values{}, params)
}
func (self *SHuaweiClient) patchRequest(method httputils.THttpMethod, 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())
}
var body jsonutils.JSONObject = nil
if len(params) > 0 {
body = jsonutils.Marshal(params)
}
header := http.Header{}
if len(self.projectId) > 0 {
header.Set("X-Project-Id", self.projectId)
}
var bodystr string
if !gotypes.IsNil(body) {
bodystr = body.String()
}
jbody := strings.NewReader(bodystr)
header.Set("Content-Length", strconv.FormatInt(int64(len(bodystr)), 10))
header.Set("Content-Type", "application/merge-patch+json")
resp, err := httputils.Request(client, context.Background(), method, url, header, jbody, self.debug)
_, respValue, err := httputils.ParseJSONResponse(bodystr, resp, err, self.debug)
if err != nil {
if e, ok := err.(*httputils.JSONClientError); ok && e.Code == 404 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, err.Error())
}
return nil, err
}
return respValue, err
}
+357
View File
@@ -0,0 +1,357 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hcso
import (
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
billing_api "yunion.io/x/onecloud/pkg/apis/billing"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
"yunion.io/x/onecloud/pkg/util/billing"
)
type SModelartsPool struct {
client *SHuaweiClient
region *SRegion
multicloud.SResourceBase
Metadata SModelartsPoolMetadata `json:"metadata"`
Spec SModelartsPoolSpec `json:"spec"`
Status SModelartsPoolStatus `json:"status"`
InstanceType string
WorkType string
}
type SModelartsPoolMetadata struct {
Name string `json:"name"`
CreationTimestamp string `json:"creationTimestamp"`
Labels SModelartsPoolMeatadataLabel
Annotations SModelartsPoolMetadataAnnotations `json:"annotations"`
}
type SModelartsPoolMeatadataLabel struct {
WorkspaceId string `json:"os.modelarts/workspace.id"`
Name string `json:"os.modelarts/name"`
ResourceId string `json:"os.modelarts/resource.id"`
}
type SModelartsPoolMetadataAnnotations struct {
Describe string `json:"os.modelarts/description"`
BillingType string `json:"os.modelarts/billing.mode"`
BillingCycle string `json:"os.modelarts/period.num"`
BillingPeriodType string `json:"os.modelarts/period.type"`
BillingMod string `json:"os.modelarts/charging.mode"`
BillingRenew string `json:"os.modelarts/auto.renew"`
OrderId string `json:"os.modelarts/order.id"`
}
type SModelartsPoolSpec struct {
Type string `json:"type"`
Scope []string `json:"scope"`
Resource []SModelartsPoolResource `json:"resources"`
}
type SModelartsPoolResource struct {
Flavor string `json:"flavor"`
Count int `json:"count"`
cloudprovider.Azs
}
type SModelartsPoolStatus struct {
Phase string `json:"phase"`
Message string `json:"message"`
}
type SModelartsPoolNetwork struct {
Metadata SModelartsPoolNetworkMetadata `json:"metadata"`
}
type SModelartsPoolNetworkMetadata struct {
Name string `json:"name"`
CreationTimestamp string `json:"creationTimestamp"`
}
func (self *SRegion) GetIModelartsPools() ([]cloudprovider.ICloudModelartsPool, error) {
pools := make([]SModelartsPool, 0)
log.Errorln("this is in GetIModelartsPools:", self.client.endpoints.Modelarts)
resObj, err := self.client.modelartsPoolList(nil)
if err != nil {
return nil, errors.Wrap(err, "region.GetPools")
}
err = resObj.Unmarshal(&pools, "items")
if err != nil {
return nil, errors.Wrap(err, "resObj unmarshal")
}
res := make([]cloudprovider.ICloudModelartsPool, len(pools))
for i := 0; i < len(pools); i++ {
pools[i].region = self
pools[i].client = self.GetClient()
res[i] = &pools[i]
}
return res, nil
}
func (self *SRegion) CreateIModelartsPool(args *cloudprovider.ModelartsPoolCreateOption) (cloudprovider.ICloudModelartsPool, error) {
netObj, err := self.client.modelartsPoolNetworkList(nil)
if err != nil {
return nil, errors.Wrap(err, "SHuaweiClient.GetPools")
}
netRes := make([]SModelartsPoolNetwork, 0)
netObj.Unmarshal(&netRes, "items")
netId := ""
if len(netRes) != 0 {
netId = netRes[0].Metadata.Name
} else {
createNetObj, err := self.client.CreatePoolNetworks()
if err != nil {
return nil, errors.Wrap(err, "SHuaweiClient.CreatePoolNetworks")
}
netId, _ = createNetObj.GetString("metadata", "name")
}
scopeArr := strings.Split(args.WorkType, ",")
params := map[string]interface{}{
"apiVersion": "v2",
"kind": "Pool",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"os.modelarts/name": args.Name,
"os.modelarts/workspace.id": "0",
},
},
"spec": map[string]interface{}{
"type": "Dedicate",
"scope": scopeArr,
"network": map[string]interface{}{
"name": netId,
},
"resources": []map[string]interface{}{
{
"flavor": args.InstanceType,
"count": 1,
},
},
},
}
obj, err := self.client.modelartsPoolCreate(params)
if err != nil {
return nil, errors.Wrap(err, "SHuaweiClient.CreatePools")
}
pool := &SModelartsPool{}
obj.Unmarshal(&pool)
res := []cloudprovider.ICloudModelartsPool{}
for i := 0; i < 1; i++ {
pool.region = self
pool.client = self.GetClient()
res = append(res, pool)
}
return res[0], nil
}
func (self *SRegion) DeletePool(poolName string) (jsonutils.JSONObject, error) {
return self.client.modelartsPoolDelete(poolName, nil)
}
func (self *SRegion) GetIModelartsPoolById(poolId string) (cloudprovider.ICloudModelartsPool, error) {
obj, err := self.client.modelartsPoolById(poolId, nil)
if err != nil {
if strings.Contains(err.Error(), "not found") {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "")
}
return nil, errors.Wrap(err, "region.modelartsPoolByName")
}
pool := &SModelartsPool{}
obj.Unmarshal(&pool)
res := []cloudprovider.ICloudModelartsPool{}
for i := 0; i < 1; i++ {
pool.region = self
pool.client = self.GetClient()
res = append(res, pool)
}
return res[0], nil
}
func (self *SRegion) MonitorPool(poolId string) (*SModelartsMetrics, error) {
resObj, err := self.client.modelartsPoolMonitor(poolId, nil)
if err != nil {
return nil, errors.Wrapf(err, "send request error")
}
metrics := SModelartsMetrics{}
err = resObj.Unmarshal(&metrics)
if err != nil {
return nil, errors.Wrapf(err, "unmarsh error")
}
return &metrics, nil
}
type SModelartsMetrics struct {
Metrics []SModelartsMetric `json:"metrics"`
}
type SModelartsMetric struct {
Metric SModelartsMetricInfo `json:"metric"`
Datapoints []SModelartsDataPoints `json:"dataPoints"`
}
type SModelartsMetricInfo struct {
Dimensions []SModelartsDimensions `json:"dimensions"`
MetricName string
Namespace string
}
type SModelartsDimensions struct {
Name string
Value string
}
type SModelartsDataPoints struct {
Timestamp int64
Unit string
Statistics []ModelartsStatistics
}
type ModelartsStatistics struct {
Statistic string
Value float64
}
func (self *SHuaweiClient) GetPoolNetworks(poolName string) (jsonutils.JSONObject, error) {
return self.modelartsPoolNetworkList(nil)
}
func (self *SHuaweiClient) CreatePoolNetworks() (jsonutils.JSONObject, error) {
params := map[string]interface{}{
"apiVersion": "v1",
"kind": "Network",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"os.modelarts/name": "test",
"os.modelarts/workspace.id": "0",
},
},
"spec": map[string]interface{}{
"cidr": "192.168.20.0/24",
},
}
return self.modelartsPoolNetworkCreate(params)
}
func (self *SModelartsPool) GetCreatedAt() time.Time {
ret, _ := time.Parse("2006-01-02T15:04:05CST", self.Metadata.CreationTimestamp)
if !ret.IsZero() {
ret = ret.Add(time.Hour * 8)
}
return ret
}
func (self *SModelartsPool) GetGlobalId() string {
return self.Metadata.Name
}
func (self *SModelartsPool) GetId() string {
return self.Metadata.Name
}
func (self *SModelartsPool) GetName() string {
return self.Metadata.Labels.Name
}
func (self *SModelartsPool) GetStatus() string {
return strings.ToLower(self.Status.Phase)
}
func (self *SModelartsPool) GetSysTags() map[string]string {
return nil
}
func (self *SModelartsPool) GetTags() (map[string]string, error) {
return nil, nil
}
func (self *SModelartsPool) IsEmulated() bool {
return false
}
func (self *SModelartsPool) GetBillingType() string {
if self.Metadata.Annotations.BillingType == "1" {
return billing_api.BILLING_TYPE_PREPAID
} else {
return billing_api.BILLING_TYPE_POSTPAID
}
return self.Metadata.Annotations.BillingType
}
// 获取资源归属项目Id
func (self *SModelartsPool) GetProjectId() string {
return self.Metadata.Name
}
func (self *SModelartsPool) GetExpiredAt() time.Time {
ret, _ := time.Parse("2006-01-02T15:04:05CST", self.Metadata.CreationTimestamp)
if !ret.IsZero() {
ret = ret.Add(time.Hour * 8)
}
return ret
}
func (self *SModelartsPool) IsAutoRenew() bool {
return false
}
func (self *SModelartsPool) Renew(bc billing.SBillingCycle) error {
return nil
}
func (self *SModelartsPool) SetAutoRenew(bc billing.SBillingCycle) error {
return nil
}
func (self *SModelartsPool) Refresh() error {
pool, err := self.client.modelartsPoolById(self.GetId(), nil)
if err != nil {
return errors.Wrapf(err, "GetModelartsPool(%s)", self.GetId())
}
return jsonutils.Update(self, pool)
}
func (self *SModelartsPool) SetTags(tags map[string]string, replace bool) error {
return nil
}
func (self *SModelartsPool) Delete() error {
_, err := self.region.DeletePool(self.GetId())
if err != nil {
return err
}
return nil
}
func (self *SModelartsPool) GetInstanceType() string {
return self.Spec.Resource[0].Flavor
}
func (self *SModelartsPool) GetWorkType() string {
return strings.Join(self.Spec.Scope, ",")
}
+130
View File
@@ -0,0 +1,130 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hcso
import (
"strconv"
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type SModelartsPoolSku struct {
multicloud.SResourceBase
multicloud.HuaweiTags
region *SRegion
Kind string `json:"kind"`
Spec SModelartsResourceflavorsSpec `json:"spec"`
Status SModelartsResourceflavorsStatus `json:"status"`
}
type SModelartsResourceflavorsSpec struct {
BillingCode string `json:"billingCode"`
BillingModes []int `json:"billingMods"`
Cpu int `json:"cpu"`
CpuArch string `json:"cpuArch"`
Gpu SModelartsResourceflavorsGpuSpec `json:"gpu"`
Npu SModelartsResourceflavorsGpuSpec `json:"npu"`
Memory string `json:"memory"`
Type string `json:"type"`
}
type SModelartsResourceflavorsGpuSpec struct {
Size int `json:"size"`
Type string `json:"type"`
}
type SModelartsResourceflavorsStatus struct {
Phase map[string]interface{} `json:"phase"`
}
func (self *SRegion) GetIModelartsPoolSku() ([]cloudprovider.ICloudModelartsPoolSku, error) {
params := make(map[string]interface{})
resourceflavors := make([]SModelartsPoolSku, 0)
obj, err := self.client.modelartsResourceflavors(params)
if err != nil {
return nil, errors.Wrap(err, "region.modelartsResourceflavors")
}
obj.Unmarshal(&resourceflavors, "items")
res := make([]cloudprovider.ICloudModelartsPoolSku, len(resourceflavors))
for i := 0; i < len(resourceflavors); i++ {
res[i] = &resourceflavors[i]
}
return res, nil
}
func (self *SModelartsPoolSku) GetCreatedAt() time.Time {
createdAt, _ := time.Parse("2006-01-02T15:04:05CST", time.Now().Format("2006-01-02T15:04:05CST"))
return createdAt
}
func (self *SModelartsPoolSku) GetGlobalId() string {
return self.Spec.BillingCode
}
func (self *SModelartsPoolSku) GetId() string {
return self.Spec.BillingCode
}
func (self *SModelartsPoolSku) GetName() string {
return self.Spec.BillingCode
}
func (self *SModelartsPoolSku) GetCpuArch() string {
return self.Spec.CpuArch
}
func (self *SModelartsPoolSku) GetCpuCoreCount() int {
return self.Spec.Cpu
}
func (self *SModelartsPoolSku) GetMemorySizeMB() int {
size, _ := strconv.Atoi(self.Spec.Memory[:len(self.Spec.Memory)-2])
return size * 1024
}
func (self *SModelartsPoolSku) GetStatus() string {
for _, v := range self.Status.Phase {
if v == "normal" {
return compute.MODELARTS_POOL_SKU_AVAILABLE
}
}
return compute.MODELARTS_POOL_SKU_SOLDOUT
}
func (self *SModelartsPoolSku) GetGpuSize() int {
return self.Spec.Gpu.Size
}
func (self *SModelartsPoolSku) GetGpuType() string {
return self.Spec.Gpu.Type
}
func (self *SModelartsPoolSku) GetNpuSize() int {
return self.Spec.Npu.Size
}
func (self *SModelartsPoolSku) GetNpuType() string {
return self.Spec.Npu.Type
}
func (self *SModelartsPoolSku) GetPoolType() string {
return self.Spec.Type
}
+75
View File
@@ -0,0 +1,75 @@
// @@ -0,0 +1,46 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudprovider"
huawei "yunion.io/x/onecloud/pkg/multicloud/hcso"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ModelartsPoolListOption struct {
PoolId string `help:"Pool Id"`
}
shellutils.R(&ModelartsPoolListOption{}, "modelarts-pool-list", "List Modelarts Pool", func(cli *huawei.SRegion, args *ModelartsPoolListOption) error {
log.Errorf("this is endpoints:%v,err:%s\n", cli.GetClient())
pools, err := cli.GetIModelartsPools()
if err != nil {
return err
}
printList(pools, len(pools), 0, 0, nil)
return nil
})
shellutils.R(&ModelartsPoolListOption{}, "modelarts-pool-detail", "List pool", func(cli *huawei.SRegion, args *ModelartsPoolListOption) error {
pool, err := cli.GetIModelartsPoolById(args.PoolId)
if err != nil {
return err
}
printObject(pool)
return nil
})
shellutils.R(&cloudprovider.ModelartsPoolCreateOption{}, "modelarts-pool-create", "Create Modelarts Pool", func(cli *huawei.SRegion, args *cloudprovider.ModelartsPoolCreateOption) error {
res, err := cli.CreateIModelartsPool(args)
if err != nil {
return err
}
printObject(res)
return nil
})
shellutils.R(&ModelartsPoolListOption{}, "modelarts-pool-delete", "Delete Modelarts Pool", func(cli *huawei.SRegion, args *ModelartsPoolListOption) error {
res, err := cli.DeletePool(args.PoolId)
if err != nil {
return err
}
printObject(res)
return nil
})
shellutils.R(&ModelartsPoolListOption{}, "modelarts-pool-monitor", "Delete Modelarts Pool", func(cli *huawei.SRegion, args *ModelartsPoolListOption) error {
res, err := cli.MonitorPool(args.PoolId)
if err != nil {
return err
}
printList(res.Metrics, len(res.Metrics), 0, 0, nil)
return nil
})
}
@@ -0,0 +1,35 @@
// @@ -0,0 +1,46 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shell
import (
huawei "yunion.io/x/onecloud/pkg/multicloud/hcso"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type ModelartsResourceflavorsListOption struct {
PoolName string `help:"Pool Name"`
}
shellutils.R(&ModelartsResourceflavorsListOption{}, "modelarts-sku-list", "List Modelarts Pool", func(cli *huawei.SRegion, args *ModelartsResourceflavorsListOption) error {
resourceflavors, err := cli.GetIModelartsPoolSku()
if err != nil {
return err
}
printList(resourceflavors, len(resourceflavors), 0, 0, nil)
return nil
})
}