Files
cloudpods/pkg/util/aliyun/instance.go
T
2018-09-15 17:05:17 +08:00

784 lines
23 KiB
Go

package aliyun
import (
"fmt"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/osprofile"
"yunion.io/x/pkg/util/seclib"
"yunion.io/x/pkg/util/secrules"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/compute/models"
)
const (
// Running:运行中
//Starting:启动中
//Stopping:停止中
//Stopped:已停止
InstanceStatusStopped = "Stopped"
InstanceStatusRunning = "Running"
InstanceStatusStopping = "Stopping"
InstanceStatusStarting = "Starting"
)
type SDedicatedHostAttribute struct {
DedicatedHostId string
DedicatedHostName string
}
type SIpAddress struct {
IpAddress []string
}
type SNetworkInterfaces struct {
NetworkInterface []SNetworkInterface
}
type SNetworkInterface struct {
MacAddress string
NetworkInterfaceId string
PrimaryIpAddress string
}
type SOperationLocks struct {
LockReason []string
}
type SSecurityGroupIds struct {
SecurityGroupId []string
}
// {"NatIpAddress":"","PrivateIpAddress":{"IpAddress":["192.168.220.214"]},"VSwitchId":"vsw-2ze9cqwza4upoyujq1thd","VpcId":"vpc-2zer4jy8ix3i8f0coc5uw"}
type SVpcAttributes struct {
NatIpAddress string
PrivateIpAddress SIpAddress
VSwitchId string
VpcId string
}
type SInstance struct {
host *SHost
// idisks []cloudprovider.ICloudDisk
AutoReleaseTime string
ClusterId string
Cpu int8
CreationTime time.Time
DedicatedHostAttribute SDedicatedHostAttribute
Description string
DeviceAvailable bool
EipAddress SEipAddress
ExpiredTime time.Time
GPUAmount int
GPUSpec string
HostName string
ImageId string
InnerIpAddress SIpAddress
InstanceChargeType InstanceChargeType
InstanceId string
InstanceName string
InstanceNetworkType string
InstanceType string
InstanceTypeFamily string
InternetChargeType string
InternetMaxBandwidthIn int
InternetMaxBandwidthOut int
IoOptimized bool
KeyPairName string
Memory int
NetworkInterfaces SNetworkInterfaces
OSName string
OSType string
OperationLocks SOperationLocks
PublicIpAddress SIpAddress
Recyclable bool
RegionId string
ResourceGroupId string
SaleCycle string
SecurityGroupIds SSecurityGroupIds
SerialNumber string
SpotPriceLimit string
SpotStrategy string
StartTime time.Time
Status string
StoppedMode string
VlanId string
VpcAttributes SVpcAttributes
ZoneId string
}
// {"AutoReleaseTime":"","ClusterId":"","Cpu":1,"CreationTime":"2018-05-23T07:58Z","DedicatedHostAttribute":{"DedicatedHostId":"","DedicatedHostName":""},"Description":"","DeviceAvailable":true,"EipAddress":{"AllocationId":"","InternetChargeType":"","IpAddress":""},"ExpiredTime":"2018-05-30T16:00Z","GPUAmount":0,"GPUSpec":"","HostName":"iZ2ze57isp1ali72tzkjowZ","ImageId":"centos_7_04_64_20G_alibase_201701015.vhd","InnerIpAddress":{"IpAddress":[]},"InstanceChargeType":"PrePaid","InstanceId":"i-2ze57isp1ali72tzkjow","InstanceName":"gaoxianqi-test-7days","InstanceNetworkType":"vpc","InstanceType":"ecs.t5-lc2m1.nano","InstanceTypeFamily":"ecs.t5","InternetChargeType":"PayByBandwidth","InternetMaxBandwidthIn":-1,"InternetMaxBandwidthOut":0,"IoOptimized":true,"Memory":512,"NetworkInterfaces":{"NetworkInterface":[{"MacAddress":"00:16:3e:10:f0:c9","NetworkInterfaceId":"eni-2zecqsagtpztl6x5hu2r","PrimaryIpAddress":"192.168.220.214"}]},"OSName":"CentOS 7.4 64位","OSType":"linux","OperationLocks":{"LockReason":[]},"PublicIpAddress":{"IpAddress":[]},"Recyclable":false,"RegionId":"cn-beijing","ResourceGroupId":"","SaleCycle":"Week","SecurityGroupIds":{"SecurityGroupId":["sg-2zecqsagtpztl6x9zynl"]},"SerialNumber":"df05d9b4-df3d-4400-88d1-5f843f0dd088","SpotPriceLimit":0.000000,"SpotStrategy":"NoSpot","StartTime":"2018-05-23T07:58Z","Status":"Running","StoppedMode":"Not-applicable","VlanId":"","VpcAttributes":{"NatIpAddress":"","PrivateIpAddress":{"IpAddress":["192.168.220.214"]},"VSwitchId":"vsw-2ze9cqwza4upoyujq1thd","VpcId":"vpc-2zer4jy8ix3i8f0coc5uw"},"ZoneId":"cn-beijing-f"}
func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit int) ([]SInstance, int, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
if len(zoneId) > 0 {
params["ZoneId"] = zoneId
}
if ids != nil && len(ids) > 0 {
params["InstanceIds"] = jsonutils.Marshal(ids).String()
}
body, err := self.ecsRequest("DescribeInstances", params)
if err != nil {
log.Errorf("GetInstances fail %s", err)
return nil, 0, err
}
instances := make([]SInstance, 0)
err = body.Unmarshal(&instances, "Instances", "Instance")
if err != nil {
log.Errorf("Unmarshal security group details fail %s", err)
return nil, 0, err
}
total, _ := body.Int("TotalCount")
return instances, int(total), nil
}
func (self *SInstance) GetMetadata() *jsonutils.JSONDict {
data := jsonutils.NewDict()
// The pricingInfo key structure is 'RegionId::InstanceType::NetworkType::OSType::IoOptimized'
optimized := "optimized"
if !self.IoOptimized {
optimized = "none"
}
priceKey := fmt.Sprintf("%s::%s::%s::%s::%s", self.RegionId, self.InstanceType, self.InstanceNetworkType, self.OSType, optimized)
data.Add(jsonutils.NewString(priceKey), "price_key")
if len(self.ImageId) > 0 {
if image, err := self.host.zone.region.GetImage(self.ImageId); err != nil {
log.Errorf("Failed to find image %s for instance %s", self.ImageId, self.GetName())
} else if meta := image.GetMetadata(); meta != nil {
data.Update(meta)
}
}
return data
}
func (self *SInstance) GetCreateTime() time.Time {
return self.CreationTime
}
func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
return self.host
}
func (self *SInstance) GetId() string {
return self.InstanceId
}
func (self *SInstance) GetName() string {
return self.HostName
}
func (self *SInstance) GetGlobalId() string {
return self.InstanceId
}
func (self *SInstance) IsEmulated() bool {
return false
}
func (self *SInstance) getVpc() (*SVpc, error) {
return self.host.zone.region.getVpc(self.VpcAttributes.VpcId)
}
func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
disks, total, err := self.host.zone.region.GetDisks(self.InstanceId, "", "", nil, 0, 50)
if err != nil {
log.Errorf("fetchDisks fail %s", err)
return nil, err
}
if total > len(disks) {
disks, _, err = self.host.zone.region.GetDisks(self.InstanceId, "", "", nil, 0, total)
}
idisks := make([]cloudprovider.ICloudDisk, len(disks))
for i := 0; i < len(disks); i += 1 {
store, err := self.host.zone.getStorageByCategory(disks[i].Category)
if err != nil {
return nil, err
}
disks[i].storage = store
idisks[i] = &disks[i]
}
return idisks, nil
}
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
nics := make([]cloudprovider.ICloudNic, 0)
for _, ip := range self.VpcAttributes.PrivateIpAddress.IpAddress {
nic := SInstanceNic{instance: self, ipAddr: ip}
nics = append(nics, &nic)
}
return nics, nil
}
func (self *SInstance) GetVcpuCount() int8 {
return self.Cpu
}
func (self *SInstance) GetVmemSizeMB() int {
return self.Memory
}
func (self *SInstance) GetBootOrder() string {
return "dcn"
}
func (self *SInstance) GetVga() string {
return "std"
}
func (self *SInstance) GetVdi() string {
return "vnc"
}
func (self *SInstance) GetOSType() string {
return osprofile.NormalizeOSType(self.OSType)
}
func (self *SInstance) GetOSName() string {
return self.OSName
}
func (self *SInstance) GetBios() string {
return "BIOS"
}
func (self *SInstance) GetMachine() string {
return "pc"
}
func (self *SInstance) GetStatus() string {
// Running:运行中
//Starting:启动中
//Stopping:停止中
//Stopped:已停止
switch self.Status {
case InstanceStatusRunning:
return models.VM_RUNNING
case InstanceStatusStarting:
return models.VM_STARTING
case InstanceStatusStopping:
return models.VM_STOPPING
case InstanceStatusStopped:
return models.VM_READY
default:
return models.VM_UNKNOWN
}
}
func (self *SInstance) Refresh() error {
new, err := self.host.zone.region.GetInstance(self.InstanceId)
if err != nil {
return err
}
return jsonutils.Update(self, new)
}
/*
func (self *SInstance) GetRemoteStatus() string {
// Running:运行中
//Starting:启动中
//Stopping:停止中
//Stopped:已停止
switch self.Status {
case InstanceStatusRunning:
return cloudprovider.CloudVMStatusRunning
case InstanceStatusStarting:
return cloudprovider.CloudVMStatusStopped
case InstanceStatusStopping:
return cloudprovider.CloudVMStatusRunning
case InstanceStatusStopped:
return cloudprovider.CloudVMStatusStopped
default:
return cloudprovider.CloudVMStatusOther
}
}
*/
func (self *SInstance) GetHypervisor() string {
return models.HYPERVISOR_ALIYUN
}
func (self *SInstance) StartVM() error {
timeout := 300*time.Second
interval := 15*time.Second
startTime := time.Now()
for time.Now().Sub(startTime) < timeout {
err := self.Refresh()
if err != nil {
return err
}
log.Debugf("status %s expect %s", self.GetStatus(), models.VM_RUNNING)
if self.GetStatus() == models.VM_RUNNING {
return nil
} else if self.GetStatus() == models.VM_READY {
err := self.host.zone.region.StartVM(self.InstanceId)
if err != nil {
return err
}
}
time.Sleep(interval)
}
return cloudprovider.ErrTimeout
}
func (self *SInstance) StopVM(isForce bool) error {
err := self.host.zone.region.StopVM(self.InstanceId, isForce)
if err != nil {
return err
}
return cloudprovider.WaitStatus(self, models.VM_READY, 10*time.Second, 300*time.Second) // 5mintues
}
func (self *SInstance) GetVNCInfo() (jsonutils.JSONObject, error) {
url, err := self.host.zone.region.GetInstanceVNCUrl(self.InstanceId)
if err != nil {
return nil, err
}
passwd := seclib.RandomPassword(6)
err = self.host.zone.region.ModifyInstanceVNCUrlPassword(self.InstanceId, passwd)
if err != nil {
return nil, err
}
ret := jsonutils.NewDict()
ret.Add(jsonutils.NewString(url), "url")
ret.Add(jsonutils.NewString(passwd), "password")
ret.Add(jsonutils.NewString("aliyun"), "protocol")
ret.Add(jsonutils.NewString(self.InstanceId), "instance_id")
return ret, nil
}
func (self *SInstance) UpdateVM(name string) error {
return self.host.zone.region.UpdateVM(self.InstanceId, name)
}
func (self *SInstance) DeployVM(name string, password string, publicKey string, deleteKeypair bool, description string) error {
var keypairName string
if len(publicKey) > 0 {
var err error
keypairName, err = self.host.zone.region.syncKeypair(publicKey)
if err != nil {
return err
}
}
return self.host.zone.region.DeployVM(self.InstanceId, name, password, keypairName, deleteKeypair, description)
}
func (self *SInstance) RebuildRoot(imageId string, passwd string, publicKey string, sysSizeGB int) (string, error) {
keypair := ""
if len(publicKey) > 0 {
var err error
keypair, err = self.host.zone.region.syncKeypair(publicKey)
if err != nil {
return "", err
}
}
diskId, err := self.host.zone.region.ReplaceSystemDisk(self.InstanceId, imageId, passwd, keypair, sysSizeGB)
if err != nil {
return "", err
}
return diskId, nil
}
func (self *SInstance) ChangeConfig(instanceId string, ncpu int, vmem int) error {
return self.host.zone.region.ChangeVMConfig(self.ZoneId, self.InstanceId, ncpu, vmem, nil)
}
func (self *SInstance) AttachDisk(diskId string) error {
return self.host.zone.region.AttachDisk(self.InstanceId, diskId)
}
func (self *SInstance) DetachDisk(diskId string) error {
return self.host.zone.region.DetachDisk(self.InstanceId, diskId)
}
func (self *SRegion) GetInstance(instanceId string) (*SInstance, error) {
instances, _, err := self.GetInstances("", []string{instanceId}, 0, 1)
if err != nil {
return nil, err
}
if len(instances) == 0 {
return nil, cloudprovider.ErrNotFound
}
return &instances[0], nil
}
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) (string, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["ImageId"] = imageId
params["InstanceType"] = instanceType
params["SecurityGroupId"] = securityGroupId
params["ZoneId"] = zoneId
params["InstanceName"] = name
params["Description"] = desc
params["InternetChargeType"] = "PayByTraffic"
params["InternetMaxBandwidthIn"] = "200"
params["InternetMaxBandwidthOut"] = "100"
params["HostName"] = name
if len(passwd) > 0 {
params["Password"] = passwd
} else {
params["PasswordInherit"] = "True"
}
params["IoOptimized"] = "optimized"
for i, d := range disks {
if i == 0 {
params["SystemDisk.Category"] = d.Category
params["SystemDisk.Size"] = fmt.Sprintf("%d", d.Size)
params["SystemDisk.DiskName"] = d.GetName()
params["SystemDisk.Description"] = d.Description
} else {
params[fmt.Sprintf("DataDisk.%d.Size", i)] = fmt.Sprintf("%d", d.Size)
params[fmt.Sprintf("DataDisk.%d.Category", i)] = d.Category
params[fmt.Sprintf("DataDisk.%d.DiskName", i)] = d.GetName()
params[fmt.Sprintf("DataDisk.%d.Description", i)] = d.Description
params[fmt.Sprintf("DataDisk.%d.Encrypted", i)] = "false"
}
}
params["VSwitchId"] = vSwitchId
params["PrivateIpAddress"] = ipAddr
params["InstanceChargeType"] = "PostPaid"
params["SpotStrategy"] = "NoSpot"
if len(keypair) > 0 {
params["KeyPairName"] = keypair
}
params["ClientToken"] = utils.GenRequestId(20)
body, err := self.ecsRequest("CreateInstance", params)
if err != nil {
log.Errorf("CreateInstance fail %s", err)
return "", err
}
instanceId, _ := body.GetString("InstanceId")
return instanceId, nil
}
func (self *SRegion) doStartVM(instanceId string) error {
return self.instanceOperation(instanceId, "StartInstance", nil)
}
func (self *SRegion) doStopVM(instanceId string, isForce bool) error {
params := make(map[string]string)
if isForce {
params["ForceStop"] = "true"
} else {
params["ForceStop"] = "false"
}
params["StoppedMode"] = "KeepCharging"
return self.instanceOperation(instanceId, "StopInstance", params)
}
func (self *SRegion) doDeleteVM(instanceId string) error {
params := make(map[string]string)
params["TerminateSubscription"] = "false"
params["Force"] = "true"
return self.instanceOperation(instanceId, "DeleteInstance", params)
}
/*func (self *SRegion) waitInstanceStatus(instanceId string, target string, interval time.Duration, timeout time.Duration) error {
startTime := time.Now()
for time.Now().Sub(startTime) < timeout {
status, err := self.GetInstanceStatus(instanceId)
if err != nil {
return err
}
if status == target {
return nil
}
time.Sleep(interval)
}
return cloudprovider.ErrTimeout
}
func (self *SInstance) waitStatus(target string, interval time.Duration, timeout time.Duration) error {
return self.host.zone.region.waitInstanceStatus(self.InstanceId, target, interval, timeout)
}*/
func (self *SRegion) StartVM(instanceId string) error {
status, err := self.GetInstanceStatus(instanceId)
if err != nil {
log.Errorf("Fail to get instance status on StartVM: %s", err)
return err
}
if status != InstanceStatusStopped {
log.Errorf("StartVM: vm status is %s expect %s", status, InstanceStatusStopped)
return cloudprovider.ErrInvalidStatus
}
return self.doStartVM(instanceId)
// if err != nil {
// return err
// }
// return self.waitInstanceStatus(instanceId, InstanceStatusRunning, time.Second*5, time.Second*180) // 3 minutes to timeout
}
func (self *SRegion) StopVM(instanceId string, isForce bool) error {
status, err := self.GetInstanceStatus(instanceId)
if err != nil {
log.Errorf("Fail to get instance status on StopVM: %s", err)
return err
}
if status != InstanceStatusRunning {
log.Errorf("StopVM: vm status is %s expect %s", status, InstanceStatusRunning)
return cloudprovider.ErrInvalidStatus
}
return self.doStopVM(instanceId, isForce)
// if err != nil {
// return err
// }
// return self.waitInstanceStatus(instanceId, InstanceStatusStopped, time.Second*10, time.Second*300) // 5 minutes to timeout
}
func (self *SRegion) DeleteVM(instanceId string) error {
status, err := self.GetInstanceStatus(instanceId)
if err != nil {
log.Errorf("Fail to get instance status on DeleteVM: %s", err)
return err
}
log.Debugf("Instance status on delete is %s", status)
if status != InstanceStatusStopped {
log.Warningf("DeleteVM: vm status is %s expect %s", status, InstanceStatusStopped)
}
return self.doDeleteVM(instanceId)
// if err != nil {
// return err
// }
// err = self.waitInstanceStatus(instanceId, InstanceStatusRunning, time.Second*10, time.Second*300) // 5 minutes to timeout
// if err == cloudprovider.ErrNotFound {
// return nil
// } else if err == nil {
// return cloudprovider.ErrTimeout
// } else {
// return err
// }
}
func (self *SRegion) DeployVM(instanceId string, name string, password string, keypairName string, deleteKeypair bool, description string) error {
instance, err := self.GetInstance(instanceId)
if err != nil {
return err
}
// 修改密钥时直接返回
if deleteKeypair {
err = self.DetachKeyPair(instanceId, instance.KeyPairName)
if err != nil {
return err
}
}
if len(keypairName) > 0 {
err = self.AttachKeypair(instanceId, keypairName)
if err != nil {
return err
}
}
params := make(map[string]string)
// if resetPassword {
// params["Password"] = seclib2.RandomPassword2(12)
// }
// 指定密码的情况下,使用指定的密码
if len(password) > 0 {
params["Password"] = password
}
if len(name) > 0 && instance.InstanceName != name {
params["InstanceName"] = name
params["HostName"] = name
}
if len(description) > 0 && instance.Description != description {
params["Description"] = description
}
if len(params) > 0 {
return self.modifyInstanceAttribute(instanceId, params)
} else {
return nil
}
}
func (self *SInstance) DeleteVM() error {
for {
err := self.host.zone.region.DeleteVM(self.InstanceId)
if err != nil {
if isError(err, "IncorrectInstanceStatus.Initializing") {
log.Infof("The instance is initializing, try later ...")
time.Sleep(10 * time.Second)
} else {
return err
}
} else {
break
}
}
return cloudprovider.WaitDeleted(self, 10*time.Second, 300*time.Second) // 5minutes
}
func (self *SRegion) UpdateVM(instanceId string, hostname string) error {
/*
api: ModifyInstanceAttribute
https://help.aliyun.com/document_detail/25503.html?spm=a2c4g.11186623.4.1.DrgpjW
*/
params := make(map[string]string)
params["HostName"] = hostname
return self.modifyInstanceAttribute(instanceId, params)
}
func (self *SRegion) modifyInstanceAttribute(instanceId string, params map[string]string) error {
return self.instanceOperation(instanceId, "ModifyInstanceAttribute", params)
}
func (self *SRegion) ReplaceSystemDisk(instanceId string, imageId string, passwd string, keypairName string, sysDiskSizeGB int) (string, error) {
params := make(map[string]string)
params["RegionId"] = self.RegionId
params["InstanceId"] = instanceId
params["ImageId"] = imageId
if len(passwd) > 0 {
params["Password"] = passwd
} else {
params["PasswordInherit"] = "True"
}
if len(keypairName) > 0 {
params["KeyPairName"] = keypairName
}
if sysDiskSizeGB > 0 {
params["SystemDisk.Size"] = fmt.Sprintf("%d", sysDiskSizeGB)
}
body, err := self.ecsRequest("ReplaceSystemDisk", params)
if err != nil {
return "", err
}
// log.Debugf("%s", body.String())
return body.GetString("DiskId")
}
func (self *SRegion) ChangeVMConfig(zoneId string, instanceId string, ncpu int, vmem int, disks []*SDisk) error {
// todo: support change disk config?
params := make(map[string]string)
instanceTypes, e := self.GetMatchInstanceTypes(ncpu, vmem, 0, zoneId)
if e != nil {
return e
}
for _, instancetype := range instanceTypes {
params["InstanceType"] = instancetype.InstanceTypeId
params["ClientToken"] = utils.GenRequestId(20)
if err := self.instanceOperation(instanceId, "ModifyInstanceSpec", params); err != nil {
log.Errorf("Failed for %s: %s", instancetype.InstanceTypeId, err)
} else {
return nil
}
}
return fmt.Errorf("Failed to change vm config, specification not supported")
}
func (self *SRegion) DetachDisk(instanceId string, diskId string) error {
params := make(map[string]string)
params["InstanceId"] = instanceId
params["DiskId"] = diskId
log.Infof("Detach instance %s disk %s", instanceId, diskId)
_, err := self.ecsRequest("DetachDisk", params)
if err != nil {
log.Errorf("DetachDisk %s to %s fail %s", diskId, instanceId, err)
return err
}
return nil
}
func (self *SRegion) AttachDisk(instanceId string, diskId string) error {
params := make(map[string]string)
params["InstanceId"] = instanceId
params["DiskId"] = diskId
_, err := self.ecsRequest("AttachDisk", params)
if err != nil {
log.Errorf("AttachDisk %s to %s fail %s", diskId, instanceId, err)
return err
}
return nil
}
func (self *SInstance) SyncSecurityGroup(secgroupId string, name string, rules []secrules.SecurityRule) error {
if vpc, err := self.getVpc(); err != nil {
return err
} else if len(secgroupId) == 0 {
for index, secgrpId := range self.SecurityGroupIds.SecurityGroupId {
if err := vpc.revokeSecurityGroup(secgrpId, self.InstanceId, index == 0); err != nil {
return err
}
}
} else if secgrpId, err := vpc.SyncSecurityGroup(secgroupId, name, rules); err != nil {
return err
} else if err := vpc.assignSecurityGroup(secgrpId, self.InstanceId); err != nil {
return err
} else {
for _, secgroupId := range self.SecurityGroupIds.SecurityGroupId {
if secgroupId != secgrpId {
if err := vpc.revokeSecurityGroup(secgroupId, self.InstanceId, false); err != nil {
return err
}
}
}
self.SecurityGroupIds.SecurityGroupId = []string{secgrpId}
}
return nil
}
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
if len(self.PublicIpAddress.IpAddress) > 0 {
eip := SEipAddress{}
eip.region = self.host.zone.region
eip.IpAddress = self.PublicIpAddress.IpAddress[0]
eip.InstanceId = self.InstanceId
eip.InstanceType = EIP_INSTANCE_TYPE_ECS
eip.Status = EIP_STATUS_INUSE
eip.AllocationId = self.InstanceId // fixed
eip.AllocationTime = self.CreationTime
eip.Bandwidth = self.InternetMaxBandwidthOut
eip.InternetChargeType = self.InternetChargeType
return &eip, nil
} else if len(self.EipAddress.IpAddress) > 0 {
return self.host.zone.region.GetEip(self.EipAddress.AllocationId)
} else {
return nil, nil
}
}
func (self *SInstance) GetBillingType() string {
switch self.InstanceChargeType {
case PrePaidInstanceChargeType:
return models.BILLING_TYPE_PREPAID
case PostPaidInstanceChargeType:
return models.BILLING_TYPE_POSTPAID
default:
return models.BILLING_TYPE_PREPAID
}
}
func (self *SInstance) GetExpiredAt() time.Time {
return self.ExpiredTime
}