| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713 |
- // 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"
- "strings"
- "time"
- billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
- 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/log"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/imagetools"
- "yunion.io/x/pkg/utils"
- )
- type InstanceConfigure struct {
- Vcpu int `json:"VCPU"`
- Gpu int `json:"GPU"`
- MemoryGb int `json:"MemoryGb"`
- DataDiskGb int `json:"DataDiskGb"`
- RootDiskGb int `json:"RootDiskGb"`
- DataDiskType string `json:"DataDiskType"`
- Vgpu string `json:"VGPU"`
- }
- type InstanceState struct {
- Name string `json:"Name"`
- OnMigrate bool `json:"OnMigrate"`
- CostTime string `json:"CostTime"`
- TimeStamp string `json:"TimeStamp"`
- }
- type Monitoring struct {
- State string `json:"State"`
- }
- type GroupSet struct {
- GroupID string `json:"GroupId"`
- }
- type InstanceSecurityGroupSet struct {
- SecurityGroupId string `json:"SecurityGroupId"`
- }
- type NetworkInterfaceSet struct {
- AllocationId string `json:"AllocationId"`
- NetworkInterfaceId string `json:"NetworkInterfaceId"`
- NetworkInterfaceType string `json:"NetworkInterfaceType"`
- VpcId string `json:"VpcId"`
- SubnetId string `json:"SubnetId"`
- MacAddress string `json:"MacAddress"`
- PrivateIPAddress string `json:"PrivateIpAddress"`
- GroupSet []GroupSet `json:"GroupSet"`
- SecurityGroupSet []InstanceSecurityGroupSet `json:"SecurityGroupSet"`
- NetworkInterfaceName string `json:"NetworkInterfaceName"`
- }
- type SystemDisk struct {
- DiskId string `json:"DiskId"`
- DiskType string `json:"DiskType"`
- DiskSize int `json:"DiskSize"`
- }
- type DataDisks struct {
- DiskId string `json:"DiskId"`
- DiskType string `json:"DiskType"`
- DiskSize int `json:"DiskSize"`
- DeleteWithInstance bool `json:"DeleteWithInstance"`
- Encrypted bool `json:"Encrypted"`
- }
- type SInstance struct {
- multicloud.SInstanceBase
- SKsyunTags
- host *SHost
- region *SRegion
- 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"`
- PrivateIPAddress string `json:"PrivateIpAddress"`
- InstanceState InstanceState `json:"InstanceState"`
- Monitoring Monitoring `json:"Monitoring"`
- NetworkInterfaceSet []NetworkInterfaceSet `json:"NetworkInterfaceSet"`
- SriovNetSupport string `json:"SriovNetSupport"`
- IsShowSriovNetSupport bool `json:"IsShowSriovNetSupport"`
- CreationDate time.Time `json:"CreationDate"`
- AvailabilityZone string `json:"AvailabilityZone"`
- AvailabilityZoneName string `json:"AvailabilityZoneName"`
- DedicatedUuid string `json:"DedicatedUuid"`
- ProductType int `json:"ProductType"`
- ProductWhat int `json:"ProductWhat"`
- LiveUpgradeSupport bool `json:"LiveUpgradeSupport"`
- ChargeType string `json:"ChargeType"`
- SystemDisk SystemDisk `json:"SystemDisk"`
- HostName string `json:"HostName"`
- UserData string `json:"UserData"`
- Migration int `json:"Migration"`
- DataDisks []DataDisks `json:"DataDisks"`
- VncSupport bool `json:"VncSupport"`
- Platform string `json:"Platform"`
- ServiceEndTime time.Time `json:"ServiceEndTime"`
- BootMode string `json:"BootMode"`
- }
- func (region *SRegion) GetInstances(zoneName string, instanceIds []string) ([]SInstance, error) {
- projectIds, err := region.client.GetSplitProjectIds()
- if err != nil {
- return nil, err
- }
- ret := []SInstance{}
- for _, projects := range projectIds {
- part, err := region.getInstances(zoneName, instanceIds, projects)
- if err != nil {
- return nil, err
- }
- ret = append(ret, part...)
- }
- return ret, nil
- }
- func (region *SRegion) getInstances(zoneName string, instanceIds []string, projectIds []string) ([]SInstance, error) {
- instances := []SInstance{}
- params := map[string]interface{}{
- "MaxResults": "1000",
- "Marker": "0",
- }
- if len(zoneName) > 0 {
- params["Filter.1.Name"] = "availability-zone-name"
- params["Filter.1.Value.1"] = zoneName
- }
- for i, v := range instanceIds {
- params[fmt.Sprintf("InstanceId.%d", i+1)] = v
- }
- for i, v := range projectIds {
- params[fmt.Sprintf("ProjectId.%d", i+1)] = v
- }
- for {
- resp, err := region.ecsRequest("DescribeInstances", params)
- if err != nil {
- return nil, errors.Wrap(err, "list instance")
- }
- 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")
- }
- instances = append(instances, part.InstancesSet...)
- if len(instances) >= part.InstanceCount {
- break
- }
- params["Marker"] = fmt.Sprintf("%d", part.Marker)
- }
- return instances, nil
- }
- func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) {
- instances, err := region.GetInstances("", []string{instanceId})
- if err != nil {
- return nil, errors.Wrap(err, "GetInstances")
- }
- for i := range instances {
- if instances[i].GetGlobalId() == instanceId {
- return &instances[i], nil
- }
- }
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", instanceId)
- }
- func (ins *SInstance) Refresh() error {
- extIns, err := ins.getRegion().GetInstance(ins.GetGlobalId())
- if err != nil {
- return errors.Wrap(err, "GetInstance")
- }
- return jsonutils.Update(ins, extIns)
- }
- func (ins *SInstance) GetTags() (map[string]string, error) {
- tags, err := ins.getRegion().ListTags("kec-instance", ins.InstanceId)
- if err != nil {
- return nil, err
- }
- return tags.GetTags(), nil
- }
- func (ins *SInstance) SetTags(tags map[string]string, replace bool) error {
- return ins.getRegion().SetResourceTags("kec-instance", ins.InstanceId, tags, replace)
- }
- func (ins *SInstance) getRegion() *SRegion {
- if ins.region != nil {
- return ins.region
- }
- return ins.host.zone.region
- }
- func (ins *SInstance) AssignSecurityGroup(secgroupId string) error {
- 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 ins.getRegion().AttachDisk(ins.InstanceId, diskId)
- }
- func (region *SRegion) AttachDisk(instanceId, diskId string) error {
- params := map[string]interface{}{
- "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]interface{}{
- "InstanceId": instanceId,
- "InstanceType": opts.InstanceType,
- }
- _, err := region.ecsRequest("ModifyInstanceType", params)
- return err
- }
- func (ins *SInstance) DeleteVM(ctx context.Context) error {
- return ins.getRegion().DeleteVM(ins.InstanceId)
- }
- func (region *SRegion) DeleteVM(instanceId string) error {
- params := map[string]interface{}{
- "InstanceId.1": instanceId,
- "ForceDelete": "true",
- }
- _, err := region.ecsRequest("TerminateInstances", params)
- return err
- }
- func (ins *SInstance) DetachDisk(ctx context.Context, diskId string) error {
- return ins.getRegion().DetachDisk(ins.InstanceId, diskId)
- }
- func (region *SRegion) DetachDisk(instanceId, diskId string) error {
- params := map[string]interface{}{
- "VolumeId": diskId,
- }
- if len(instanceId) > 0 {
- params["InstanceId"] = instanceId
- }
- _, err := region.ecsRequest("DetachVolume", params)
- return err
- }
- func (ins *SInstance) GetBios() cloudprovider.TBiosType {
- if strings.Contains(ins.BootMode, "BIOS") {
- return cloudprovider.BIOS
- }
- return cloudprovider.UEFI
- }
- func (ins *SInstance) GetBootOrder() string {
- return ""
- }
- func (ins *SInstance) GetError() error {
- return nil
- }
- func (ins *SInstance) GetFullOsName() string {
- return ins.Platform
- }
- func (ins *SInstance) GetGlobalId() string {
- return ins.InstanceId
- }
- func (ins *SInstance) GetId() string {
- return ins.InstanceId
- }
- func (ins *SInstance) GetInstanceType() string {
- return ins.InstanceType
- }
- func (ins *SInstance) GetMachine() string {
- return "pc"
- }
- func (ins *SInstance) GetHostname() string {
- return ins.HostName
- }
- func (ins *SInstance) GetName() string {
- return ins.InstanceName
- }
- func (ins *SInstance) GetOsArch() string {
- return imagetools.NormalizeImageInfo(ins.Platform, "", "", "", "").OsArch
- }
- func (ins *SInstance) GetOsDist() string {
- return imagetools.NormalizeImageInfo(ins.Platform, "", "", "", "").OsArch
- }
- func (ins *SInstance) GetOsLang() string {
- return ""
- }
- func (ins *SInstance) GetOsType() cloudprovider.TOsType {
- imageInfo := imagetools.NormalizeImageInfo("", "", "", ins.Platform, "")
- return cloudprovider.TOsType(imageInfo.OsType)
- }
- func (ins *SInstance) GetOsVersion() string {
- return imagetools.NormalizeImageInfo(ins.Platform, "", "", "", "").OsVersion
- }
- func (ins *SInstance) GetProjectId() string {
- 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)
- }
- }
- return ids, nil
- }
- func (ins *SInstance) GetStatus() string {
- switch ins.InstanceState.Name {
- case "block_device_mapping", "scheduling", "updating_password", "rebuilding", "updating_hostname":
- return api.VM_DEPLOYING
- case "active":
- return api.VM_RUNNING
- case "stopping":
- return api.VM_STOPPING
- case "stopped":
- return api.VM_READY
- }
- return ins.InstanceState.Name
- }
- func (ins *SInstance) GetHypervisor() string {
- return api.HYPERVISOR_KSYUN
- }
- func (ins *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
- disks, err := ins.getRegion().GetDiskByInstanceId(ins.GetId())
- if err != nil {
- 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])
- }
- if ins.SystemDisk.DiskType == api.STORAGE_KSYUN_LOCAL_SSD {
- disk := &SDisk{
- VolumeId: ins.SystemDisk.DiskId,
- VolumeType: ins.SystemDisk.DiskType,
- VolumeName: ins.SystemDisk.DiskId,
- Size: ins.SystemDisk.DiskSize,
- VolumeCategory: "system",
- }
- storage := &SStorage{
- zone: ins.host.zone,
- StorageType: api.STORAGE_KSYUN_LOCAL_SSD,
- }
- disk.storage = storage
- res = append(res, disk)
- }
- for i := range ins.DataDisks {
- if ins.DataDisks[i].DiskType == api.STORAGE_KSYUN_LOCAL_SSD {
- disk := &SDisk{
- VolumeId: ins.DataDisks[i].DiskId,
- VolumeType: ins.DataDisks[i].DiskType,
- VolumeName: ins.DataDisks[i].DiskId,
- Size: ins.DataDisks[i].DiskSize,
- VolumeCategory: "data",
- }
- storage := &SStorage{
- zone: ins.host.zone,
- StorageType: api.STORAGE_KSYUN_LOCAL_SSD,
- }
- disk.storage = storage
- res = append(res, disk)
- }
- }
- return res, nil
- }
- func (ins *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
- eipIds := []string{}
- for _, set := range ins.NetworkInterfaceSet {
- if len(set.AllocationId) > 0 {
- eipIds = append(eipIds, set.AllocationId)
- }
- }
- if len(eipIds) == 0 {
- return nil, cloudprovider.ErrNotFound
- }
- eips, err := ins.getRegion().GetEips(eipIds)
- if err != nil {
- return nil, errors.Wrap(err, "get eips")
- }
- if len(eips) == 0 {
- return nil, errors.ErrNotFound
- }
- for _, eip := range eips {
- if utils.IsInStringArray(eip.GetId(), eipIds) {
- eip.region = ins.getRegion()
- return &eip, nil
- }
- }
- return nil, errors.Wrapf(err, "instanceId id:%s", ins.GetGlobalId())
- }
- func (ins *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
- nics := []cloudprovider.ICloudNic{}
- for i := 0; i < len(ins.NetworkInterfaceSet); i++ {
- nic := SInstanceNic{
- Instance: ins,
- Id: ins.NetworkInterfaceSet[i].SubnetId,
- IpAddr: ins.NetworkInterfaceSet[i].PrivateIPAddress,
- MacAddr: ins.NetworkInterfaceSet[i].MacAddress,
- }
- nics = append(nics, &nic)
- }
- return nics, nil
- }
- func (ins *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
- vnc, err := ins.getRegion().GetVNCInfo(ins.InstanceId)
- if err != nil {
- return nil, errors.Wrap(err, "GetVNCInfo")
- }
- ret := &cloudprovider.ServerVncOutput{
- Url: fmt.Sprintf("http://kec.console.ksyun.com/kec/connect/vnc?VncUrl=%s", vnc),
- Protocol: "ksyun",
- InstanceId: ins.InstanceId,
- Hypervisor: api.HYPERVISOR_KSYUN,
- }
- return ret, nil
- }
- /*
- {
- "RequestId":
- "91f6c5ea-f0b0-4d1a-9f87-6154f1823442003",
- "VncUrl":
- "ws://tjwqone.vnc.ksyun.com:80/websockify?token=u4-394839af-a920-4394-bfe3-f99b88c87fa1"
- }
- */
- func (region *SRegion) GetVNCInfo(instanceId string) (string, error) {
- resp, err := region.ecsRequest("DescribeInstanceVncUrl", map[string]interface{}{"InstanceId": instanceId})
- if err != nil {
- return "", errors.Wrap(err, "GetVNCAddress")
- }
- return resp.GetString("VncUrl")
- }
- func (ins *SInstance) GetVcpuCount() int {
- return ins.InstanceConfigure.Vcpu
- }
- func (ins *SInstance) GetVmemSizeMB() int {
- return ins.InstanceConfigure.MemoryGb * 1024
- }
- func (ins *SInstance) GetVdi() string {
- return ""
- }
- func (ins *SInstance) GetVga() string {
- return ""
- }
- func (region *SRegion) BindKeypair(instanceId, keyName, publicKey string) error {
- keyId, err := region.syncKeypair(keyName, publicKey)
- if err != nil {
- return errors.Wrapf(err, "syncKeypair %s", keyName)
- }
- return region.AttachKey(instanceId, keyId)
- }
- func (region *SRegion) AttachKey(instanceId, keyId string) error {
- params := map[string]interface{}{
- "InstanceId.1": instanceId,
- "KeyId.1": keyId,
- }
- _, err := region.ecsRequest("AttachKey", params)
- return err
- }
- func (ins *SInstance) RebuildRoot(ctx context.Context, opts *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
- err := ins.getRegion().RebuildRoot(ins.InstanceId, opts)
- if err != nil {
- return "", err
- }
- if len(opts.PublicKey) > 0 {
- keyName := opts.KeypairName
- if len(keyName) == 0 {
- keyName = ins.InstanceName
- }
- err = ins.getRegion().BindKeypair(ins.InstanceId, keyName, opts.PublicKey)
- if err != nil {
- log.Errorf("BindKeypair %s error: %v", keyName, 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]interface{}{
- "InstanceId": instanceId,
- "ImageId": opts.ImageId,
- }
- if len(opts.Password) > 0 {
- params["InstancePassword"] = opts.Password
- }
- if len(opts.UserData) > 0 {
- params["UserData"] = opts.UserData
- }
- _, err := region.ecsRequest("ModifyInstanceImage", params)
- return err
- }
- func (ins *SInstance) SetSecurityGroups(secgroupIds []string) error {
- 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 ins.getRegion().StartVM(ins.InstanceId)
- }
- func (ins *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
- return ins.getRegion().StopVM(ins.InstanceId, opts.IsForce, opts.StopCharging)
- }
- func (region *SRegion) StartVM(instanceId string) error {
- params := map[string]interface{}{
- "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]interface{}{
- "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.ErrNotSupported
- }
- 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]interface{}{
- "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 {
- return ins.host
- }
- func (ins *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
- if len(opts.PublicKey) > 0 {
- return ins.getRegion().BindKeypair(ins.InstanceId, opts.KeypairName, opts.PublicKey)
- }
- return ins.getRegion().DeployVM(ins.InstanceId, opts)
- }
- func (region *SRegion) DeployVM(instanceId string, opts *cloudprovider.SInstanceDeployOptions) error {
- params := map[string]interface{}{
- "InstanceId": instanceId,
- "InstancePassword": opts.Password,
- "RestartMode": "Restart",
- }
- _, err := region.ecsRequest("ModifyInstanceAttribute", params)
- return err
- }
- func (ins *SInstance) GetBillingType() string {
- if ins.ChargeType == "Monthly" {
- return billing_api.BILLING_TYPE_PREPAID
- }
- return billing_api.BILLING_TYPE_POSTPAID
- }
- func (ins *SInstance) GetCreatedAt() time.Time {
- return ins.CreationDate
- }
- func (ins *SInstance) GetExpiredAt() time.Time {
- return ins.ServiceEndTime
- }
- func (ins *SInstance) SaveImage(opts *cloudprovider.SaveImageOptions) (cloudprovider.ICloudImage, error) {
- return ins.host.zone.region.SaveImage(ins.InstanceId, opts)
- }
- func (region *SRegion) SaveImage(instanceId string, opts *cloudprovider.SaveImageOptions) (cloudprovider.ICloudImage, error) {
- params := map[string]interface{}{
- "InstanceId": instanceId,
- "Name": opts.Name,
- }
- resp, err := region.ecsRequest("CreateImage", params)
- if err != nil {
- return nil, errors.Wrapf(err, "CreateImage")
- }
- imageId, err := resp.GetString("ImageId")
- if err != nil {
- return nil, errors.Wrapf(err, "get imageId")
- }
- return region.GetImage(imageId)
- }
|