| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- // Copyright 2023 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 volcengine
- 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/pkg/errors"
- "yunion.io/x/pkg/util/billing"
- "yunion.io/x/pkg/util/imagetools"
- "yunion.io/x/pkg/util/osprofile"
- "yunion.io/x/pkg/utils"
- )
- const (
- InstanceStatusCreating = "CREATING"
- InstanceStatusRunning = "RUNNING"
- InstanceStatusStopping = "STOPPING"
- InstanceStatusStopped = "STOPPED"
- InstanceStatusRebooting = "REBOOTING"
- InstanceStatusStarting = "STARTING"
- InstanceStatusRebuilding = "REBUILDING"
- InstanceStatusResizing = "RESIZING"
- InstanceStatusError = "ERROR"
- InstanceStatusDeleting = "DELETING"
- )
- type SSecurityGroupIds []string
- type SRdmaIPAddress []string
- type SInstance struct {
- multicloud.SInstanceBase
- VolcEngineTags
- host *SHost
- osInfo *imagetools.ImageInfo
- CreatedAt time.Time
- UpdatedAt time.Time
- InstanceId string
- ZoneId string
- ImageId string
- Status string
- InstanceName string
- Description string
- Hostname string
- VpcId string
- InstanceTypeId string
- Cpus int
- MemorySize int
- OsName string
- OsType string
- NetworkInterfaces []SNetworkInterface
- RdmaIpAddress SRdmaIPAddress
- KeyPairName string
- KeyPairId string
- InstanceChargeType string
- StoppedMode string
- SpotStrategy string
- DeploymentSetId string
- EipAddress SEipAddress
- ExpiredAt time.Time
- Uuid string
- ProjectName string
- }
- func billingCycle2Params(bc *billing.SBillingCycle, params map[string]string) error {
- if bc.GetMonths() > 0 {
- params["PeriodUnit"] = "Month"
- params["Period"] = fmt.Sprintf("%d", bc.GetMonths())
- } else if bc.GetWeeks() > 0 {
- params["PeriodUnit"] = "Week"
- params["Period"] = fmt.Sprintf("%d", bc.GetWeeks())
- // renew by week is not currently supported
- return fmt.Errorf("invalid renew time period %s", bc.String())
- } else {
- return fmt.Errorf("invalid renew time period %s", bc.String())
- }
- return nil
- }
- func (instance *SInstance) UpdatePassword(passwd string) error {
- params := make(map[string]string)
- params["Password"] = passwd
- return instance.host.zone.region.modifyInstanceAttribute(instance.InstanceId, params)
- }
- func (instance *SInstance) UpdateUserData(userData string) error {
- params := make(map[string]string)
- params["UserData"] = userData
- return instance.host.zone.region.modifyInstanceAttribute(instance.InstanceId, params)
- }
- func (instance *SInstance) GetUserData() (string, error) {
- params := make(map[string]string)
- params["InstanceId"] = instance.InstanceId
- body, err := instance.host.zone.region.ecsRequest("DescribeUserData", params)
- if err != nil {
- return "", errors.Wrapf(err, "GetUserData")
- }
- userData, err := body.GetString("UserData")
- if err != nil {
- return "", errors.Wrapf(err, "GetUserData")
- }
- return userData, nil
- }
- func (region *SRegion) GetInstance(instanceId string) (*SInstance, error) {
- instances, err := region.GetInstances("", []string{instanceId})
- if err != nil {
- return nil, err
- }
- for i := range instances {
- if instances[i].InstanceId == instanceId {
- return &instances[i], nil
- }
- }
- return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s", instanceId)
- }
- func (region *SRegion) GetInstances(zoneId string, ids []string) ([]SInstance, error) {
- params := make(map[string]string)
- params["MaxResults"] = "100"
- if len(zoneId) > 0 {
- params["ZoneId"] = zoneId
- }
- for index, id := range ids {
- key := fmt.Sprintf("InstanceIds.%d", index+1)
- params[key] = id
- }
- ret := []SInstance{}
- for {
- resp, err := region.ecsRequest("DescribeInstances", params)
- if err != nil {
- return nil, errors.Wrapf(err, "DescribeInstances")
- }
- part := struct {
- Instances []SInstance
- NextToken string
- }{}
- err = resp.Unmarshal(&part)
- if err != nil {
- return nil, err
- }
- ret = append(ret, part.Instances...)
- if len(part.NextToken) == 0 || len(part.Instances) == 0 {
- break
- }
- params["NextToken"] = part.NextToken
- }
- return ret, nil
- }
- func (instance *SInstance) GetIHost() cloudprovider.ICloudHost {
- return instance.host
- }
- func (instance *SInstance) GetIHostId() string {
- return instance.host.GetGlobalId()
- }
- func (instance *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
- disks, err := instance.host.zone.region.GetDisks(instance.InstanceId, "", "", nil)
- if err != nil {
- return nil, err
- }
- idisks := make([]cloudprovider.ICloudDisk, len(disks))
- for i := 0; i < len(disks); i += 1 {
- storage := &SStorage{zone: instance.host.zone, storageType: disks[i].VolumeType}
- disks[i].storage = storage
- idisks[i] = &disks[i]
- }
- return idisks, nil
- }
- func (instance *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
- if len(instance.EipAddress.AllocationId) > 0 {
- return instance.host.zone.region.GetEip(instance.EipAddress.AllocationId)
- }
- for _, nic := range instance.NetworkInterfaces {
- if len(nic.AssociatedElasticIp.EipAddress) > 0 {
- eip := SEipAddress{region: instance.host.zone.region}
- eip.region = instance.host.zone.region
- eip.EipAddress = nic.AssociatedElasticIp.EipAddress
- eip.InstanceId = instance.InstanceId
- eip.AllocationId = instance.InstanceId
- return &eip, nil
- }
- }
- return nil, cloudprovider.ErrNotFound
- }
- func (instance *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
- ret := []cloudprovider.ICloudNic{}
- nics, err := instance.host.zone.region.GetNetworkInterfaces("", instance.InstanceId)
- if err != nil {
- return nil, err
- }
- for i := range nics {
- nics[i].region = instance.host.zone.region
- ret = append(ret, &nics[i])
- }
- return ret, nil
- }
- func (instance *SInstance) GetId() string {
- return instance.InstanceId
- }
- func (instance *SInstance) GetName() string {
- if len(instance.InstanceName) > 0 {
- return instance.InstanceName
- }
- return instance.InstanceId
- }
- func (instance *SInstance) GetHostname() string {
- return instance.Hostname
- }
- func (instance *SInstance) GetGlobalId() string {
- return instance.InstanceId
- }
- func (instance *SInstance) GetInstanceType() string {
- return instance.InstanceTypeId
- }
- func (instance *SInstance) SetTags(tags map[string]string, replace bool) error {
- _tags, err := instance.GetTags()
- if err != nil {
- return errors.Wrapf(err, "GetTags")
- }
- keys, upperKeys := []string{}, []string{}
- for k := range tags {
- keys = append(keys, k)
- upperKeys = append(upperKeys, strings.ToUpper(k))
- }
- if replace {
- if len(tags) > 0 {
- removeKeys := []string{}
- for k := range _tags {
- if !utils.IsInStringArray(k, keys) {
- removeKeys = append(removeKeys, k)
- }
- }
- if len(removeKeys) > 0 {
- err := instance.host.zone.region.UntagResources(instance.InstanceId, "instance", removeKeys)
- if err != nil {
- return errors.Wrapf(err, "UntagResource")
- }
- }
- }
- } else {
- removeKeys := []string{}
- for k := range _tags {
- if !utils.IsInStringArray(k, keys) && utils.IsInStringArray(strings.ToUpper(k), upperKeys) {
- removeKeys = append(removeKeys, k)
- }
- }
- if len(removeKeys) > 0 {
- err := instance.host.zone.region.UntagResources(instance.InstanceId, "instance", removeKeys)
- if err != nil {
- return errors.Wrapf(err, "UntagResource")
- }
- }
- }
- return instance.host.zone.region.TagResources(instance.InstanceId, "instance", tags)
- }
- func (region *SRegion) TagResources(resId, resType string, tags map[string]string) error {
- params := map[string]string{
- "ResourceIds.1": resId,
- "ResourceType": resType,
- }
- idx := 1
- for k, v := range tags {
- params[fmt.Sprintf("Tags.%d.Key", idx)] = k
- params[fmt.Sprintf("Tags.%d.Value", idx)] = v
- idx++
- }
- _, err := region.ecsRequest("TagResources", params)
- if err != nil {
- return errors.Wrapf(err, "TagResources")
- }
- return nil
- }
- func (region *SRegion) UntagResources(resId, resType string, tags []string) error {
- params := map[string]string{
- "ResourceIds.1": resId,
- "ResourceType": resType,
- }
- idx := 1
- for _, tag := range tags {
- params[fmt.Sprintf("TagKeys.%d", idx)] = tag
- idx++
- }
- _, err := region.ecsRequest("UntagResources", params)
- if err != nil {
- return errors.Wrapf(err, "UntagResources")
- }
- return nil
- }
- func (instance *SInstance) GetSecurityGroupIds() ([]string, error) {
- nics, err := instance.host.zone.region.GetNetworkInterfaces("", instance.InstanceId)
- if err != nil {
- return nil, err
- }
- for _, nic := range nics {
- if len(nic.SecurityGroupIds) > 0 {
- return nic.SecurityGroupIds, nil
- }
- }
- return []string{}, nil
- }
- func (instance *SInstance) GetVcpuCount() int {
- return instance.Cpus
- }
- func (instance *SInstance) GetVmemSizeMB() int {
- return instance.MemorySize
- }
- func (instance *SInstance) GetBootOrder() string {
- return "dcn"
- }
- func (instance *SInstance) GetVga() string {
- return "std"
- }
- func (instance *SInstance) GetVdi() string {
- return "vnc"
- }
- func (ins *SInstance) getNormalizedOsInfo() *imagetools.ImageInfo {
- if ins.osInfo == nil {
- osInfo := imagetools.NormalizeImageInfo(ins.OsName, "", ins.OsType, "", "")
- ins.osInfo = &osInfo
- }
- return ins.osInfo
- }
- func (instance *SInstance) GetOsType() cloudprovider.TOsType {
- return cloudprovider.TOsType(osprofile.NormalizeOSType(instance.OsType))
- }
- func (instance *SInstance) GetFullOsName() string {
- return instance.OsName
- }
- func (ins *SInstance) GetBios() cloudprovider.TBiosType {
- return cloudprovider.ToBiosType(ins.getNormalizedOsInfo().OsBios)
- }
- func (ins *SInstance) GetOsArch() string {
- return ins.getNormalizedOsInfo().OsArch
- }
- func (ins *SInstance) GetOsDist() string {
- return ins.getNormalizedOsInfo().OsDistro
- }
- func (ins *SInstance) GetOsVersion() string {
- return ins.getNormalizedOsInfo().OsVersion
- }
- func (ins *SInstance) GetOsLang() string {
- return ins.getNormalizedOsInfo().OsLang
- }
- func (instance *SInstance) GetMachine() string {
- return "pc"
- }
- func (instance *SInstance) GetStatus() string {
- switch instance.Status {
- case InstanceStatusRunning:
- return api.VM_RUNNING
- case InstanceStatusStarting:
- return api.VM_STARTING
- case InstanceStatusStopping:
- return api.VM_STOPPING
- case InstanceStatusStopped:
- return api.VM_READY
- case InstanceStatusDeleting:
- return api.VM_DELETING
- default:
- return api.VM_UNKNOWN
- }
- }
- func (instance *SInstance) Refresh() error {
- ins, err := instance.host.zone.region.GetInstance(instance.InstanceId)
- if err != nil {
- return err
- }
- return jsonutils.Update(instance, ins)
- }
- func (instance *SInstance) GetHypervisor() string {
- return api.HYPERVISOR_VOLCENGINE
- }
- func (instance *SInstance) GetCreatedAt() time.Time {
- return instance.CreatedAt
- }
- func (instance *SInstance) GetExpiredAt() time.Time {
- if instance.InstanceChargeType != "PostPaid" {
- return instance.ExpiredAt
- }
- return time.Time{}
- }
- func (instance *SInstance) GetBillingType() string {
- if instance.InstanceChargeType == "PostPaid" {
- return billing_api.BILLING_TYPE_POSTPAID
- }
- return billing_api.BILLING_TYPE_PREPAID
- }
- func (instance *SInstance) SetSecurityGroups(secgroupIds []string) error {
- for _, nic := range instance.NetworkInterfaces {
- return instance.host.zone.region.ModifyNetworkInterfaceAttributes(nic.NetworkInterfaceId, secgroupIds)
- }
- return nil
- }
- func (self *SRegion) ModifyNetworkInterfaceAttributes(id string, secgroupIds []string) error {
- params := map[string]string{
- "NetworkInterfaceId": id,
- }
- for i, id := range secgroupIds {
- params[fmt.Sprintf("SecurityGroupIds.%d", i+1)] = id
- }
- _, err := self.vpcRequest("ModifyNetworkInterfaceAttributes", params)
- return err
- }
- func (instance *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
- if config.InstanceType == "nil" {
- return errors.Wrapf(cloudprovider.ErrInputParameter, "InstanceType")
- }
- return instance.host.zone.region.ChangeConfig(instance.InstanceId, config.InstanceType)
- }
- func (instance *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
- url, err := instance.host.zone.region.DescribeInstanceVncUrl(instance.InstanceId)
- if err != nil {
- return nil, err
- }
- protocol := api.HYPERVISOR_VOLCENGINE
- ret := &cloudprovider.ServerVncOutput{
- Url: strings.TrimPrefix(url, "wss://"),
- Protocol: protocol,
- InstanceId: instance.InstanceId,
- Region: instance.host.zone.region.RegionId,
- InstanceName: instance.InstanceName,
- Hypervisor: api.HYPERVISOR_VOLCENGINE,
- }
- return ret, nil
- }
- func (self *SRegion) DescribeInstanceVncUrl(id string) (string, error) {
- params := map[string]string{
- "InstanceId": id,
- }
- resp, err := self.ecsRequest("DescribeInstanceVncUrl", params)
- if err != nil {
- return "", err
- }
- return resp.GetString("VncUrl")
- }
- func (instance *SInstance) StartVM(ctx context.Context) error {
- err := instance.host.zone.region.StartVM(instance.InstanceId)
- return err
- }
- func (instance *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
- err := instance.host.zone.region.StopVM(instance.InstanceId, opts.IsForce, opts.StopCharging)
- if err != nil {
- return err
- }
- return cloudprovider.WaitStatus(instance, api.VM_READY, 10*time.Second, 300*time.Second)
- }
- func (instance *SInstance) DeleteVM(ctx context.Context) error {
- return instance.host.zone.region.DeleteVM(instance.InstanceId)
- }
- func (instance *SInstance) UpdateVM(ctx context.Context, input cloudprovider.SInstanceUpdateOptions) error {
- return instance.host.zone.region.UpdateVM(instance.InstanceId, input.NAME, input.Description)
- }
- func (instance *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
- return instance.host.zone.region.DeployVM(instance.InstanceId, opts)
- }
- func (instance *SInstance) AttachDisk(ctx context.Context, diskId string) error {
- return instance.host.zone.region.AttachDisk(instance.InstanceId, diskId)
- }
- func (instance *SInstance) DetachDisk(ctx context.Context, diskId string) error {
- return cloudprovider.RetryOnError(
- func() error {
- return instance.host.zone.region.DetachDisk(instance.InstanceId, diskId)
- },
- []string{
- `"Code":"InvalidOperation.Conflict"`,
- },
- 4)
- }
- func (instance *SInstance) GetProjectId() string {
- return instance.ProjectName
- }
- func (instance *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
- return "", cloudprovider.ErrNotSupported
- }
- func (instance *SInstance) SaveImage(opts *cloudprovider.SaveImageOptions) (cloudprovider.ICloudImage, error) {
- image, err := instance.host.zone.region.SaveImage(instance.InstanceId, opts)
- if err != nil {
- return nil, errors.Wrapf(err, "SaveImage %s", opts.Name)
- }
- return image, nil
- }
- // region
- func (region *SRegion) CreateInstance(zoneId string, opts *cloudprovider.SManagedVMCreateConfig) (string, error) {
- params := make(map[string]string)
- params["RegionId"] = region.RegionId
- params["ImageId"] = opts.ExternalImageId
- params["InstanceType"] = opts.InstanceType
- params["ZoneId"] = zoneId
- params["InstanceName"] = opts.Name
- if len(opts.ProjectId) > 0 {
- params["ProjectName"] = opts.ProjectId
- }
- if len(opts.Hostname) > 0 {
- params["HostName"] = opts.Hostname
- }
- params["Description"] = opts.Description
- if len(opts.Password) > 0 {
- params["Password"] = opts.Password
- }
- if len(opts.KeypairName) > 0 {
- params["KeyPairName"] = opts.KeypairName
- }
- if len(opts.Password) == 0 && len(opts.KeypairName) == 0 {
- params["KeepImageCredential"] = "True"
- }
- if len(opts.UserData) > 0 {
- params["UserData"] = opts.UserData
- }
- tagIdx := 1
- for k, v := range opts.Tags {
- params[fmt.Sprintf("Tags.%d.Key", tagIdx)] = k
- params[fmt.Sprintf("Tags.%d.Value", tagIdx)] = v
- tagIdx += 1
- }
- params["Volumes.1.Size"] = fmt.Sprintf("%d", opts.SysDisk.SizeGB)
- params["Volumes.1.VolumeType"] = opts.SysDisk.StorageType
- for idx, disk := range opts.DataDisks {
- params[fmt.Sprintf("Volumes.%d.Size", idx+2)] = fmt.Sprintf("%d", disk.SizeGB)
- params[fmt.Sprintf("Volumes.%d.VolumeType", idx+2)] = disk.StorageType
- }
- params["NetworkInterfaces.1.SubnetId"] = opts.ExternalNetworkId
- if len(opts.IpAddr) > 0 {
- //params["NetworkInterfaces.1.IpAddr"] = opts.IpAddr
- }
- for idx, id := range opts.ExternalSecgroupIds {
- params[fmt.Sprintf("NetworkInterfaces.1.SecurityGroupIds.%d", idx+1)] = id
- }
- params["InstanceChargeType"] = "PostPaid"
- params["SpotStrategy"] = "NoSpot"
- if opts.BillingCycle != nil {
- params["InstanceChargeType"] = "PrePaid"
- err := billingCycle2Params(opts.BillingCycle, params)
- if err != nil {
- return "", err
- }
- params["AutoRenew"] = "False"
- if opts.BillingCycle.AutoRenew {
- params["AutoRenew"] = "true"
- params["AutoRenewPeriod"] = "1"
- }
- }
- params["ClientToken"] = utils.GenRequestId(20)
- resp, err := region.ecsRequest("RunInstances", params)
- if err != nil {
- return "", errors.Wrapf(err, "RunInstances")
- }
- ids := []string{}
- err = resp.Unmarshal(&ids, "InstanceIds")
- if err != nil {
- return "", err
- }
- for _, id := range ids {
- return id, nil
- }
- return "", errors.Wrapf(cloudprovider.ErrNotFound, "after created")
- }
- func (region *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle) error {
- params := make(map[string]string)
- params["InstanceId"] = instanceId
- err := billingCycle2Params(&bc, params)
- if err != nil {
- return err
- }
- params["ClientToken"] = utils.GenRequestId(20)
- _, err = region.ecsRequest("RenewInstance", params)
- if err != nil {
- return errors.Wrapf(err, "RenewInstance fail")
- }
- return nil
- }
- func (region *SRegion) ChangeConfig(instanceId string, instanceTypeId string) error {
- params := make(map[string]string)
- params["InstanceTypeId"] = instanceTypeId
- return region.instanceOperation(instanceId, "ModifyInstanceSpec", params)
- }
- func (region *SRegion) StartVM(instanceId string) error {
- status, err := region.GetInstanceStatus(instanceId)
- if err != nil {
- return errors.Wrapf(err, "Fail to get instance status on StartVM")
- }
- if status != InstanceStatusStopped {
- return errors.Wrapf(cloudprovider.ErrInvalidStatus, "StartVM: vm status is %s expect %s", status, InstanceStatusStopped)
- }
- return region.doStartVM(instanceId)
- }
- func (region *SRegion) StopVM(instanceId string, isForce, stopCharging bool) error {
- status, err := region.GetInstanceStatus(instanceId)
- if err != nil {
- return errors.Wrapf(err, "Fail to get instance status on StopVM")
- }
- if status == InstanceStatusStopped {
- return nil
- }
- if status != InstanceStatusRunning {
- return errors.Wrapf(cloudprovider.ErrInvalidStatus, "StartVM: vm status is %s expect %s", status, InstanceStatusRunning)
- }
- return region.doStopVM(instanceId, isForce, stopCharging)
- }
- func (region *SRegion) DeleteVM(instanceId string) error {
- return region.instanceOperation(instanceId, "DeleteInstance", nil)
- }
- func (region *SRegion) doStartVM(instanceId string) error {
- return region.instanceOperation(instanceId, "StartInstance", nil)
- }
- func (region *SRegion) doStopVM(instanceId string, isForce, stopCharging bool) error {
- params := make(map[string]string)
- if isForce {
- params["ForceStop"] = "true"
- } else {
- params["ForceStop"] = "false"
- }
- params["StoppedMode"] = "KeepCharging"
- if stopCharging {
- params["StoppedMode"] = "StopCharging"
- }
- return region.instanceOperation(instanceId, "StopInstance", params)
- }
- func (region *SRegion) modifyInstanceAttribute(instanceId string, params map[string]string) error {
- return region.instanceOperation(instanceId, "ModifyInstanceAttribute", params)
- }
- func (region *SRegion) UpdateVM(instanceId string, name, description string) error {
- params := make(map[string]string)
- params["InstanceName"] = name
- params["Description"] = description
- return region.modifyInstanceAttribute(instanceId, params)
- }
- func (region *SRegion) DeployVM(instanceId string, opts *cloudprovider.SInstanceDeployOptions) error {
- instance, err := region.GetInstance(instanceId)
- if err != nil {
- return err
- }
- if opts.DeleteKeypair {
- err = region.DetachKeyPair(instanceId, instance.KeyPairName)
- if err != nil {
- return err
- }
- }
- if len(opts.PublicKey) > 0 {
- keypairName, err := instance.host.zone.region.syncKeypair(opts.PublicKey)
- if err != nil {
- return err
- }
- err = region.AttachKeypair(instanceId, keypairName)
- if err != nil {
- return err
- }
- }
- if len(opts.Password) > 0 {
- params := make(map[string]string)
- params["Password"] = opts.Password
- return region.modifyInstanceAttribute(instanceId, params)
- }
- return nil
- }
- func (region *SRegion) DetachDisk(instanceId string, diskId string) error {
- params := make(map[string]string)
- params["InstanceId"] = instanceId
- params["VolumeId"] = diskId
- _, err := region.storageRequest("DetachVolume", params)
- if err != nil {
- return errors.Wrap(err, "DetachDisk")
- }
- return nil
- }
- func (region *SRegion) AttachDisk(instanceId string, diskId string) error {
- params := make(map[string]string)
- params["InstanceId"] = instanceId
- params["VolumeId"] = diskId
- _, err := region.storageRequest("AttachVolume", params)
- if err != nil {
- return errors.Wrapf(err, "AttachDisk %s to %s fail", diskId, instanceId)
- }
- return nil
- }
- func (region *SRegion) SaveImage(instanceId string, opts *cloudprovider.SaveImageOptions) (*SImage, error) {
- params := map[string]string{
- "InstanceId": instanceId,
- "ImageName": opts.Name,
- "Description": opts.Notes,
- "ClientToken": utils.GenRequestId(20),
- }
- body, err := region.ecsRequest("CreateImage", params)
- if err != nil {
- return nil, errors.Wrapf(err, "CreateImage")
- }
- imageId, err := body.GetString("ImageId")
- if err != nil {
- return nil, errors.Wrapf(err, "get imageId")
- }
- cloudprovider.Wait(time.Second*3, time.Minute, func() (bool, error) {
- _, err := region.GetImage(imageId)
- if err != nil {
- if errors.Cause(err) == cloudprovider.ErrNotFound {
- return false, nil
- }
- return false, err
- }
- return true, nil
- })
- return region.GetImage(imageId)
- }
|