diff --git a/cmd/bingocli/main.go b/cmd/bingocli/main.go index b29b63558..573a38491 100644 --- a/cmd/bingocli/main.go +++ b/cmd/bingocli/main.go @@ -96,12 +96,11 @@ func newClient(options *BaseOptions) (*bingocloud.SRegion, error) { options.Endpoint, options.AccessKey, options.SecretKey, - ).Debug(options.Debug). - CloudproviderConfig( - cloudprovider.ProviderConfig{ - ProxyFunc: proxyFunc, - }, - ), + ).Debug(options.Debug).SetCloudproviderConfig( + cloudprovider.ProviderConfig{ + ProxyFunc: proxyFunc, + }, + ), ) if err != nil { return nil, err diff --git a/pkg/multicloud/bingocloud/account.go b/pkg/multicloud/bingocloud/account.go index 3a37f6485..49ef04a78 100644 --- a/pkg/multicloud/bingocloud/account.go +++ b/pkg/multicloud/bingocloud/account.go @@ -1,12 +1,63 @@ package bingocloud +import ( + "crypto/aes" + "crypto/cipher" + "encoding/base64" + "fmt" + "unicode/utf8" +) + type SAccount struct { - AccessKeyId string - SecretAccessKey string - Arn string - DeptId string - DeptName string - IsEncrypted string - UserId string - UserName string + Id string `json:"Id"` + AccessKeyId string `json:"AccessKeyId"` + Arn string `json:"Arn"` + FullName string `json:"FullName"` + IsAdmin string `json:"IsAdmin"` + IsEncrypted string `json:"IsEncrypted"` + SecurityKey string `json:"SecurityKey"` + Status string `json:"Status"` + Type string `json:"Type"` + UserId string `json:"UserId"` + UserName string `json:"UserName"` +} + +func (self *SAccount) decryptKeys(masterSecretKey string) (string, string) { + if len(self.SecurityKey) == len(masterSecretKey) { + return self.AccessKeyId, self.SecurityKey + } + + secretKeyBytes, err := base64.StdEncoding.DecodeString(self.SecurityKey) + if err != nil { + return "", "" + } + var adminSecretKey = "" + if len(masterSecretKey) >= 32 { + adminSecretKey = masterSecretKey[0:32] + } else { + adminSecretKey = fmt.Sprintf("%s%032s", masterSecretKey, "")[0:32] + } + decryptVal, err := aesCrtCrypt([]byte(secretKeyBytes), []byte(adminSecretKey), make([]byte, 16)) + if err != nil { + return "", "" + } + + decryptSecret := fmt.Sprintf("%s", decryptVal) + + if !utf8.ValidString(decryptSecret) { + return self.AccessKeyId, self.SecurityKey + } + + return self.AccessKeyId, decryptSecret +} + +func aesCrtCrypt(val, key, iv []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + blockMode := cipher.NewCTR(block, iv) + body := make([]byte, len(val)) + blockMode.XORKeyStream(body, val) + return body, nil } diff --git a/pkg/multicloud/bingocloud/bingo.go b/pkg/multicloud/bingocloud/bingo.go index 404fbf820..e6274c9d5 100644 --- a/pkg/multicloud/bingocloud/bingo.go +++ b/pkg/multicloud/bingocloud/bingo.go @@ -45,6 +45,16 @@ const ( MAX_RESULT = 20 ) +var ( + ManagerActions = []string{ + "DescribeNodes", + "DescribePhysicalHosts", + "DescribeClusters", + "DescribeAvailabilityZones", + "DescribeStorages", + } +) + type BingoCloudConfig struct { cpcfg cloudprovider.ProviderConfig endpoint string @@ -63,11 +73,15 @@ func NewBingoCloudClientConfig(endpoint, accessKey, secretKey string) *BingoClou return cfg } -func (cfg *BingoCloudConfig) CloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *BingoCloudConfig { +func (cfg *BingoCloudConfig) SetCloudproviderConfig(cpcfg cloudprovider.ProviderConfig) *BingoCloudConfig { cfg.cpcfg = cpcfg return cfg } +func (cfg *BingoCloudConfig) GetCloudproviderConfig() cloudprovider.ProviderConfig { + return cfg.cpcfg +} + func (cfg *BingoCloudConfig) Debug(debug bool) *BingoCloudConfig { cfg.debug = debug return cfg @@ -77,23 +91,31 @@ type SBingoCloudClient struct { *BingoCloudConfig regions []SRegion + + managerClient *SBingoCloudClient + + user string } func NewBingoCloudClient(cfg *BingoCloudConfig) (*SBingoCloudClient, error) { client := &SBingoCloudClient{BingoCloudConfig: cfg} - var err error - client.regions, err = client.GetRegions() - if err != nil { - return nil, err - } - for i := range client.regions { - client.regions[i].client = client + client.regions, _ = client.GetRegions() + if client.regions != nil { + for i := range client.regions { + client.regions[i].client = client + } } + client.user = client.getAccountUser() return client, nil } +func (self *SBingoCloudClient) SetManagerClient(client *SBingoCloudClient) { + self.regions = client.regions + self.managerClient = client +} + func (self *SBingoCloudClient) GetAccountId() string { - return self.endpoint + return self.accessKey } func (self *SBingoCloudClient) GetRegion(id string) (*SRegion, error) { @@ -296,13 +318,28 @@ func (self *SBingoCloudClient) GetSubAccounts() ([]cloudprovider.SSubAccount, er } _ = result.Unmarshal(&tags, "tagSet") - var subAccounts []cloudprovider.SSubAccount + var subAccounts = []cloudprovider.SSubAccount{{ + Id: self.getAccountUser(), + Account: self.accessKey, + Secret: self.secretKey, + Name: self.cpcfg.Name, + HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL, + }} + for i := range tags { + account, err := self.listAccessKeys(tags[i].ResourceId) + if err != nil { + continue + } + ak, sk := account.decryptKeys(self.secretKey) subAccount := cloudprovider.SSubAccount{ - Account: self.accessKey, - Name: tags[i].ResourceId, - DefaultProjectId: tags[i].Value, + Id: account.UserId, + Name: account.UserName, HealthStatus: api.CLOUD_PROVIDER_HEALTH_NORMAL, + Account: ak, + Secret: sk, + IsSubAccount: true, + DefaultProjectId: tags[i].Value, } subAccounts = append(subAccounts, subAccount) } @@ -310,42 +347,7 @@ func (self *SBingoCloudClient) GetSubAccounts() ([]cloudprovider.SSubAccount, er } func (self *SBingoCloudClient) GetEnrollmentAccounts() ([]cloudprovider.SEnrollmentAccount, error) { - params := map[string]string{"Marker": "", "MaxItems": "1000", "AccountName": "paas_app"} - var result struct { - IsTruncated string - Marker string `json:"marker,omitempty"` - Users struct { - Member *SAccount `json:"member,omitempty"` - } - } - var eas []cloudprovider.SEnrollmentAccount - for { - resp, err := self.invoke("ListAccounts", params) - if err != nil { - return nil, err - } - err = resp.Unmarshal(&result, "ListAccountsResult") - if err != nil { - return nil, err - } - ea := cloudprovider.SEnrollmentAccount{ - Id: result.Users.Member.UserId, - Name: result.Users.Member.UserName, - } - eas = append(eas, ea) - //for _, user := range result.Users.Member { - // ea := cloudprovider.SEnrollmentAccount{ - // Id: user.UserId, - // Name: user.UserName, - // } - // eas = append(eas, ea) - //} - if params["Marker"] == result.Marker { - break - } - params["Marker"] = result.Marker - } - return eas, nil + return nil, nil } func (self *SBingoCloudClient) GetIRegions() []cloudprovider.ICloudRegion { @@ -357,6 +359,44 @@ func (self *SBingoCloudClient) GetIRegions() []cloudprovider.ICloudRegion { return ret } +func (self *SBingoCloudClient) listAccessKeys(userName string) (*SAccount, error) { + params := map[string]string{"Marker": "", "MaxItems": "1000", "UserName": userName} + + resp, err := self.managerClient.invoke("ListAccessKeys", params) + if err != nil { + return nil, err + } + + var account *SAccount + err = resp.Unmarshal(&account, "ListAccessKeysResult", "AccessKeyMetadata", "member") + if err != nil { + return nil, err + } + + return account, nil +} + +func (self *SBingoCloudClient) getAccountUser() string { + quotas, err := self.getQuotas() + if err != nil { + return "" + } + ownerId := "" + if len(quotas) > 0 { + ownerId = quotas[0].OwnerId + } + return ownerId +} + +func (self *SBingoCloudClient) getQuotas() ([]SQuotas, error) { + resp, err := self.invoke("DescribeQuotas", nil) + if err != nil { + return nil, err + } + var ret []SQuotas + return ret, resp.Unmarshal(&ret, "quotaSet") +} + func (self *SBingoCloudClient) describeTags(filter map[string]string) (jsonutils.JSONObject, error) { params := map[string]string{"MaxResults": "10000"} i := 1 diff --git a/pkg/multicloud/bingocloud/disk.go b/pkg/multicloud/bingocloud/disk.go index 69ac7e922..4a48013b3 100644 --- a/pkg/multicloud/bingocloud/disk.go +++ b/pkg/multicloud/bingocloud/disk.go @@ -19,6 +19,7 @@ import ( "fmt" "strconv" + "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" api "yunion.io/x/cloudmux/pkg/apis/compute" @@ -60,6 +61,8 @@ type SDisk struct { StorageId string `json:"storageId"` VolumeId string `json:"volumeId"` VolumeName string `json:"volumeName"` + + ImageId string `json:"imageId"` } func (self *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) { @@ -118,7 +121,13 @@ func (self *SDisk) GetIsAutoDelete() bool { } func (self *SDisk) GetTemplateId() string { - return "" + if self.ImageId == "" && len(self.AttachmentSet) > 0 { + instances, _, _ := self.storage.cluster.region.GetInstances(self.AttachmentSet[0].InstanceId, "", 1, "") + if instances != nil { + self.ImageId = instances[0].InstancesSet.ImageId + } + } + return self.ImageId } func (self *SDisk) GetDiskType() string { @@ -187,6 +196,14 @@ func (self *SDisk) Rebuild(ctx context.Context) error { return cloudprovider.ErrNotImplemented } +func (self *SDisk) Refresh() error { + newDisk, err := self.storage.cluster.region.GetDisk(self.GetGlobalId()) + if err != nil { + return err + } + return jsonutils.Update(self, &newDisk) +} + func (self *SDisk) GetStatus() string { switch self.Status { case "available", "in-use": @@ -203,6 +220,10 @@ func (self *SRegion) GetDisks(id string, maxResult int, nextToken string) ([]SDi params[fmt.Sprintf("Filter.%d.Name", idx)] = "volume-id" params[fmt.Sprintf("Filter.%d.Value.1", idx)] = id idx++ + } else { + params[fmt.Sprintf("Filter.%d.Name", idx)] = "owner-id" + params[fmt.Sprintf("Filter.%d.Value.1", idx)] = self.client.user + idx++ } if len(nextToken) > 0 { @@ -277,7 +298,7 @@ func (self *SRegion) GetDisk(id string) (*SDisk, error) { func (self *SStorage) CreateIDisk(conf *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) { params := map[string]string{} params["VolumeName"] = conf.Name - params["AvailabilityZone"] = self.cluster.ClusterId + params["AvailabilityZone"] = conf.ZoneId params["Size"] = strconv.Itoa(conf.SizeGb) resp, err := self.cluster.region.invoke("CreateVolume", params) @@ -286,6 +307,7 @@ func (self *SStorage) CreateIDisk(conf *cloudprovider.DiskCreateConfig) (cloudpr } ret := &SDisk{} _ = resp.Unmarshal(&ret) + ret.storage = self return ret, nil } diff --git a/pkg/multicloud/bingocloud/image.go b/pkg/multicloud/bingocloud/image.go index 1433c66ab..d418e899d 100644 --- a/pkg/multicloud/bingocloud/image.go +++ b/pkg/multicloud/bingocloud/image.go @@ -197,6 +197,11 @@ func (self *SRegion) GetImages(id, nextToken string) ([]SImage, string, error) { if len(nextToken) > 0 { params["NextToken"] = nextToken } + //idx := 1 + //params[fmt.Sprintf("Filter.%d.Name", idx)] = "owner-id" + //params[fmt.Sprintf("Filter.%d.Value.1", idx)] = self.client.user + //idx++ + resp, err := self.invoke("DescribeImages", params) if err != nil { return nil, "", err @@ -250,7 +255,8 @@ func (self *SStoragecache) GetIImageById(id string) (cloudprovider.ICloudImage, return nil, err } for i := range images { - if images[i].GetGlobalId() == id && images[i].StorageId == self.storageId { + // && images[i].StorageId == self.storageId + if images[i].GetGlobalId() == id { images[i].cache = self return &images[i], nil } diff --git a/pkg/multicloud/bingocloud/instance.go b/pkg/multicloud/bingocloud/instance.go index 791d984f4..8cbd4b999 100644 --- a/pkg/multicloud/bingocloud/instance.go +++ b/pkg/multicloud/bingocloud/instance.go @@ -180,6 +180,19 @@ func (self *SInstance) DeployVM(ctx context.Context, name string, username strin return self.node.cluster.region.modifyInstanceAttribute(self.InstancesSet.InstanceId, attrs) } +func (self *SInstance) LiveMigrateVM(hostid string) error { + return self.MigrateVM(hostid) +} + +func (self *SInstance) MigrateVM(hostid string) error { + params := map[string]string{} + params["InstanceId"] = self.InstancesSet.InstanceId + params["ToNodeId"] = hostid + + _, err := self.node.cluster.region.invoke("MigrateInstance", params) + return err +} + func (self *SInstance) DeleteVM(ctx context.Context) error { params := map[string]string{} params["InstanceId.1"] = self.InstancesSet.InstanceId @@ -286,6 +299,7 @@ func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) { if err != nil { return nil, err } + disk.ImageId = self.InstancesSet.ImageId storage, ok := storageMaps[disk.StorageId] if ok { storage.cluster = self.node.cluster @@ -496,7 +510,7 @@ func (self *SRegion) GetInstances(id, nodeId string, maxResult int, nextToken st } idx := 1 - if len(nodeId) > 0 { + if len(nodeId) > 0 && len(id) == 0 { params[fmt.Sprintf("Filter.%d.Name", idx)] = "node-id" params[fmt.Sprintf("Filter.%d.Value.1", idx)] = nodeId idx++ @@ -506,6 +520,10 @@ func (self *SRegion) GetInstances(id, nodeId string, maxResult int, nextToken st params[fmt.Sprintf("Filter.%d.Name", idx)] = "instance-id" params[fmt.Sprintf("Filter.%d.Value.1", idx)] = id idx++ + } else { + params[fmt.Sprintf("Filter.%d.Name", idx)] = "owner-id" + params[fmt.Sprintf("Filter.%d.Value.1", idx)] = self.client.user + idx++ } resp, err := self.invoke("DescribeInstances", params) @@ -527,7 +545,7 @@ func (self *SRegion) modifyInstanceAttribute(instanceId string, attrs map[string for key, value := range attrs { params["Attribute"] = key params["Value"] = value - _, err := self.client.invoke("ModifyInstanceAttribute", params) + _, err := self.invoke("ModifyInstanceAttribute", params) if err != nil { return err } diff --git a/pkg/multicloud/bingocloud/instance_snapshot.go b/pkg/multicloud/bingocloud/instance_snapshot.go index 076485659..cec5c0d19 100644 --- a/pkg/multicloud/bingocloud/instance_snapshot.go +++ b/pkg/multicloud/bingocloud/instance_snapshot.go @@ -87,7 +87,7 @@ func (self *SRegion) createInstanceSnapshot(instanceId, name string, desc string params["Description"] = desc params["DiskOnly"] = "false" - resp, err := self.client.invoke("CreateInstanceSnapshot", params) + resp, err := self.invoke("CreateInstanceSnapshot", params) if err != nil { return "", err } @@ -106,7 +106,7 @@ func (self *SRegion) getInstanceSnapshots(instanceId, snapshotId string) ([]SIns params["InstanceSnapshotId.1"] = snapshotId } - resp, err := self.client.invoke("DescribeInstanceSnapshots", params) + resp, err := self.invoke("DescribeInstanceSnapshots", params) if err != nil { return nil, err } @@ -120,20 +120,20 @@ func (self *SRegion) getInstanceSnapshots(instanceId, snapshotId string) ([]SIns func (self *SRegion) deleteInstanceSnapshot(id string) error { params := map[string]string{} params["InstanceSnapshotId.1"] = id - _, err := self.client.invoke("DeleteInstanceSnapshots", params) + _, err := self.invoke("DeleteInstanceSnapshots", params) return err } func (self *SRegion) revertInstanceSnapshot(id string) error { params := map[string]string{} params["InstanceSnapshotId.1"] = id - _, err := self.client.invoke("RevertInstanceSnapshot", params) + _, err := self.invoke("RevertInstanceSnapshot", params) return err } func (self *SRegion) deleteInstanceBackup(id string) error { params := map[string]string{} params["BackupId"] = id - _, err := self.client.invoke("DeleteInstanceBackup", params) + _, err := self.invoke("DeleteInstanceBackup", params) return err } diff --git a/pkg/multicloud/bingocloud/monitor.go b/pkg/multicloud/bingocloud/monitor.go index db2afac94..097d4ebca 100644 --- a/pkg/multicloud/bingocloud/monitor.go +++ b/pkg/multicloud/bingocloud/monitor.go @@ -58,7 +58,7 @@ func (self *SBingoCloudClient) DescribeMetricList(ns, metricNm, dimensionName, d params["EndTime"] = until.UTC().Format(time.RFC3339) params["Statistics.member.1"] = "Average" params["Period"] = "60" - resp, err := self.invoke("GetMetricStatistics", params) + resp, err := self.managerClient.invoke("GetMetricStatistics", params) if err != nil { return nil, errors.Wrap(err, "GetMetricStatistics err") } @@ -84,15 +84,16 @@ func (self *SBingoCloudClient) GetEcsMetrics(opts *cloudprovider.MetricListOptio var ret []cloudprovider.MetricValues for metricType, metricName := range map[cloudprovider.TMetricType]string{ cloudprovider.VM_METRIC_TYPE_CPU_USAGE: "CPUUtilization", - cloudprovider.VM_METRIC_TYPE_MEM_USAGE: "MemoryUsage", + cloudprovider.VM_METRIC_TYPE_MEM_USAGE: "MemeryUsage", cloudprovider.VM_METRIC_TYPE_NET_BPS_RX: "NetworkIn", cloudprovider.VM_METRIC_TYPE_NET_BPS_TX: "NetworkOut", cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_BPS: "DiskReadBytes", cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_BPS: "DiskWriteBytes", cloudprovider.VM_METRIC_TYPE_DISK_IO_READ_IOPS: "DiskReadOps", cloudprovider.VM_METRIC_TYPE_DISK_IO_WRITE_IOPS: "DiskWriteOps", + cloudprovider.VM_METRIC_TYPE_DISK_USAGE: "DiskUsage", } { - data, err := self.DescribeMetricList("AWS/EC2", metricName, "InstanceId", opts.ResourceId, opts.StartTime, opts.EndTime) + data, err := self.managerClient.DescribeMetricList("AWS/EC2", metricName, "InstanceId", opts.ResourceId, opts.StartTime, opts.EndTime) if err != nil { log.Errorf("DescribeMetricList error: %v", err) continue @@ -123,7 +124,7 @@ func (self *SBingoCloudClient) GetHostMetrics(opts *cloudprovider.MetricListOpti cloudprovider.HOST_METRIC_TYPE_DISK_IO_READ_IOPS: "DiskReadOps", cloudprovider.HOST_METRIC_TYPE_DISK_IO_WRITE_IOPS: "DiskWriteOps", } { - data, err := self.DescribeMetricList("AWS/HOST", metricName, "HostId", opts.ResourceId, opts.StartTime, opts.EndTime) + data, err := self.managerClient.DescribeMetricList("AWS/HOST", metricName, "HostId", opts.ResourceId, opts.StartTime, opts.EndTime) if err != nil { log.Errorf("DescribeMetricList error: %v", err) continue diff --git a/pkg/multicloud/bingocloud/provider/provider.go b/pkg/multicloud/bingocloud/provider/provider.go index daa3fb7ae..4292f4fd8 100644 --- a/pkg/multicloud/bingocloud/provider/provider.go +++ b/pkg/multicloud/bingocloud/provider/provider.go @@ -78,11 +78,25 @@ func (self *SBingoCloudProviderFactory) GetProvider(cfg cloudprovider.ProviderCo client, err := bingocloud.NewBingoCloudClient( bingocloud.NewBingoCloudClientConfig( cfg.URL, cfg.Account, cfg.Secret, - ).CloudproviderConfig(cfg), + ).SetCloudproviderConfig(cfg), ) if err != nil { return nil, err } + client.SetManagerClient(client) + + if cfg.ManagerProviderConfig != nil { + managerClient, err := bingocloud.NewBingoCloudClient( + bingocloud.NewBingoCloudClientConfig( + cfg.ManagerProviderConfig.URL, cfg.ManagerProviderConfig.Account, cfg.ManagerProviderConfig.Secret, + ).SetCloudproviderConfig(*cfg.ManagerProviderConfig), + ) + if err != nil { + return nil, err + } + client.SetManagerClient(managerClient) + } + return &SBingoCloudProvider{ SBaseProvider: cloudprovider.NewBaseProvider(self), client: client, @@ -107,6 +121,14 @@ type SBingoCloudProvider struct { client *bingocloud.SBingoCloudClient } +func (self *SBingoCloudProvider) GetProviderConfig() cloudprovider.ProviderConfig { + return self.client.GetCloudproviderConfig() +} + +func (self *SBingoCloudProvider) SetProviderConfig(cfg cloudprovider.ProviderConfig) { + self.client.SetCloudproviderConfig(cfg) +} + func (self *SBingoCloudProvider) GetSysInfo() (jsonutils.JSONObject, error) { return jsonutils.NewDict(), nil } diff --git a/pkg/multicloud/bingocloud/quotas.go b/pkg/multicloud/bingocloud/quotas.go index cb2319ea6..03fcece01 100644 --- a/pkg/multicloud/bingocloud/quotas.go +++ b/pkg/multicloud/bingocloud/quotas.go @@ -8,12 +8,3 @@ type SQuotas struct { HardLimit int InUse int } - -func (self *SRegion) GetQuotas() ([]SQuotas, error) { - resp, err := self.invoke("DescribeQuotas", nil) - if err != nil { - return nil, err - } - var ret []SQuotas - return ret, resp.Unmarshal(&ret, "quotaSet") -} diff --git a/pkg/multicloud/bingocloud/region.go b/pkg/multicloud/bingocloud/region.go index 5f0a05a3d..03ffd187e 100644 --- a/pkg/multicloud/bingocloud/region.go +++ b/pkg/multicloud/bingocloud/region.go @@ -19,6 +19,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" + "yunion.io/x/pkg/utils" api "yunion.io/x/cloudmux/pkg/apis/compute" "yunion.io/x/cloudmux/pkg/cloudprovider" @@ -79,23 +80,14 @@ func (self *SRegion) GetCloudEnv() string { return "" } -func (self *SRegion) getAccountUser() string { - quotas, err := self.GetQuotas() - if err != nil { - return "" - } - ownerId := "" - if len(quotas) > 0 { - ownerId = quotas[0].OwnerId - } - return ownerId -} - func (self *SRegion) GetGeographicInfo() cloudprovider.SGeographicInfo { return cloudprovider.SGeographicInfo{} } func (self *SRegion) invoke(action string, params map[string]string) (jsonutils.JSONObject, error) { + if utils.IsInStringArray(action, ManagerActions) { + return self.client.managerClient.invoke(action, params) + } return self.client.invoke(action, params) } @@ -108,6 +100,10 @@ func (self *SBingoCloudClient) GetRegions() ([]SRegion, error) { return ret, resp.Unmarshal(&ret, "regionInfo") } +func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) { + return self.GetDisk(id) +} + func (self *SRegion) GetIStorageById(id string) (cloudprovider.ICloudStorage, error) { storages, err := self.getStorages() if err != nil { @@ -161,6 +157,28 @@ func (self *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStorag return nil, errors.Wrapf(cloudprovider.ErrNotFound, id) } +func (self *SRegion) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) { + part, nextToken, err := self.GetSecurityGroups("", "", "") + if err != nil { + return nil, err + } + var groups []SSecurityGroup + groups = append(groups, part...) + for len(nextToken) > 0 { + part, nextToken, err = self.GetSecurityGroups("", "", nextToken) + if err != nil { + return nil, err + } + groups = append(groups, part...) + } + var ret []cloudprovider.ICloudSecurityGroup + for i := range groups { + groups[i].region = self + ret = append(ret, &groups[i]) + } + return ret, nil +} + func (self *SRegion) GetIHosts() ([]cloudprovider.ICloudHost, error) { zones, err := self.GetIZones() if err != nil { diff --git a/pkg/multicloud/bingocloud/securitygroup.go b/pkg/multicloud/bingocloud/securitygroup.go index ec95efa1c..3cb480fd6 100644 --- a/pkg/multicloud/bingocloud/securitygroup.go +++ b/pkg/multicloud/bingocloud/securitygroup.go @@ -16,6 +16,7 @@ package bingocloud import ( "encoding/json" + "fmt" "strings" "yunion.io/x/log" @@ -200,20 +201,26 @@ func (self *SRegion) addSecurityGroupRules(secGrpId string, rule cloudprovider.S func (self *SRegion) GetSecurityGroups(id, name, nextToken string) ([]SSecurityGroup, string, error) { params := map[string]string{} - params["Filter.1.Name"] = "owner-id" - params["Filter.1.Value.1"] = self.getAccountUser() if len(id) > 0 { params["GroupId.1"] = id } - if len(name) > 0 { - params["Filter.2.Name"] = "group-name" - params["Filter.2.Value.1"] = name - } + if len(nextToken) > 0 { params["NextToken"] = nextToken } + idx := 1 + if len(name) > 0 { + params[fmt.Sprintf("Filter.%d.Name", idx)] = "group-name" + params[fmt.Sprintf("Filter.%d.Value.1", idx)] = name + idx++ + } + + params[fmt.Sprintf("Filter.%d.Name", idx)] = "owner-id" + params[fmt.Sprintf("Filter.%d.Value.1", idx)] = self.client.user + idx++ + resp, err := self.invoke("DescribeSecurityGroups", params) if err != nil { return nil, "", err @@ -266,6 +273,10 @@ func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreat params := map[string]string{} if len(conf.Name) > 0 { params["GroupName"] = conf.Name + existSecgroups, _, _ := self.GetSecurityGroups("", conf.Name, "") + if len(existSecgroups) > 0 { + return &existSecgroups[0], nil + } } resp, err := self.invoke("CreateSecurityGroup", params) if err != nil { @@ -276,24 +287,6 @@ func (self *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreat _ = resp.Unmarshal(&ret) if ret.Return { - //rule := cloudprovider.SecurityRule{ - // ExternalId: ret.GroupId, - // SecurityRule: secrules.SecurityRule{ - // Action: secrules.SecurityRuleAllow, - // Protocol: secrules.PROTO_ANY, - // Direction: secrules.DIR_IN, - // Priority: 1, - // Ports: []int{}, - // PortStart: 1, - // PortEnd: 65535, - // }, - //} - //rule.ParseCIDR("0.0.0.0/0") - //err = self.addSecurityGroupRules(ret.GroupId, rule) - //if err != nil { - // _ = self.deleteSecurityGroup(ret.GroupId) - // return nil, err - //} return self.GetISecurityGroupById(ret.GroupId) } diff --git a/pkg/multicloud/bingocloud/snapshot.go b/pkg/multicloud/bingocloud/snapshot.go index d515aaa84..571cdcdf9 100644 --- a/pkg/multicloud/bingocloud/snapshot.go +++ b/pkg/multicloud/bingocloud/snapshot.go @@ -54,7 +54,8 @@ func (self SSnapshot) Refresh() error { return err } if len(newSnapshot) == 1 { - return jsonutils.Update(self, &newSnapshot[0]) + newSnapshot[0].region = self.region + return jsonutils.Update(&self, newSnapshot[0]) } return cloudprovider.ErrNotFound } @@ -105,7 +106,7 @@ func (self *SRegion) createSnapshot(volumeId, name string, desc string) (string, params["SnapshotName"] = name params["Description"] = desc - resp, err := self.client.invoke("CreateSnapshot", params) + resp, err := self.invoke("CreateSnapshot", params) if err != nil { return "", err } @@ -124,7 +125,7 @@ func (self *SRegion) getSnapshots(id, name string) ([]SSnapshot, error) { params["Filter.1.Name"] = name } - resp, err := self.client.invoke("DescribeSnapshots", params) + resp, err := self.invoke("DescribeSnapshots", params) if err != nil { return nil, err } @@ -138,6 +139,6 @@ func (self *SRegion) getSnapshots(id, name string) ([]SSnapshot, error) { func (self *SRegion) deleteSnapshot(id string) error { params := map[string]string{} params["SnapshotId"] = id - _, err := self.client.invoke("DeleteSnapshot", params) + _, err := self.invoke("DeleteSnapshot", params) return err } diff --git a/pkg/multicloud/bingocloud/vpc.go b/pkg/multicloud/bingocloud/vpc.go index 6f33035e8..52af060d6 100644 --- a/pkg/multicloud/bingocloud/vpc.go +++ b/pkg/multicloud/bingocloud/vpc.go @@ -15,6 +15,8 @@ package bingocloud import ( + "fmt" + "yunion.io/x/pkg/errors" api "yunion.io/x/cloudmux/pkg/apis/compute" @@ -68,6 +70,10 @@ func (self *SVpc) GetCidrBlock() string { return self.CidrBlock } +func (self *SVpc) IsPublic() bool { + return self.Shared == "true" +} + func (self *SVpc) GetIRouteTableById(id string) (cloudprovider.ICloudRouteTable, error) { return nil, cloudprovider.ErrNotImplemented } @@ -115,19 +121,37 @@ func (self *SVpc) GetStatus() string { } } +func (self *SRegion) GetIVpcById(id string) (cloudprovider.ICloudVpc, error) { + vpcs, err := self.GetIVpcs() + if err != nil { + return nil, err + } + for i := range vpcs { + if vpcs[i].GetGlobalId() == id { + return vpcs[i], nil + } + } + return nil, cloudprovider.ErrNotFound +} + func (self *SRegion) GetVpcs(id string) ([]SVpc, error) { params := map[string]string{} if len(id) > 0 { params["VpcId"] = id } + idx := 1 + params[fmt.Sprintf("Filter.%d.Name", idx)] = "owner-id" + params[fmt.Sprintf("Filter.%d.Value.1", idx)] = self.client.user + idx++ resp, err := self.invoke("DescribeVpcs", params) if err != nil { return nil, err } var vpcs []SVpc + resp.Unmarshal(&vpcs, "vpcSet") - return vpcs, resp.Unmarshal(&vpcs, "vpcSet") + return vpcs, nil } func (self *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {