mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-29 03:51:54 +08:00
feat(region): support bingocloud sync
This commit is contained in:
@@ -31,7 +31,7 @@ require (
|
||||
github.com/apache/thrift v0.12.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.39.0
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
|
||||
github.com/basgys/goxml2json v1.1.0
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/benbjohnson/clock v1.0.0
|
||||
github.com/bitly/go-simplejson v0.5.0
|
||||
@@ -157,7 +157,7 @@ require (
|
||||
yunion.io/x/jsonutils v0.0.0-20220106020632-953b71a4c3a8
|
||||
yunion.io/x/log v0.0.0-20201210064738-43181789dc74
|
||||
yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7
|
||||
yunion.io/x/pkg v0.0.0-20211116020154-6a76ba2f7e97
|
||||
yunion.io/x/pkg v0.0.0-20220227083757-28690b33ce38
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e
|
||||
yunion.io/x/sqlchemy v0.0.0-20220119131341-fadec84c0638
|
||||
yunion.io/x/structarg v0.0.0-20220224030024-02b7582b2546
|
||||
|
||||
@@ -137,8 +137,8 @@ github.com/aws/aws-sdk-go v1.39.0 h1:74BBwkEmiqBbi2CGflEh34l0YNtIibTjZsibGarkNjo
|
||||
github.com/aws/aws-sdk-go v1.39.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f h1:ZNv7On9kyUzm7fvRZumSyy/IUiSC7AzL0I1jKKtwooA=
|
||||
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f/go.mod h1:AuiFmCCPBSrqvVMvuqFuk0qogytodnVFVSN5CeJB8Gc=
|
||||
github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw=
|
||||
github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 h1:fKPpQHBQgt4dQuG6x+yH4gdgtodFDgN9rvHzwJzTKeg=
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw=
|
||||
github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
|
||||
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
|
||||
github.com/benbjohnson/clock v1.0.0 h1:78Jk/r6m4wCi6sndMpty7A//t4dw/RW5fV4ZgDVfX1w=
|
||||
@@ -974,8 +974,8 @@ yunion.io/x/ovsdb v0.0.0-20200526071744-27bf0940cbc7/go.mod h1:0vLkNEhlmA64HViPB
|
||||
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20200814072949-4f1b541857d6/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20211116020154-6a76ba2f7e97 h1:lY+5NlWwO2aIkfNnVOGKHmZvMt6m4ZuGtarIjwNfUsg=
|
||||
yunion.io/x/pkg v0.0.0-20211116020154-6a76ba2f7e97/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/pkg v0.0.0-20220227083757-28690b33ce38 h1:QV3gVskJfi1J0e5kTs4oTx8D+Mc0JFik3Qe6c1PgO90=
|
||||
yunion.io/x/pkg v0.0.0-20220227083757-28690b33ce38/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e h1:v+EzIadodSwkdZ/7bremd7J8J50Cise/HCylsOJngmo=
|
||||
yunion.io/x/s3cli v0.0.0-20190917004522-13ac36d8687e/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
|
||||
yunion.io/x/sqlchemy v0.0.0-20220119131341-fadec84c0638 h1:Tc7bMp/mahI1Zua5dxBNrXSKl4hCUSA7CPBcqBnK8Uw=
|
||||
|
||||
@@ -17,6 +17,7 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
@@ -335,12 +336,18 @@ func (self *SCloudregion) GetServerSkus() ([]SServerSku, error) {
|
||||
return skus, nil
|
||||
}
|
||||
|
||||
func (manager *SCloudregionManager) GetRegionByExternalIdPrefix(prefix string) ([]SCloudregion, error) {
|
||||
regions := make([]SCloudregion, 0)
|
||||
q := manager.Query().Startswith("external_id", prefix)
|
||||
err := db.FetchModelObjects(manager, q, ®ions)
|
||||
func (self *SCloudprovider) GetRegionByExternalIdPrefix(prefix string) ([]SCloudregion, error) {
|
||||
factory, err := self.GetProviderFactory()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
regions := make([]SCloudregion, 0)
|
||||
q := CloudregionManager.Query().Startswith("external_id", prefix)
|
||||
if !factory.IsPublicCloud() && !strings.Contains(prefix, "/") {
|
||||
q = CloudregionManager.Query().Equals("manager_id", self.Id)
|
||||
}
|
||||
err = db.FetchModelObjects(CloudregionManager, q, ®ions)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return nil, err
|
||||
}
|
||||
return regions, nil
|
||||
@@ -386,7 +393,7 @@ func (manager *SCloudregionManager) SyncRegions(
|
||||
remoteRegions := make([]cloudprovider.ICloudRegion, 0)
|
||||
cloudProviderRegions := make([]SCloudproviderregion, 0)
|
||||
|
||||
dbRegions, err := manager.GetRegionByExternalIdPrefix(externalIdPrefix)
|
||||
dbRegions, err := cloudProvider.GetRegionByExternalIdPrefix(externalIdPrefix)
|
||||
if err != nil {
|
||||
syncResult.Error(err)
|
||||
return nil, nil, nil, syncResult
|
||||
|
||||
@@ -17,10 +17,13 @@ package regiondrivers
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/compute/models"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
@@ -39,6 +42,29 @@ func (self *SBingoCloudRegionDriver) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_BINGO_CLOUD
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) IsAllowSecurityGroupNameRepeat() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) GenerateSecurityGroupName(name string) string {
|
||||
if strings.ToLower(name) == "default" {
|
||||
return "DefaultGroup"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) IsSecurityGroupBelongVpc() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) GetDefaultSecurityGroupInRule() cloudprovider.SecurityRule {
|
||||
return cloudprovider.SecurityRule{SecurityRule: *secrules.MustParseSecurityRule("in:deny any")}
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) GetDefaultSecurityGroupOutRule() cloudprovider.SecurityRule {
|
||||
return cloudprovider.SecurityRule{SecurityRule: *secrules.MustParseSecurityRule("out:deny any")}
|
||||
}
|
||||
|
||||
func (self *SBingoCloudRegionDriver) ValidateCreateLoadbalancerData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
|
||||
return nil, httperrors.NewUnsupportOperationError("%s does not support creating loadbalancer", self.GetProvider())
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func (self *SGoogleRegionDriver) RequestCreateVpc(ctx context.Context, userCred
|
||||
}
|
||||
db.SetExternalId(vpc, userCred, ivpc.GetGlobalId())
|
||||
|
||||
regions, err := models.CloudregionManager.GetRegionByExternalIdPrefix(self.GetProvider())
|
||||
regions, err := provider.GetRegionByExternalIdPrefix(self.GetProvider())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetRegionByExternalIdPrefix")
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ type BaseListOptions struct {
|
||||
|
||||
Manager string `help:"List objects belonging to the cloud provider" json:"manager,omitempty"`
|
||||
Account string `help:"List objects belonging to the cloud account" json:"account,omitempty"`
|
||||
Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|ZStack|Google|Ctyun|Cloudpods" json:"provider,omitempty"`
|
||||
Provider []string `help:"List objects from the provider" choices:"OneCloud|VMware|Aliyun|Qcloud|Azure|Aws|Huawei|OpenStack|Ucloud|ZStack|Google|Ctyun|Cloudpods|Nutanix|BingoCloud" json:"provider,omitempty"`
|
||||
Brand []string `help:"List objects belonging to a special brand"`
|
||||
CloudEnv string `help:"Cloud environment" choices:"public|private|onpremise|private_or_onpremise" json:"cloud_env,omitempty"`
|
||||
PublicCloud *bool `help:"List objects belonging to public cloud" json:"public_cloud"`
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
package bingocloud
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
@@ -136,6 +138,64 @@ func (self *SBingoCloudClient) sign(query string) string {
|
||||
return base64.StdEncoding.EncodeToString(hmac.Sum(nil))
|
||||
}
|
||||
|
||||
func setItemToArray(obj jsonutils.JSONObject) jsonutils.JSONObject {
|
||||
objDict, ok := obj.(*jsonutils.JSONDict)
|
||||
if ok {
|
||||
for k, v := range objDict.Value() {
|
||||
if v.String() == `""` {
|
||||
objDict.Remove(k)
|
||||
continue
|
||||
}
|
||||
vDict, ok := v.(*jsonutils.JSONDict)
|
||||
if ok {
|
||||
if vDict.Contains("item") {
|
||||
item, _ := vDict.Get("item")
|
||||
_, ok := item.(*jsonutils.JSONArray)
|
||||
if !ok {
|
||||
if k != "instancesSet" {
|
||||
item = setItemToArray(item)
|
||||
objDict.Set(k, jsonutils.NewArray(item))
|
||||
} else {
|
||||
objDict.Set(k, setItemToArray(item))
|
||||
}
|
||||
} else {
|
||||
items, _ := item.GetArray()
|
||||
for i := range items {
|
||||
items[i] = setItemToArray(items[i])
|
||||
}
|
||||
objDict.Set(k, jsonutils.NewArray(items...))
|
||||
}
|
||||
for _, nk := range []string{"nextToken", "NextToken"} {
|
||||
nextToken, _ := vDict.GetString(nk)
|
||||
if len(nextToken) > 0 {
|
||||
objDict.Set(nk, jsonutils.NewString(nextToken))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
objDict.Set(k, setItemToArray(v))
|
||||
}
|
||||
} else if _, ok = v.(*jsonutils.JSONArray); ok {
|
||||
if ok {
|
||||
arr, _ := v.GetArray()
|
||||
for i := range arr {
|
||||
arr[i] = setItemToArray(arr[i])
|
||||
}
|
||||
objDict.Set(k, jsonutils.NewArray(arr...))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_, ok = obj.(*jsonutils.JSONArray)
|
||||
if ok {
|
||||
arr, _ := obj.GetArray()
|
||||
for i := range arr {
|
||||
arr[i] = setItemToArray(arr[i])
|
||||
}
|
||||
return jsonutils.NewArray(arr...)
|
||||
}
|
||||
return objDict
|
||||
}
|
||||
|
||||
func (self *SBingoCloudClient) invoke(action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
var encode = func(k, v string) string {
|
||||
d := url.Values{}
|
||||
@@ -161,13 +221,14 @@ func (self *SBingoCloudClient) invoke(action string, params map[string]string) (
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
result, err := xj.Convert(resp.Body)
|
||||
data, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if self.debug {
|
||||
log.Debugf("response: %s", result.String())
|
||||
result, err := xj.Convert(bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
obj, err := jsonutils.Parse([]byte(result.String()))
|
||||
@@ -175,6 +236,12 @@ func (self *SBingoCloudClient) invoke(action string, params map[string]string) (
|
||||
return nil, errors.Wrapf(err, "jsonutils.Parse")
|
||||
}
|
||||
|
||||
obj = setItemToArray(obj)
|
||||
|
||||
if self.debug {
|
||||
log.Debugf("response: %s", obj.PrettyString())
|
||||
}
|
||||
|
||||
respKey := action + "Response"
|
||||
if obj.Contains(respKey) {
|
||||
obj, err = obj.Get(respKey)
|
||||
@@ -183,21 +250,42 @@ func (self *SBingoCloudClient) invoke(action string, params map[string]string) (
|
||||
}
|
||||
}
|
||||
|
||||
// 处理请求单个资源情况
|
||||
if strings.HasPrefix(action, "Describe") && strings.HasSuffix(action, "s") {
|
||||
objDict := obj.(*jsonutils.JSONDict)
|
||||
for k, v := range objDict.Value() {
|
||||
if (strings.HasSuffix(k, "Set") || k == "regionInfo") && v.Contains("item") {
|
||||
value := v.(*jsonutils.JSONDict)
|
||||
item, _ := v.Get("item")
|
||||
_, ok := item.(*jsonutils.JSONArray)
|
||||
if !ok {
|
||||
value.Set("item", jsonutils.NewArray(item))
|
||||
objDict.Set(k, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func (self *SBingoCloudClient) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
subAccount := cloudprovider.SSubAccount{
|
||||
Account: self.accessKey,
|
||||
Name: self.cpcfg.Name,
|
||||
|
||||
HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL,
|
||||
}
|
||||
return []cloudprovider.SSubAccount{subAccount}, nil
|
||||
|
||||
}
|
||||
|
||||
func (self *SBingoCloudClient) GetIRegions() []cloudprovider.ICloudRegion {
|
||||
ret := []cloudprovider.ICloudRegion{}
|
||||
for i := range self.regions {
|
||||
self.regions[i].client = self
|
||||
ret = append(ret, &self.regions[i])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *SBingoCloudClient) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
iregions := self.GetIRegions()
|
||||
for i := range iregions {
|
||||
if iregions[i].GetGlobalId() == id {
|
||||
return iregions[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SBingoCloudClient) GetCapabilities() []string {
|
||||
return []string{
|
||||
cloudprovider.CLOUD_CAPABILITY_COMPUTE + cloudprovider.READ_ONLY_SUFFIX,
|
||||
cloudprovider.CLOUD_CAPABILITY_NETWORK + cloudprovider.READ_ONLY_SUFFIX,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,247 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SDisk struct {
|
||||
multicloud.BingoTags
|
||||
multicloud.SDisk
|
||||
|
||||
storage *SStorage
|
||||
|
||||
AttachmentSet []AttachmentSet `json:"attachmentSet"`
|
||||
AvailabilityZone string `json:"availabilityZone"`
|
||||
CreateTime string `json:"createTime"`
|
||||
Description string `json:"description"`
|
||||
DetachBehavior string `json:"detachBehavior"`
|
||||
Goal string `json:"goal"`
|
||||
Iops string `json:"iops"`
|
||||
IsDeductQuota string `json:"isDeductQuota"`
|
||||
IsEncrypt string `json:"isEncrypt"`
|
||||
IsForSleepInst string `json:"isForSleepInst"`
|
||||
IsMirrorVolume string `json:"isMirrorVolume"`
|
||||
IsMultiAttach string `json:"isMultiAttach"`
|
||||
IsOneInst string `json:"isOneInst"`
|
||||
IsRoot string `json:"isRoot"`
|
||||
Location string `json:"location"`
|
||||
MirrorFrom string `json:"mirrorFrom"`
|
||||
MirrorProcess string `json:"mirrorProcess"`
|
||||
MirrorStatus string `json:"mirrorStatus"`
|
||||
NodeId string `json:"nodeId"`
|
||||
Owner string `json:"owner"`
|
||||
Passphrase string `json:"passphrase"`
|
||||
Readonly string `json:"readonly"`
|
||||
Size int `json:"size"`
|
||||
SnapshotId string `json:"snapshotId"`
|
||||
Status string `json:"status"`
|
||||
StorageId string `json:"storageId"`
|
||||
VolumeId string `json:"volumeId"`
|
||||
VolumeName string `json:"volumeName"`
|
||||
}
|
||||
|
||||
type AttachmentSet struct {
|
||||
AttachTime string `json:"attachTime"`
|
||||
Cache string `json:"cache"`
|
||||
DeleteOnTermination string `json:"deleteOnTermination"`
|
||||
Device string `json:"device"`
|
||||
InstanceId string `json:"instanceId"`
|
||||
Status string `json:"status"`
|
||||
VolumeId string `json:"volumeId"`
|
||||
}
|
||||
|
||||
func (self *SDisk) GetName() string {
|
||||
return self.VolumeName
|
||||
}
|
||||
|
||||
func (self *SDisk) GetId() string {
|
||||
return self.VolumeId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
|
||||
return self.storage, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIStorageId() string {
|
||||
return self.StorageId
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskFormat() string {
|
||||
return "raw"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskSizeMB() int {
|
||||
return self.Size * 1024
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsAutoDelete() bool {
|
||||
return self.IsRoot == "true"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetTemplateId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDiskType() string {
|
||||
if self.IsRoot == "true" {
|
||||
return api.DISK_TYPE_SYS
|
||||
}
|
||||
return api.DISK_TYPE_DATA
|
||||
}
|
||||
|
||||
func (self *SDisk) GetFsFormat() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetIsNonPersistent() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SDisk) GetDriver() string {
|
||||
return "virtio"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetCacheMode() string {
|
||||
return "none"
|
||||
}
|
||||
|
||||
func (self *SDisk) GetMountpoint() string {
|
||||
for _, att := range self.AttachmentSet {
|
||||
return att.Device
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) GetAccessPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SDisk) Delete(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (self *SDisk) Resize(ctx context.Context, newSizeMB int64) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) Rebuild(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SDisk) GetStatus() string {
|
||||
switch self.Status {
|
||||
case "available", "in-use":
|
||||
return api.DISK_READY
|
||||
default:
|
||||
return self.Status
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetDisks(id, nextToken string) ([]SDisk, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["volumeId"] = id
|
||||
}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribeVolumes", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
ret := struct {
|
||||
NextToken string
|
||||
VolumeSet []SDisk
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.VolumeSet, ret.NextToken, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
part, nextToken, err := self.zone.region.GetDisks("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disks := []SDisk{}
|
||||
disks = append(disks, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.zone.region.GetDisks("", nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
disks = append(disks, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudDisk{}
|
||||
for i := range disks {
|
||||
if disks[i].StorageId == self.StorageId {
|
||||
disks[i].storage = self
|
||||
ret = append(ret, &disks[i])
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
|
||||
disk, err := self.zone.region.GetDisk(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if disk.StorageId != self.StorageId {
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
disk.storage = self
|
||||
return disk, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetDisk(id string) (*SDisk, error) {
|
||||
disks, _, err := self.GetDisks(id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range disks {
|
||||
if disks[i].GetGlobalId() == id {
|
||||
return &disks[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
|
||||
type SEip struct {
|
||||
}
|
||||
|
||||
func (self *SRegion) GetEips(ip, nextToken string) ([]SEip, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(ip) > 0 {
|
||||
params["publicIp"] = ip
|
||||
}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribeAddresses", params)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrapf(err, "DescribeAddresses")
|
||||
}
|
||||
ret := struct {
|
||||
AddressesSet []SEip
|
||||
NextToken string
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.AddressesSet, ret.NextToken, nil
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SHost struct {
|
||||
multicloud.SHostBase
|
||||
multicloud.STagBase
|
||||
|
||||
zone *SZone
|
||||
|
||||
CPUHz string `json:"CpuHz"`
|
||||
ModelId string `json:"ModelId"`
|
||||
MonitorType string `json:"MonitorType"`
|
||||
IpmiMgrEnabled string `json:"IpmiMgrEnabled"`
|
||||
JoinTime time.Time `json:"JoinTime"`
|
||||
IsBareMetal string `json:"isBareMetal"`
|
||||
BmcPwd string `json:"BmcPwd"`
|
||||
Extra string `json:"Extra"`
|
||||
InstanceId string `json:"instanceId"`
|
||||
Manufacturer string `json:"Manufacturer"`
|
||||
BaseBoardSerial string `json:"BaseBoardSerial"`
|
||||
BareMetalHWInfo string `json:"BareMetalHWInfo"`
|
||||
BmcPort string `json:"BmcPort"`
|
||||
CPUCores int `json:"CpuCores"`
|
||||
BmcIP string `json:"BmcIp"`
|
||||
Cabinet string `json:"Cabinet"`
|
||||
Memo string `json:"Memo"`
|
||||
HostIP string `json:"HostIp"`
|
||||
Memory int `json:"Memory"`
|
||||
HostId string `json:"HostId"`
|
||||
CPUKind string `json:"CpuKind"`
|
||||
SystemSerial string `json:"SystemSerial"`
|
||||
InCloud string `json:"InCloud"`
|
||||
Location string `json:"Location"`
|
||||
BmcUser string `json:"BmcUser"`
|
||||
PublicIP string `json:"PublicIp"`
|
||||
Status string `json:"Status"`
|
||||
Room string `json:"Room"`
|
||||
SSHMgrEnabled string `json:"SshMgrEnabled"`
|
||||
BmState string `json:"bmState"`
|
||||
HostName string `json:"HostName"`
|
||||
}
|
||||
|
||||
func (self *SHost) GetId() string {
|
||||
return self.HostId
|
||||
}
|
||||
|
||||
func (self *SHost) GetGlobalId() string {
|
||||
return self.HostId
|
||||
}
|
||||
|
||||
func (self *SHost) GetName() string {
|
||||
return self.HostName
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessIp() string {
|
||||
return self.HostIP
|
||||
}
|
||||
|
||||
func (self *SHost) GetAccessMac() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetSysInfo() jsonutils.JSONObject {
|
||||
return jsonutils.NewDict()
|
||||
}
|
||||
|
||||
func (self *SHost) GetSN() string {
|
||||
return self.BaseBoardSerial
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuCount() int {
|
||||
return self.CPUCores
|
||||
}
|
||||
|
||||
func (self *SHost) GetNodeCount() int8 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuDesc() string {
|
||||
return self.CPUKind
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuMhz() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetCpuCmtbound() float32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SHost) GetMemSizeMB() int {
|
||||
return self.Memory
|
||||
}
|
||||
|
||||
func (self *SHost) GetMemCmtbound() float32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (self *SHost) GetReservedMemoryMb() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageSizeMB() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SHost) GetStorageType() string {
|
||||
return api.STORAGE_LOCAL_SSD
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostType() string {
|
||||
return api.HOST_TYPE_BINGO_CLOUD
|
||||
}
|
||||
|
||||
func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorages()
|
||||
}
|
||||
|
||||
func (self *SHost) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
return self.zone.GetIStorageById(id)
|
||||
}
|
||||
|
||||
func (self *SHost) GetEnabled() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SHost) GetHostStatus() string {
|
||||
if self.Status == "available" {
|
||||
return api.HOST_ONLINE
|
||||
}
|
||||
return api.HOST_OFFLINE
|
||||
}
|
||||
|
||||
func (self *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
|
||||
vms := []SInstance{}
|
||||
part, nextToken, err := self.zone.region.GetInstances("", self.zone.ZoneName, 100, "")
|
||||
vms = append(vms, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.zone.region.GetInstances("", self.zone.ZoneName, 100, nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vms = append(vms, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudVM{}
|
||||
for i := range vms {
|
||||
if strings.HasSuffix(vms[i].InstancesSet.HostAddress, self.HostIP) {
|
||||
vms[i].host = self
|
||||
ret = append(ret, &vms[i])
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SHost) GetSchedtags() ([]string, error) {
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (self *SHost) GetIsMaintenance() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SHost) GetVersion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SHost) GetStatus() string {
|
||||
return api.HOST_STATUS_RUNNING
|
||||
}
|
||||
|
||||
func (self *SRegion) GetHosts(nextToken string) ([]SHost, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribePhysicalHosts", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
ret := struct {
|
||||
DescribePhysicalHostsResult struct {
|
||||
PhysicalHostSet []SHost
|
||||
}
|
||||
NextToken string
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.DescribePhysicalHostsResult.PhysicalHostSet, ret.NextToken, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
hosts, err := self.region.GetIHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range hosts {
|
||||
if hosts[i].GetGlobalId() == id {
|
||||
return hosts[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SZone) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
hosts := []SHost{}
|
||||
part, nextToken, err := self.region.GetHosts("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hosts = append(hosts, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.region.GetHosts(nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
hosts = append(hosts, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudHost{}
|
||||
for i := range hosts {
|
||||
hosts[i].zone = self
|
||||
ret = append(ret, &hosts[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
type SImage struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.BingoTags
|
||||
cache *SStoragecache
|
||||
|
||||
Architecture string `json:"architecture"`
|
||||
BlockDeviceMapping string `json:"blockDeviceMapping"`
|
||||
Bootloader string `json:"bootloader"`
|
||||
Clonemode string `json:"clonemode"`
|
||||
ClusterId string `json:"clusterId"`
|
||||
Contentmode string `json:"contentmode"`
|
||||
DefaultStorageId string `json:"defaultStorageId"`
|
||||
Description string `json:"description"`
|
||||
DiskBus string `json:"diskBus"`
|
||||
ExtendDisk string `json:"extendDisk"`
|
||||
Features string `json:"features"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
ImageId string `json:"imageId"`
|
||||
ImageLocation string `json:"imageLocation"`
|
||||
ImageOwnerId string `json:"imageOwnerId"`
|
||||
ImagePath string `json:"imagePath"`
|
||||
ImageSize int64 `json:"imageSize"`
|
||||
ImageState string `json:"imageState"`
|
||||
ImageType string `json:"imageType"`
|
||||
IsBareMetal string `json:"isBareMetal"`
|
||||
IsPublic bool `json:"isPublic"`
|
||||
KernelId string `json:"kernelId"`
|
||||
Name string `json:"name"`
|
||||
OsId string `json:"osId"`
|
||||
OSName string `json:"osName"`
|
||||
Platform string `json:"platform"`
|
||||
RamdiskId string `json:"ramdiskId"`
|
||||
RootDeviceName string `json:"rootDeviceName"`
|
||||
RootDeviceType string `json:"rootDeviceType"`
|
||||
ScheduleTags string `json:"scheduleTags"`
|
||||
Shared string `json:"shared"`
|
||||
Sharemode string `json:"sharemode"`
|
||||
StateReason string `json:"stateReason"`
|
||||
StorageId string `json:"storageId"`
|
||||
}
|
||||
|
||||
func (self *SImage) GetId() string {
|
||||
return self.ImageId
|
||||
}
|
||||
|
||||
func (self *SImage) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SImage) GetName() string {
|
||||
return self.Name
|
||||
}
|
||||
|
||||
func (self *SImage) Delete(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return self.cache
|
||||
}
|
||||
|
||||
func (self *SImage) GetSizeByte() int64 {
|
||||
return self.ImageSize
|
||||
}
|
||||
|
||||
func (self *SImage) GetImageType() cloudprovider.TImageType {
|
||||
if self.IsPublic {
|
||||
return cloudprovider.ImageTypeSystem
|
||||
}
|
||||
return cloudprovider.ImageTypeCustomized
|
||||
}
|
||||
|
||||
func (self *SImage) GetImageStatus() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsType() cloudprovider.TOsType {
|
||||
if self.Platform == "linux" {
|
||||
return cloudprovider.OsTypeLinux
|
||||
}
|
||||
return cloudprovider.OsTypeWindows
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsDist() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsVersion() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SImage) GetOsArch() string {
|
||||
return self.Architecture
|
||||
}
|
||||
|
||||
func (self *SImage) GetMinOsDiskSizeGb() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SImage) GetMinRamSizeMb() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (self *SImage) GetImageFormat() string {
|
||||
return "raw"
|
||||
}
|
||||
|
||||
func (self *SImage) GetCreatedAt() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (self *SImage) UEFI() bool {
|
||||
return self.Bootloader == "uefi"
|
||||
}
|
||||
|
||||
func (self *SImage) GetPublicScope() rbacutils.TRbacScope {
|
||||
if self.Shared == "true" {
|
||||
return rbacutils.ScopeSystem
|
||||
}
|
||||
return rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
func (self *SImage) GetSubImages() []cloudprovider.SSubImage {
|
||||
return []cloudprovider.SSubImage{}
|
||||
}
|
||||
|
||||
func (self *SImage) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SImage) GetStatus() string {
|
||||
switch self.ImageState {
|
||||
case "available":
|
||||
return api.CACHED_IMAGE_STATUS_ACTIVE
|
||||
default:
|
||||
return self.ImageState
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetImages(id, nextToken string) ([]SImage, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["imageId"] = id
|
||||
}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribeImages", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
ret := struct {
|
||||
NextToken string
|
||||
ImagesSet []SImage
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.ImagesSet, ret.NextToken, nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetICloudImages() ([]cloudprovider.ICloudImage, error) {
|
||||
part, nextToken, err := self.region.GetImages("", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
images := []SImage{}
|
||||
images = append(images, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.region.GetImages("", nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
images = append(images, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudImage{}
|
||||
for i := range images {
|
||||
if images[i].StorageId == self.storageId {
|
||||
images[i].cache = self
|
||||
ret = append(ret, &images[i])
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetIImageById(id string) (cloudprovider.ICloudImage, error) {
|
||||
images, _, err := self.region.GetImages(id, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range images {
|
||||
if images[i].GetGlobalId() == id && images[i].StorageId == self.storageId {
|
||||
images[i].cache = self
|
||||
return &images[i], nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
@@ -15,115 +15,315 @@
|
||||
package bingocloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SInstance struct {
|
||||
multicloud.BingoTags
|
||||
multicloud.SInstanceBase
|
||||
host *SHost
|
||||
|
||||
ReservationId string `json:"reservationId"`
|
||||
OwnerId string
|
||||
GroupSet struct {
|
||||
Item struct {
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
GroupSet []struct {
|
||||
GroupId string
|
||||
GroupName string
|
||||
}
|
||||
InstancesSet struct {
|
||||
Item struct {
|
||||
InstanceId string `json:"instanceId"`
|
||||
InstanceName string `json:"instanceName"`
|
||||
HostName string `json:"hostName"`
|
||||
ImageId string `json:"imageId"`
|
||||
InstanceState struct {
|
||||
Code int `json:"code"`
|
||||
Name string `json:"name"`
|
||||
PendingProgress string `json:"pendingProgress"`
|
||||
} `json:"instanceState"`
|
||||
PrivateDNSName string `json:"privateDnsName"`
|
||||
DNSName string `json:"dnsName"`
|
||||
PrivateIPAddress string `json:"privateIpAddress"`
|
||||
PrivateIPAddresses string `json:"privateIpAddresses"`
|
||||
IPAddress string `json:"ipAddress"`
|
||||
NifInfo string `json:"nifInfo"`
|
||||
KeyName string `json:"keyName"`
|
||||
AmiLaunchIndex int `json:"amiLaunchIndex"`
|
||||
ProductCodesSet struct {
|
||||
Item struct {
|
||||
ProductCode string `json:"productCode"`
|
||||
} `json:"item"`
|
||||
} `json:"productCodesSet"`
|
||||
InstanceType string `json:"instanceType"`
|
||||
VmtypeCPU int `json:"vmtype_cpu"`
|
||||
VmtypeMem int `json:"vmtype_mem"`
|
||||
VmtypeDisk int `json:"vmtype_disk"`
|
||||
VmtypeGpu int `json:"vmtype_gpu"`
|
||||
VmtypeSsd int `json:"vmtype_ssd"`
|
||||
VmtypeHdd int `json:"vmtype_hdd"`
|
||||
VmtypeHba int `json:"vmtype_hba"`
|
||||
VmtypeSriov int `json:"vmtype_sriov"`
|
||||
LaunchTime time.Time `json:"launchTime"`
|
||||
RootDeviceType string `json:"rootDeviceType"`
|
||||
HostAddress string `json:"hostAddress"`
|
||||
Platform string `json:"platform"`
|
||||
UseCompactMode bool `json:"useCompactMode"`
|
||||
ExtendDisk bool `json:"extendDisk"`
|
||||
Placement struct {
|
||||
AvailabilityZone string `json:"availabilityZone"`
|
||||
} `json:"placement"`
|
||||
Namespace string `json:"namespace"`
|
||||
KernelId string `json:"kernelId"`
|
||||
RamdiskId string `json:"ramdiskId"`
|
||||
OperName string `json:"operName"`
|
||||
OperProgress int `json:"operProgress"`
|
||||
Features string `json:"features"`
|
||||
Monitoring struct {
|
||||
State string `json:"state"`
|
||||
} `json:"monitoring"`
|
||||
SubnetId string `json:"subnetId"`
|
||||
VpcId string `json:"vpcId"`
|
||||
StorageId string `json:"storageId"`
|
||||
DisableAPITermination bool `json:"disableApiTermination"`
|
||||
Vncdisabled bool `json:"vncdisabled"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
CustomStatus string `json:"customStatus"`
|
||||
SystemStatus int `json:"systemStatus"`
|
||||
NetworkStatus int `json:"networkStatus"`
|
||||
ScheduleTags string `json:"scheduleTags"`
|
||||
StorageScheduleTags string `json:"storageScheduleTags"`
|
||||
IsEncrypt bool `json:"isEncrypt"`
|
||||
IsImported bool `json:"isImported"`
|
||||
Ec2Version string `json:"ec2Version"`
|
||||
Passphrase string `json:"passphrase"`
|
||||
DrsEnabled bool `json:"drs_enabled"`
|
||||
LaunchPriority int `json:"launchPriority"`
|
||||
CPUPriority int `json:"cpuPriority"`
|
||||
MemPriority int `json:"memPriority"`
|
||||
CPUQuota int `json:"cpuQuota"`
|
||||
AutoMigrate bool `json:"autoMigrate"`
|
||||
DrMirrorId string `json:"drMirrorId"`
|
||||
BlockDeviceMapping struct {
|
||||
Item struct {
|
||||
DeviceName string `json:"deviceName"`
|
||||
Ebs struct {
|
||||
AttachTime time.Time `json:"attachTime"`
|
||||
DeleteOnTermination bool `json:"deleteOnTermination"`
|
||||
Status string `json:"status"`
|
||||
VolumeId string `json:"volumeId"`
|
||||
Size int `json:"size"`
|
||||
} `json:"ebs"`
|
||||
} `json:"item"`
|
||||
} `json:"blockDeviceMapping"`
|
||||
EnableLiveScaleup bool `json:"enableLiveScaleup"`
|
||||
ImageBytes int64 `json:"imageBytes"`
|
||||
StatusReason string `json:"statusReason"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
Bootloader string `json:"bootloader"`
|
||||
BmMachineId string `json:"bmMachineId"`
|
||||
}
|
||||
InstanceId string `json:"instanceId"`
|
||||
InstanceName string `json:"instanceName"`
|
||||
HostName string `json:"hostName"`
|
||||
ImageId string `json:"imageId"`
|
||||
InstanceState struct {
|
||||
Code int `json:"code"`
|
||||
Name string `json:"name"`
|
||||
PendingProgress string `json:"pendingProgress"`
|
||||
} `json:"instanceState"`
|
||||
PrivateDNSName string `json:"privateDnsName"`
|
||||
DNSName string `json:"dnsName"`
|
||||
PrivateIPAddress string `json:"privateIpAddress"`
|
||||
PrivateIPAddresses string `json:"privateIpAddresses"`
|
||||
IPAddress string `json:"ipAddress"`
|
||||
NifInfo string `json:"nifInfo"`
|
||||
KeyName string `json:"keyName"`
|
||||
AmiLaunchIndex int `json:"amiLaunchIndex"`
|
||||
ProductCodesSet []struct {
|
||||
ProductCode string `json:"productCode"`
|
||||
} `json:"productCodesSet"`
|
||||
InstanceType string `json:"instanceType"`
|
||||
VmtypeCPU int `json:"vmtype_cpu"`
|
||||
VmtypeMem int `json:"vmtype_mem"`
|
||||
VmtypeDisk int `json:"vmtype_disk"`
|
||||
VmtypeGpu int `json:"vmtype_gpu"`
|
||||
VmtypeSsd int `json:"vmtype_ssd"`
|
||||
VmtypeHdd int `json:"vmtype_hdd"`
|
||||
VmtypeHba int `json:"vmtype_hba"`
|
||||
VmtypeSriov int `json:"vmtype_sriov"`
|
||||
LaunchTime time.Time `json:"launchTime"`
|
||||
RootDeviceType string `json:"rootDeviceType"`
|
||||
HostAddress string `json:"hostAddress"`
|
||||
Platform string `json:"platform"`
|
||||
UseCompactMode bool `json:"useCompactMode"`
|
||||
ExtendDisk bool `json:"extendDisk"`
|
||||
Placement struct {
|
||||
AvailabilityZone string `json:"availabilityZone"`
|
||||
} `json:"placement"`
|
||||
Namespace string `json:"namespace"`
|
||||
KernelId string `json:"kernelId"`
|
||||
RamdiskId string `json:"ramdiskId"`
|
||||
OperName string `json:"operName"`
|
||||
OperProgress int `json:"operProgress"`
|
||||
Features string `json:"features"`
|
||||
Monitoring struct {
|
||||
State string `json:"state"`
|
||||
} `json:"monitoring"`
|
||||
SubnetId string `json:"subnetId"`
|
||||
VpcId string `json:"vpcId"`
|
||||
StorageId string `json:"storageId"`
|
||||
DisableAPITermination bool `json:"disableApiTermination"`
|
||||
Vncdisabled bool `json:"vncdisabled"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
CustomStatus string `json:"customStatus"`
|
||||
SystemStatus int `json:"systemStatus"`
|
||||
NetworkStatus int `json:"networkStatus"`
|
||||
ScheduleTags string `json:"scheduleTags"`
|
||||
StorageScheduleTags string `json:"storageScheduleTags"`
|
||||
IsEncrypt bool `json:"isEncrypt"`
|
||||
IsImported bool `json:"isImported"`
|
||||
Ec2Version string `json:"ec2Version"`
|
||||
Passphrase string `json:"passphrase"`
|
||||
DrsEnabled bool `json:"drs_enabled"`
|
||||
LaunchPriority int `json:"launchPriority"`
|
||||
CPUPriority int `json:"cpuPriority"`
|
||||
MemPriority int `json:"memPriority"`
|
||||
CPUQuota int `json:"cpuQuota"`
|
||||
AutoMigrate bool `json:"autoMigrate"`
|
||||
DrMirrorId string `json:"drMirrorId"`
|
||||
BlockDeviceMapping []struct {
|
||||
DeviceName string `json:"deviceName"`
|
||||
Ebs struct {
|
||||
AttachTime time.Time `json:"attachTime"`
|
||||
DeleteOnTermination bool `json:"deleteOnTermination"`
|
||||
Status string `json:"status"`
|
||||
VolumeId string `json:"volumeId"`
|
||||
Size int `json:"size"`
|
||||
} `json:"ebs"`
|
||||
} `json:"blockDeviceMapping"`
|
||||
EnableLiveScaleup bool `json:"enableLiveScaleup"`
|
||||
ImageBytes int64 `json:"imageBytes"`
|
||||
StatusReason string `json:"statusReason"`
|
||||
Hypervisor string `json:"hypervisor"`
|
||||
Bootloader string `json:"bootloader"`
|
||||
BmMachineId string `json:"bmMachineId"`
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) DescribeInstances(id string, maxResult int, nextToken string) ([]SInstance, string, error) {
|
||||
func (self *SInstance) GetId() string {
|
||||
return self.InstancesSet.InstanceId
|
||||
}
|
||||
|
||||
func (self *SInstance) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SInstance) GetName() string {
|
||||
if len(self.InstancesSet.InstanceName) > 0 {
|
||||
return self.InstancesSet.InstanceName
|
||||
}
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SInstance) GetSecurityGroupIds() ([]string, error) {
|
||||
ret := []string{}
|
||||
for _, sec := range self.GroupSet {
|
||||
ret = append(ret, sec.GroupId)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) AssignSecurityGroup(secgroupId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) DetachDisk(ctx context.Context, diskId string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) DeployVM(ctx context.Context, name string, username string, password string, publicKey string, deleteKeypair bool, description string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) DeleteVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVcpuCount() int {
|
||||
return self.InstancesSet.VmtypeCPU
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVmemSizeMB() int {
|
||||
return self.InstancesSet.VmtypeMem
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBootOrder() string {
|
||||
return "cdn"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVga() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVdi() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetOSArch() string {
|
||||
return "x86"
|
||||
}
|
||||
|
||||
func (self *SInstance) GetOsType() cloudprovider.TOsType {
|
||||
if self.InstancesSet.Platform == "linux" {
|
||||
return cloudprovider.OsTypeLinux
|
||||
}
|
||||
return cloudprovider.OsTypeWindows
|
||||
}
|
||||
|
||||
func (self *SInstance) GetOSName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetBios() string {
|
||||
return strings.ToUpper(self.InstancesSet.Bootloader)
|
||||
}
|
||||
|
||||
func (self *SInstance) GetMachine() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetInstanceType() string {
|
||||
return self.InstancesSet.InstanceType
|
||||
}
|
||||
|
||||
func (self *SInstance) GetError() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetHostname() string {
|
||||
return self.InstancesSet.HostName
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
|
||||
return self.host
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIHostId() string {
|
||||
info := strings.Split(self.InstancesSet.HostAddress, "@")
|
||||
if len(info) == 2 {
|
||||
return info[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetHypervisor() string {
|
||||
return api.HYPERVISOR_BINGO_CLOUD
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
|
||||
storages, err := self.host.zone.region.getStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storageMaps := map[string]SStorage{}
|
||||
for i := range storages {
|
||||
storageMaps[storages[i].StorageId] = storages[i]
|
||||
}
|
||||
ret := []cloudprovider.ICloudDisk{}
|
||||
for _, _disk := range self.InstancesSet.BlockDeviceMapping {
|
||||
disk, err := self.host.zone.region.GetDisk(_disk.Ebs.VolumeId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storage, ok := storageMaps[disk.StorageId]
|
||||
if ok {
|
||||
storage.zone = self.host.zone
|
||||
disk.storage = &storage
|
||||
ret = append(ret, disk)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
|
||||
nics, err := self.host.zone.region.GetInstanceNics(self.InstancesSet.InstanceId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudNic{}
|
||||
for i := range nics {
|
||||
ret = append(ret, &nics[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SInstance) GetStatus() string {
|
||||
switch self.InstancesSet.InstanceState.Name {
|
||||
default:
|
||||
return self.InstancesSet.InstanceState.Name
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) RebuildRoot(ctx context.Context, config *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) StartVM(ctx context.Context) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateUserData(userData string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstance) UpdateVM(ctx context.Context, name string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstances(id, zoneId string, maxResult int, nextToken string) ([]SInstance, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["instanceId"] = id
|
||||
@@ -134,19 +334,25 @@ func (self *SRegion) DescribeInstances(id string, maxResult int, nextToken strin
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
|
||||
idx := 1
|
||||
if len(zoneId) > 0 {
|
||||
params[fmt.Sprintf("Filter.%d.Name", idx)] = "availability-zone"
|
||||
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = zoneId
|
||||
idx++
|
||||
}
|
||||
|
||||
resp, err := self.invoke("DescribeInstances", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
result := struct {
|
||||
NextToken string
|
||||
ReservationSet struct {
|
||||
Item []SInstance
|
||||
}
|
||||
ReservationSet []SInstance
|
||||
}{}
|
||||
err = resp.Unmarshal(&result)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return result.ReservationSet.Item, result.NextToken, nil
|
||||
return result.ReservationSet, result.NextToken, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import "yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
|
||||
type SInstanceNic struct {
|
||||
Association string `json:"association"`
|
||||
Attachment struct {
|
||||
AttachTime string `json:"attachTime"`
|
||||
AttachmentId string `json:"attachmentId"`
|
||||
DeleteOnTermination string `json:"deleteOnTermination"`
|
||||
DeviceIndex string `json:"deviceIndex"`
|
||||
InstanceId string `json:"instanceId"`
|
||||
InstanceOwnerId string `json:"instanceOwnerId"`
|
||||
Status string `json:"status"`
|
||||
} `json:"attachment"`
|
||||
AvailabilityZone string `json:"availabilityZone"`
|
||||
Description string `json:"description"`
|
||||
FirstPacketLimit string `json:"firstPacketLimit"`
|
||||
MACAddress string `json:"macAddress"`
|
||||
Model string `json:"model"`
|
||||
NetworkInterfaceId string `json:"networkInterfaceId"`
|
||||
NoMatchPort string `json:"noMatchPort"`
|
||||
OwnerId string `json:"ownerId"`
|
||||
PrivateDNSName string `json:"privateDnsName"`
|
||||
PrivateIPAddress string `json:"privateIpAddress"`
|
||||
PrivateIPAddressesSet []struct {
|
||||
Association string `json:"association"`
|
||||
Primary string `json:"primary"`
|
||||
PrivateDNSName string `json:"privateDnsName"`
|
||||
PrivateIPAddress string `json:"privateIpAddress"`
|
||||
} `json:"privateIpAddressesSet"`
|
||||
RequesterManaged string `json:"requesterManaged"`
|
||||
SourceDestCheck string `json:"sourceDestCheck"`
|
||||
Status string `json:"status"`
|
||||
SubnetId string `json:"subnetId"`
|
||||
VpcId string `json:"vpcId"`
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetId() string {
|
||||
return self.NetworkInterfaceId
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetIP() string {
|
||||
return self.PrivateIPAddress
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetMAC() string {
|
||||
return self.MACAddress
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) InClassicNetwork() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetDriver() string {
|
||||
return self.Model
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetINetworkId() string {
|
||||
return self.SubnetId
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) GetSubAddress() ([]string, error) {
|
||||
ret := []string{}
|
||||
for _, ip := range self.PrivateIPAddressesSet {
|
||||
if ip.PrivateIPAddress != self.PrivateIPAddress {
|
||||
ret = append(ret, ip.PrivateIPAddress)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) AssignNAddress(count int) ([]string, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) AssignAddress(ipAddrs []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SInstanceNic) UnassignAddress(ipAddrs []string) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SRegion) GetInstanceNics(insId string) ([]SInstanceNic, error) {
|
||||
params := map[string]string{}
|
||||
if len(insId) > 0 {
|
||||
params["instanceId"] = insId
|
||||
}
|
||||
resp, err := self.invoke("DescribeNetworkInterfaces", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := struct {
|
||||
NetworkInterfaceSet []SInstanceNic
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.NetworkInterfaceSet, nil
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/netutils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
||||
)
|
||||
|
||||
type SNetwork struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.STagBase
|
||||
wire *SWire
|
||||
|
||||
CidrBlock string `json:"cidrBlock"`
|
||||
MapPublicIPOnLaunch string `json:"mapPublicIpOnLaunch"`
|
||||
RouterId string `json:"routerId"`
|
||||
NetworkFrom string `json:"networkFrom"`
|
||||
NetworkNode string `json:"networkNode"`
|
||||
IsManagedNetwork string `json:"isManagedNetwork"`
|
||||
SubnetName string `json:"subnetName"`
|
||||
NetworkMask string `json:"networkMask"`
|
||||
NetName string `json:"netName"`
|
||||
Index string `json:"index"`
|
||||
VpcIsPublic string `json:"vpcIsPublic"`
|
||||
Description string `json:"description"`
|
||||
MicroSegmentation string `json:"microSegmentation"`
|
||||
State string `json:"state"`
|
||||
DefaultForAz string `json:"defaultForAz"`
|
||||
Router string `json:"router"`
|
||||
Active string `json:"active"`
|
||||
VpcShared string `json:"vpcShared"`
|
||||
DvswitchName string `json:"dvswitchName"`
|
||||
AvailableIPAddressCount string `json:"availableIpAddressCount"`
|
||||
VlanNum string `json:"vlanNum"`
|
||||
RouterCc2 string `json:"router_cc2"`
|
||||
ResStatus string `json:"res_status"`
|
||||
IPAddressCount string `json:"ipAddressCount"`
|
||||
RouterCc string `json:"router_cc"`
|
||||
VpcId string `json:"vpcId"`
|
||||
NetworkTo string `json:"networkTo"`
|
||||
Broadcast string `json:"broadcast"`
|
||||
UserName string `json:"userName"`
|
||||
IPVersion string `json:"ipVersion"`
|
||||
AvailabilityZone string `json:"availabilityZone"`
|
||||
Network string `json:"network"`
|
||||
RouterMac string `json:"router_mac"`
|
||||
CheckIP string `json:"checkIp"`
|
||||
FloatingPool string `json:"floatingPool"`
|
||||
StaticPool string `json:"staticPool"`
|
||||
DvsPortGroup string `json:"dvsPortGroup"`
|
||||
SubnetId string `json:"subnetId"`
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetId() string {
|
||||
return self.SubnetId
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGlobalId() string {
|
||||
return self.SubnetId
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetName() string {
|
||||
if len(self.SubnetName) > 0 {
|
||||
return self.SubnetName
|
||||
}
|
||||
return self.SubnetId
|
||||
}
|
||||
|
||||
func (self *SNetwork) Delete() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetAllocTimeoutSeconds() int {
|
||||
return 300
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetGateway() string {
|
||||
prefix, err := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
if err == nil {
|
||||
return prefix.Address.StepUp().String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpStart() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
startIp := pref.Address.NetAddr(pref.MaskLen) // 0
|
||||
startIp = startIp.StepUp() // 1
|
||||
return startIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpEnd() string {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
endIp := pref.Address.BroadcastAddr(pref.MaskLen) // 255
|
||||
endIp = endIp.StepDown() // 254
|
||||
endIp = endIp.StepDown() // 253
|
||||
endIp = endIp.StepDown() // 252
|
||||
return endIp.String()
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIpMask() int8 {
|
||||
pref, _ := netutils.NewIPV4Prefix(self.CidrBlock)
|
||||
return pref.MaskLen
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetIWire() cloudprovider.ICloudWire {
|
||||
return self.wire
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetPublicScope() rbacutils.TRbacScope {
|
||||
return rbacutils.ScopeDomain
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetServerType() string {
|
||||
return api.NETWORK_TYPE_GUEST
|
||||
}
|
||||
|
||||
func (self *SNetwork) GetStatus() string {
|
||||
return strings.ToLower(self.State)
|
||||
}
|
||||
|
||||
func (self *SWire) CreateINetwork(opts *cloudprovider.SNetworkCreateOptions) (cloudprovider.ICloudNetwork, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
|
||||
networks, err := self.vpc.region.GetNetworks("", self.zone.ZoneName, self.vpc.VpcId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudNetwork{}
|
||||
for i := range networks {
|
||||
networks[i].wire = self
|
||||
ret = append(ret, &networks[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SWire) GetINetworkById(id string) (cloudprovider.ICloudNetwork, error) {
|
||||
networks, err := self.GetINetworks()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range networks {
|
||||
if networks[i].GetGlobalId() == id {
|
||||
return networks[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetNetworks(id, zoneId, vpcId string) ([]SNetwork, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["subnetId"] = id
|
||||
}
|
||||
idx := 1
|
||||
if len(zoneId) > 0 {
|
||||
params[fmt.Sprintf("Filter.%d.Name", idx)] = "availability-zone"
|
||||
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = zoneId
|
||||
idx++
|
||||
}
|
||||
if len(vpcId) > 0 {
|
||||
params[fmt.Sprintf("Filter.%d.Name", idx)] = "vpc-id"
|
||||
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = vpcId
|
||||
idx++
|
||||
}
|
||||
resp, err := self.invoke("DescribeSubnets", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
networks := []SNetwork{}
|
||||
return networks, resp.Unmarshal(&networks, "subnetSet")
|
||||
}
|
||||
@@ -118,7 +118,7 @@ func (self *SBingoCloudProvider) GetVersion() string {
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetSubAccounts() ([]cloudprovider.SSubAccount, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
return self.client.GetSubAccounts()
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetAccountId() string {
|
||||
@@ -126,12 +126,11 @@ func (self *SBingoCloudProvider) GetAccountId() string {
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetIRegions() []cloudprovider.ICloudRegion {
|
||||
// TODO
|
||||
return nil
|
||||
return self.client.GetIRegions()
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetIRegionById(id string) (cloudprovider.ICloudRegion, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
return self.client.GetIRegionById(id)
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetBalance() (float64, string, error) {
|
||||
@@ -140,7 +139,6 @@ func (self *SBingoCloudProvider) GetBalance() (float64, string, error) {
|
||||
|
||||
func (self *SBingoCloudProvider) GetIProjects() ([]cloudprovider.ICloudProject, error) {
|
||||
return []cloudprovider.ICloudProject{}, nil
|
||||
//return self.client.GetIProjects()
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetStorageClasses(regionId string) []string {
|
||||
@@ -156,5 +154,5 @@ func (self *SBingoCloudProvider) GetObjectCannedAcls(regionId string) []string {
|
||||
}
|
||||
|
||||
func (self *SBingoCloudProvider) GetCapabilities() []string {
|
||||
return []string{}
|
||||
return self.client.GetCapabilities()
|
||||
}
|
||||
|
||||
@@ -14,9 +14,26 @@
|
||||
|
||||
package bingocloud
|
||||
|
||||
import "yunion.io/x/jsonutils"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SRegion struct {
|
||||
multicloud.SRegion
|
||||
multicloud.SRegionEipBase
|
||||
multicloud.SRegionLbBase
|
||||
multicloud.SRegionOssBase
|
||||
multicloud.SRegionSecurityGroupBase
|
||||
multicloud.SRegionVpcBase
|
||||
multicloud.SRegionZoneBase
|
||||
|
||||
client *SBingoCloudClient
|
||||
|
||||
RegionId string
|
||||
@@ -26,10 +43,46 @@ type SRegion struct {
|
||||
RegionEndpoint string
|
||||
}
|
||||
|
||||
func (self *SRegion) GetId() string {
|
||||
return self.RegionId
|
||||
}
|
||||
|
||||
func (self *SRegion) GetName() string {
|
||||
return self.RegionName
|
||||
}
|
||||
|
||||
func (self *SRegion) GetGlobalId() string {
|
||||
return fmt.Sprintf("%s/%s", CLOUD_PROVIDER_BINGO_CLOUD, self.RegionId)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetClient() *SBingoCloudClient {
|
||||
return self.client
|
||||
}
|
||||
|
||||
func (self *SRegion) GetCapabilities() []string {
|
||||
return self.client.GetCapabilities()
|
||||
}
|
||||
|
||||
func (self *SRegion) GetI18n() cloudprovider.SModelI18nTable {
|
||||
return cloudprovider.SModelI18nTable{}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetProvider() string {
|
||||
return api.CLOUD_PROVIDER_BINGO_CLOUD
|
||||
}
|
||||
|
||||
func (self *SRegion) GetStatus() string {
|
||||
return api.CLOUD_REGION_STATUS_INSERVER
|
||||
}
|
||||
|
||||
func (self *SRegion) GetCloudEnv() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo {
|
||||
return cloudprovider.SGeographicInfo{}
|
||||
}
|
||||
|
||||
func (self *SRegion) invoke(action string, params map[string]string) (jsonutils.JSONObject, error) {
|
||||
return self.client.invoke(action, params)
|
||||
}
|
||||
@@ -39,14 +92,84 @@ func (self *SBingoCloudClient) GetRegions() ([]SRegion, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := struct {
|
||||
RegionInfo struct {
|
||||
Item []SRegion
|
||||
}
|
||||
}{}
|
||||
err = resp.Unmarshal(&result)
|
||||
ret := []SRegion{}
|
||||
err = resp.Unmarshal(&ret, "regionInfo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.RegionInfo.Item, nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
|
||||
storages := []SStorage{}
|
||||
part, nextToken, err := self.GetStorages("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storages = append(storages, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.GetStorages(nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storages = append(storages, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudStoragecache{}
|
||||
for i := range storages {
|
||||
cache := SStoragecache{
|
||||
region: self,
|
||||
storageName: storages[i].StorageName,
|
||||
storageId: storages[i].StorageId,
|
||||
}
|
||||
ret = append(ret, &cache)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
|
||||
caches, err := self.GetIStoragecaches()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range caches {
|
||||
if caches[i].GetGlobalId() == id {
|
||||
return caches[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) {
|
||||
zones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudHost{}
|
||||
for i := range zones {
|
||||
hosts, err := zones[i].GetIHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, hosts...)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIHostById(id string) (cloudprovider.ICloudHost, error) {
|
||||
zones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range zones {
|
||||
hosts, err := zones[i].GetIHosts()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range hosts {
|
||||
if hosts[i].GetGlobalId() == id {
|
||||
return hosts[i], nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/secrules"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SSecurityGroup struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.BingoTags
|
||||
region *SRegion
|
||||
|
||||
ComplexIPPermissions string `json:"complexIpPermissions"`
|
||||
ComplexIPPermissionsEgress string `json:"complexIpPermissionsEgress"`
|
||||
DisplayName string `json:"displayName"`
|
||||
GroupDescription string `json:"groupDescription"`
|
||||
GroupId string `json:"groupId"`
|
||||
GroupName string `json:"groupName"`
|
||||
IPPermissionType string `json:"ipPermissionType"`
|
||||
IPPermissions string `json:"ipPermissions"`
|
||||
IPPermissionsEgress []IPPermissionsEgress `json:"ipPermissionsEgress"`
|
||||
OwnerId string `json:"ownerId"`
|
||||
}
|
||||
|
||||
type IPPermissionsEgress struct {
|
||||
BoundType string `json:"boundType"`
|
||||
Description string `json:"description"`
|
||||
FromPort int `json:"fromPort"`
|
||||
IPProtocol string `json:"ipProtocol"`
|
||||
Groups []struct {
|
||||
GroupId string
|
||||
GroupName string
|
||||
} `json:"groups"`
|
||||
IPRanges []struct {
|
||||
CIdRIP string `json:"cidrIp"`
|
||||
} `json:"ipRanges"`
|
||||
L2Accept string `json:"l2Accept"`
|
||||
PermissionId string `json:"permissionId"`
|
||||
Policy string `json:"policy"`
|
||||
ToPort int `json:"toPort"`
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetId() string {
|
||||
return self.GroupId
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetName() string {
|
||||
return self.GroupName
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) Delete() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetDescription() string {
|
||||
return self.GroupDescription
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetProjectId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
|
||||
return []cloudprovider.SecurityGroupReference{}, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetRules() ([]cloudprovider.SecurityRule, error) {
|
||||
ret := []cloudprovider.SecurityRule{}
|
||||
for _, _rule := range self.IPPermissionsEgress {
|
||||
if len(_rule.Groups) > 0 {
|
||||
continue
|
||||
}
|
||||
rule := cloudprovider.SecurityRule{}
|
||||
rule.Direction = secrules.DIR_IN
|
||||
rule.Priority = 1
|
||||
rule.Action = secrules.SecurityRuleAllow
|
||||
rule.Protocol = secrules.PROTO_ANY
|
||||
rule.Description = _rule.Description
|
||||
if _rule.BoundType == "Out" {
|
||||
rule.Direction = secrules.DIR_OUT
|
||||
}
|
||||
if _rule.Policy == "DROP" {
|
||||
rule.Action = secrules.SecurityRuleDeny
|
||||
}
|
||||
if _rule.IPProtocol != "all" {
|
||||
rule.Protocol = _rule.IPProtocol
|
||||
}
|
||||
if rule.Protocol == secrules.PROTO_TCP || rule.Protocol == secrules.PROTO_UDP {
|
||||
rule.PortStart, rule.PortEnd = _rule.FromPort, _rule.ToPort
|
||||
}
|
||||
|
||||
for _, ip := range _rule.IPRanges {
|
||||
if ip.CIdRIP == "::/0" {
|
||||
ip.CIdRIP = "0.0.0.0/0"
|
||||
}
|
||||
rule.ParseCIDR(ip.CIdRIP)
|
||||
err := rule.ValidateRule()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret = append(ret, rule)
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetVpcId() string {
|
||||
return api.NORMAL_VPC_ID
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) GetStatus() string {
|
||||
return api.SECGROUP_STATUS_READY
|
||||
}
|
||||
|
||||
func (self *SSecurityGroup) SyncRules(common, inAdds, outAdds, inDels, outDels []cloudprovider.SecurityRule) error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SRegion) GetSecurityGroups(id, name, nextToken string) ([]SSecurityGroup, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["groupId"] = id
|
||||
}
|
||||
if len(name) > 0 {
|
||||
params["groupName"] = name
|
||||
}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribeSecurityGroups", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
ret := struct {
|
||||
SecurityGroupInfo []SSecurityGroup
|
||||
NextToken string
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.SecurityGroupInfo, ret.NextToken, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISecurityGroupById(id string) (cloudprovider.ICloudSecurityGroup, error) {
|
||||
groups, _, err := self.GetSecurityGroups(id, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range groups {
|
||||
if groups[i].GetGlobalId() == id {
|
||||
groups[i].region = self
|
||||
return &groups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SRegion) GetISecurityGroupByName(opts *cloudprovider.SecurityGroupFilterOptions) (cloudprovider.ICloudSecurityGroup, error) {
|
||||
groups, _, err := self.GetSecurityGroups("", opts.Name, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range groups {
|
||||
if groups[i].GetName() == opts.Name {
|
||||
groups[i].region = self
|
||||
return &groups[i], nil
|
||||
}
|
||||
}
|
||||
return nil, cloudprovider.ErrNotFound
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type DiskListOptions struct {
|
||||
Id string
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&DiskListOptions{}, "disk-list", "list disks", func(cli *bingocloud.SRegion, args *DiskListOptions) error {
|
||||
vms, _, err := cli.GetDisks(args.Id, args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(vms, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type EipListOptions struct {
|
||||
Ip string
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&EipListOptions{}, "eip-list", "list eips", func(cli *bingocloud.SRegion, args *EipListOptions) error {
|
||||
eips, _, err := cli.GetEips(args.Ip, args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(eips, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type HostListOptions struct {
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&HostListOptions{}, "host-list", "List hosts", func(cli *bingocloud.SRegion, args *HostListOptions) error {
|
||||
hosts, _, err := cli.GetHosts(args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(hosts, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ImageListOptions struct {
|
||||
Id string
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&ImageListOptions{}, "image-list", "list images", func(cli *bingocloud.SRegion, args *ImageListOptions) error {
|
||||
images, _, err := cli.GetImages(args.Id, args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(images, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -22,11 +22,12 @@ import (
|
||||
func init() {
|
||||
type InstanceListOptions struct {
|
||||
Id string
|
||||
ZoneId string
|
||||
MaxResult int
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&InstanceListOptions{}, "instance-list", "list instances", func(cli *bingocloud.SRegion, args *InstanceListOptions) error {
|
||||
vms, _, err := cli.DescribeInstances(args.Id, args.MaxResult, args.NextToken)
|
||||
vms, _, err := cli.GetInstances(args.Id, args.ZoneId, args.MaxResult, args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -34,18 +35,16 @@ func init() {
|
||||
return nil
|
||||
})
|
||||
|
||||
type InstanceIdOptions struct {
|
||||
ID string
|
||||
type InstanceNicListOptions struct {
|
||||
InstanceId string
|
||||
}
|
||||
|
||||
shellutils.R(&InstanceIdOptions{}, "instance-show", "show instance", func(cli *bingocloud.SRegion, args *InstanceIdOptions) error {
|
||||
/*
|
||||
vm, err := cli.GetInstance(args.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printObject(vm)
|
||||
*/
|
||||
shellutils.R(&InstanceNicListOptions{}, "instance-nic-list", "list instance nics", func(cli *bingocloud.SRegion, args *InstanceNicListOptions) error {
|
||||
nics, err := cli.GetInstanceNics(args.InstanceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(nics, 0, 0, 0, []string{})
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type NetworkListOptions struct {
|
||||
Id string
|
||||
ZoneId string
|
||||
VpcId string
|
||||
}
|
||||
shellutils.R(&NetworkListOptions{}, "network-list", "List networks", func(cli *bingocloud.SRegion, args *NetworkListOptions) error {
|
||||
networks, err := cli.GetNetworks(args.Id, args.ZoneId, args.VpcId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(networks, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type SecurityGroupListOptions struct {
|
||||
Id string
|
||||
Name string
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&SecurityGroupListOptions{}, "security-group-list", "List security-groups", func(cli *bingocloud.SRegion, args *SecurityGroupListOptions) error {
|
||||
groups, _, err := cli.GetSecurityGroups(args.Id, args.Name, args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(groups, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type StorageListOptions struct {
|
||||
NextToken string
|
||||
}
|
||||
shellutils.R(&StorageListOptions{}, "storage-list", "List storages", func(cli *bingocloud.SRegion, args *StorageListOptions) error {
|
||||
storages, _, err := cli.GetStorages(args.NextToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(storages, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type VpcListOptions struct {
|
||||
Id string
|
||||
}
|
||||
shellutils.R(&VpcListOptions{}, "vpc-list", "List vpcs", func(cli *bingocloud.SRegion, args *VpcListOptions) error {
|
||||
vpcs, err := cli.GetVpcs(args.Id)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(vpcs, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package shell
|
||||
|
||||
import (
|
||||
"yunion.io/x/onecloud/pkg/multicloud/bingocloud"
|
||||
"yunion.io/x/onecloud/pkg/util/shellutils"
|
||||
)
|
||||
|
||||
func init() {
|
||||
type ZoneListOptions struct {
|
||||
}
|
||||
shellutils.R(&ZoneListOptions{}, "zone-list", "List zones", func(cli *bingocloud.SRegion, args *ZoneListOptions) error {
|
||||
zones, err := cli.GetZones()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printList(zones, 0, 0, 0, nil)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package bingocloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SStorage struct {
|
||||
multicloud.STagBase
|
||||
multicloud.SStorageBase
|
||||
zone *SZone
|
||||
|
||||
StorageId string `json:"storageId"`
|
||||
Location string `json:"location"`
|
||||
UsedBy string `json:"usedBy"`
|
||||
SpaceUsed int64 `json:"spaceUsed"`
|
||||
StorageName string `json:"storageName"`
|
||||
FileFormat string `json:"fileFormat"`
|
||||
Disabled string `json:"disabled"`
|
||||
SpaceMax int64 `json:"spaceMax"`
|
||||
StorageType string `json:"storageType"`
|
||||
DrCloudId string `json:"drCloudId"`
|
||||
ParameterSet []struct {
|
||||
Name string
|
||||
Value string
|
||||
} `json:"parameterSet"`
|
||||
ClusterId string `json:"clusterId"`
|
||||
IsDRStorage string `json:"isDRStorage"`
|
||||
ResUsage string `json:"resUsage"`
|
||||
ScheduleTags string `json:"scheduleTags"`
|
||||
}
|
||||
|
||||
func (self *SStorage) GetName() string {
|
||||
return self.StorageName
|
||||
}
|
||||
|
||||
func (self *SStorage) GetId() string {
|
||||
return self.StorageId
|
||||
}
|
||||
|
||||
func (self *SStorage) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SStorage) CreateIDisk(conf *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SStorage) DisableSync() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
|
||||
return &SStoragecache{storageId: self.StorageId, storageName: self.StorageName, region: self.zone.region}
|
||||
}
|
||||
|
||||
func (self *SStorage) GetIZone() cloudprovider.ICloudZone {
|
||||
return self.zone
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageType() string {
|
||||
return self.StorageType
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMediumType() string {
|
||||
return api.DISK_TYPE_SSD
|
||||
}
|
||||
|
||||
func (self *SStorage) GetCapacityMB() int64 {
|
||||
return self.SpaceMax * 1024
|
||||
}
|
||||
|
||||
func (self *SStorage) GetCapacityUsedMB() int64 {
|
||||
return self.SpaceUsed * 1024
|
||||
}
|
||||
|
||||
func (self *SStorage) GetMountPoint() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStatus() string {
|
||||
return api.STORAGE_ONLINE
|
||||
}
|
||||
|
||||
func (self *SStorage) GetStorageConf() jsonutils.JSONObject {
|
||||
return jsonutils.Marshal(self.ParameterSet)
|
||||
}
|
||||
|
||||
func (self *SStorage) GetEnabled() bool {
|
||||
return self.Disabled == "false"
|
||||
}
|
||||
|
||||
func (self *SStorage) IsSysDiskStore() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SRegion) GetStorages(nextToken string) ([]SStorage, string, error) {
|
||||
params := map[string]string{}
|
||||
if len(nextToken) > 0 {
|
||||
params["nextToken"] = nextToken
|
||||
}
|
||||
resp, err := self.invoke("DescribeStorages", params)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
ret := struct {
|
||||
NextToken string
|
||||
StorageSet []SStorage
|
||||
}{}
|
||||
resp.Unmarshal(&ret)
|
||||
return ret.StorageSet, ret.NextToken, nil
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) {
|
||||
storages, err := self.GetIStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range storages {
|
||||
if storages[i].GetGlobalId() == id {
|
||||
return storages[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SZone) GetIStorages() ([]cloudprovider.ICloudStorage, error) {
|
||||
storages, err := self.region.getStorages()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudStorage{}
|
||||
for i := range storages {
|
||||
storages[i].zone = self
|
||||
ret = append(ret, &storages[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) getStorages() ([]SStorage, error) {
|
||||
storages := []SStorage{}
|
||||
part, nextToken, err := self.GetStorages("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storages = append(storages, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.GetStorages(nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
storages = append(storages, part...)
|
||||
}
|
||||
return storages, nil
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SStoragecache struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.STagBase
|
||||
|
||||
region *SRegion
|
||||
storageId string
|
||||
storageName string
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetId() string {
|
||||
return fmt.Sprintf("%s-%s", self.region.GetGlobalId(), self.storageId)
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetName() string {
|
||||
return self.storageName
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetICustomizedCloudImages() ([]cloudprovider.ICloudImage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetPath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *SStoragecache) GetStatus() string {
|
||||
return "available"
|
||||
}
|
||||
|
||||
func (self *SStoragecache) CreateIImage(snapshotId, imageName, osType, imageDesc string) (cloudprovider.ICloudImage, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SStoragecache) DownloadImage(userCred mcclient.TokenCredential, imageId string, extId string, path string) (jsonutils.JSONObject, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SStoragecache) UploadImage(ctx context.Context, userCred mcclient.TokenCredential, image *cloudprovider.SImageCreateOption, callback func(float32)) (string, error) {
|
||||
return "", cloudprovider.ErrNotImplemented
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SVpc struct {
|
||||
multicloud.SVpc
|
||||
multicloud.STagBase
|
||||
|
||||
region *SRegion
|
||||
|
||||
RequestId string `json:"requestId"`
|
||||
VlanNum string `json:"vlanNum"`
|
||||
AsGateway string `json:"asGateway"`
|
||||
DhcpOptionsId string `json:"dhcpOptionsId"`
|
||||
VpcName string `json:"vpcName"`
|
||||
OwnerId string `json:"ownerId"`
|
||||
WanCode string `json:"wanCode"`
|
||||
Shared string `json:"shared"`
|
||||
SubnetPolicy string `json:"subnetPolicy"`
|
||||
Description string `json:"description"`
|
||||
VpcId string `json:"vpcId"`
|
||||
IsPublicNetwork string `json:"isPublicNetwork"`
|
||||
GatewayId string `json:"gatewayId"`
|
||||
IsDefault string `json:"isDefault"`
|
||||
Provider string `json:"provider"`
|
||||
State string `json:"state"`
|
||||
CidrBlock string `json:"cidrBlock"`
|
||||
InstanceTenancy string `json:"instanceTenancy"`
|
||||
}
|
||||
|
||||
func (self *SVpc) GetId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVpc) GetGlobalId() string {
|
||||
return self.VpcId
|
||||
}
|
||||
|
||||
func (self *SVpc) GetName() string {
|
||||
return self.VpcName
|
||||
}
|
||||
|
||||
func (self *SVpc) Delete() error {
|
||||
return cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVpc) GetCidrBlock() string {
|
||||
return self.CidrBlock
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIRouteTableById(id string) (cloudprovider.ICloudRouteTable, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIRouteTables() ([]cloudprovider.ICloudRouteTable, error) {
|
||||
return nil, cloudprovider.ErrNotImplemented
|
||||
}
|
||||
|
||||
func (self *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
|
||||
part, nextToken, err := self.region.GetSecurityGroups("", "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groups := []SSecurityGroup{}
|
||||
groups = append(groups, part...)
|
||||
for len(nextToken) > 0 {
|
||||
part, nextToken, err = self.region.GetSecurityGroups("", "", nextToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groups = append(groups, part...)
|
||||
}
|
||||
ret := []cloudprovider.ICloudSecurityGroup{}
|
||||
for i := range groups {
|
||||
groups[i].region = self.region
|
||||
ret = append(ret, &groups[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIsDefault() bool {
|
||||
return self.IsDefault == "true"
|
||||
}
|
||||
|
||||
func (self *SVpc) GetRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SVpc) GetStatus() string {
|
||||
switch self.State {
|
||||
case "available":
|
||||
return api.VPC_STATUS_AVAILABLE
|
||||
default:
|
||||
return self.State
|
||||
}
|
||||
}
|
||||
|
||||
func (self *SRegion) GetVpcs(id string) ([]SVpc, error) {
|
||||
params := map[string]string{}
|
||||
if len(id) > 0 {
|
||||
params["vpcId"] = id
|
||||
}
|
||||
resp, err := self.invoke("DescribeVpcs", params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vpcs := []SVpc{}
|
||||
return vpcs, resp.Unmarshal(&vpcs, "vpcSet")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
|
||||
vpcs, err := self.GetVpcs("")
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetVpcs")
|
||||
}
|
||||
ret := []cloudprovider.ICloudVpc{}
|
||||
for i := range vpcs {
|
||||
vpcs[i].region = self
|
||||
ret = append(ret, &vpcs[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SWire struct {
|
||||
multicloud.STagBase
|
||||
multicloud.SResourceBase
|
||||
|
||||
zone *SZone
|
||||
vpc *SVpc
|
||||
}
|
||||
|
||||
func (self *SWire) GetId() string {
|
||||
return fmt.Sprintf("%s/%s", self.vpc.GetGlobalId(), self.zone.GetGlobalId())
|
||||
}
|
||||
|
||||
func (self *SWire) GetGlobalId() string {
|
||||
return self.GetId()
|
||||
}
|
||||
|
||||
func (self *SWire) GetName() string {
|
||||
return fmt.Sprintf("%s-%s", self.vpc.GetName(), self.zone.GetName())
|
||||
}
|
||||
|
||||
func (self *SWire) GetBandwidth() int {
|
||||
return 1000
|
||||
}
|
||||
|
||||
func (self *SWire) GetStatus() string {
|
||||
return api.WIRE_STATUS_AVAILABLE
|
||||
}
|
||||
|
||||
func (self *SWire) GetIVpc() cloudprovider.ICloudVpc {
|
||||
return self.vpc
|
||||
}
|
||||
|
||||
func (self *SWire) IsEmulated() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self *SWire) GetIZone() cloudprovider.ICloudZone {
|
||||
return self.zone
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIWireById(id string) (cloudprovider.ICloudWire, error) {
|
||||
wires, err := self.GetIWires()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range wires {
|
||||
if wires[i].GetGlobalId() == id {
|
||||
return wires[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
|
||||
func (self *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
|
||||
zones, err := self.region.GetZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []cloudprovider.ICloudWire{}
|
||||
for i := range zones {
|
||||
wire := &SWire{
|
||||
vpc: self,
|
||||
zone: &zones[i],
|
||||
}
|
||||
ret = append(ret, wire)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// 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 bingocloud
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudprovider"
|
||||
"yunion.io/x/onecloud/pkg/multicloud"
|
||||
)
|
||||
|
||||
type SZone struct {
|
||||
multicloud.SResourceBase
|
||||
multicloud.STagBase
|
||||
|
||||
region *SRegion
|
||||
ZoneName string
|
||||
DisplayName string
|
||||
ZoneState string
|
||||
}
|
||||
|
||||
func (self *SZone) GetGlobalId() string {
|
||||
return self.ZoneName
|
||||
}
|
||||
|
||||
func (self *SZone) GetId() string {
|
||||
return self.ZoneName
|
||||
}
|
||||
|
||||
func (self *SZone) GetName() string {
|
||||
return self.DisplayName
|
||||
}
|
||||
|
||||
func (self *SZone) GetI18n() cloudprovider.SModelI18nTable {
|
||||
return cloudprovider.SModelI18nTable{}
|
||||
}
|
||||
|
||||
func (self *SZone) GetIRegion() cloudprovider.ICloudRegion {
|
||||
return self.region
|
||||
}
|
||||
|
||||
func (self *SZone) GetStatus() string {
|
||||
if self.ZoneState == "available" {
|
||||
return api.ZONE_ENABLE
|
||||
}
|
||||
return api.ZONE_DISABLE
|
||||
}
|
||||
|
||||
func (self *SRegion) GetZones() ([]SZone, error) {
|
||||
resp, err := self.invoke("DescribeAvailabilityZones", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ret := []SZone{}
|
||||
return ret, resp.Unmarshal(&ret, "availabilityZoneInfo")
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZones() ([]cloudprovider.ICloudZone, error) {
|
||||
zones, err := self.GetZones()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetZones")
|
||||
}
|
||||
ret := []cloudprovider.ICloudZone{}
|
||||
for i := range zones {
|
||||
zones[i].region = self
|
||||
ret = append(ret, &zones[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SRegion) GetIZoneById(id string) (cloudprovider.ICloudZone, error) {
|
||||
zones, err := self.GetIZones()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range zones {
|
||||
if zones[i].GetGlobalId() == id {
|
||||
return zones[i], nil
|
||||
}
|
||||
}
|
||||
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
|
||||
}
|
||||
@@ -429,3 +429,26 @@ func (self *CloudpodsTags) GetSysTags() map[string]string {
|
||||
func (self *CloudpodsTags) SetTags(tags map[string]string, replace bool) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags")
|
||||
}
|
||||
|
||||
type BingoTags struct {
|
||||
TagSet []struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
}
|
||||
|
||||
func (self *BingoTags) GetTags() (map[string]string, error) {
|
||||
tags := map[string]string{}
|
||||
for _, tag := range self.TagSet {
|
||||
tags[tag.Key] = tag.Value
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (self *BingoTags) GetSysTags() map[string]string {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *BingoTags) SetTags(tags map[string]string, replace bool) error {
|
||||
return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags")
|
||||
}
|
||||
|
||||
+27
-2
@@ -53,7 +53,7 @@ Go package that converts XML to JSON
|
||||
```json
|
||||
{
|
||||
"osm": {
|
||||
"-version": "0.6",
|
||||
"-version": 0.6,
|
||||
"-generator": "CGImap 0.0.2",
|
||||
"bounds": {
|
||||
"-minlat": "54.0889580",
|
||||
@@ -66,17 +66,42 @@ Go package that converts XML to JSON
|
||||
}
|
||||
```
|
||||
|
||||
**With type conversion**
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
xj "github.com/basgys/goxml2json"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// xml is an io.Reader
|
||||
xml := strings.NewReader(`<?xml version="1.0" encoding="UTF-8"?><price>19.95</price>`)
|
||||
json, err := xj.Convert(xml, xj.WithTypeConverter(xj.Float))
|
||||
if err != nil {
|
||||
panic("That's embarrassing...")
|
||||
}
|
||||
|
||||
fmt.Println(json.String())
|
||||
// {"price": 19.95}
|
||||
}
|
||||
```
|
||||
|
||||
### Contributing
|
||||
Feel free to contribute to this project if you want to fix/extend/improve it.
|
||||
|
||||
### Contributors
|
||||
|
||||
- [DirectX](https://github.com/directx)
|
||||
- [powerslacker](https://github.com/powerslacker)
|
||||
- [samuelhug](https://github.com/samuelhug)
|
||||
|
||||
### TODO
|
||||
|
||||
* Extract data types in JSON (numbers, boolean, ...)
|
||||
* Categorise errors
|
||||
* Option to prettify the JSON output
|
||||
* Benchmark
|
||||
|
||||
+4
-3
@@ -6,17 +6,18 @@ import (
|
||||
)
|
||||
|
||||
// Convert converts the given XML document to JSON
|
||||
func Convert(r io.Reader) (*bytes.Buffer, error) {
|
||||
func Convert(r io.Reader, ps ...plugin) (*bytes.Buffer, error) {
|
||||
// Decode XML document
|
||||
root := &Node{}
|
||||
err := NewDecoder(r).Decode(root)
|
||||
err := NewDecoder(r, ps...).Decode(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Then encode it in JSON
|
||||
buf := new(bytes.Buffer)
|
||||
err = NewEncoder(buf).Encode(root)
|
||||
e := NewEncoder(buf, ps...)
|
||||
err = e.Encode(root)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+25
-10
@@ -19,6 +19,8 @@ type Decoder struct {
|
||||
err error
|
||||
attributePrefix string
|
||||
contentPrefix string
|
||||
excludeAttrs map[string]bool
|
||||
formatters []nodeFormatter
|
||||
}
|
||||
|
||||
type element struct {
|
||||
@@ -35,6 +37,16 @@ func (dec *Decoder) SetContentPrefix(prefix string) {
|
||||
dec.contentPrefix = prefix
|
||||
}
|
||||
|
||||
func (dec *Decoder) AddFormatters(formatters []nodeFormatter) {
|
||||
dec.formatters = formatters
|
||||
}
|
||||
|
||||
func (dec *Decoder) ExcludeAttributes(attrs []string) {
|
||||
for _, attr := range attrs {
|
||||
dec.excludeAttrs[attr] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (dec *Decoder) DecodeWithCustomPrefixes(root *Node, contentPrefix string, attributePrefix string) error {
|
||||
dec.contentPrefix = contentPrefix
|
||||
dec.attributePrefix = attributePrefix
|
||||
@@ -42,21 +54,17 @@ func (dec *Decoder) DecodeWithCustomPrefixes(root *Node, contentPrefix string, a
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
func NewDecoder(r io.Reader) *Decoder {
|
||||
return &Decoder{r: r}
|
||||
func NewDecoder(r io.Reader, plugins ...plugin) *Decoder {
|
||||
d := &Decoder{r: r, contentPrefix: contentPrefix, attributePrefix: attrPrefix, excludeAttrs: map[string]bool{}}
|
||||
for _, p := range plugins {
|
||||
d = p.AddToDecoder(d)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// Decode reads the next JSON-encoded value from its
|
||||
// input and stores it in the value pointed to by v.
|
||||
func (dec *Decoder) Decode(root *Node) error {
|
||||
|
||||
if dec.contentPrefix == "" {
|
||||
dec.contentPrefix = contentPrefix
|
||||
}
|
||||
if dec.attributePrefix == "" {
|
||||
dec.attributePrefix = attrPrefix
|
||||
}
|
||||
|
||||
xmlDec := xml.NewDecoder(dec.r)
|
||||
|
||||
// That will convert the charset if the provided XML is non-UTF-8
|
||||
@@ -85,6 +93,9 @@ func (dec *Decoder) Decode(root *Node) error {
|
||||
|
||||
// Extract attributes as children
|
||||
for _, a := range se.Attr {
|
||||
if _, ok := dec.excludeAttrs[a.Name.Local]; ok {
|
||||
continue
|
||||
}
|
||||
elem.n.AddChild(dec.attributePrefix+a.Name.Local, &Node{Data: a.Value})
|
||||
}
|
||||
case xml.CharData:
|
||||
@@ -101,6 +112,10 @@ func (dec *Decoder) Decode(root *Node) error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, formatter := range dec.formatters {
|
||||
formatter.Format(root)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+19
-25
@@ -12,25 +12,16 @@ type Encoder struct {
|
||||
err error
|
||||
contentPrefix string
|
||||
attributePrefix string
|
||||
tc encoderTypeConverter
|
||||
}
|
||||
|
||||
// NewEncoder returns a new encoder that writes to w.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{w: w}
|
||||
}
|
||||
|
||||
func (enc *Encoder) SetAttributePrefix(prefix string) {
|
||||
enc.attributePrefix = prefix
|
||||
}
|
||||
|
||||
func (enc *Encoder) SetContentPrefix(prefix string) {
|
||||
enc.contentPrefix = prefix
|
||||
}
|
||||
|
||||
func (enc *Encoder) EncodeWithCustomPrefixes(root *Node, contentPrefix string, attributePrefix string) error {
|
||||
enc.contentPrefix = contentPrefix
|
||||
enc.attributePrefix = attributePrefix
|
||||
return enc.Encode(root)
|
||||
func NewEncoder(w io.Writer, plugins ...plugin) *Encoder {
|
||||
e := &Encoder{w: w, contentPrefix: contentPrefix, attributePrefix: attrPrefix}
|
||||
for _, p := range plugins {
|
||||
e = p.AddToEncoder(e)
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// Encode writes the JSON encoding of v to the stream
|
||||
@@ -41,12 +32,6 @@ func (enc *Encoder) Encode(root *Node) error {
|
||||
if root == nil {
|
||||
return nil
|
||||
}
|
||||
if enc.contentPrefix == "" {
|
||||
enc.contentPrefix = contentPrefix
|
||||
}
|
||||
if enc.attributePrefix == "" {
|
||||
enc.attributePrefix = attrPrefix
|
||||
}
|
||||
|
||||
enc.err = enc.format(root, 0)
|
||||
|
||||
@@ -82,7 +67,7 @@ func (enc *Encoder) format(n *Node, lvl int) error {
|
||||
enc.write(label)
|
||||
enc.write("\": ")
|
||||
|
||||
if len(children) > 1 {
|
||||
if n.ChildrenAlwaysAsArray || len(children) > 1 {
|
||||
// Array
|
||||
enc.write("[")
|
||||
for j, c := range children {
|
||||
@@ -106,8 +91,14 @@ func (enc *Encoder) format(n *Node, lvl int) error {
|
||||
|
||||
enc.write("}")
|
||||
} else {
|
||||
// TODO : Extract data type
|
||||
enc.write(sanitiseString(n.Data))
|
||||
s := sanitiseString(n.Data)
|
||||
if enc.tc == nil {
|
||||
// do nothing
|
||||
} else {
|
||||
s = enc.tc.Convert(s)
|
||||
}
|
||||
enc.write(s)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -124,6 +115,7 @@ func sanitiseString(s string) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
buf.WriteByte('"')
|
||||
|
||||
start := 0
|
||||
for i := 0; i < len(s); {
|
||||
if b := s[i]; b < utf8.RuneSelf {
|
||||
@@ -192,6 +184,8 @@ func sanitiseString(s string) string {
|
||||
if start < len(s) {
|
||||
buf.WriteString(s[start:])
|
||||
}
|
||||
|
||||
buf.WriteByte('"')
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
package xml2json
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// https://cswr.github.io/JsonSchema/spec/basic_types/
|
||||
// JSType is a JavaScript extracted from a string
|
||||
type JSType int
|
||||
|
||||
const (
|
||||
Bool JSType = iota
|
||||
Int
|
||||
Float
|
||||
String
|
||||
Null
|
||||
)
|
||||
|
||||
// Str2JSType extract a JavaScript type from a string
|
||||
func Str2JSType(s string) JSType {
|
||||
var (
|
||||
output JSType
|
||||
)
|
||||
s = strings.TrimSpace(s) // santize the given string
|
||||
switch {
|
||||
case isBool(s):
|
||||
output = Bool
|
||||
case isFloat(s):
|
||||
output = Float
|
||||
case isInt(s):
|
||||
output = Int
|
||||
case isNull(s):
|
||||
output = Null
|
||||
default:
|
||||
output = String // if all alternatives have been eliminated, the input is a string
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func isBool(s string) bool {
|
||||
return s == "true" || s == "false"
|
||||
}
|
||||
|
||||
func isFloat(s string) bool {
|
||||
var output = false
|
||||
if strings.Contains(s, ".") {
|
||||
_, err := strconv.ParseFloat(s, 64)
|
||||
if err == nil { // the string successfully converts to a decimal
|
||||
output = true
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func isInt(s string) bool {
|
||||
var output = false
|
||||
if len(s) >= 1 {
|
||||
_, err := strconv.Atoi(s)
|
||||
if err == nil { // the string successfully converts to an int
|
||||
if s != "0" && s[0] == '0' {
|
||||
// if the first rune is '0' and there is more than 1 rune, then the input is most likely a float or intended to be
|
||||
// a string value -- such as in the case of a guid, or an international phone number
|
||||
} else {
|
||||
output = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func isNull(s string) bool {
|
||||
return s == "null"
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
package xml2json
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type (
|
||||
// an plugin is added to an encoder or/and to an decoder to allow custom functionality at runtime
|
||||
plugin interface {
|
||||
AddToEncoder(*Encoder) *Encoder
|
||||
AddToDecoder(*Decoder) *Decoder
|
||||
}
|
||||
// a type converter overides the default string sanitization for encoding json
|
||||
encoderTypeConverter interface {
|
||||
Convert(string) string
|
||||
}
|
||||
// customTypeConverter converts strings to JSON types using a best guess approach, only parses the JSON types given
|
||||
// when initialized via WithTypeConverter
|
||||
customTypeConverter struct {
|
||||
parseTypes []JSType
|
||||
}
|
||||
|
||||
attrPrefixer string
|
||||
contentPrefixer string
|
||||
|
||||
excluder []string
|
||||
|
||||
nodesFormatter struct {
|
||||
list []nodeFormatter
|
||||
}
|
||||
nodeFormatter struct {
|
||||
path string
|
||||
plugin nodePlugin
|
||||
}
|
||||
|
||||
nodePlugin interface {
|
||||
AddTo(*Node)
|
||||
}
|
||||
|
||||
arrayFormatter struct{}
|
||||
)
|
||||
|
||||
// WithTypeConverter allows customized js type conversion behavior by passing in the desired JSTypes
|
||||
func WithTypeConverter(ts ...JSType) *customTypeConverter {
|
||||
return &customTypeConverter{parseTypes: ts}
|
||||
}
|
||||
|
||||
func (tc *customTypeConverter) parseAsString(t JSType) bool {
|
||||
if t == String {
|
||||
return true
|
||||
}
|
||||
for i := 0; i < len(tc.parseTypes); i++ {
|
||||
if tc.parseTypes[i] == t {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Adds the type converter to the encoder
|
||||
func (tc *customTypeConverter) AddToEncoder(e *Encoder) *Encoder {
|
||||
e.tc = tc
|
||||
return e
|
||||
}
|
||||
|
||||
func (tc *customTypeConverter) AddToDecoder(d *Decoder) *Decoder {
|
||||
return d
|
||||
}
|
||||
|
||||
func (tc *customTypeConverter) Convert(s string) string {
|
||||
// remove quotes if they exists
|
||||
if strings.HasPrefix(s, `"`) && strings.HasSuffix(s, `"`) {
|
||||
s = s[1 : len(s)-1]
|
||||
}
|
||||
jsType := Str2JSType(s)
|
||||
if tc.parseAsString(jsType) {
|
||||
// add the quotes removed at the start of this func
|
||||
s = `"` + s + `"`
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// WithAttrPrefix appends the given prefix to the json output of xml attribute fields to preserve namespaces
|
||||
func WithAttrPrefix(prefix string) *attrPrefixer {
|
||||
ap := attrPrefixer(prefix)
|
||||
return &ap
|
||||
}
|
||||
|
||||
func (a *attrPrefixer) AddToEncoder(e *Encoder) *Encoder {
|
||||
e.attributePrefix = string((*a))
|
||||
return e
|
||||
}
|
||||
|
||||
func (a *attrPrefixer) AddToDecoder(d *Decoder) *Decoder {
|
||||
d.attributePrefix = string((*a))
|
||||
return d
|
||||
}
|
||||
|
||||
// WithContentPrefix appends the given prefix to the json output of xml content fields to preserve namespaces
|
||||
func WithContentPrefix(prefix string) *contentPrefixer {
|
||||
c := contentPrefixer(prefix)
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c *contentPrefixer) AddToEncoder(e *Encoder) *Encoder {
|
||||
e.contentPrefix = string((*c))
|
||||
return e
|
||||
}
|
||||
|
||||
func (c *contentPrefixer) AddToDecoder(d *Decoder) *Decoder {
|
||||
d.contentPrefix = string((*c))
|
||||
return d
|
||||
}
|
||||
|
||||
// ExcludeAttributes excludes some xml attributes, for example, xmlns:xsi, xsi:noNamespaceSchemaLocation
|
||||
func ExcludeAttributes(attrs []string) *excluder {
|
||||
ex := excluder(attrs)
|
||||
return &ex
|
||||
}
|
||||
|
||||
func (ex *excluder) AddToEncoder(e *Encoder) *Encoder {
|
||||
return e
|
||||
}
|
||||
|
||||
func (ex *excluder) AddToDecoder(d *Decoder) *Decoder {
|
||||
d.ExcludeAttributes([]string((*ex)))
|
||||
return d
|
||||
}
|
||||
|
||||
// WithNodes formats specific nodes
|
||||
func WithNodes(n ...nodeFormatter) *nodesFormatter {
|
||||
return &nodesFormatter{list: n}
|
||||
}
|
||||
|
||||
func (nf *nodesFormatter) AddToEncoder(e *Encoder) *Encoder {
|
||||
return e
|
||||
}
|
||||
|
||||
func (nf *nodesFormatter) AddToDecoder(d *Decoder) *Decoder {
|
||||
d.AddFormatters(nf.list)
|
||||
return d
|
||||
}
|
||||
|
||||
func NodePlugin(path string, plugin nodePlugin) nodeFormatter {
|
||||
return nodeFormatter{path: path, plugin: plugin}
|
||||
}
|
||||
|
||||
func (nf *nodeFormatter) Format(node *Node) {
|
||||
child := node.GetChild(nf.path)
|
||||
if child != nil {
|
||||
nf.plugin.AddTo(child)
|
||||
}
|
||||
}
|
||||
|
||||
func ToArray() *arrayFormatter {
|
||||
return &arrayFormatter{}
|
||||
}
|
||||
|
||||
func (af *arrayFormatter) AddTo(n *Node) {
|
||||
n.ChildrenAlwaysAsArray = true
|
||||
}
|
||||
+24
-2
@@ -1,9 +1,14 @@
|
||||
package xml2json
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Node is a data element on a tree
|
||||
type Node struct {
|
||||
Children map[string]Nodes
|
||||
Data string
|
||||
Children map[string]Nodes
|
||||
Data string
|
||||
ChildrenAlwaysAsArray bool
|
||||
}
|
||||
|
||||
// Nodes is a list of nodes
|
||||
@@ -23,3 +28,20 @@ func (n *Node) AddChild(s string, c *Node) {
|
||||
func (n *Node) IsComplex() bool {
|
||||
return len(n.Children) > 0
|
||||
}
|
||||
|
||||
// GetChild returns child by path if exists. Path looks like "grandparent.parent.child.grandchild"
|
||||
func (n *Node) GetChild(path string) *Node {
|
||||
result := n
|
||||
names := strings.Split(path, ".")
|
||||
for _, name := range names {
|
||||
children, exists := result.Children[name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
if len(children) == 0 {
|
||||
return nil
|
||||
}
|
||||
result = children[0]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Vendored
+2
-2
@@ -199,7 +199,7 @@ github.com/aws/aws-sdk-go/service/sso/ssoiface
|
||||
github.com/aws/aws-sdk-go/service/sts
|
||||
github.com/aws/aws-sdk-go/service/sts/stsiface
|
||||
github.com/aws/aws-sdk-go/service/wafv2
|
||||
# github.com/basgys/goxml2json v1.1.0
|
||||
# github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313
|
||||
github.com/basgys/goxml2json
|
||||
# github.com/beevik/etree v1.1.0
|
||||
github.com/beevik/etree
|
||||
@@ -1234,7 +1234,7 @@ yunion.io/x/log/hooks
|
||||
yunion.io/x/ovsdb/cli_util
|
||||
yunion.io/x/ovsdb/schema/ovn_nb
|
||||
yunion.io/x/ovsdb/types
|
||||
# yunion.io/x/pkg v0.0.0-20211116020154-6a76ba2f7e97
|
||||
# yunion.io/x/pkg v0.0.0-20220227083757-28690b33ce38
|
||||
yunion.io/x/pkg/errors
|
||||
yunion.io/x/pkg/gotypes
|
||||
yunion.io/x/pkg/prettytable
|
||||
|
||||
+6
@@ -35,6 +35,7 @@ var SIZE_REG *regexp.Regexp
|
||||
var MONTH_REG *regexp.Regexp
|
||||
var DATE_REG *regexp.Regexp
|
||||
var DATE_COMPACT_REG *regexp.Regexp
|
||||
var DATE_EXCEL_REG *regexp.Regexp
|
||||
var ISO_TIME_REG *regexp.Regexp
|
||||
var ISO_NO_SECOND_TIME_REG *regexp.Regexp
|
||||
var FULLISO_TIME_REG *regexp.Regexp
|
||||
@@ -68,6 +69,7 @@ func init() {
|
||||
MONTH_REG = regexp.MustCompile(`^\d{4}-\d{2}$`)
|
||||
DATE_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}$`)
|
||||
DATE_COMPACT_REG = regexp.MustCompile(`^\d{8}$`)
|
||||
DATE_EXCEL_REG = regexp.MustCompile(`^\d{2}-\d{2}-\d{2}$`)
|
||||
ISO_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})$`)
|
||||
ISO_NO_SECOND_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(Z|[+-]\d{2}:\d{2})$`)
|
||||
FULLISO_TIME_REG = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3,9}(Z|[+-]\d{2}:\d{2})$`)
|
||||
@@ -192,6 +194,10 @@ func MatchDateCompact(str string) bool {
|
||||
return DATE_COMPACT_REG.MatchString(str)
|
||||
}
|
||||
|
||||
func MatchDateExcel(str string) bool {
|
||||
return DATE_EXCEL_REG.MatchString(str)
|
||||
}
|
||||
|
||||
func MatchZStackTime(str string) bool {
|
||||
return ZSTACK_TIME_REG.MatchString(str)
|
||||
}
|
||||
|
||||
+11
@@ -54,6 +54,7 @@ const (
|
||||
CompactTimeFormat = "20060102150405"
|
||||
DateFormat = "2006-01-02"
|
||||
ShortDateFormat = "20060102"
|
||||
DateExcelFormat = "01-02-06"
|
||||
MonthFormat = "2006-01"
|
||||
ShortMonthFormat = "200601"
|
||||
ZStackTimeFormat = "Jan 2, 2006 15:04:05 PM"
|
||||
@@ -101,6 +102,10 @@ func ShortDate(now time.Time) string {
|
||||
return Utcify(now).Format(ShortDateFormat)
|
||||
}
|
||||
|
||||
func DateExcelStr(now time.Time) string {
|
||||
return Utcify(now).Format(DateExcelFormat)
|
||||
}
|
||||
|
||||
func MonthStr(now time.Time) string {
|
||||
return Utcify(now).Format(MonthFormat)
|
||||
}
|
||||
@@ -187,6 +192,10 @@ func ParseShortDate(str string) (time.Time, error) {
|
||||
return time.Parse(ShortDateFormat, str)
|
||||
}
|
||||
|
||||
func ParseDateExcel(str string) (time.Time, error) {
|
||||
return time.Parse(DateExcelFormat, str)
|
||||
}
|
||||
|
||||
func ParseZStackDate(str string) (time.Time, error) {
|
||||
return time.ParseInLocation(ZStackTimeFormat, str, time.Local)
|
||||
}
|
||||
@@ -219,6 +228,8 @@ func ParseTimeStr(str string) (time.Time, error) {
|
||||
return ParseDate(str)
|
||||
} else if regutils.MatchDateCompact(str) {
|
||||
return ParseShortDate(str)
|
||||
} else if regutils.MatchDateExcel(str) {
|
||||
return ParseDateExcel(str)
|
||||
} else if regutils.MatchZStackTime(str) {
|
||||
return ParseZStackDate(str)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user