instance.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package ucloud
  15. import (
  16. "context"
  17. "encoding/base64"
  18. "fmt"
  19. "strings"
  20. "time"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/errors"
  24. "yunion.io/x/pkg/util/billing"
  25. "yunion.io/x/pkg/util/imagetools"
  26. "yunion.io/x/pkg/utils"
  27. billing_api "yunion.io/x/cloudmux/pkg/apis/billing"
  28. api "yunion.io/x/cloudmux/pkg/apis/compute"
  29. "yunion.io/x/cloudmux/pkg/cloudprovider"
  30. "yunion.io/x/cloudmux/pkg/multicloud"
  31. )
  32. type SInstance struct {
  33. multicloud.SInstanceBase
  34. UcloudTags
  35. host *SHost
  36. osInfo *imagetools.ImageInfo
  37. UHostID string `json:"UHostId"`
  38. Zone string `json:"Zone"`
  39. LifeCycle string `json:"LifeCycle"`
  40. OSName string `json:"OsName"`
  41. ImageID string `json:"ImageId"`
  42. BasicImageID string `json:"BasicImageId"`
  43. BasicImageName string `json:"BasicImageName"`
  44. Tag string `json:"Tag"`
  45. Name string `json:"Name"`
  46. Remark string `json:"Remark"`
  47. State string `json:"State"`
  48. NetworkState string `json:"NetworkState"`
  49. HostType string `json:"HostType"`
  50. StorageType string `json:"StorageType"`
  51. TotalDiskSpace int `json:"TotalDiskSpace"`
  52. DiskSet []DiskSet `json:"DiskSet"`
  53. NetCapability string `json:"NetCapability"`
  54. IPSet []IPSet `json:"IPSet"`
  55. SubnetType string `json:"SubnetType"`
  56. ChargeType string `json:"ChargeType"`
  57. ExpireTime int64 `json:"ExpireTime"`
  58. AutoRenew string `json:"AutoRenew"`
  59. IsExpire string `json:"IsExpire"`
  60. UHostType string `json:"UHostType"`
  61. OSType string `json:"OsType"`
  62. CreateTime int64 `json:"CreateTime"`
  63. CPU int `json:"CPU"`
  64. GPU int `json:"GPU"`
  65. MemoryMB int `json:"Memory"`
  66. TimemachineFeature string `json:"TimemachineFeature"`
  67. HotplugFeature bool `json:"HotplugFeature"`
  68. NetCapFeature bool `json:"NetCapFeature"`
  69. BootDiskState string `json:"BootDiskState"`
  70. }
  71. func (self *SInstance) GetSecurityGroupIds() ([]string, error) {
  72. secgroups, err := self.GetSecurityGroups()
  73. if err != nil {
  74. log.Errorln(err)
  75. }
  76. secgroupIds := make([]string, 0)
  77. for _, secgroup := range secgroups {
  78. secgroupIds = append(secgroupIds, secgroup.GetId())
  79. }
  80. return secgroupIds, nil
  81. }
  82. func (self *SInstance) GetProjectId() string {
  83. return self.host.zone.region.client.projectId
  84. }
  85. func (self *SInstance) GetError() error {
  86. return nil
  87. }
  88. type DiskSet struct {
  89. DiskID string `json:"DiskId"`
  90. DiskType string `json:"DiskType"`
  91. Drive string `json:"Drive"`
  92. IsBoot bool `json:"IsBoot"`
  93. Size int `json:"Size"`
  94. Encrypted string `json:"Encrypted"`
  95. Type string `json:"Type"`
  96. }
  97. type IPSet struct {
  98. Type string `json:"Type"`
  99. IP string `json:"IP"`
  100. IPId string `json:"IPId"` // IP资源ID (内网IP无对应的资源ID)
  101. MAC string `json:"Mac"`
  102. VPCID string `json:"VPCId"`
  103. SubnetID string `json:"SubnetId"`
  104. }
  105. type SVncInfo struct {
  106. VNCIP string `json:"VncIP"`
  107. VNCPassword string `json:"VncPassword"`
  108. UHostID string `json:"UHostId"`
  109. Action string `json:"Action"`
  110. VNCPort int64 `json:"VncPort"`
  111. }
  112. func (self *SInstance) GetId() string {
  113. return self.UHostID
  114. }
  115. func (self *SInstance) GetName() string {
  116. if len(self.Name) == 0 {
  117. return self.GetId()
  118. }
  119. return self.Name
  120. }
  121. func (self *SInstance) GetHostname() string {
  122. return ""
  123. }
  124. func (self *SInstance) GetGlobalId() string {
  125. return self.GetId()
  126. }
  127. // 实例状态,枚举值:
  128. // >初始化: Initializing;
  129. // >启动中: Starting;
  130. // > 运行中: Running;
  131. // > 关机中: Stopping;
  132. // >关机: Stopped
  133. // >安装失败: Install Fail;
  134. // >重启中: Rebooting
  135. func (self *SInstance) GetStatus() string {
  136. switch self.State {
  137. case "Running":
  138. return api.VM_RUNNING
  139. case "Stopped":
  140. return api.VM_READY
  141. case "Rebooting":
  142. return api.VM_STOPPING
  143. case "Initializing":
  144. return api.VM_INIT
  145. case "Starting":
  146. return api.VM_STARTING
  147. case "Stopping":
  148. return api.VM_STOPPING
  149. case "Install Fail":
  150. return api.VM_CREATE_FAILED
  151. default:
  152. return api.VM_UNKNOWN
  153. }
  154. }
  155. func (self *SInstance) Refresh() error {
  156. new, err := self.host.zone.region.GetInstanceByID(self.GetId())
  157. if err != nil {
  158. return err
  159. }
  160. new.host = self.host
  161. return jsonutils.Update(self, new)
  162. }
  163. // 计费模式,枚举值为: Year,按年付费; Month,按月付费; Dynamic,按需付费(需开启权限);
  164. func (self *SInstance) GetBillingType() string {
  165. switch self.ChargeType {
  166. case "Year", "Month":
  167. return billing_api.BILLING_TYPE_PREPAID
  168. default:
  169. return billing_api.BILLING_TYPE_POSTPAID
  170. }
  171. }
  172. func (self *SInstance) GetCreatedAt() time.Time {
  173. return time.Unix(self.CreateTime, 0)
  174. }
  175. func (self *SInstance) GetExpiredAt() time.Time {
  176. if self.AutoRenew != "Yes" {
  177. return time.Unix(self.ExpireTime, 0)
  178. }
  179. return time.Time{}
  180. }
  181. func (self *SInstance) GetIHost() cloudprovider.ICloudHost {
  182. return self.host
  183. }
  184. func (self *SInstance) GetLocalDisk(diskId, storageType string, sizeGB int, isBoot bool) SDisk {
  185. diskType := ""
  186. if isBoot {
  187. diskType = "SystemDisk"
  188. }
  189. disk := SDisk{
  190. SDisk: multicloud.SDisk{},
  191. Status: "Available",
  192. UHostID: self.GetId(),
  193. Name: diskId,
  194. Zone: self.host.zone.GetId(),
  195. DiskType: diskType,
  196. UDiskID: diskId,
  197. UHostName: self.GetName(),
  198. CreateTime: self.CreateTime,
  199. SizeGB: sizeGB,
  200. }
  201. disk.storage = &SStorage{zone: self.host.zone, storageType: storageType}
  202. return disk
  203. }
  204. func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
  205. localDisks := make([]SDisk, 0)
  206. diskIds := make([]string, 0)
  207. for _, disk := range self.DiskSet {
  208. if utils.IsInStringArray(disk.DiskType, []string{api.STORAGE_UCLOUD_LOCAL_NORMAL, api.STORAGE_UCLOUD_LOCAL_SSD}) {
  209. localDisks = append(localDisks, self.GetLocalDisk(disk.DiskID, disk.DiskType, disk.Size, disk.IsBoot))
  210. } else {
  211. diskIds = append(diskIds, disk.DiskID)
  212. }
  213. }
  214. disks := []SDisk{}
  215. var err error
  216. if len(diskIds) > 0 {
  217. disks, err = self.host.zone.region.GetDisks("", "", diskIds)
  218. if err != nil {
  219. return nil, err
  220. }
  221. }
  222. disks = append(disks, localDisks...)
  223. idisks := make([]cloudprovider.ICloudDisk, len(disks))
  224. for i := 0; i < len(disks); i += 1 {
  225. if disks[i].storage == nil {
  226. var category string
  227. if strings.Contains(disks[i].DiskType, "SSD") {
  228. category = api.STORAGE_UCLOUD_CLOUD_SSD
  229. } else {
  230. category = api.STORAGE_UCLOUD_CLOUD_NORMAL
  231. }
  232. storage, err := self.host.zone.getStorageByCategory(category)
  233. if err != nil {
  234. return nil, err
  235. }
  236. disks[i].storage = storage
  237. }
  238. idisks[i] = &disks[i]
  239. // 将系统盘放到第0个位置
  240. if disks[i].GetDiskType() == api.DISK_TYPE_SYS {
  241. idisks[0], idisks[i] = idisks[i], idisks[0]
  242. }
  243. }
  244. return idisks, nil
  245. }
  246. func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
  247. nics := make([]cloudprovider.ICloudNic, 0)
  248. for _, ip := range self.IPSet {
  249. if len(ip.SubnetID) == 0 {
  250. continue
  251. }
  252. nic := SInstanceNic{
  253. instance: self,
  254. ipAddr: ip.IP,
  255. macAddr: ip.MAC,
  256. }
  257. nics = append(nics, &nic)
  258. }
  259. return nics, nil
  260. }
  261. // 国际: Internation,BGP: BGP,内网: Private
  262. func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
  263. for _, ip := range self.IPSet {
  264. if len(ip.IPId) > 0 {
  265. eip, err := self.host.zone.region.GetEipById(ip.IPId)
  266. if err != nil {
  267. return nil, err
  268. }
  269. return &eip, nil
  270. }
  271. }
  272. return nil, nil
  273. }
  274. func (self *SInstance) GetVcpuCount() int {
  275. return self.CPU
  276. }
  277. func (self *SInstance) GetVmemSizeMB() int {
  278. return self.MemoryMB
  279. }
  280. func (self *SInstance) GetBootOrder() string {
  281. return "dcn"
  282. }
  283. func (self *SInstance) GetVga() string {
  284. return "std"
  285. }
  286. func (self *SInstance) GetVdi() string {
  287. return "vnc"
  288. }
  289. func (ins *SInstance) getNormalizedOsInfo() *imagetools.ImageInfo {
  290. if ins.osInfo == nil {
  291. osInfo := imagetools.NormalizeImageInfo(ins.OSName, "", ins.OSType, "", "")
  292. ins.osInfo = &osInfo
  293. }
  294. return ins.osInfo
  295. }
  296. func (ins *SInstance) GetOsType() cloudprovider.TOsType {
  297. return cloudprovider.TOsType(ins.getNormalizedOsInfo().OsType)
  298. }
  299. func (ins *SInstance) GetFullOsName() string {
  300. return ins.OSName
  301. }
  302. func (ins *SInstance) GetBios() cloudprovider.TBiosType {
  303. return cloudprovider.ToBiosType(ins.getNormalizedOsInfo().OsBios)
  304. }
  305. func (ins *SInstance) GetOsArch() string {
  306. return ins.getNormalizedOsInfo().OsArch
  307. }
  308. func (ins *SInstance) GetOsDist() string {
  309. return ins.getNormalizedOsInfo().OsDistro
  310. }
  311. func (ins *SInstance) GetOsVersion() string {
  312. return ins.getNormalizedOsInfo().OsVersion
  313. }
  314. func (ins *SInstance) GetOsLang() string {
  315. return ins.getNormalizedOsInfo().OsLang
  316. }
  317. func (self *SInstance) GetMachine() string {
  318. return "pc"
  319. }
  320. func (self *SInstance) GetInstanceType() string {
  321. // C1.c8.m24
  322. if strings.HasPrefix(self.HostType, "G") {
  323. return fmt.Sprintf("%s.c%d.m%d.g%d", self.HostType, self.CPU, self.MemoryMB/1014, self.GPU)
  324. } else {
  325. return fmt.Sprintf("%s.c%d.m%d", self.HostType, self.CPU, self.MemoryMB/1014)
  326. }
  327. }
  328. // https://docs.ucloud.cn/api/unet-api/grant_firewall
  329. func (self *SInstance) SetSecurityGroups(secgroupIds []string) error {
  330. if len(secgroupIds) == 0 {
  331. return fmt.Errorf("SetSecurityGroups secgroup id should not be empty")
  332. } else if len(secgroupIds) > 1 {
  333. return fmt.Errorf("SetSecurityGroups only allowed to assign one secgroup id. %d given", len(secgroupIds))
  334. }
  335. return self.host.zone.region.assignSecurityGroups(self.GetId(), secgroupIds[0])
  336. }
  337. func (self *SInstance) GetHypervisor() string {
  338. return api.HYPERVISOR_UCLOUD
  339. }
  340. func (self *SInstance) StartVM(ctx context.Context) error {
  341. err := self.host.zone.region.StartVM(self.GetId())
  342. if err != nil {
  343. return err
  344. }
  345. err = cloudprovider.WaitStatusWithDelay(self, api.VM_RUNNING, 10*time.Second, 10*time.Second, 600*time.Second)
  346. if err != nil {
  347. return errors.Wrap(err, "StartVM")
  348. }
  349. return nil
  350. }
  351. func (self *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
  352. err := self.host.zone.region.StopVM(self.GetId())
  353. if err != nil {
  354. return err
  355. }
  356. err = cloudprovider.WaitStatusWithDelay(self, api.VM_READY, 10*time.Second, 10*time.Second, 600*time.Second)
  357. if err != nil {
  358. return errors.Wrap(err, "StopVM")
  359. }
  360. return nil
  361. }
  362. func (self *SInstance) DeleteVM(ctx context.Context) error {
  363. return self.host.zone.region.DeleteVM(self.GetId())
  364. }
  365. func (self *SInstance) UpdateVM(ctx context.Context, input cloudprovider.SInstanceUpdateOptions) error {
  366. return self.host.zone.region.UpdateVM(self.GetId(), input.NAME)
  367. }
  368. func (self *SInstance) UpdateUserData(userData string) error {
  369. return cloudprovider.ErrNotSupported
  370. }
  371. // https://docs.ucloud.cn/api/uhost-api/reinstall_uhost_instance
  372. // 1.请确认在重新安装之前,该实例已被关闭;
  373. // 2.请确认该实例未挂载UDisk;
  374. // todo:// 3.将原系统重装为不同类型的系统时(Linux-&gt;Windows),不可选择保留数据盘;
  375. // 4.重装不同版本的系统时(CentOS6-&gt;CentOS7),若选择保留数据盘,请注意数据盘的文件系统格式;
  376. // 5.若主机CPU低于2核,不可重装为Windows系统。
  377. func (self *SInstance) RebuildRoot(ctx context.Context, desc *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
  378. if len(desc.PublicKey) > 0 {
  379. return "", fmt.Errorf("DeployVM not support assign ssh keypair")
  380. }
  381. if self.GetStatus() != api.VM_READY {
  382. return "", fmt.Errorf("DeployVM instance status %s , expected %s.", self.GetStatus(), api.VM_READY)
  383. }
  384. if len(self.DiskSet) > 1 {
  385. for _, disk := range self.DiskSet {
  386. if disk.Type == "Data" {
  387. err := self.host.zone.region.DetachDisk(self.host.zone.GetId(), self.GetId(), disk.DiskID)
  388. if err != nil {
  389. return "", fmt.Errorf("RebuildRoot detach disk %s", err)
  390. }
  391. defer self.host.zone.region.AttachDisk(self.host.zone.GetId(), self.GetId(), disk.DiskID)
  392. }
  393. }
  394. }
  395. err := self.host.zone.region.RebuildRoot(self.GetId(), desc.ImageId, desc.Password)
  396. if err != nil {
  397. return "", err
  398. }
  399. err = cloudprovider.WaitStatusWithDelay(self, api.VM_RUNNING, 10*time.Second, 15*time.Second, 300*time.Second)
  400. if err != nil {
  401. return "", errors.Wrap(err, "RebuildRoot")
  402. }
  403. disks, err := self.GetIDisks()
  404. if len(disks) > 0 {
  405. return disks[0].GetId(), nil
  406. } else {
  407. return "", fmt.Errorf("RebuildRoot %s", err)
  408. }
  409. }
  410. func (self *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
  411. if len(opts.PublicKey) > 0 {
  412. return fmt.Errorf("DeployVM not support assign ssh keypair")
  413. }
  414. if opts.DeleteKeypair {
  415. return fmt.Errorf("DeployVM not support delete ssh keypair")
  416. }
  417. if self.GetStatus() != api.VM_READY {
  418. return fmt.Errorf("DeployVM instance status %s , expected %s.", self.GetStatus(), api.VM_READY)
  419. }
  420. if len(opts.Password) > 0 {
  421. err := self.host.zone.region.ResetVMPasswd(self.GetId(), opts.Password)
  422. if err != nil {
  423. return err
  424. }
  425. }
  426. err := cloudprovider.WaitStatus(self, api.VM_READY, 10*time.Second, 300*time.Second)
  427. if err != nil {
  428. return errors.Wrap(err, "DeployVM")
  429. }
  430. return nil
  431. }
  432. func (self *SInstance) ChangeConfig(ctx context.Context, config *cloudprovider.SManagedVMChangeConfig) error {
  433. if len(config.InstanceType) > 0 {
  434. return self.ChangeConfig2(ctx, config.InstanceType)
  435. }
  436. return self.host.zone.region.ResizeVM(self.GetId(), config.Cpu, config.MemoryMB)
  437. }
  438. func (self *SInstance) ChangeConfig2(ctx context.Context, instanceType string) error {
  439. i, err := ParseInstanceType(instanceType)
  440. if err != nil {
  441. return err
  442. }
  443. return self.host.zone.region.ResizeVM(self.GetId(), i.CPU, i.MemoryMB)
  444. }
  445. func (self *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
  446. return self.host.zone.region.GetInstanceVNCUrl(self.GetId())
  447. }
  448. func (self *SInstance) AttachDisk(ctx context.Context, diskId string) error {
  449. return self.host.zone.region.AttachDisk(self.host.zone.GetId(), self.GetId(), diskId)
  450. }
  451. func (self *SInstance) DetachDisk(ctx context.Context, diskId string) error {
  452. err := self.host.zone.region.DetachDisk(self.host.zone.GetId(), self.GetId(), diskId)
  453. if err != nil {
  454. return err
  455. }
  456. disk, err := self.host.zone.region.GetDisk(diskId)
  457. if err != nil {
  458. return err
  459. }
  460. disk.storage = &SStorage{zone: self.host.zone, storageType: disk.GetStorageType()}
  461. err = cloudprovider.WaitStatusWithDelay(disk, api.DISK_READY, 10*time.Second, 10*time.Second, 60*time.Second)
  462. if err != nil {
  463. return errors.Wrap(err, "DetachDisk")
  464. }
  465. return nil
  466. }
  467. func (self *SInstance) Renew(bc billing.SBillingCycle) error {
  468. // return self.host.zone.region
  469. return self.host.zone.region.RenewInstance(self.GetId(), bc)
  470. }
  471. func (self *SInstance) GetSecurityGroups() ([]SSecurityGroup, error) {
  472. return self.host.zone.region.GetSecurityGroups("", self.GetId(), "")
  473. }
  474. // https://docs.ucloud.cn/api/uhost-api/get_uhost_instance_vnc_info
  475. func (self *SRegion) GetInstanceVNCUrl(instanceId string) (*cloudprovider.ServerVncOutput, error) {
  476. params := NewUcloudParams()
  477. params.Set("UHostId", instanceId)
  478. vnc := SVncInfo{}
  479. err := self.DoAction("GetUHostInstanceVncInfo", params, &vnc)
  480. if err != nil {
  481. return nil, err
  482. }
  483. ret := &cloudprovider.ServerVncOutput{
  484. Host: vnc.VNCIP,
  485. Port: vnc.VNCPort,
  486. Password: vnc.VNCPassword,
  487. Hypervisor: api.HYPERVISOR_UCLOUD,
  488. }
  489. return ret, nil
  490. }
  491. // https://docs.ucloud.cn/api/unet-api/grant_firewall
  492. func (self *SRegion) assignSecurityGroups(instanceId string, secgroupId string) error {
  493. params := NewUcloudParams()
  494. params.Set("FWId", secgroupId)
  495. params.Set("ResourceType", "uhost")
  496. params.Set("ResourceId", instanceId)
  497. return self.DoAction("GrantFirewall", params, nil)
  498. }
  499. // https://docs.ucloud.cn/api/uhost-api/start_uhost_instance
  500. func (self *SRegion) StartVM(instanceId string) error {
  501. params := NewUcloudParams()
  502. params.Set("UHostId", instanceId)
  503. return self.DoAction("StartUHostInstance", params, nil)
  504. }
  505. // https://docs.ucloud.cn/api/uhost-api/stop_uhost_instance
  506. func (self *SRegion) StopVM(instanceId string) error {
  507. params := NewUcloudParams()
  508. params.Set("UHostId", instanceId)
  509. return self.DoAction("StopUHostInstance", params, nil)
  510. }
  511. // https://docs.ucloud.cn/api/uhost-api/terminate_uhost_instance
  512. func (self *SRegion) DeleteVM(instanceId string) error {
  513. params := NewUcloudParams()
  514. params.Set("UHostId", instanceId)
  515. params.Set("Destroy", 1) // 跳过回收站,直接删除
  516. return self.DoAction("TerminateUHostInstance", params, nil)
  517. }
  518. // https://docs.ucloud.cn/api/uhost-api/modify_uhost_instance_name
  519. func (self *SRegion) UpdateVM(instanceId, name string) error {
  520. params := NewUcloudParams()
  521. params.Set("UHostId", instanceId)
  522. params.Set("Name", name)
  523. return self.DoAction("ModifyUHostInstanceName", params, nil)
  524. }
  525. // ChargeType : Dynamic(按需)/Month(按月)/Year(按年)
  526. func (self *SRegion) RenewInstance(instanceId string, bc billing.SBillingCycle) error {
  527. params := NewUcloudParams()
  528. params.Set("ResourceId", instanceId)
  529. params.Set("ResourceType", "Host")
  530. if bc.GetMonths() >= 10 && bc.GetMonths() < 12 {
  531. params.Set("ChargeType", "Year")
  532. params.Set("Quantity", 1)
  533. } else if bc.GetYears() >= 1 {
  534. params.Set("ChargeType", "Year")
  535. params.Set("Quantity", bc.GetYears())
  536. } else {
  537. params.Set("ChargeType", "Month")
  538. params.Set("Quantity", bc.GetMonths())
  539. }
  540. return self.DoAction("CreateRenew", params, nil)
  541. }
  542. // https://docs.ucloud.cn/api/uhost-api/reset_uhost_instance_password
  543. // 该操作需要UHost实例处于关闭状态。
  544. func (self *SRegion) ResetVMPasswd(instanceId, password string) error {
  545. params := NewUcloudParams()
  546. params.Set("UHostId", instanceId)
  547. params.Set("Password", base64.StdEncoding.EncodeToString([]byte(password)))
  548. return self.DoAction("ResetUHostInstancePassword", params, nil)
  549. }
  550. // https://docs.ucloud.cn/api/uhost-api/reinstall_uhost_instance
  551. // (密码格式使用BASE64编码;LoginMode不可变更)
  552. func (self *SRegion) RebuildRoot(instanceId, imageId, password string) error {
  553. params := NewUcloudParams()
  554. params.Set("UHostId", instanceId)
  555. params.Set("Password", base64.StdEncoding.EncodeToString([]byte(password)))
  556. params.Set("ImageId", imageId)
  557. return self.DoAction("ReinstallUHostInstance", params, nil)
  558. }
  559. // https://docs.ucloud.cn/api/uhost-api/resize_uhost_instance
  560. func (self *SRegion) ResizeVM(instanceId string, cpu, memoryMB int) error {
  561. params := NewUcloudParams()
  562. params.Set("UHostId", instanceId)
  563. params.Set("CPU", cpu)
  564. params.Set("Memory", memoryMB)
  565. return self.DoAction("ResizeUHostInstance", params, nil)
  566. }