feat(region): support bingocloud sync

This commit is contained in:
ioito
2022-03-01 20:24:04 +08:00
parent 6b8c4147b6
commit 885faa5020
43 changed files with 3147 additions and 203 deletions
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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=
+13 -6
View File
@@ -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, &regions)
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, &regions)
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
+26
View File
@@ -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())
}
+1 -1
View File
@@ -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")
}
+1 -1
View File
@@ -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"`
+107 -19
View File
@@ -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,
}
}
+247
View File
@@ -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)
}
+40
View File
@@ -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
}
+264
View File
@@ -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
}
+225
View File
@@ -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)
}
+307 -101
View File
@@ -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
}
+113
View File
@@ -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
}
+199
View File
@@ -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()
}
+131 -8
View File
@@ -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)
}
+190
View File
@@ -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
}
+35
View File
@@ -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
})
}
+35
View File
@@ -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
})
}
+34
View File
@@ -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
})
}
+35
View File
@@ -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
})
}
+10 -11
View File
@@ -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
})
}
+34
View File
@@ -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
})
}
+33
View File
@@ -0,0 +1,33 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package 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
})
}
+173
View File
@@ -0,0 +1,173 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package 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
}
+71
View File
@@ -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
}
+142
View File
@@ -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
}
+94
View File
@@ -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
}
+95
View File
@@ -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)
}
+23
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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 {