fix(region): vendor update (#23398)

This commit is contained in:
屈轩
2025-09-26 18:05:24 +08:00
committed by GitHub
parent e67f8392a7
commit 85ad508d83
28 changed files with 1641 additions and 260 deletions
+1 -1
View File
@@ -95,7 +95,7 @@ require (
k8s.io/cri-api v0.22.17
k8s.io/klog/v2 v2.20.0
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926060637-3dea34e8fa4e
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926093134-932d0643fbc0
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
+2 -2
View File
@@ -1411,8 +1411,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926060637-3dea34e8fa4e h1:ZiXgmtdPInE7vSgYqU1/PeFikCKQahLew1EueuEoWog=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926060637-3dea34e8fa4e/go.mod h1:R5iP/4nGCluuekoa30B5hM/49IfPpGHXwFK3yT7m6Vw=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926093134-932d0643fbc0 h1:Tz+EbZ2QUrvOOBYdAx2zY2cUv0SwOQX4UJX9pDOdjhI=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926093134-932d0643fbc0/go.mod h1:R5iP/4nGCluuekoa30B5hM/49IfPpGHXwFK3yT7m6Vw=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
+6
View File
@@ -141,6 +141,12 @@ const (
STORAGE_BAIDU_ENHANCED_SSD_PL2 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL2
STORAGE_BAIDU_ENHANCED_SSD_PL3 = compute.STORAGE_BAIDU_ENHANCED_SSD_PL3
STORAGE_KSYUN_SSD3_0 = compute.STORAGE_KSYUN_SSD3_0
STORAGE_KSYUN_EHDD = compute.STORAGE_KSYUN_EHDD
STORAGE_KSYUN_ESSD_PL1 = compute.STORAGE_KSYUN_ESSD_PL1
STORAGE_KSYUN_ESSD_PL2 = compute.STORAGE_KSYUN_ESSD_PL2
STORAGE_KSYUN_ESSD_PL3 = compute.STORAGE_KSYUN_ESSD_PL3
// zettakit
STORAGE_ZETTAKIT_NORMAL = compute.STORAGE_ZETTAKIT_NORMAL
+72 -5
View File
@@ -15,9 +15,12 @@
package guestdrivers
import (
"fmt"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/pkg/util/billing"
"yunion.io/x/pkg/util/rbacscope"
"yunion.io/x/pkg/utils"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
@@ -50,6 +53,51 @@ func (self *SKsyunGuestDriver) GetMinimalSysDiskSizeGb() int {
return 20
}
func (self *SKsyunGuestDriver) GetStorageTypes() []string {
return []string{
api.STORAGE_KSYUN_SSD3_0,
api.STORAGE_KSYUN_EHDD,
api.STORAGE_KSYUN_ESSD_PL1,
api.STORAGE_KSYUN_ESSD_PL2,
api.STORAGE_KSYUN_ESSD_PL3,
}
}
func (self *SKsyunGuestDriver) ChooseHostStorage(host *models.SHost, guest *models.SGuest, diskConfig *api.DiskConfig, storageIds []string) (*models.SStorage, error) {
return chooseHostStorage(self, host, diskConfig.Backend, storageIds), nil
}
func (self *SKsyunGuestDriver) GetDetachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SKsyunGuestDriver) GetAttachDiskStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SKsyunGuestDriver) IsAllowSaveImageOnRunning() bool {
return true
}
func (self *SKsyunGuestDriver) GetChangeInstanceTypeStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SKsyunGuestDriver) GetDeployStatus() ([]string, error) {
return []string{api.VM_READY, api.VM_RUNNING}, nil
}
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterRebuild() string {
return api.VM_RUNNING
}
func (self *SKsyunGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error {
if !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING}) {
return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status)
}
return nil
}
func (self *SKsyunGuestDriver) GetComputeQuotaKeys(scope rbacscope.TRbacScope, ownerId mcclient.IIdentityProvider, brand string) models.SComputeResourceKeys {
keys := models.SComputeResourceKeys{}
keys.SBaseProjectQuotaKeys = quotas.OwnerIdProjectQuotaKeys(scope, ownerId)
@@ -74,15 +122,27 @@ func (self *SKsyunGuestDriver) GetInstanceCapability() cloudprovider.SInstanceCa
Changeable: false,
},
},
Storages: cloudprovider.Storage{
DataDisk: []cloudprovider.StorageInfo{
{StorageType: api.STORAGE_KSYUN_SSD3_0, MaxSizeGb: 65535, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_EHDD, MaxSizeGb: 65535, MinSizeGb: 1, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL1, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL2, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL3, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
},
SysDisk: []cloudprovider.StorageInfo{
{StorageType: api.STORAGE_KSYUN_SSD3_0, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_EHDD, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL1, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL2, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
{StorageType: api.STORAGE_KSYUN_ESSD_PL3, MaxSizeGb: 65535, MinSizeGb: 20, StepSizeGb: 1, Resizable: true},
},
},
}
}
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterCreate() string {
return api.VM_READY
}
func (self *SKsyunGuestDriver) GetGuestInitialStateAfterRebuild() string {
return api.VM_READY
return api.VM_RUNNING
}
func (self *SKsyunGuestDriver) AllowReconfigGuest() bool {
@@ -90,6 +150,9 @@ func (self *SKsyunGuestDriver) AllowReconfigGuest() bool {
}
func (self *SKsyunGuestDriver) IsSupportedBillingCycle(bc billing.SBillingCycle) bool {
if bc.GetMonths() >= 1 && bc.GetMonths() <= 36 {
return true
}
return false
}
@@ -100,3 +163,7 @@ func (self *SKsyunGuestDriver) IsSupportPublicipToEip() bool {
func (self *SKsyunGuestDriver) IsSupportSetAutoRenew() bool {
return false
}
func (self *SKsyunGuestDriver) IsSupportShutdownMode() bool {
return true
}
+17 -1
View File
@@ -4136,6 +4136,22 @@ func (self *SGuest) SyncVMDisks(
return result
}
func (self *SGuest) setSystemDisk() error {
sq := GuestdiskManager.Query("disk_id").Equals("guest_id", self.Id).Equals("index", 0).SubQuery()
disks := DiskManager.Query().In("id", sq)
disk := &SDisk{}
disk.SetModelManager(DiskManager, disk)
err := disks.First(disk)
if err != nil {
return err
}
_, err = db.Update(disk, func() error {
disk.DiskType = api.DISK_TYPE_SYS
return nil
})
return err
}
func (self *SGuest) fixSysDiskIndex() error {
disks := DiskManager.Query().SubQuery()
sysQ := GuestdiskManager.Query().Equals("guest_id", self.Id)
@@ -4145,7 +4161,7 @@ func (self *SGuest) fixSysDiskIndex() error {
err := sysQ.First(sysDisk)
if err != nil {
if errors.Cause(err) == sql.ErrNoRows {
return nil
return self.setSystemDisk()
}
return err
}
+38
View File
@@ -16,7 +16,12 @@ package regiondrivers
import (
"context"
"fmt"
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/apis"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/compute/models"
"yunion.io/x/onecloud/pkg/mcclient"
@@ -38,3 +43,36 @@ func (self *SKsyunRegionDriver) GetProvider() string {
func (self *SKsyunRegionDriver) ValidateCreateSnapshotData(ctx context.Context, userCred mcclient.TokenCredential, disk *models.SDisk, storage *models.SStorage, input *api.SnapshotCreateInput) error {
return nil
}
func (self *SKsyunRegionDriver) CreateDefaultSecurityGroup(
ctx context.Context,
userCred mcclient.TokenCredential,
ownerId mcclient.IIdentityProvider,
vpc *models.SVpc,
) (*models.SSecurityGroup, error) {
region, err := vpc.GetRegion()
if err != nil {
return nil, errors.Wrapf(err, "GetRegion")
}
driver := region.GetDriver()
newGroup := &models.SSecurityGroup{}
newGroup.SetModelManager(models.SecurityGroupManager, newGroup)
newGroup.Name = fmt.Sprintf("%s-%d", driver.GetDefaultSecurityGroupNamePrefix(), time.Now().Unix())
// 部分云可能不需要vpcId, 创建完安全组后会自动置空
newGroup.VpcId = vpc.Id
newGroup.ManagerId = vpc.ManagerId
newGroup.CloudregionId = vpc.CloudregionId
newGroup.DomainId = ownerId.GetProjectDomainId()
newGroup.ProjectId = ownerId.GetProjectId()
newGroup.ProjectSrc = string(apis.OWNER_SOURCE_LOCAL)
err = models.SecurityGroupManager.TableSpec().Insert(ctx, newGroup)
if err != nil {
return nil, errors.Wrapf(err, "insert")
}
err = driver.RequestCreateSecurityGroup(ctx, userCred, newGroup, api.SSecgroupRuleResourceSet{})
if err != nil {
return nil, errors.Wrapf(err, "RequestCreateSecurityGroup")
}
return newGroup, nil
}
+1 -1
View File
@@ -1875,7 +1875,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926060637-3dea34e8fa4e
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250926093134-932d0643fbc0
## explicit; go 1.24
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
+7
View File
@@ -132,6 +132,13 @@ const (
STORAGE_BAIDU_ENHANCED_SSD_PL2 = "enhanced_ssd_pl2" // 增强型SSD_PL2
STORAGE_BAIDU_ENHANCED_SSD_PL3 = "enhanced_ssd_pl3" // 增强型SSD_PL2
// ksyun storage type
STORAGE_KSYUN_ESSD_PL1 = "ESSD_PL1"
STORAGE_KSYUN_ESSD_PL2 = "ESSD_PL2"
STORAGE_KSYUN_ESSD_PL3 = "ESSD_PL3"
STORAGE_KSYUN_SSD3_0 = "SSD3.0"
STORAGE_KSYUN_EHDD = "EHDD"
// cnware storage type
STORAGE_CNWARE_FC_SAN = "fc-san"
STORAGE_CNWARE_IP_SAN = "ip-scan"
+3
View File
@@ -364,6 +364,9 @@ type ServerVncOutput struct {
// sangfor
Cookie string `json:"cookie"`
// ksyun
Cookies map[string]string `json:"cookies"`
Hypervisor string `json:"hypervisor"`
}
+101 -15
View File
@@ -21,6 +21,7 @@ import (
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
)
@@ -42,25 +43,38 @@ type SDisk struct {
multicloud.SDisk
SKsyunTags
VolumeID string `json:"VolumeId"`
VolumeId string `json:"VolumeId"`
VolumeName string `json:"VolumeName"`
VolumeDesc string `json:"VolumeDesc,omitempty"`
Size int `json:"Size"`
VolumeStatus string `json:"VolumeStatus"`
VolumeType string `json:"VolumeType"`
VolumeCategory string `json:"VolumeCategory"`
InstanceID string `json:"InstanceId"`
InstanceId string `json:"InstanceId"`
AvailabilityZone string `json:"AvailabilityZone"`
ChargeType string `json:"ChargeType"`
InstanceTradeType int `json:"InstanceTradeType"`
CreateTime string `json:"CreateTime"`
Attachment []Attachment `json:"Attachment"`
ProjectID int `json:"ProjectId"`
ProjectId string `json:"ProjectId"`
ExpireTime string `json:"ExpireTime,omitempty"`
HistoryAttachment []HistoryAttachment `json:"HistoryAttachment,omitempty"`
DeleteWithInstance bool `json:"DeleteWithInstance"`
}
func (region *SRegion) GetDisk(diskId string) (*SDisk, error) {
disks, err := region.GetDisks([]string{diskId}, "", "")
if err != nil {
return nil, err
}
for i := range disks {
if disks[i].VolumeId == diskId {
return &disks[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "disk %s", diskId)
}
func (region *SRegion) GetDisks(diskIds []string, storageType, zoneId string) ([]SDisk, error) {
disks := []SDisk{}
params := map[string]string{
@@ -103,7 +117,6 @@ func (region *SRegion) GetDisks(diskIds []string, storageType, zoneId string) ([
return res, nil
}
return disks, nil
}
func (region *SRegion) GetDiskByInstanceId(instanceId string) ([]SDisk, error) {
@@ -121,7 +134,7 @@ func (region *SRegion) GetDiskByInstanceId(instanceId string) ([]SDisk, error) {
func (disk *SDisk) GetIStorage() (cloudprovider.ICloudStorage, error) {
if disk.storage == nil {
return nil, fmt.Errorf("disk %s(%s) missing storage", disk.VolumeName, disk.VolumeID)
return nil, fmt.Errorf("disk %s(%s) missing storage", disk.VolumeName, disk.VolumeId)
}
return disk.storage, nil
}
@@ -138,11 +151,11 @@ func (disk *SDisk) GetDiskFormat() string {
}
func (disk *SDisk) GetId() string {
return disk.VolumeID
return disk.VolumeId
}
func (disk *SDisk) GetTags() (map[string]string, error) {
tags, err := disk.storage.zone.region.ListTags("volume", disk.VolumeID)
tags, err := disk.storage.zone.region.ListTags("volume", disk.VolumeId)
if err != nil {
return nil, err
}
@@ -150,13 +163,25 @@ func (disk *SDisk) GetTags() (map[string]string, error) {
}
func (disk *SDisk) GetGlobalId() string {
return disk.VolumeID
return disk.VolumeId
}
func (disk *SDisk) GetName() string {
return disk.VolumeName
}
func (disk *SDisk) GetProjectId() string {
return disk.ProjectId
}
func (disk *SDisk) Refresh() error {
disk, err := disk.storage.zone.region.GetDisk(disk.VolumeId)
if err != nil {
return err
}
return jsonutils.Update(disk, disk)
}
func (disk *SDisk) GetStatus() string {
// creating、available、attaching、inuse、detaching、extending、deleting、error
switch disk.VolumeStatus {
@@ -166,6 +191,8 @@ func (disk *SDisk) GetStatus() string {
return api.DISK_DETACHING
case "error":
return api.DISK_UNKNOWN
case "creating":
return api.DISK_ALLOCATING
default:
return disk.VolumeStatus
}
@@ -219,15 +246,28 @@ func (disk *SDisk) GetAccessPath() string {
}
func (disk *SDisk) Delete(ctx context.Context) error {
return cloudprovider.ErrNotSupported
return disk.storage.zone.region.DeleteDisk(disk.VolumeId)
}
func (disk *SDisk) CreateISnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudSnapshot, error) {
return nil, cloudprovider.ErrNotSupported
ret, err := disk.storage.zone.region.CreateSnapshot(disk.VolumeId, name, desc)
if err != nil {
return nil, err
}
return ret, nil
}
func (disk *SDisk) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
return nil, cloudprovider.ErrNotSupported
snapshots, err := disk.storage.zone.region.GetSnapshots("", disk.VolumeId)
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudSnapshot{}
for i := range snapshots {
snapshots[i].region = disk.storage.zone.region
ret = append(ret, &snapshots[i])
}
return ret, nil
}
func (disk *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
@@ -235,17 +275,63 @@ func (disk *SDisk) GetExtSnapshotPolicyIds() ([]string, error) {
}
func (disk *SDisk) Resize(ctx context.Context, newSizeMB int64) error {
return cloudprovider.ErrNotSupported
return disk.storage.zone.region.ResizeDisk(disk.VolumeId, newSizeMB)
}
func (disk *SDisk) Reset(ctx context.Context, snapshotId string) (string, error) {
return "", cloudprovider.ErrNotSupported
return disk.VolumeId, disk.storage.zone.region.ResetDisk(disk.VolumeId, snapshotId)
}
func (disk *SDisk) Rebuild(ctx context.Context) error {
return cloudprovider.ErrNotSupported
}
func (disk *SDisk) SetStorage(storage SStorage) {
disk.storage = &storage
func (region *SRegion) DeleteDisk(id string) error {
_, err := region.ebsRequest("DeleteVolume", map[string]string{
"VolumeId": id,
"ForceDelete": "true",
})
return err
}
func (region *SRegion) ResizeDisk(id string, newSizeMB int64) error {
_, err := region.ebsRequest("ResizeVolume", map[string]string{
"VolumeId": id,
"Size": fmt.Sprintf("%d", newSizeMB/1024),
})
return err
}
func (region *SRegion) ResetDisk(id string, snapshotId string) error {
_, err := region.ebsRequest("ResetVolume", map[string]string{
"VolumeId": id,
"SnapshotId": snapshotId,
})
return err
}
func (region *SRegion) CreateDisk(storageType, zoneId string, opts *cloudprovider.DiskCreateConfig) (*SDisk, error) {
params := map[string]string{
"VolumeName": opts.Name,
"VolumeDesc": opts.Desc,
"Size": fmt.Sprintf("%d", opts.SizeGb),
"VolumeType": storageType,
"AvailabilityZone": zoneId,
"ChargeType": "HourlyInstantSettlement",
}
if len(opts.ProjectId) > 0 {
params["ProjectId"] = opts.ProjectId
}
if len(opts.SnapshotId) > 0 {
params["SnapshotId"] = opts.SnapshotId
}
resp, err := region.ebsRequest("CreateVolume", params)
if err != nil {
return nil, err
}
diskId, err := resp.GetString("VolumeId")
if err != nil {
return nil, err
}
return region.GetDisk(diskId)
}
+94 -35
View File
@@ -16,6 +16,7 @@ package ksyun
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
@@ -40,22 +41,22 @@ type SEip struct {
SKsyunTags
PublicIP string `json:"PublicIp"`
AllocationID string `json:"AllocationId"`
AllocationId string `json:"AllocationId"`
State string `json:"State"`
IPState string `json:"IpState"`
LineID string `json:"LineId"`
LineId string `json:"LineId"`
BandWidth int `json:"BandWidth"`
InstanceType string `json:"InstanceType"`
InstanceID string `json:"InstanceId"`
InstanceId string `json:"InstanceId"`
ChargeType string `json:"ChargeType"`
IPVersion string `json:"IpVersion"`
ProjectID string `json:"ProjectId"`
ProjectId string `json:"ProjectId"`
CreateTime string `json:"CreateTime"`
Mode string `json:"Mode"`
NetworkInterfaceID string `json:"NetworkInterfaceId,omitempty"`
NetworkInterfaceId string `json:"NetworkInterfaceId,omitempty"`
NetworkInterfaceType string `json:"NetworkInterfaceType,omitempty"`
PrivateIPAddress string `json:"PrivateIpAddress,omitempty"`
InternetGatewayID string `json:"InternetGatewayId,omitempty"`
InternetGatewayId string `json:"InternetGatewayId,omitempty"`
HostType string `json:"HostType,omitempty"`
}
@@ -100,19 +101,19 @@ func (region *SRegion) GetEip(eipId string) (*SEip, error) {
}
func (eip *SEip) GetId() string {
return eip.AllocationID
return eip.AllocationId
}
func (eip *SEip) GetName() string {
return eip.AllocationID
return eip.AllocationId
}
func (eip *SEip) GetGlobalId() string {
return eip.AllocationID
return eip.AllocationId
}
func (eip *SEip) GetTags() (map[string]string, error) {
tags, err := eip.region.ListTags("eip", eip.AllocationID)
tags, err := eip.region.ListTags("eip", eip.AllocationId)
if err != nil {
return nil, err
}
@@ -131,7 +132,7 @@ func (eip *SEip) GetStatus() string {
}
func (eip *SEip) Refresh() error {
extEip, err := eip.region.GetEip(eip.AllocationID)
extEip, err := eip.region.GetEip(eip.AllocationId)
if err != nil {
return errors.Wrap(err, "region.GetEip")
}
@@ -158,7 +159,7 @@ func (eip *SEip) GetAssociationType() string {
}
func (eip *SEip) GetAssociationExternalId() string {
return eip.InstanceID
return eip.InstanceId
}
func (eip *SEip) GetBandwidth() int {
@@ -170,7 +171,10 @@ func (eip *SEip) GetINetworkId() string {
}
func (eip *SEip) GetInternetChargeType() string {
return ""
if eip.ChargeType == "Monthly" {
return api.EIP_CHARGE_TYPE_BY_BANDWIDTH
}
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
func (eip *SEip) GetBillingType() string {
@@ -190,48 +194,103 @@ func (eip *SEip) GetExpiredAt() time.Time {
}
func (eip *SEip) Delete() error {
return cloudprovider.ErrNotImplemented
return eip.region.DeallocateEIP(eip.AllocationId)
}
func (eip *SEip) Associate(conf *cloudprovider.AssociateConfig) error {
return cloudprovider.ErrNotImplemented
return eip.region.AssociateEip(eip.AllocationId, conf.InstanceId)
}
func (eip *SEip) Dissociate() error {
return cloudprovider.ErrNotImplemented
return eip.region.DissociateEip(eip.AllocationId)
}
func (eip *SEip) ChangeBandwidth(bw int) error {
return cloudprovider.ErrNotImplemented
}
func (region *SRegion) GetInstancePortId(instanceId string) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (region *SRegion) AllocateEIP(opts *cloudprovider.SEip) (*SEip, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (region *SRegion) DeallocateEIP(eipId string) error {
return cloudprovider.ErrNotImplemented
params := map[string]string{
"AllocationId": eipId,
}
_, err := region.eipRequest("ReleaseAddress", params)
return err
}
func (region *SRegion) AssociateEip(eipId string, instanceId string) error {
return cloudprovider.ErrNotImplemented
}
func (region *SRegion) AssociateEipWithPortId(eipId string, portId string) error {
return cloudprovider.ErrNotImplemented
params := map[string]string{
"AllocationId": eipId,
"InstanceId": instanceId,
"InstanceType": "",
}
_, err := region.eipRequest("AssociateAddress", params)
return err
}
func (region *SRegion) DissociateEip(eipId string) error {
return region.AssociateEipWithPortId(eipId, "")
}
func (region *SRegion) UpdateEipBandwidth(bandwidthId string, bw int) error {
return cloudprovider.ErrNotImplemented
params := map[string]string{
"AllocationId": eipId,
}
_, err := region.eipRequest("DisassociateAddress", params)
return err
}
func (eip *SEip) GetProjectId() string {
return ""
return eip.ProjectId
}
func (region *SRegion) CreateEip(opts *cloudprovider.SEip) (*SEip, error) {
lines, err := region.GetLines()
if err != nil {
return nil, errors.Wrap(err, "GetLines")
}
lineId := ""
for i := range lines {
if strings.Contains(lines[i].LineName, "BGP") {
lineId = lines[i].LineId
break
}
}
if len(lineId) == 0 {
return nil, errors.Wrap(errors.ErrNotFound, "No bgp lines found")
}
params := map[string]string{
"LineId": lineId,
"BandWidth": fmt.Sprintf("%d", opts.BandwidthMbps),
"ChargeType": "DailyPaidByTransfer",
}
if opts.ChargeType == api.EIP_CHARGE_TYPE_BY_BANDWIDTH {
params["ChargeType"] = "Monthlys"
params["PurchaseTime"] = "1"
}
body, err := region.eipRequest("AllocateAddress", params)
if err != nil {
return nil, errors.Wrap(err, "AllocateAddress")
}
ret := &SEip{region: region}
err = body.Unmarshal(ret)
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
return ret, nil
}
type SLine struct {
LineId string `json:"LineId"`
LineName string `json:"LineName"`
}
func (region *SRegion) GetLines() ([]SLine, error) {
params := map[string]string{}
body, err := region.eipRequest("GetLines", params)
if err != nil {
return nil, errors.Wrap(err, "GetLines")
}
ret := []SLine{}
err = body.Unmarshal(&ret, "LineSet")
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
return ret, nil
}
+115 -5
View File
@@ -15,6 +15,9 @@
package ksyun
import (
"fmt"
"time"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
@@ -50,8 +53,111 @@ func (host *SHost) GetIVMById(vmId string) (cloudprovider.ICloudVM, error) {
return ins, nil
}
func (host *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
return nil, cloudprovider.ErrNotImplemented
func (host *SHost) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (cloudprovider.ICloudVM, error) {
vm, err := host.zone.region.CreateVM(opts)
if err != nil {
return nil, err
}
vm.host = host
return vm, nil
}
func (region *SRegion) syncKeypair(keyName, publicKey string) (string, error) {
keypairs, err := region.client.GetKeypairs()
if err != nil {
return "", err
}
for i := range keypairs {
if keypairs[i].PublicKey == publicKey {
return keypairs[i].KeyPairId, nil
}
}
keypair, err := region.client.CreateKeypair(keyName, publicKey)
if err != nil {
return "", err
}
return keypair.KeyPairId, nil
}
func (region *SRegion) CreateVM(opts *cloudprovider.SManagedVMCreateConfig) (*SInstance, error) {
params := map[string]string{
"InstanceName": opts.Name,
"ImageId": opts.ExternalImageId,
"InstanceType": opts.InstanceType,
"MaxCount": "1",
"MinCount": "1",
"SubnetId": opts.ExternalNetworkId,
"ChargeType": "HourlyInstantSettlement",
"SystemDisk.DiskType": opts.SysDisk.StorageType,
"SystemDisk.DiskSize": fmt.Sprintf("%d", opts.SysDisk.SizeGB),
"SyncTag": "true",
}
if len(opts.Password) > 0 {
params["InstancePassword"] = opts.Password
}
if opts.BillingCycle != nil {
params["ChargeType"] = "Monthly"
params["PurchaseTime"] = fmt.Sprintf("%d", opts.BillingCycle.GetMonths())
}
for i, group := range opts.ExternalSecgroupIds {
params[fmt.Sprintf("SecurityGroupId.%d", i+1)] = group
}
if len(opts.IpAddr) > 0 {
params["PrivateIpAddress"] = opts.IpAddr
}
if len(opts.ProjectId) > 0 {
params["ProjectId"] = opts.ProjectId
}
if len(opts.UserData) > 0 {
params["UserData"] = opts.UserData
}
if len(opts.PublicKey) > 0 {
var err error
params["KeyId.1"], err = region.syncKeypair(opts.Name, opts.PublicKey)
if err != nil {
return nil, err
}
}
for i, disk := range opts.DataDisks {
params[fmt.Sprintf("DataDisk.%d.DeleteWithInstance", i+1)] = "true"
params[fmt.Sprintf("DataDisk.%d.Size", i+1)] = fmt.Sprintf("%d", disk.SizeGB)
params[fmt.Sprintf("DataDisk.%d.Type", i+1)] = disk.StorageType
}
tagIdx := 1
for k, v := range opts.Tags {
params[fmt.Sprintf("Tag.%d.Key", tagIdx)] = k
params[fmt.Sprintf("Tag.%d.Value", tagIdx)] = v
}
resp, err := region.ecsRequest("RunInstances", params)
if err != nil {
return nil, errors.Wrapf(err, "RunInstances")
}
ret := []struct {
InstanceId string
InstanceName string
}{}
err = resp.Unmarshal(&ret, "InstancesSet")
if err != nil {
return nil, errors.Wrapf(err, "Unmarshal")
}
if len(ret) == 0 {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after created")
}
vmId := ret[0].InstanceId
err = cloudprovider.Wait(time.Second*3, time.Minute, func() (bool, error) {
_, err := region.GetInstance(vmId)
if err != nil {
if errors.Cause(err) == cloudprovider.ErrNotFound {
return false, nil
}
return false, err
}
return true, nil
})
if err != nil {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after vm %s created", vmId)
}
return region.GetInstance(vmId)
}
func (host *SHost) GetAccessIp() string {
@@ -111,7 +217,7 @@ func (host *SHost) GetStorageType() string {
}
func (host *SHost) GetEnabled() bool {
return false
return true
}
func (host *SHost) GetIsMaintenance() bool {
@@ -127,7 +233,7 @@ func (host *SHost) GetId() string {
}
func (host *SHost) GetHostStatus() string {
return api.HOST_STATUS_READY
return api.HOST_ONLINE
}
func (host *SHost) GetHostType() string {
@@ -135,7 +241,11 @@ func (host *SHost) GetHostType() string {
}
func (host *SHost) GetIHostNics() ([]cloudprovider.ICloudHostNetInterface, error) {
return nil, errors.ErrNotImplemented
wires, err := host.zone.GetIWires()
if err != nil {
return nil, errors.Wrap(err, "GetIWires")
}
return cloudprovider.GetHostNetifs(host, wires), nil
}
func (host *SHost) GetIStorageById(storageId string) (cloudprovider.ICloudStorage, error) {
+251
View File
@@ -0,0 +1,251 @@
// 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 ksyun
import (
"context"
"time"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/util/imagetools"
)
/*
{
"ImageId": "IMG-8990a317-b0ff-4319-bf41-6dfc1732455c",
"ContainerFormat": "ovf",
"Type": "CommonImage",
"Name": "ubuntu-16.04-gpu-20180102203641",
"ImageState": "active",
"CreationDate": "2018-02-27T13:48:32Z",
"Platform": "ubuntu-16.04",
"IsPublic": true,
"IsNpe": true,
"UserCategory": "common",
"SysDisk": 20,
"Progress": "100",
"ImageSource": "system",
"CloudInitSupport": false,
"Ipv6Support": false,
"IsModifyType": false,
"FastBoot": false,
"IsCloudMarket": false,
"RealImageId": "ab836124-d008-404e-8e78-f3160e3b8df3",
"OnlineExpansion": true,
"BootMode": "BIOS(Legacy)",
"ImageOpenstackDefinedPagePerVq": "false"
}
*/
type SImage struct {
multicloud.SImageBase
SKsyunTags
storageCache *SStoragecache
// normalized image info
imgInfo *imagetools.ImageInfo
ImageId string
ContainerFormat string
Type string
Name string
ImageState string
CreationDate time.Time
Platform string
IsPublic string
IsNpe string
UserCategory string
SysDisk int
Progress string
ImageSource string
CloudInitSupport string
Ipv6Support string
IsModifyType string
FastBoot string
IsCloudMarket string
RealImageId string
OnlineExpansion string
BootMode string
ImageOpenstackDefinedPagePerVq string
Architecture string
}
func (image *SImage) GetMinRamSizeMb() int {
return 0
}
func (image *SImage) GetId() string {
return image.ImageId
}
func (image *SImage) GetName() string {
return image.Name
}
func (image *SImage) Delete(ctx context.Context) error {
return image.storageCache.region.DeleteImage(image.ImageId)
}
func (image *SImage) GetGlobalId() string {
return image.ImageId
}
func (image *SImage) GetIStoragecache() cloudprovider.ICloudStoragecache {
return image.storageCache
}
func (image *SImage) GetStatus() string {
switch image.ImageState {
case "creating":
return api.CACHED_IMAGE_STATUS_SAVING
case "active":
return api.CACHED_IMAGE_STATUS_ACTIVE
default:
return api.CACHED_IMAGE_STATUS_CACHE_FAILED
}
}
func (image *SImage) GetImageStatus() string {
switch image.ImageState {
case "creating":
return cloudprovider.IMAGE_STATUS_QUEUED
case "active":
return cloudprovider.IMAGE_STATUS_ACTIVE
default:
return cloudprovider.IMAGE_STATUS_KILLED
}
}
func (image *SImage) Refresh() error {
ret, err := image.storageCache.region.GetImage(image.ImageId)
if err != nil {
return err
}
return jsonutils.Update(image, ret)
}
func (image *SImage) GetImageType() cloudprovider.TImageType {
switch image.Type {
case "CommonImage":
return cloudprovider.ImageTypeSystem
case "CustomImage":
return cloudprovider.ImageTypeCustomized
case "MarketImage":
return cloudprovider.ImageTypeMarket
default:
return cloudprovider.ImageTypeCustomized
}
}
func (image *SImage) GetSizeByte() int64 {
return int64(image.SysDisk) * 1024 * 1024 * 1024
}
func (self *SImage) GetOsType() cloudprovider.TOsType {
return cloudprovider.TOsType(self.getNormalizedImageInfo().OsType)
}
func (self *SImage) GetOsDist() string {
return self.getNormalizedImageInfo().OsDistro
}
func (self *SImage) getNormalizedImageInfo() *imagetools.ImageInfo {
if self.imgInfo == nil {
imgInfo := imagetools.NormalizeImageInfo(self.Platform, self.Architecture, "", "", "")
self.imgInfo = &imgInfo
}
return self.imgInfo
}
func (self *SImage) GetFullOsName() string {
return self.Name
}
func (self *SImage) GetOsVersion() string {
return self.getNormalizedImageInfo().OsVersion
}
func (self *SImage) GetOsLang() string {
return self.getNormalizedImageInfo().OsLang
}
func (self *SImage) GetOsArch() string {
return self.getNormalizedImageInfo().OsArch
}
func (self *SImage) GetBios() cloudprovider.TBiosType {
return cloudprovider.ToBiosType(self.getNormalizedImageInfo().OsBios)
}
func (self *SImage) GetMinOsDiskSizeGb() int {
return self.SysDisk
}
func (self *SImage) GetImageFormat() string {
return self.ContainerFormat
}
func (self *SImage) GetCreatedAt() time.Time {
return self.CreationDate
}
func (region *SRegion) GetImage(imageId string) (*SImage, error) {
images, err := region.GetImages(imageId, "")
if err != nil {
return nil, err
}
for i := range images {
if images[i].ImageId == imageId {
return &images[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (region *SRegion) GetImages(id string, imageType string) ([]SImage, error) {
params := map[string]string{}
if len(id) > 0 {
params["ImageId"] = id
}
if len(imageType) > 0 {
params["ImageType"] = imageType
}
resp, err := region.ecsRequest("DescribeImages", params)
if err != nil {
return nil, err
}
ret := struct {
ImagesSet []SImage
NextToken string
}{}
err = resp.Unmarshal(&ret)
if err != nil {
return nil, err
}
return ret.ImagesSet, nil
}
func (region *SRegion) DeleteImage(imageId string) error {
params := map[string]string{
"ImageId": imageId,
}
_, err := region.ecsRequest("DeleteImage", params)
return err
}
+1 -9
View File
@@ -56,13 +56,5 @@ func (nic *SInstanceNic) GetDriver() string {
}
func (nic *SInstanceNic) GetINetworkId() string {
return nic.Instance.SubnetID
}
func (nic *SInstanceNic) AssignAddress(ipAddrs []string) error {
return cloudprovider.ErrNotImplemented
}
func (nic *SInstanceNic) UnassignAddress(ipAddrs []string) error {
return cloudprovider.ErrNotImplemented
return nic.Instance.SubnetId
}
+246 -53
View File
@@ -29,13 +29,6 @@ import (
"yunion.io/x/pkg/utils"
)
type SInstanceResp struct {
Marker int `json:"Marker"`
InstanceCount int `json:"InstanceCount"`
RequestID string `json:"RequestId"`
InstancesSet []SInstance `json:"InstancesSet"`
}
type InstanceConfigure struct {
Vcpu int `json:"VCPU"`
Gpu int `json:"GPU"`
@@ -62,15 +55,15 @@ type GroupSet struct {
}
type InstanceSecurityGroupSet struct {
SecurityGroupID string `json:"SecurityGroupId"`
SecurityGroupId string `json:"SecurityGroupId"`
}
type NetworkInterfaceSet struct {
AllocationId string `json:"AllocationId"`
NetworkInterfaceID string `json:"NetworkInterfaceId"`
NetworkInterfaceId string `json:"NetworkInterfaceId"`
NetworkInterfaceType string `json:"NetworkInterfaceType"`
VpcID string `json:"VpcId"`
SubnetID string `json:"SubnetId"`
VpcId string `json:"VpcId"`
SubnetId string `json:"SubnetId"`
MacAddress string `json:"MacAddress"`
PrivateIPAddress string `json:"PrivateIpAddress"`
GroupSet []GroupSet `json:"GroupSet"`
@@ -84,7 +77,7 @@ type SystemDisk struct {
}
type DataDisks struct {
DiskID string `json:"DiskId"`
DiskId string `json:"DiskId"`
DiskType string `json:"DiskType"`
DiskSize int `json:"DiskSize"`
DeleteWithInstance bool `json:"DeleteWithInstance"`
@@ -97,15 +90,15 @@ type SInstance struct {
host *SHost
region *SRegion
InstanceID string `json:"InstanceId"`
ProjectID string `json:"ProjectId"`
InstanceId string `json:"InstanceId"`
ProjectId string `json:"ProjectId"`
ShutdownNoCharge bool `json:"ShutdownNoCharge"`
IsDistributeIpv6 bool `json:"IsDistributeIpv6"`
InstanceName string `json:"InstanceName"`
InstanceType string `json:"InstanceType"`
InstanceConfigure InstanceConfigure `json:"InstanceConfigure"`
ImageID string `json:"ImageId"`
SubnetID string `json:"SubnetId"`
SubnetId string `json:"SubnetId"`
PrivateIPAddress string `json:"PrivateIpAddress"`
InstanceState InstanceState `json:"InstanceState"`
Monitoring Monitoring `json:"Monitoring"`
@@ -115,7 +108,7 @@ type SInstance struct {
CreationDate time.Time `json:"CreationDate"`
AvailabilityZone string `json:"AvailabilityZone"`
AvailabilityZoneName string `json:"AvailabilityZoneName"`
DedicatedUUID string `json:"DedicatedUuid"`
DedicatedUuid string `json:"DedicatedUuid"`
ProductType int `json:"ProductType"`
ProductWhat int `json:"ProductWhat"`
LiveUpgradeSupport bool `json:"LiveUpgradeSupport"`
@@ -167,7 +160,11 @@ func (region *SRegion) getInstances(zoneName string, instanceIds []string, proje
if err != nil {
return nil, errors.Wrap(err, "list instance")
}
part := SInstanceResp{}
part := struct {
InstancesSet []SInstance `json:"InstancesSet"`
Marker int `json:"Marker"`
InstanceCount int `json:"InstanceCount"`
}{}
err = resp.Unmarshal(&part)
if err != nil {
return nil, errors.Wrap(err, "unmarshal instances")
@@ -204,7 +201,7 @@ func (ins *SInstance) Refresh() error {
}
func (ins *SInstance) GetTags() (map[string]string, error) {
tags, err := ins.getRegion().ListTags("kec-instance", ins.InstanceID)
tags, err := ins.getRegion().ListTags("kec-instance", ins.InstanceId)
if err != nil {
return nil, err
}
@@ -219,23 +216,67 @@ func (ins *SInstance) getRegion() *SRegion {
}
func (ins *SInstance) AssignSecurityGroup(secgroupId string) error {
return cloudprovider.ErrNotImplemented
groupIds, err := ins.GetSecurityGroupIds()
if err != nil {
return err
}
groupIds = append(groupIds, secgroupId)
return ins.SetSecurityGroups(groupIds)
}
func (ins *SInstance) AttachDisk(ctx context.Context, diskId string) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().AttachDisk(ins.InstanceId, diskId)
}
func (ins *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
return cloudprovider.ErrNotImplemented
func (region *SRegion) AttachDisk(instanceId, diskId string) error {
params := map[string]string{
"VolumeId": diskId,
"InstanceId": instanceId,
"DeleteWithInstance": "true",
}
_, err := region.ebsRequest("AttachVolume", params)
return err
}
func (ins *SInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedVMChangeConfig) error {
return ins.getRegion().ChangeConfig(ins.InstanceId, opts)
}
func (region *SRegion) ChangeConfig(instanceId string, opts *cloudprovider.SManagedVMChangeConfig) error {
params := map[string]string{
"InstanceId": instanceId,
"InstanceType": opts.InstanceType,
}
_, err := region.ecsRequest("ModifyInstanceType", params)
return err
}
func (ins *SInstance) DeleteVM(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().DeleteVM(ins.InstanceId)
}
func (region *SRegion) DeleteVM(instanceId string) error {
params := map[string]string{
"InstanceId.1": instanceId,
"ForceDelete": "true",
}
_, err := region.ecsRequest("TerminateInstances", params)
return err
}
func (ins *SInstance) DetachDisk(ctx context.Context, diskId string) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().DetachDisk(ins.InstanceId, diskId)
}
func (region *SRegion) DetachDisk(instanceId, diskId string) error {
params := map[string]string{
"VolumeId": diskId,
}
if len(instanceId) > 0 {
params["InstanceId"] = instanceId
}
_, err := region.ecsRequest("DetachVolume", params)
return err
}
func (ins *SInstance) GetBios() cloudprovider.TBiosType {
@@ -255,11 +296,11 @@ func (ins *SInstance) GetFullOsName() string {
}
func (ins *SInstance) GetGlobalId() string {
return ins.InstanceID
return ins.InstanceId
}
func (ins *SInstance) GetId() string {
return ins.InstanceID
return ins.InstanceId
}
func (ins *SInstance) GetInstanceType() string {
@@ -300,14 +341,14 @@ func (ins *SInstance) GetOsVersion() string {
}
func (ins *SInstance) GetProjectId() string {
return ins.ProjectID
return ins.ProjectId
}
func (ins *SInstance) GetSecurityGroupIds() ([]string, error) {
ids := []string{}
for _, netSet := range ins.NetworkInterfaceSet {
for _, secgroupSet := range netSet.SecurityGroupSet {
ids = append(ids, secgroupSet.SecurityGroupID)
ids = append(ids, secgroupSet.SecurityGroupId)
}
}
return ids, nil
@@ -315,8 +356,12 @@ func (ins *SInstance) GetSecurityGroupIds() ([]string, error) {
func (ins *SInstance) GetStatus() string {
switch ins.InstanceState.Name {
case "block_device_mapping", "scheduling":
return api.VM_DEPLOYING
case "active":
return api.VM_RUNNING
case "stopping":
return api.VM_STOPPING
case "stopped":
return api.VM_READY
}
@@ -333,7 +378,20 @@ func (ins *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
return nil, errors.Wrap(err, "getDisks")
}
res := []cloudprovider.ICloudDisk{}
storages, err := ins.host.zone.GetStorages()
if err != nil {
return nil, errors.Wrap(err, "GetStorages")
}
for i := 0; i < len(disks); i++ {
for j := range storages {
if disks[i].VolumeType == storages[j].StorageType {
disks[i].storage = &storages[j]
break
}
}
if disks[i].storage == nil {
return nil, fmt.Errorf("failed to found disk storage type %s", disks[i].VolumeType)
}
res = append(res, &disks[i])
}
return res, nil
@@ -368,7 +426,7 @@ func (ins *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
for i := 0; i < len(ins.NetworkInterfaceSet); i++ {
nic := SInstanceNic{
Instance: ins,
Id: ins.NetworkInterfaceSet[i].SubnetID,
Id: ins.NetworkInterfaceSet[i].SubnetId,
IpAddr: ins.NetworkInterfaceSet[i].PrivateIPAddress,
MacAddr: ins.NetworkInterfaceSet[i].MacAddress,
}
@@ -378,27 +436,61 @@ func (ins *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
}
func (ins *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
// TODO
resp, err := ins.getRegion().ecsRequest("GetVNCAddress", map[string]string{"InstanceId": ins.InstanceID})
vnc, err := ins.getRegion().GetVNCInfo(ins.InstanceId)
if err != nil {
return nil, errors.Wrap(err, "GetVNCInfo")
}
ret := &cloudprovider.ServerVncOutput{
Url: fmt.Sprintf("https://%s:%s", vnc.VNCAddress.Host, vnc.VNCAddress.Port),
Protocol: "ksyun",
InstanceId: ins.InstanceId,
Hypervisor: api.HYPERVISOR_KSYUN,
Cookies: map[string]string{},
}
for _, cookie := range vnc.Cookies {
ret.Cookies[cookie.CookieKey] = cookie.CookieValue
}
switch vnc.VNCAddress.Port {
case "80":
ret.Url = fmt.Sprintf("http://%s", vnc.VNCAddress.Host)
case "443":
ret.Url = fmt.Sprintf("https://%s", vnc.VNCAddress.Host)
default:
ret.Url = fmt.Sprintf("https://%s:%s", vnc.VNCAddress.Host, vnc.VNCAddress.Port)
}
return ret, nil
}
/*{"VNCAddress":{"Port":"80","Host":"tjwqone.vnc.ksyun.com"},"Cookies":[{"CookieKey":"user_id","CookieValue":"2dc683372ad24e3eb4f13646f2a26306"},{"CookieKey":"token","CookieValue":"aa9fba7c-2ce9-4e14-9f80-90eebf20dc49"},{"CookieKey":"md5","CookieValue":"78188c9557573bb912488a2cb2c8c8f8"},{"CookieKey":"time","CookieValue":"1758795275577"}],"Domain":".ksyun.com","RequestId":"dcf64f30-8f9d-4ae2-9790-8b8466974625001"}*/
type VNCAddress struct {
Port string `json:"Port"`
Host string `json:"Host"`
}
type Cookies struct {
CookieKey string `json:"CookieKey"`
CookieValue string `json:"CookieValue"`
}
type VNCInfo struct {
VNCAddress VNCAddress `json:"VNCAddress"`
Cookies []Cookies `json:"Cookies"`
Domain string `json:"Domain"`
RequestId string `json:"RequestId"`
}
func (region *SRegion) GetVNCInfo(instanceId string) (*VNCInfo, error) {
resp, err := region.ecsRequest("GetVNCAddress", map[string]string{"InstanceId": instanceId})
if err != nil {
return nil, errors.Wrap(err, "GetVNCAddress")
}
temp := struct {
VNCAddress struct {
Port string `json:"Port"`
Host string `json:"Host"`
}
Cookies []struct {
CookieKey string `json:"CookieKey"`
CookieValue string `json:"CookieValue"`
} `json:"Cookies"`
Domain string `json:"Domain"`
}{}
err = resp.Unmarshal(&temp)
ret := &VNCInfo{}
err = resp.Unmarshal(ret)
if err != nil {
return nil, errors.Wrap(err, "unmarshal vnc info")
}
return nil, errors.ErrNotImplemented
return ret, nil
}
func (ins *SInstance) GetVcpuCount() int {
@@ -417,28 +509,109 @@ func (ins *SInstance) GetVga() string {
return ""
}
func (ins *SInstance) RebuildRoot(ctx context.Context, config *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
return "", errors.ErrNotImplemented
func (ins *SInstance) RebuildRoot(ctx context.Context, opts *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
err := ins.getRegion().RebuildRoot(ins.InstanceId, opts)
if err != nil {
return "", err
}
disks, err := ins.GetIDisks()
if err != nil {
return "", err
}
if len(disks) == 0 {
return "", fmt.Errorf("server %s has no volume attached.", ins.GetId())
}
return disks[0].GetGlobalId(), nil
}
func (region *SRegion) RebuildRoot(instanceId string, opts *cloudprovider.SManagedVMRebuildRootConfig) error {
params := map[string]string{
"InstanceId": instanceId,
"ImageId": opts.ImageId,
}
if len(opts.Password) > 0 {
params["InstancePassword"] = opts.Password
}
/*
if len(opts.PublicKey) > 0 {
params["KeyPairName"] = opts.PublicKey
}
*/
if len(opts.UserData) > 0 {
params["UserData"] = opts.UserData
}
_, err := region.ecsRequest("ModifyInstanceImage", params)
return err
}
func (ins *SInstance) SetSecurityGroups(secgroupIds []string) error {
return errors.ErrNotImplemented
nicId := ""
for _, netSet := range ins.NetworkInterfaceSet {
if netSet.NetworkInterfaceType == "primary" {
nicId = netSet.NetworkInterfaceId
break
}
}
return ins.getRegion().SetSecurityGroups(secgroupIds, ins.InstanceId, nicId, ins.SubnetId)
}
func (ins *SInstance) StartVM(ctx context.Context) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().StartVM(ins.InstanceId)
}
func (ins *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().StopVM(ins.InstanceId, opts.IsForce, opts.StopCharging)
}
func (region *SRegion) StartVM(instanceId string) error {
params := map[string]string{
"InstanceId.1": instanceId,
}
_, err := region.ecsRequest("StartInstances", params)
if err != nil {
return errors.Wrap(err, "StartInstances")
}
return nil
}
func (region *SRegion) StopVM(instanceId string, force, stopCharging bool) error {
params := map[string]string{
"InstanceId.1": instanceId,
"StoppedMode": "KeepCharging",
}
if stopCharging {
params["StoppedMode"] = "StopCharging"
}
if force {
params["ForceStop"] = "true"
}
_, err := region.ecsRequest("StopInstances", params)
if err != nil {
return errors.Wrap(err, "StopInstances")
}
return nil
}
func (ins *SInstance) UpdateUserData(userData string) error {
return cloudprovider.ErrNotImplemented
return cloudprovider.ErrNotSupported
}
func (ins *SInstance) UpdateVM(ctx context.Context, input cloudprovider.SInstanceUpdateOptions) error {
return cloudprovider.ErrNotImplemented
func (ins *SInstance) UpdateVM(ctx context.Context, opts cloudprovider.SInstanceUpdateOptions) error {
return ins.getRegion().UpdateVM(ins.InstanceId, opts)
}
func (region *SRegion) UpdateVM(instanceId string, opts cloudprovider.SInstanceUpdateOptions) error {
params := map[string]string{
"InstanceId": instanceId,
}
if len(opts.NAME) > 0 {
params["InstanceName"] = opts.NAME
}
if len(opts.HostName) > 0 {
params["HostName"] = opts.HostName
}
_, err := region.ecsRequest("ModifyInstanceAttribute", params)
return err
}
func (ins *SInstance) GetIHost() cloudprovider.ICloudHost {
@@ -446,7 +619,27 @@ func (ins *SInstance) GetIHost() cloudprovider.ICloudHost {
}
func (ins *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
return cloudprovider.ErrNotImplemented
return ins.getRegion().DeployVM(ins.InstanceId, opts)
}
func (region *SRegion) DeployVM(instanceId string, opts *cloudprovider.SInstanceDeployOptions) error {
params := map[string]string{
"InstanceId": instanceId,
}
if len(opts.Password) > 0 {
params["InstancePassword"] = opts.Password
params["RestartMode"] = "Restart"
}
/*
if len(opts.PublicKey) > 0 {
params["KeyPairName"] = opts.PublicKey
}
if len(opts.UserData) > 0 {
params["UserData"] = opts.UserData
}
*/
_, err := region.ecsRequest("ModifyInstanceAttribute", params)
return err
}
func (ins *SInstance) GetBillingType() string {
+66
View File
@@ -0,0 +1,66 @@
// 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 ksyun
type SKeypair struct {
KeyPairName string
KeyPairId string
PublicKey string
}
func (cli *SKsyunClient) GetKeypairs() ([]SKeypair, error) {
params := map[string]string{
"MaxResults": "1000",
}
ret := []SKeypair{}
for {
body, err := cli.sksRequest("", "DescribeKeys", params)
if err != nil {
return nil, err
}
part := struct {
KeySet []SKeypair
NextToken string
}{}
err = body.Unmarshal(&part)
if err != nil {
return nil, err
}
ret = append(ret, part.KeySet...)
if len(part.NextToken) == 0 {
break
}
params["NextToken"] = part.NextToken
}
return ret, nil
}
func (cli *SKsyunClient) CreateKeypair(name, publicKey string) (*SKeypair, error) {
params := map[string]string{
"KeyName": name,
"PublicKey": publicKey,
"IsCheck": "true",
}
resp, err := cli.sksRequest("", "ImportKey", params)
if err != nil {
return nil, err
}
ret := SKeypair{}
err = resp.Unmarshal(&ret, "Key")
if err != nil {
return nil, err
}
return &ret, nil
}
+15 -6
View File
@@ -43,6 +43,7 @@ const (
KSYUN_DEFAULT_REGION = "cn-beijing-6"
KSYUN_DEFAULT_API_VERSION = "2016-03-04"
KSYUN_RDS_API_VERSION = "2016-07-01"
KSYUN_SKS_API_VERSION = "2015-11-01"
)
type KsyunClientConfig struct {
@@ -127,7 +128,7 @@ func (cli *SKsyunClient) getUrl(service, regionId string) (string, error) {
regionId = KSYUN_DEFAULT_REGION
}
switch service {
case "kingpay", "iam", "vpc", "ebs", "eip":
case "kingpay", "iam", "vpc", "ebs", "eip", "sks":
return fmt.Sprintf("http://%s.api.ksyun.com", service), nil
case "kec", "tag", "krds":
return fmt.Sprintf("https://%s.%s.api.ksyun.com", service, regionId), nil
@@ -171,8 +172,9 @@ func (cli *SKsyunClient) getDefaultClient() *http.Client {
// {"RequestId":"51aee78d-8c35-4778-92fb-a622c40fa5ae","Error":{"Code":"INVALID_ACTION","Message":"Not Found"}}
type sKsyunError struct {
StatusCode int `json:"StatusCode"`
RequestId string `json:"RequestId"`
Params map[string]string `json:"Params"`
StatusCode int `json:"StatusCode"`
RequestId string `json:"RequestId"`
ErrorMsg struct {
Code string `json:"Code"`
Message string `json:"Message"`
@@ -260,6 +262,10 @@ func (cli *SKsyunClient) ebsRequest(regionId, apiName string, params map[string]
return cli.request("ebs", regionId, apiName, KSYUN_DEFAULT_API_VERSION, params)
}
func (cli *SKsyunClient) sksRequest(regionId, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return cli.request("sks", regionId, apiName, KSYUN_SKS_API_VERSION, params)
}
func (cli *SKsyunClient) rdsRequest(regionId, apiName string, params map[string]string) (jsonutils.JSONObject, error) {
return cli.request("krds", regionId, apiName, KSYUN_RDS_API_VERSION, params)
}
@@ -297,7 +303,7 @@ func (cli *SKsyunClient) request(service, regionId, apiName, apiVersion string,
method = httputils.POST
}
req := httputils.NewJsonRequest(method, uri, nil)
ksErr := &sKsyunError{}
ksErr := &sKsyunError{Params: params}
client := httputils.NewJsonClient(cli)
_, resp, err := client.Send(cli.ctx, req, ksErr, cli.debug)
if err != nil {
@@ -354,9 +360,12 @@ func (cli *SKsyunClient) QueryCashWalletAction() (*CashWalletDetail, error) {
func (cli *SKsyunClient) GetCapabilities() []string {
caps := []string{
cloudprovider.CLOUD_CAPABILITY_COMPUTE + cloudprovider.READ_ONLY_SUFFIX,
cloudprovider.CLOUD_CAPABILITY_PROJECT + cloudprovider.READ_ONLY_SUFFIX,
cloudprovider.CLOUD_CAPABILITY_COMPUTE,
cloudprovider.CLOUD_CAPABILITY_PROJECT,
cloudprovider.CLOUD_CAPABILITY_CLOUDID,
cloudprovider.CLOUD_CAPABILITY_NETWORK,
cloudprovider.CLOUD_CAPABILITY_SECURITY_GROUP,
cloudprovider.CLOUD_CAPABILITY_EIP,
cloudprovider.CLOUD_CAPABILITY_OBJECTSTORE,
cloudprovider.CLOUD_CAPABILITY_RDS + cloudprovider.READ_ONLY_SUFFIX,
}
+46 -11
View File
@@ -37,19 +37,19 @@ type SNetwork struct {
SKsyunTags
wire *SWire
RouteTableID string `json:"RouteTableId"`
NetworkACLID string `json:"NetworkAclId"`
NatID string `json:"NatId"`
RouteTableId string `json:"RouteTableId"`
NetworkAclId string `json:"NetworkAclId"`
NatId string `json:"NatId"`
CreateTime string `json:"CreateTime"`
DhcpIPTo string `json:"DhcpIpTo"`
DhcpIpTo string `json:"DhcpIpTo"`
DNS1 string `json:"Dns1"`
CidrBlock string `json:"CidrBlock"`
DNS2 string `json:"Dns2"`
ProvidedIpv6CidrBlock bool `json:"ProvidedIpv6CidrBlock"`
SubnetID string `json:"SubnetId"`
SubnetId string `json:"SubnetId"`
SubnetType string `json:"SubnetType"`
SubnetName string `json:"SubnetName"`
VpcID string `json:"VpcId"`
VpcId string `json:"VpcId"`
GatewayIP string `json:"GatewayIp"`
AvailabilityZoneName string `json:"AvailabilityZoneName"`
DhcpIPFrom string `json:"DhcpIpFrom"`
@@ -112,19 +112,19 @@ func (region *SRegion) GetNetwork(networkId string) (*SNetwork, error) {
}
func (net *SNetwork) GetId() string {
return net.SubnetID
return net.SubnetId
}
func (net *SNetwork) GetName() string {
if len(net.SubnetName) == 0 {
return net.SubnetID
return net.SubnetId
}
return net.SubnetName
}
func (net *SNetwork) GetGlobalId() string {
return net.SubnetID
return net.SubnetId
}
func (net *SNetwork) GetStatus() string {
@@ -140,7 +140,7 @@ func (net *SNetwork) Refresh() error {
}
func (net *SNetwork) GetTags() (map[string]string, error) {
tags, err := net.wire.zone.region.ListTags("subnet", net.SubnetID)
tags, err := net.wire.zone.region.ListTags("subnet", net.SubnetId)
if err != nil {
return nil, err
}
@@ -187,7 +187,7 @@ func (net *SNetwork) GetPublicScope() rbacscope.TRbacScope {
}
func (net *SNetwork) Delete() error {
return cloudprovider.ErrNotImplemented
return net.wire.zone.region.DeleteNetwork(net.SubnetId)
}
func (net *SNetwork) GetAllocTimeoutSeconds() int {
@@ -201,3 +201,38 @@ func (net *SNetwork) GetProjectId() string {
func (net *SNetwork) GetDescription() string {
return ""
}
func (region *SRegion) DeleteNetwork(networkId string) error {
params := map[string]string{
"SubnetId": networkId,
}
_, err := region.vpcRequest("DeleteSubnet", params)
return err
}
func (region *SRegion) CreateNetwork(vpcId, zoneId string, opts *cloudprovider.SNetworkCreateOptions) (*SNetwork, error) {
pref, err := netutils.NewIPV4Prefix(opts.Cidr)
if err != nil {
return nil, err
}
startIp := pref.Address.NetAddr(pref.MaskLen) // 0
gateway := startIp.StepUp() // 1
params := map[string]string{
"VpcId": vpcId,
"SubnetName": opts.Name,
"CidrBlock": opts.Cidr,
"SubnetType": "Normal",
"AvailabilityZone": zoneId,
"GatewayIp": gateway.String(),
}
resp, err := region.vpcRequest("CreateSubnet", params)
if err != nil {
return nil, err
}
ret := &SNetwork{}
err = resp.Unmarshal(ret, "Subnet")
if err != nil {
return nil, err
}
return ret, nil
}
+23
View File
@@ -18,6 +18,7 @@ import (
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/pkg/errors"
)
type SProject struct {
@@ -94,3 +95,25 @@ func (self *SKsyunClient) GetIProjects() ([]cloudprovider.ICloudProject, error)
}
return ret, nil
}
func (cli *SKsyunClient) CreateProject(name string) (*SProject, error) {
params := map[string]string{
"ProjectName": name,
}
_, err := cli.iamRequest("", "CreateProject", params)
if err != nil {
return nil, err
}
project, err := cli.GetProjects()
if err != nil {
return nil, err
}
for i := range project {
project[i].client = cli
if project[i].ProjectName == name {
return &project[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "GetProject %s", name)
}
+1 -5
View File
@@ -37,10 +37,6 @@ func (self *SKsyunProviderFactory) GetName() string {
return ksyun.CLOUD_PROVIDER_KSYUN_CN
}
func (self *SKsyunProviderFactory) IsReadOnly() bool {
return true
}
func (self *SKsyunProviderFactory) ValidateCreateCloudaccountData(ctx context.Context, input cloudprovider.SCloudaccountCredential) (cloudprovider.SCloudaccount, error) {
output := cloudprovider.SCloudaccount{}
if len(input.AccessKeyId) == 0 {
@@ -171,7 +167,7 @@ func (self *SKsyunProvider) GetIProjects() ([]cloudprovider.ICloudProject, error
}
func (self *SKsyunProvider) CreateIProject(name string) (cloudprovider.ICloudProject, error) {
return nil, cloudprovider.ErrNotImplemented
return self.client.CreateProject(name)
}
func (self *SKsyunProvider) GetStorageClasses(regionId string) []string {
+3 -3
View File
@@ -83,15 +83,15 @@ func (region *SRegion) GetClient() *SKsyunClient {
}
func (region *SRegion) CreateEIP(opts *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
return nil, cloudprovider.ErrNotImplemented
return region.CreateEip(opts)
}
func (region *SRegion) CreateISecurityGroup(conf *cloudprovider.SecurityGroupCreateInput) (cloudprovider.ICloudSecurityGroup, error) {
return nil, cloudprovider.ErrNotImplemented
return region.CreateSecurityGroup(conf)
}
func (region *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprovider.ICloudVpc, error) {
return nil, cloudprovider.ErrNotImplemented
return region.CreateVpc(opts)
}
func (region *SRegion) GetIVpcs() ([]cloudprovider.ICloudVpc, error) {
+95 -4
View File
@@ -16,8 +16,10 @@ package ksyun
import (
"fmt"
"strings"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/secrules"
)
@@ -25,6 +27,7 @@ import (
type SPermission struct {
region *SRegion
SecurityGroupId string `json:"SecurityGroupId"`
Policy string `json:"Policy"`
PortRangeTo int `json:"PortRangeTo"`
Description string `json:"Description"`
@@ -35,13 +38,13 @@ type SPermission struct {
CidrBlock string `json:"CidrBlock"`
Direction string `json:"Direction"`
PortRangeFrom int `json:"PortRangeFrom"`
SecurityGroupEntryID string `json:"SecurityGroupEntryId"`
SecurityGroupEntryId string `json:"SecurityGroupEntryId"`
RuleTag string `json:"RuleTag"`
Protocol string `json:"Protocol"`
}
func (rule *SPermission) GetGlobalId() string {
return rule.SecurityGroupEntryID
return rule.SecurityGroupEntryId
}
func (rule *SPermission) GetDirection() secrules.TSecurityRuleDirection {
@@ -60,6 +63,9 @@ func (rule *SPermission) GetAction() secrules.TSecurityRuleAction {
}
func (rule *SPermission) GetProtocol() string {
if rule.Protocol == "ip" {
return secrules.PROTO_ANY
}
return rule.Protocol
}
@@ -82,9 +88,94 @@ func (rule *SPermission) GetCIDRs() []string {
}
func (rule *SPermission) Update(opts *cloudprovider.SecurityGroupRuleUpdateOptions) error {
return errors.ErrNotImplemented
return errors.ErrNotSupported
}
func (rule *SPermission) Delete() error {
return errors.ErrNotImplemented
return rule.region.DeleteSecurityGroupRule(rule.SecurityGroupId, rule.SecurityGroupEntryId)
}
func (region *SRegion) DeleteSecurityGroupRule(groupId string, ruleId string) error {
params := map[string]string{
"SecurityGroupId": groupId,
"SecurityGroupEntryId": ruleId,
}
_, err := region.ecsRequest("RevokeSecurityGroupEntry", params)
return err
}
func (group *SSecurityGroup) CreateRule(opts *cloudprovider.SecurityGroupRuleCreateOptions) (cloudprovider.ISecurityGroupRule, error) {
rule, err := group.region.CreateSecurityGroupRule(group.SecurityGroupId, opts)
if err != nil {
return nil, err
}
return rule, nil
}
func (region *SRegion) CreateSecurityGroupRule(groupId string, opts *cloudprovider.SecurityGroupRuleCreateOptions) (*SPermission, error) {
params := map[string]string{
"SecurityGroupId": groupId,
"CidrBlock": opts.CIDR,
"Direction": string(opts.Direction),
"Protocol": opts.Protocol,
"Priority": fmt.Sprintf("%d", opts.Priority),
"Policy": "Accept",
}
if opts.Action == secrules.SecurityRuleDeny {
params["Policy"] = "Drop"
}
if len(opts.Desc) > 0 {
params["Description"] = opts.Desc
}
switch opts.Protocol {
case secrules.PROTO_ANY:
params["Protocol"] = "ip"
case secrules.PROTO_TCP, secrules.PROTO_UDP:
if len(opts.Ports) == 0 {
params["PortRangeFrom"] = "1"
params["PortRangeTo"] = "65535"
} else {
if strings.Contains(opts.Ports, "-") {
info := strings.Split(opts.Ports, "-")
if len(info) == 2 {
params["PortRangeFrom"] = info[0]
params["PortRangeTo"] = info[1]
}
} else {
params["PortRangeFrom"] = opts.Ports
params["PortRangeTo"] = opts.Ports
}
}
case secrules.PROTO_ICMP:
params["IcmpType"] = "-1"
params["IcmpCode"] = "-1"
}
resp, err := region.vpcRequest("AuthorizeSecurityGroupEntry", params)
if err != nil {
return nil, err
}
ret := []string{}
err = resp.Unmarshal(&ret, "SecurityGroupEntryIdSet")
if err != nil {
return nil, err
}
ruleId := ""
for i := range ret {
ruleId = ret[i]
}
if len(ruleId) == 0 {
return nil, fmt.Errorf("invalid rule create response %s", resp.String())
}
group, err := region.GetSecurityGroup(groupId)
if err != nil {
return nil, err
}
for i := range group.SecurityGroupEntrySet {
if group.SecurityGroupEntrySet[i].SecurityGroupEntryId == ruleId {
group.SecurityGroupEntrySet[i].region = region
group.SecurityGroupEntrySet[i].SecurityGroupId = groupId
return &group.SecurityGroupEntrySet[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "after create %s", jsonutils.Marshal(opts))
}
+61 -61
View File
@@ -40,11 +40,11 @@ type SSecurityGroup struct {
CreateTime string `json:"CreateTime"`
ProductTag string `json:"ProductTag"`
SecurityGroupEntrySet []SPermission `json:"SecurityGroupEntrySet"`
SecurityGroupID string `json:"SecurityGroupId"`
SecurityGroupId string `json:"SecurityGroupId"`
SecurityGroupName string `json:"SecurityGroupName"`
SecurityGroupType string `json:"SecurityGroupType"`
UserTag string `json:"UserTag"`
VpcID string `json:"VpcId"`
VpcId string `json:"VpcId"`
}
type SecurityGroupEntrySet struct {
@@ -58,28 +58,29 @@ type SecurityGroupEntrySet struct {
ProductTag string `json:"ProductTag"`
Protocol string `json:"Protocol"`
RuleTag string `json:"RuleTag,omitempty"`
SecurityGroupEntryID string `json:"SecurityGroupEntryId"`
SecurityGroupEntryId string `json:"SecurityGroupEntryId"`
UserTag string `json:"UserTag"`
PortRangeFrom int `json:"PortRangeFrom,omitempty"`
PortRangeTo int `json:"PortRangeTo,omitempty"`
}
func (secgroup *SSecurityGroup) GetVpcId() string {
return secgroup.VpcID
return secgroup.VpcId
}
func (secgroup *SSecurityGroup) GetId() string {
return secgroup.SecurityGroupID
return secgroup.SecurityGroupId
}
func (secgroup *SSecurityGroup) GetGlobalId() string {
return secgroup.SecurityGroupID
return secgroup.SecurityGroupId
}
func (secgroup *SSecurityGroup) GetRules() ([]cloudprovider.ISecurityGroupRule, error) {
ret := make([]cloudprovider.ISecurityGroupRule, 0)
for i := range secgroup.SecurityGroupEntrySet {
secgroup.SecurityGroupEntrySet[i].region = secgroup.region
secgroup.SecurityGroupEntrySet[i].SecurityGroupId = secgroup.SecurityGroupId
ret = append(ret, &secgroup.SecurityGroupEntrySet[i])
}
return ret, nil
@@ -89,7 +90,7 @@ func (secgroup *SSecurityGroup) GetName() string {
if len(secgroup.SecurityGroupName) > 0 {
return secgroup.SecurityGroupName
}
return secgroup.SecurityGroupID
return secgroup.SecurityGroupId
}
func (secgroup *SSecurityGroup) GetStatus() string {
@@ -97,7 +98,7 @@ func (secgroup *SSecurityGroup) GetStatus() string {
}
func (secgroup *SSecurityGroup) Refresh() error {
group, err := secgroup.region.GetSecurityGroup(secgroup.SecurityGroupID)
group, err := secgroup.region.GetSecurityGroup(secgroup.SecurityGroupId)
if err != nil {
return err
}
@@ -105,7 +106,7 @@ func (secgroup *SSecurityGroup) Refresh() error {
}
func (secgroup *SSecurityGroup) GetTags() (map[string]string, error) {
tags, err := secgroup.region.ListTags("security-group", secgroup.SecurityGroupID)
tags, err := secgroup.region.ListTags("security-group", secgroup.SecurityGroupId)
if err != nil {
return nil, err
}
@@ -113,39 +114,7 @@ func (secgroup *SSecurityGroup) GetTags() (map[string]string, error) {
}
func (secgroup *SSecurityGroup) GetReferences() ([]cloudprovider.SecurityGroupReference, error) {
references, err := secgroup.region.DescribeSecurityGroupReferences(secgroup.SecurityGroupID)
if err != nil {
return nil, errors.Wrapf(err, "DescribeSecurityGroupReferences")
}
ret := []cloudprovider.SecurityGroupReference{}
for _, reference := range references {
if reference.SecurityGroupId == secgroup.SecurityGroupID {
for _, sec := range reference.ReferencingSecurityGroups.ReferencingSecurityGroup {
ret = append(ret, cloudprovider.SecurityGroupReference{
Id: sec.SecurityGroupId,
})
}
}
}
return ret, nil
}
type ReferencingSecurityGroup struct {
AliUid string
SecurityGroupId string
}
type ReferencingSecurityGroups struct {
ReferencingSecurityGroup []ReferencingSecurityGroup
}
type SecurityGroupReferences struct {
SecurityGroupId string
ReferencingSecurityGroups ReferencingSecurityGroups
}
func (region *SRegion) DescribeSecurityGroupReferences(id string) ([]SecurityGroupReferences, error) {
return nil, errors.ErrNotImplemented
return nil, errors.ErrNotSupported
}
func (region *SRegion) GetSecurityGroups(vpcId string, securityGroupIds []string) ([]SSecurityGroup, error) {
@@ -162,24 +131,23 @@ func (region *SRegion) GetSecurityGroups(vpcId string, securityGroupIds []string
}
for {
secgroupResp := struct {
RequestID string `json:"RequestId"`
SecurityGroupSet []SSecurityGroup `json:"SecurityGroupSet"`
NextToken string `json:"NextToken"`
}{}
resp, err := region.vpcRequest("DescribeSecurityGroups", params)
if err != nil {
return nil, errors.Wrap(err, "DescribeSecurityGroups")
}
err = resp.Unmarshal(&secgroupResp)
part := struct {
SecurityGroupSet []SSecurityGroup `json:"SecurityGroupSet"`
NextToken string `json:"NextToken"`
}{}
err = resp.Unmarshal(&part)
if err != nil {
return nil, errors.Wrap(err, "unmarshal secgroups")
}
ret = append(ret, secgroupResp.SecurityGroupSet...)
if len(secgroupResp.NextToken) == 0 {
ret = append(ret, part.SecurityGroupSet...)
if len(part.NextToken) == 0 {
break
}
params["NextToken"] = secgroupResp.NextToken
params["NextToken"] = part.NextToken
}
return ret, nil
@@ -196,22 +164,54 @@ func (region *SRegion) GetSecurityGroup(id string) (*SSecurityGroup, error) {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, "security_group id:%s", id)
}
func (region *SRegion) CreateSecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (string, error) {
return "", errors.ErrNotImplemented
func (region *SRegion) CreateSecurityGroup(opts *cloudprovider.SecurityGroupCreateInput) (*SSecurityGroup, error) {
params := map[string]string{
"VpcId": opts.VpcId,
"SecurityGroupName": opts.Name,
}
if len(opts.Desc) > 0 {
params["Description"] = opts.Desc
}
resp, err := region.vpcRequest("CreateSecurityGroup", params)
if err != nil {
return nil, err
}
ret := &SSecurityGroup{region: region}
err = resp.Unmarshal(ret, "SecurityGroup")
if err != nil {
return nil, err
}
return ret, nil
}
func (region *SRegion) SetSecurityGroups(secgroupIds []string, instanceId string) error {
return errors.ErrNotImplemented
func (region *SRegion) SetSecurityGroups(secgroupIds []string, instanceId, nicId, subnetId string) error {
params := map[string]string{
"InstanceId": instanceId,
"NetworkInterfaceId": nicId,
"SubnetId": subnetId,
}
for i, secgroupId := range secgroupIds {
params[fmt.Sprintf("SecurityGroupId.%d", i+1)] = secgroupId
}
_, err := region.ecsRequest("ModifyNetworkInterfaceAttribute", params)
if err != nil {
return err
}
return nil
}
func (region *SRegion) DeleteSecurityGroup(secGrpId string) error {
return errors.ErrNotImplemented
}
func (region *SSecurityGroup) GetProjectId() string {
func (sg *SSecurityGroup) GetProjectId() string {
return ""
}
func (sg *SSecurityGroup) Delete() error {
return errors.ErrNotImplemented
return sg.region.DeleteSecurityGroup(sg.SecurityGroupId)
}
func (region *SRegion) DeleteSecurityGroup(secGrpId string) error {
params := map[string]string{
"SecurityGroupId": secGrpId,
}
_, err := region.vpcRequest("DeleteSecurityGroup", params)
return err
}
+229
View File
@@ -0,0 +1,229 @@
// 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 ksyun
import (
"fmt"
"strings"
"time"
api "yunion.io/x/cloudmux/pkg/apis/compute"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
"yunion.io/x/jsonutils"
)
/*
{
"SnapshotId": "780618d7-05d0-4445-8905-94a5a1fe8a3d",
"SnapshotName": "test-snap",
"SnapshotDesc": "",
"VolumeId": "d9329bb8-fa1d-4e13-ac36-64096fea1a3a",
"Size": 20,
"BillSize": "0",
"ProjectAvailable": true,
"ProjectId": 0,
"CreateTime": "2025-09-25 16:53:41",
"SnapshotStatus": "available",
"VolumeCategory": "data",
"VolumeName": "test-disk",
"VolumeType": "SSD3.0",
"Progress": "100%",
"AvailabilityZone": "cn-beijing-6a",
"VolumeStatus": "available",
"SnapshotType": "CommonSnapShot",
"AutoSnapshot": false,
"ImageRelated": false,
"CopyFrom": false,
"EbsClusterType": "Public"
}
*/
type SSnapshot struct {
multicloud.SVirtualResourceBase
SKsyunTags
region *SRegion
SnapshotId string
VolumeId string
SnapshotName string
SnapshotDesc string
Size int
BillSize string
ProjectAvailable bool
ProjectId int
SnapshotStatus string
VolumeCategory string
VolumeName string
VolumeType string
Progress string
AvailabilityZone string
VolumeStatus string
SnapshotType string
AutoSnapshot bool
ImageRelated bool
CopyFrom bool
EbsClusterType string
CreateTime time.Time
}
func (snap *SSnapshot) GetId() string {
return snap.SnapshotId
}
func (snap *SSnapshot) GetName() string {
if len(snap.SnapshotName) > 0 {
return snap.SnapshotName
}
return snap.SnapshotId
}
func (snap *SSnapshot) GetStatus() string {
switch snap.SnapshotStatus {
case "available":
return api.SNAPSHOT_READY
case "creating":
return api.SNAPSHOT_CREATING
case "failed":
return api.SNAPSHOT_FAILED
default:
return strings.ToLower(snap.SnapshotStatus)
}
}
func (snap *SSnapshot) GetSizeMb() int32 {
return int32(snap.Size * 1024)
}
func (snap *SSnapshot) GetDiskId() string {
return snap.VolumeId
}
func (snap *SSnapshot) GetDiskType() string {
if snap.VolumeCategory == "data" {
return api.DISK_TYPE_DATA
} else if snap.VolumeCategory == "system" {
return api.DISK_TYPE_SYS
} else {
return ""
}
}
func (snap *SSnapshot) Refresh() error {
ret, err := snap.region.GetSnapshot(snap.SnapshotId)
if err != nil {
return err
}
return jsonutils.Update(snap, ret)
}
func (snap *SSnapshot) GetGlobalId() string {
return snap.SnapshotId
}
func (region *SRegion) GetISnapshots() ([]cloudprovider.ICloudSnapshot, error) {
snapshots, err := region.GetSnapshots("", "")
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudSnapshot{}
for i := 0; i < len(snapshots); i += 1 {
snapshots[i].region = region
ret[i] = &snapshots[i]
}
return ret, nil
}
func (self *SSnapshot) Delete() error {
return self.region.DeleteSnapshot(self.SnapshotId)
}
func (region *SRegion) CreateSnapshot(diskId, name, desc string) (*SSnapshot, error) {
params := map[string]string{
"VolumeId": diskId,
"SnapshotName": name,
"SnapshotDesc": desc,
}
body, err := region.ebsRequest("CreateSnapshot", params)
if err != nil {
return nil, err
}
id, err := body.GetString("SnapshotId")
if err != nil {
return nil, err
}
return region.GetSnapshot(id)
}
func (region *SRegion) GetSnapshots(snapshotId, volumeId string) ([]SSnapshot, error) {
params := map[string]string{
"PageSize": "1000",
}
if len(snapshotId) > 0 {
params["SnapshotId"] = snapshotId
}
if len(volumeId) > 0 {
params["VolumeId"] = volumeId
}
PageNumber := 1
ret := []SSnapshot{}
for {
params["PageNumber"] = fmt.Sprintf("%d", PageNumber)
body, err := region.ebsRequest("DescribeSnapshots", params)
if err != nil {
return nil, err
}
part := struct {
Snapshots []SSnapshot
Page struct {
TotalCount int64
}
}{}
err = body.Unmarshal(&part)
if err != nil {
return nil, err
}
ret = append(ret, part.Snapshots...)
if len(part.Snapshots) == 0 || len(ret) > int(part.Page.TotalCount) {
break
}
PageNumber++
}
return ret, nil
}
func (region *SRegion) GetSnapshot(id string) (*SSnapshot, error) {
snapshots, err := region.GetSnapshots("", id)
if err != nil {
return nil, err
}
for i := range snapshots {
snapshots[i].region = region
if snapshots[i].SnapshotId == id {
return &snapshots[i], nil
}
}
return nil, cloudprovider.ErrNotFound
}
func (region *SRegion) DeleteSnapshot(snapshotId string) error {
params := map[string]string{
"SnapshotId": snapshotId,
}
_, err := region.ebsRequest("DeleteSnapshot", params)
return err
}
+101
View File
@@ -0,0 +1,101 @@
// 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 ksyun
import (
"context"
"fmt"
"yunion.io/x/cloudmux/pkg/apis"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/cloudmux/pkg/multicloud"
)
type SStoragecache struct {
multicloud.SResourceBase
SKsyunTags
region *SRegion
}
func (cache *SStoragecache) GetId() string {
return fmt.Sprintf("%s-%s", cache.region.client.cpcfg.Id, cache.region.GetId())
}
func (cache *SStoragecache) GetName() string {
return fmt.Sprintf("%s-%s", cache.region.client.cpcfg.Name, cache.region.GetId())
}
func (cache *SStoragecache) GetStatus() string {
return apis.STATUS_AVAILABLE
}
func (cache *SStoragecache) Refresh() error {
return nil
}
func (cache *SStoragecache) GetGlobalId() string {
return fmt.Sprintf("%s-%s", cache.region.client.cpcfg.Id, cache.region.GetGlobalId())
}
func (cache *SStoragecache) GetICloudImages() ([]cloudprovider.ICloudImage, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (cache *SStoragecache) GetICustomizedCloudImages() ([]cloudprovider.ICloudImage, error) {
images, err := cache.region.GetImages("", "custom")
if err != nil {
return nil, err
}
ret := []cloudprovider.ICloudImage{}
for i := range images {
images[i].storageCache = cache
ret = append(ret, &images[i])
}
return ret, nil
}
func (cache *SStoragecache) GetIImageById(extId string) (cloudprovider.ICloudImage, error) {
img, err := cache.region.GetImage(extId)
if err != nil {
return nil, err
}
img.storageCache = cache
return img, nil
}
func (cache *SStoragecache) GetPath() string {
return ""
}
func (cache *SStoragecache) UploadImage(ctx context.Context, image *cloudprovider.SImageCreateOption, callback func(float32)) (string, error) {
return "", cloudprovider.ErrNotImplemented
}
func (region *SRegion) getStoragecache() *SStoragecache {
return &SStoragecache{region: region}
}
func (region *SRegion) GetIStoragecaches() ([]cloudprovider.ICloudStoragecache, error) {
cache := region.getStoragecache()
return []cloudprovider.ICloudStoragecache{cache}, nil
}
func (region *SRegion) GetIStoragecacheById(id string) (cloudprovider.ICloudStoragecache, error) {
storageCache := region.getStoragecache()
if id == storageCache.GetGlobalId() {
return storageCache, nil
}
return nil, cloudprovider.ErrNotFound
}
+10 -4
View File
@@ -33,7 +33,13 @@ type SStorage struct {
StorageType string
}
var ksDiskTypes = []string{"ESSD_PL1", "ESSD_PL2", "ESSD_PL3", "SSD3.0", "EHDD"}
var ksDiskTypes = []string{
api.STORAGE_KSYUN_ESSD_PL1,
api.STORAGE_KSYUN_ESSD_PL2,
api.STORAGE_KSYUN_ESSD_PL3,
api.STORAGE_KSYUN_SSD3_0,
api.STORAGE_KSYUN_EHDD,
}
func (storage *SStorage) GetId() string {
return fmt.Sprintf("%s-%s-%s", storage.zone.region.client.cpcfg.Id, storage.zone.GetId(), storage.StorageType)
@@ -96,8 +102,8 @@ func (storage *SStorage) GetEnabled() bool {
return true
}
func (storage *SStorage) CreateIDisk(conf *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) {
return nil, cloudprovider.ErrNotSupported
func (storage *SStorage) CreateIDisk(opts *cloudprovider.DiskCreateConfig) (cloudprovider.ICloudDisk, error) {
return storage.zone.region.CreateDisk(storage.StorageType, storage.zone.AvailabilityZone, opts)
}
func (storage *SStorage) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
@@ -127,7 +133,7 @@ func (storage *SStorage) DisableSync() bool {
}
func (storage *SStorage) GetIStoragecache() cloudprovider.ICloudStoragecache {
return nil
return storage.zone.region.getStoragecache()
}
func (storage *SStorage) GetStatus() string {
+29 -37
View File
@@ -32,7 +32,7 @@ type SVpc struct {
region *SRegion
IsDefault bool `json:"IsDefault"`
VpcID string `json:"VpcId"`
VpcId string `json:"VpcId"`
CreateTime string `json:"CreateTime"`
CidrBlock string `json:"CidrBlock"`
VpcName string `json:"VpcName"`
@@ -81,18 +81,18 @@ func (region *SRegion) GetVpc(id string) (*SVpc, error) {
}
func (vpc *SVpc) GetId() string {
return vpc.VpcID
return vpc.VpcId
}
func (vpc *SVpc) GetName() string {
if len(vpc.VpcName) > 0 {
return vpc.VpcName
}
return vpc.VpcID
return vpc.VpcId
}
func (vpc *SVpc) GetGlobalId() string {
return vpc.VpcID
return vpc.VpcId
}
func (vpc *SVpc) GetStatus() string {
@@ -139,7 +139,7 @@ func (vpc *SVpc) GetIWires() ([]cloudprovider.ICloudWire, error) {
}
func (vpc *SVpc) GetISecurityGroups() ([]cloudprovider.ICloudSecurityGroup, error) {
secgroups, err := vpc.region.GetSecurityGroups(vpc.VpcID, nil)
secgroups, err := vpc.region.GetSecurityGroups(vpc.VpcId, nil)
if err != nil {
return nil, errors.Wrap(err, "GetSecurityGroups")
}
@@ -160,11 +160,11 @@ func (vpc *SVpc) GetIRouteTableById(routeTableId string) (cloudprovider.ICloudRo
}
func (vpc *SVpc) Delete() error {
return cloudprovider.ErrNotImplemented
return vpc.region.DeleteVpc(vpc.VpcId)
}
func (vpc *SVpc) GetTags() (map[string]string, error) {
tags, err := vpc.region.ListTags("vpc", vpc.VpcID)
tags, err := vpc.region.ListTags("vpc", vpc.VpcId)
if err != nil {
return nil, err
}
@@ -184,35 +184,27 @@ func (vpc *SVpc) GetIWireById(wireId string) (cloudprovider.ICloudWire, error) {
return nil, errors.Wrapf(errors.ErrNotFound, "wire id:%s", wireId)
}
func (vpc *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) GetICloudVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) GetICloudAccepterVpcPeeringConnections() ([]cloudprovider.ICloudVpcPeeringConnection, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) GetICloudVpcPeeringConnectionById(id string) (cloudprovider.ICloudVpcPeeringConnection, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) CreateICloudVpcPeeringConnection(opts *cloudprovider.VpcPeeringConnectionCreateOptions) (cloudprovider.ICloudVpcPeeringConnection, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) AcceptICloudVpcPeeringConnection(id string) error {
return cloudprovider.ErrNotImplemented
}
func (vpc *SVpc) GetAuthorityOwnerId() string {
return ""
}
func (vpc *SRegion) DeleteVpc(vpcId string) error {
return cloudprovider.ErrNotImplemented
params := map[string]string{
"VpcId": vpcId,
}
_, err := vpc.vpcRequest("DeleteVpc", params)
return err
}
func (region *SRegion) CreateVpc(opts *cloudprovider.VpcCreateOptions) (*SVpc, error) {
params := map[string]string{
"VpcName": opts.NAME,
"CidrBlock": opts.CIDR,
}
body, err := region.vpcRequest("CreateVpc", params)
if err != nil {
return nil, err
}
ret := &SVpc{region: region}
err = body.Unmarshal(ret, "Vpc")
if err != nil {
return nil, errors.Wrap(err, "Unmarshal")
}
return ret, nil
}
+7 -2
View File
@@ -64,7 +64,7 @@ func (wire *SWire) GetIZone() cloudprovider.ICloudZone {
}
func (wire *SWire) GetINetworks() ([]cloudprovider.ICloudNetwork, error) {
networks, err := wire.vpc.region.GetNetworks([]string{wire.vpc.VpcID}, []string{}, wire.zone.GetName())
networks, err := wire.vpc.region.GetNetworks([]string{wire.vpc.VpcId}, []string{}, wire.zone.GetName())
if err != nil {
return nil, errors.Wrap(err, "GetNetworks")
}
@@ -81,7 +81,12 @@ func (wire *SWire) GetBandwidth() int {
}
func (wire *SWire) CreateINetwork(opts *cloudprovider.SNetworkCreateOptions) (cloudprovider.ICloudNetwork, error) {
return nil, cloudprovider.ErrNotImplemented
network, err := wire.vpc.region.CreateNetwork(wire.vpc.VpcId, wire.zone.AvailabilityZone, opts)
if err != nil {
return nil, err
}
network.wire = wire
return network, nil
}
func (wire *SWire) GetINetworkById(netid string) (cloudprovider.ICloudNetwork, error) {