diff --git a/pkg/cloudprovider/resources.go b/pkg/cloudprovider/resources.go index 48a77829c9..896e94069c 100644 --- a/pkg/cloudprovider/resources.go +++ b/pkg/cloudprovider/resources.go @@ -341,6 +341,8 @@ type ICloudVM interface { ResetToInstanceSnapshot(ctx context.Context, idStr string) error SaveImage(opts *SaveImageOptions) (ICloudImage, error) + + AllocatePublicIpAddress() (string, error) } type ICloudNic interface { diff --git a/pkg/compute/guestdrivers/aliyun.go b/pkg/compute/guestdrivers/aliyun.go index 6642a04534..c505754ac8 100644 --- a/pkg/compute/guestdrivers/aliyun.go +++ b/pkg/compute/guestdrivers/aliyun.go @@ -18,6 +18,8 @@ import ( "context" "fmt" + "yunion.io/x/log" + "yunion.io/x/pkg/errors" "yunion.io/x/pkg/utils" api "yunion.io/x/onecloud/pkg/apis/compute" @@ -27,6 +29,7 @@ import ( "yunion.io/x/onecloud/pkg/httperrors" "yunion.io/x/onecloud/pkg/mcclient" "yunion.io/x/onecloud/pkg/util/billing" + "yunion.io/x/onecloud/pkg/util/logclient" "yunion.io/x/onecloud/pkg/util/rbacutils" ) @@ -228,3 +231,18 @@ func (self *SAliyunGuestDriver) IsSupportPublicipToEip() bool { func (self *SAliyunGuestDriver) IsSupportSetAutoRenew() bool { return true } + +func (self *SAliyunGuestDriver) IsSupportPublicIp() bool { + return true +} + +func (self *SAliyunGuestDriver) RemoteActionAfterGuestCreated(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, host *models.SHost, iVM cloudprovider.ICloudVM, desc *cloudprovider.SManagedVMCreateConfig) { + if desc.PublicIpBw > 0 { + publicIp, err := iVM.AllocatePublicIpAddress() + if err != nil { + logclient.AddSimpleActionLog(guest, logclient.ACT_ALLOCATE, errors.Wrapf(err, "iVM.AllocatePublicIpAddress"), userCred, false) + return + } + log.Infof("AllocatePublicIpAddress for instance %s %s", guest.Name, publicIp) + } +} diff --git a/pkg/multicloud/aliyun/host.go b/pkg/multicloud/aliyun/host.go index c45b321472..1ea5b2ad7c 100644 --- a/pkg/multicloud/aliyun/host.go +++ b/pkg/multicloud/aliyun/host.go @@ -19,6 +19,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + "yunion.io/x/pkg/errors" api "yunion.io/x/onecloud/pkg/apis/compute" "yunion.io/x/onecloud/pkg/cloudprovider" @@ -178,16 +179,15 @@ func (self *SHost) CreateVM(desc *cloudprovider.SManagedVMCreateConfig) (cloudpr vmId, err := self._createVM(desc.Name, desc.ExternalImageId, desc.SysDisk, desc.Cpu, desc.MemoryMB, desc.InstanceType, desc.ExternalNetworkId, desc.IpAddr, desc.Description, desc.Password, desc.DataDisks, desc.PublicKey, desc.ExternalSecgroupId, desc.UserData, desc.BillingCycle, - desc.ProjectId, desc.OsType, desc.Tags) + desc.ProjectId, desc.OsType, desc.Tags, desc.SPublicIpInfo) if err != nil { return nil, err } vm, err := self.GetInstanceById(vmId) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "GetInstanceById") } - // err = vm.waitStatus(InstanceStatusStopped, time.Second*10, time.Second*1800) - return vm, err + return vm, nil } func (self *SHost) _createVM(name string, imgId string, @@ -195,7 +195,7 @@ func (self *SHost) _createVM(name string, imgId string, vswitchId string, ipAddr string, desc string, passwd string, dataDisks []cloudprovider.SDiskInfo, publicKey string, secgroupId string, userData string, bc *billing.SBillingCycle, projectId, osType string, - tags map[string]string, + tags map[string]string, publicIp cloudprovider.SPublicIpInfo, ) (string, error) { net := self.zone.getNetworkById(vswitchId) if net == nil { @@ -251,7 +251,7 @@ func (self *SHost) _createVM(name string, imgId string, if len(instanceType) > 0 { log.Debugf("Try instancetype : %s", instanceType) - vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType, tags) + vmId, err := self.zone.region.CreateInstance(name, imgId, instanceType, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType, tags, publicIp) if err != nil { log.Errorf("Failed for %s: %s", instanceType, err) return "", fmt.Errorf("Failed to create specification %s.%s", instanceType, err.Error()) @@ -271,7 +271,7 @@ func (self *SHost) _createVM(name string, imgId string, for _, instType := range instanceTypes { instanceTypeId := instType.InstanceTypeId log.Debugf("Try instancetype : %s", instanceTypeId) - vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType, tags) + vmId, err = self.zone.region.CreateInstance(name, imgId, instanceTypeId, secgroupId, self.zone.ZoneId, desc, passwd, disks, vswitchId, ipAddr, keypair, userData, bc, projectId, osType, tags, publicIp) if err != nil { log.Errorf("Failed for %s: %s", instanceTypeId, err) } else { diff --git a/pkg/multicloud/aliyun/instance.go b/pkg/multicloud/aliyun/instance.go index beeeb4244c..d30ec42c7f 100644 --- a/pkg/multicloud/aliyun/instance.go +++ b/pkg/multicloud/aliyun/instance.go @@ -594,7 +594,7 @@ func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) { func (self *SRegion) CreateInstance(name string, imageId string, instanceType string, securityGroupId string, zoneId string, desc string, passwd string, disks []SDisk, vSwitchId string, ipAddr string, keypair string, userData string, bc *billing.SBillingCycle, projectId, osType string, - tags map[string]string, + tags map[string]string, publicIp cloudprovider.SPublicIpInfo, ) (string, error) { params := make(map[string]string) params["RegionId"] = self.RegionId @@ -607,6 +607,10 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st params["InternetChargeType"] = "PayByTraffic" params["InternetMaxBandwidthIn"] = "200" params["InternetMaxBandwidthOut"] = "100" + if publicIp.PublicIpBw > 0 && publicIp.PublicIpChargeType == cloudprovider.ElasticipChargeTypeByBandwidth { + params["InternetChargeType"] = "PayByBandwidth" + params["InternetMaxBandwidthOut"] = fmt.Sprintf("%d", publicIp.PublicIpBw) + } params["HostName"] = stringutils2.GenerateHostName(name, osType) if len(passwd) > 0 { params["Password"] = passwd @@ -697,6 +701,21 @@ func (self *SRegion) CreateInstance(name string, imageId string, instanceType st return instanceId, nil } +func (self *SRegion) AllocatePublicIpAddress(instanceId string) (string, error) { + params := map[string]string{ + "InstanceId": instanceId, + } + resp, err := self.ecsRequest("AllocatePublicIpAddress", params) + if err != nil { + return "", errors.Wrapf(err, "AllocatePublicIpAddress") + } + return resp.GetString("IpAddress") +} + +func (self *SInstance) AllocatePublicIpAddress() (string, error) { + return self.host.zone.region.AllocatePublicIpAddress(self.InstanceId) +} + func (self *SRegion) doStartVM(instanceId string) error { return self.instanceOperation(instanceId, "StartInstance", nil) } diff --git a/pkg/multicloud/instance_base.go b/pkg/multicloud/instance_base.go index 808ab8d0fd..ac08778036 100644 --- a/pkg/multicloud/instance_base.go +++ b/pkg/multicloud/instance_base.go @@ -66,3 +66,7 @@ func (instance *SInstanceBase) ResetToInstanceSnapshot(ctx context.Context, idSt func (self *SInstanceBase) SaveImage(opts *cloudprovider.SaveImageOptions) (cloudprovider.ICloudImage, error) { return nil, errors.Wrapf(cloudprovider.ErrNotImplemented, "SaveImage") } + +func (self *SInstanceBase) AllocatePublicIpAddress() (string, error) { + return "", errors.Wrapf(cloudprovider.ErrNotImplemented, "AllocatePublicIpAddress") +}