From 13fae52ea3534e18dde32382187b0eeb838f3425 Mon Sep 17 00:00:00 2001 From: TangBin Date: Wed, 12 Dec 2018 18:56:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8D=E7=A7=B0=E5=90=8C=E6=AD=A5=E7=AD=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/compute/guestdrivers/aws.go | 15 ++++++++++++ pkg/compute/models/capabilities.go | 6 ++--- pkg/util/aws/eip.go | 25 ++++++++++++++++++-- pkg/util/aws/instance.go | 37 +++++++++++++++++++++++++++++- pkg/util/aws/securitygroup.go | 15 ++++++++---- pkg/util/aws/snapshot.go | 16 +++++++++---- pkg/util/aws/vpc.go | 2 +- 7 files changed, 101 insertions(+), 15 deletions(-) diff --git a/pkg/compute/guestdrivers/aws.go b/pkg/compute/guestdrivers/aws.go index ee0dc499db..8d773673f0 100644 --- a/pkg/compute/guestdrivers/aws.go +++ b/pkg/compute/guestdrivers/aws.go @@ -6,6 +6,7 @@ import ( "time" "yunion.io/x/onecloud/pkg/util/ansible" + "yunion.io/x/pkg/utils" "yunion.io/x/jsonutils" "yunion.io/x/log" @@ -75,6 +76,20 @@ func (self *SAwsGuestDriver) ValidateCreateData(ctx context.Context, userCred mc return self.SManagedVirtualizedGuestDriver.ValidateCreateData(ctx, userCred, data) } +func (self *SAwsGuestDriver) ValidateResizeDisk(guest *models.SGuest, disk *models.SDisk, storage *models.SStorage) error { + // https://docs.amazonaws.cn/AWSEC2/latest/UserGuide/stop-start.html + if !utils.IsInStringArray(guest.Status, []string{models.VM_RUNNING, models.VM_READY}) { + return fmt.Errorf("Cannot resize disk when guest in status %s", guest.Status) + } + if disk.DiskType == models.DISK_TYPE_SYS { + return fmt.Errorf("Cannot resize system disk") + } + if !utils.IsInStringArray(storage.StorageType, []string{models.STORAGE_GP2_SSD, models.STORAGE_IO1_SSD, models.STORAGE_ST1_HDD, models.STORAGE_SC1_SSD, models.STORAGE_STANDARD_SSD}) { + return fmt.Errorf("Cannot resize %s disk", storage.StorageType) + } + return nil +} + func (self *SAwsGuestDriver) RequestDeployGuestOnHost(ctx context.Context, guest *models.SGuest, host *models.SHost, task taskman.ITask) error { config := guest.GetDeployConfigOnHost(ctx, host, task.GetParams()) log.Debugf("RequestDeployGuestOnHost: %s", config) diff --git a/pkg/compute/models/capabilities.go b/pkg/compute/models/capabilities.go index f0bdff951f..4462fe4104 100644 --- a/pkg/compute/models/capabilities.go +++ b/pkg/compute/models/capabilities.go @@ -11,9 +11,9 @@ import ( ) type SCapabilities struct { - Hypervisors []string `json:",allowempty"` - StorageTypes []string `json:",allowempty"` - GPUModels []string `json:",allowempty"` + Hypervisors []string `json:",allowempty"` + StorageTypes []string `json:",allowempty"` + GPUModels []string `json:",allowempty"` MinNicCount int MaxNicCount int MinDataDiskCount int diff --git a/pkg/util/aws/eip.go b/pkg/util/aws/eip.go index 61fac8ac4f..393e5bbef7 100644 --- a/pkg/util/aws/eip.go +++ b/pkg/util/aws/eip.go @@ -30,6 +30,7 @@ type SEipAddress struct { NetworkInterfaceOwnerId string PrivateIpAddress string IpAddress string + Name string } func (self *SEipAddress) GetId() string { @@ -37,7 +38,11 @@ func (self *SEipAddress) GetId() string { } func (self *SEipAddress) GetName() string { - return self.IpAddress + if len(self.Name) == 0 { + return self.IpAddress + } + + return self.Name } func (self *SEipAddress) GetGlobalId() string { @@ -177,6 +182,7 @@ func (self *SRegion) GetEips(eipId string, offset int, limit int) ([]SEipAddress NetworkInterfaceOwnerId: *ip.NetworkInterfaceOwnerId, PrivateIpAddress: *ip.PrivateIpAddress, IpAddress: *ip.PublicIp, + Name: tagspec.GetNameTag(), }) } return eips, len(eips), nil @@ -212,7 +218,22 @@ func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) { func (self *SRegion) CreateEIP(name string, bwMbps int, chargeType string) (cloudprovider.ICloudEIP, error) { // todo: aws 不支持指定bwMbps, chargeType ? log.Debugf("CreateEip: aws not support specific params name/bwMbps/chargeType.") - return self.AllocateEIP("vpc") + ieip, err := self.AllocateEIP("vpc") + if err == nil && len(name) > 0 { + eipId := ieip.GetId() + k := "Name" + nameTag := &ec2.Tag{Key: &k, Value: &name} + params := &ec2.CreateTagsInput{} + params.SetResources([]*string{&eipId}) + params.SetTags([]*ec2.Tag{nameTag}) + + // name 创建成功与否不影响eip的正常使用 + if _, e := self.ec2Client.CreateTags(params); e != nil { + log.Infof("CreateEIP create name tag failed: %s", e) + } + } + + return ieip, err } func (self *SRegion) DeallocateEIP(eipId string) error { diff --git a/pkg/util/aws/instance.go b/pkg/util/aws/instance.go index 963798331d..2ca2e53682 100644 --- a/pkg/util/aws/instance.go +++ b/pkg/util/aws/instance.go @@ -689,9 +689,23 @@ func (self *SRegion) DeleteVM(instanceId string) error { return err } + // 检查删除保护状态.如果已开启则先关闭删除保护再进行删除操作 + protect, err := self.deleteProtectStatusVM(instanceId) + if err != nil { + return err + } + + if protect { + log.Warningf("DeleteVM instance %s which termination protect is in open status", instanceId) + err = self.deleteProtectVM(instanceId, false) + if err != nil { + return err + } + } + params := &ec2.TerminateInstancesInput{} params.SetInstanceIds([]*string{&instanceId}) - _, err := self.ec2Client.TerminateInstances(params) + _, err = self.ec2Client.TerminateInstances(params) return err } @@ -855,6 +869,27 @@ func (self *SRegion) AttachDisk(instanceId string, diskId string, deviceName str return err } +func (self *SRegion) deleteProtectStatusVM(instanceId string) (bool, error) { + p := &ec2.DescribeInstanceAttributeInput{} + p.SetInstanceId(instanceId) + p.SetAttribute("disableApiTermination") + ret, err := self.ec2Client.DescribeInstanceAttribute(p) + if err != nil { + return false, err + } + + return *ret.DisableApiTermination.Value, nil +} + +func (self *SRegion) deleteProtectVM(instanceId string, disableDelete bool) error { + p2 := &ec2.ModifyInstanceAttributeInput{ + DisableApiTermination: &ec2.AttributeBooleanValue{Value: &disableDelete}, + InstanceId: &instanceId, + } + _, err := self.ec2Client.ModifyInstanceAttribute(p2) + return err +} + func (self *SInstance) CreateDisk(ctx context.Context, sizeMb int, uuid string, driver string) error { return cloudprovider.ErrNotSupported } diff --git a/pkg/util/aws/securitygroup.go b/pkg/util/aws/securitygroup.go index 1d06c72dce..70740edd17 100644 --- a/pkg/util/aws/securitygroup.go +++ b/pkg/util/aws/securitygroup.go @@ -218,6 +218,9 @@ func (self *SRegion) createSecurityGroup(vpcId string, name string, secgroupIdTa } tagspec := TagSpec{ResourceType: "security-group"} + if len(secgroupIdTag) > 0 { + tagspec.SetTag("id", secgroupIdTag) + } tagspec.SetNameTag(name) tagspec.SetDescTag(desc) tags, _ := tagspec.GetTagSpecifications() @@ -288,7 +291,11 @@ func (self *SRegion) GetSecurityGroupDetails(secGroupId string) (*SSecurityGroup } } -func (self *SRegion) getSecurityGroupByTag(vpcId, secgroupId string) (*SSecurityGroup, error) { +func (self *SRegion) getSecurityGroupById(vpcId, secgroupId string) (*SSecurityGroup, error) { + if len(secgroupId) == 0 { + return nil, httperrors.NewInputParameterError("security group id should not be empty") + } + secgroups, total, err := self.GetSecurityGroups(vpcId, secgroupId, 0, 0) if err != nil { return nil, err @@ -408,15 +415,15 @@ func (self *SRegion) getSecRules(ingress []*ec2.IpPermission, egress []*ec2.IpPe return rules } -func (self *SRegion) GetSecurityGroups(vpcId string, secgroupIdTag string, offset int, limit int) ([]SSecurityGroup, int, error) { +func (self *SRegion) GetSecurityGroups(vpcId string, secgroupId string, offset int, limit int) ([]SSecurityGroup, int, error) { params := &ec2.DescribeSecurityGroupsInput{} filters := make([]*ec2.Filter, 0) if len(vpcId) > 0 { filters = AppendSingleValueFilter(filters, "vpc-id", vpcId) } - if len(secgroupIdTag) > 0 { - filters = AppendSingleValueFilter(filters, "tag:id", secgroupIdTag) + if len(secgroupId) > 0 { + params.SetGroupIds([]*string{&secgroupId}) } if len(filters) > 0 { diff --git a/pkg/util/aws/snapshot.go b/pkg/util/aws/snapshot.go index eb61b9c38a..b01b6296ef 100644 --- a/pkg/util/aws/snapshot.go +++ b/pkg/util/aws/snapshot.go @@ -41,6 +41,10 @@ func (self *SSnapshot) GetId() string { } func (self *SSnapshot) GetName() string { + if len(self.SnapshotName) == 0 { + return self.SnapshotId + } + return self.SnapshotName } @@ -108,10 +112,10 @@ func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName filters = AppendSingleValueFilter(filters, "volume-id", diskId) } - // not supported. use Tag? - // if len(snapshotName) > 0 { - // filters = AppendSingleValueFilter(filters, "volume-id", diskId) - // } + if len(snapshotName) > 0 { + filters = AppendSingleValueFilter(filters, "tag:Name", snapshotName) + } + if len(filters) > 0 { params.SetFilters(filters) } @@ -135,6 +139,9 @@ func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName return nil, 0, err } + tagspec := TagSpec{ResourceType: "snapshot"} + tagspec.LoadingEc2Tags(item.Tags) + snapshot := SSnapshot{} snapshot.SnapshotId = *item.SnapshotId snapshot.Status = SnapshotStatusType(*item.State) @@ -144,6 +151,7 @@ func (self *SRegion) GetSnapshots(instanceId string, diskId string, snapshotName snapshot.SourceDiskId = *item.VolumeId snapshot.SourceDiskSize = int32(*item.VolumeSize) // snapshot.SourceDiskType + snapshot.SnapshotName = tagspec.GetNameTag() snapshots = append(snapshots, snapshot) } diff --git a/pkg/util/aws/vpc.go b/pkg/util/aws/vpc.go index cd9543a8c9..3c52986ff3 100644 --- a/pkg/util/aws/vpc.go +++ b/pkg/util/aws/vpc.go @@ -145,7 +145,7 @@ func (self *SRegion) SyncSecurityGroup(secgroupId string, vpcId string, name str secgroupId = fmt.Sprintf("%s-%s", vpcId, secgroupId) } - if secgroup, err := self.getSecurityGroupByTag(vpcId, secgroupId); err != nil { + if secgroup, err := self.getSecurityGroupById(vpcId, secgroupId); err != nil { if len(desc) == 0 { desc = fmt.Sprintf("security group %s for vpc %s", name, vpcId) }