instance.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  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 cloudpods
  15. import (
  16. "context"
  17. "fmt"
  18. "time"
  19. "yunion.io/x/cloudmux/pkg/cloudprovider"
  20. "yunion.io/x/cloudmux/pkg/multicloud"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/pkg/errors"
  23. "yunion.io/x/pkg/utils"
  24. "yunion.io/x/onecloud/pkg/apis"
  25. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  26. api "yunion.io/x/onecloud/pkg/apis/compute"
  27. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  28. "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
  29. "yunion.io/x/onecloud/pkg/mcclient/modules/logger"
  30. "yunion.io/x/onecloud/pkg/mcclient/modules/webconsole"
  31. )
  32. type SInstance struct {
  33. multicloud.SInstanceBase
  34. CloudpodsTags
  35. host *SHost
  36. api.ServerDetails
  37. }
  38. func (vm *SInstance) GetName() string {
  39. return vm.Name
  40. }
  41. func (vm *SInstance) GetHostname() string {
  42. return vm.Hostname
  43. }
  44. func (vm *SInstance) GetId() string {
  45. return vm.Id
  46. }
  47. func (vm *SInstance) GetGlobalId() string {
  48. return vm.Id
  49. }
  50. func (vm *SInstance) GetStatus() string {
  51. return vm.Status
  52. }
  53. func (vm *SInstance) Refresh() error {
  54. ins, err := vm.host.zone.region.GetInstance(vm.Id)
  55. if err != nil {
  56. return err
  57. }
  58. vm.DisksInfo = nil
  59. vm.Nics = nil
  60. vm.Secgroups = nil
  61. vm.SubIPs = nil
  62. vm.IsolatedDevices = nil
  63. vm.Cdrom = nil
  64. vm.Floppy = nil
  65. return jsonutils.Update(vm, ins)
  66. }
  67. func (vm *SInstance) GetCreatedAt() time.Time {
  68. return vm.CreatedAt
  69. }
  70. func (vm *SInstance) GetExpiredAt() time.Time {
  71. return vm.ExpiredAt
  72. }
  73. func (vm *SInstance) GetIHost() cloudprovider.ICloudHost {
  74. return vm.host
  75. }
  76. func (vm *SInstance) GetIHostId() string {
  77. return vm.HostId
  78. }
  79. func (vm *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
  80. disks, err := vm.host.zone.region.GetDisks("", vm.Id)
  81. if err != nil {
  82. return nil, err
  83. }
  84. ret := []cloudprovider.ICloudDisk{}
  85. for i := range disks {
  86. disks[i].region = vm.host.zone.region
  87. ret = append(ret, &disks[i])
  88. }
  89. return ret, nil
  90. }
  91. func (vm *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
  92. if len(vm.Eip) > 0 {
  93. eips, err := vm.host.zone.region.GetEips(vm.Id)
  94. if err != nil {
  95. return nil, err
  96. }
  97. for i := range eips {
  98. eips[i].region = vm.host.zone.region
  99. return &eips[i], nil
  100. }
  101. return nil, cloudprovider.ErrNotFound
  102. }
  103. return nil, nil
  104. }
  105. func (vm *SInstance) GetVcpuCount() int {
  106. return vm.VcpuCount
  107. }
  108. func (vm *SInstance) GetVmemSizeMB() int {
  109. return vm.VmemSize
  110. }
  111. func (vm *SInstance) GetBootOrder() string {
  112. return vm.BootOrder
  113. }
  114. func (vm *SInstance) GetVga() string {
  115. return vm.Vga
  116. }
  117. func (vm *SInstance) GetVdi() string {
  118. return vm.Vdi
  119. }
  120. func (vm *SInstance) GetOsType() cloudprovider.TOsType {
  121. return cloudprovider.TOsType(vm.OsType)
  122. }
  123. func (vm *SInstance) GetFullOsName() string {
  124. return vm.OsName
  125. }
  126. func (vm *SInstance) GetBios() cloudprovider.TBiosType {
  127. return cloudprovider.ToBiosType(vm.Bios)
  128. }
  129. func (vm *SInstance) GetOsDist() string {
  130. val, ok := vm.Metadata["os_distribution"]
  131. if ok {
  132. return val
  133. }
  134. return ""
  135. }
  136. func (vm *SInstance) GetOsVersion() string {
  137. val, ok := vm.Metadata["os_version"]
  138. if ok {
  139. return val
  140. }
  141. return ""
  142. }
  143. func (vm *SInstance) GetOsLang() string {
  144. val, ok := vm.Metadata["os_language"]
  145. if ok {
  146. return val
  147. }
  148. return ""
  149. }
  150. func (vm *SInstance) GetOsArch() string {
  151. return vm.OsArch
  152. }
  153. func (vm *SInstance) GetMachine() string {
  154. return vm.Machine
  155. }
  156. func (vm *SInstance) GetInstanceType() string {
  157. return vm.InstanceType
  158. }
  159. func (vm *SInstance) GetSecurityGroupIds() ([]string, error) {
  160. ret := []string{}
  161. for _, sec := range vm.Secgroups {
  162. ret = append(ret, sec.Id)
  163. }
  164. return ret, nil
  165. }
  166. func (vm *SInstance) GetProjectId() string {
  167. return vm.TenantId
  168. }
  169. func (vm *SInstance) SetSecurityGroups(ids []string) error {
  170. if vm.Hypervisor == api.HYPERVISOR_ESXI {
  171. return nil
  172. }
  173. input := api.GuestSetSecgroupInput{}
  174. input.SecgroupIds = ids
  175. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "set-secgroup", input)
  176. return err
  177. }
  178. func (vm *SInstance) GetHypervisor() string {
  179. return vm.Hypervisor
  180. }
  181. func (vm *SInstance) StartVM(ctx context.Context) error {
  182. if vm.Status == api.VM_RUNNING {
  183. return nil
  184. }
  185. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "start", nil)
  186. return err
  187. }
  188. func (vm *SInstance) StopVM(ctx context.Context, opts *cloudprovider.ServerStopOptions) error {
  189. if vm.Status == api.VM_READY {
  190. return nil
  191. }
  192. input := api.ServerStopInput{}
  193. input.IsForce = opts.IsForce
  194. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "stop", input)
  195. return err
  196. }
  197. func (vm *SInstance) DeleteVM(ctx context.Context) error {
  198. if vm.DisableDelete != nil && *vm.DisableDelete {
  199. input := api.ServerUpdateInput{}
  200. disableDelete := false
  201. input.DisableDelete = &disableDelete
  202. vm.host.zone.region.cli.update(&modules.Servers, vm.Id, input)
  203. }
  204. return vm.host.zone.region.cli.delete(&modules.Servers, vm.Id)
  205. }
  206. func (vm *SInstance) UpdateVM(ctx context.Context, input cloudprovider.SInstanceUpdateOptions) error {
  207. if vm.Name != input.NAME {
  208. param := api.ServerUpdateInput{}
  209. param.Name = input.NAME
  210. param.Description = input.Description
  211. vm.host.zone.region.cli.update(&modules.Servers, vm.Id, input)
  212. return cloudprovider.WaitMultiStatus(vm, []string{api.VM_READY, api.VM_RUNNING}, time.Second*5, time.Minute*3)
  213. }
  214. return nil
  215. }
  216. func (vm *SInstance) UpdateUserData(userData string) error {
  217. input := api.ServerUserDataInput{}
  218. input.UserData = userData
  219. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "user-data", input)
  220. return err
  221. }
  222. func (vm *SInstance) RebuildRoot(ctx context.Context, opts *cloudprovider.SManagedVMRebuildRootConfig) (string, error) {
  223. input := api.ServerRebuildRootInput{}
  224. input.ImageId = opts.ImageId
  225. input.Password = opts.Password
  226. if len(opts.PublicKey) > 0 {
  227. keypairId, err := vm.host.zone.region.syncKeypair(vm.Name, opts.PublicKey)
  228. if err != nil {
  229. return "", errors.Wrapf(err, "syncKeypair")
  230. }
  231. input.KeypairId = keypairId
  232. }
  233. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "rebuild-root", input)
  234. if err != nil {
  235. return "", err
  236. }
  237. return vm.DisksInfo[0].Id, nil
  238. }
  239. func (vm *SInstance) DeployVM(ctx context.Context, opts *cloudprovider.SInstanceDeployOptions) error {
  240. input := api.ServerDeployInput{}
  241. input.Password = opts.Password
  242. input.DeleteKeypair = opts.DeleteKeypair
  243. if len(opts.PublicKey) > 0 {
  244. keypairId, err := vm.host.zone.region.syncKeypair(vm.Name, opts.PublicKey)
  245. if err != nil {
  246. return errors.Wrapf(err, "syncKeypair")
  247. }
  248. input.KeypairId = keypairId
  249. }
  250. cloudprovider.WaitMultiStatus(vm, []string{api.VM_READY, api.VM_RUNNING}, time.Second*5, time.Minute*3)
  251. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "deploy", input)
  252. if err != nil {
  253. return errors.Wrapf(err, "deploy")
  254. }
  255. timeout := time.Minute * 3
  256. if vm.Hypervisor == api.HYPERVISOR_BAREMETAL {
  257. timeout = time.Minute * 10
  258. }
  259. return cloudprovider.WaitMultiStatus(vm, []string{api.VM_READY, api.VM_RUNNING}, time.Second*5, timeout)
  260. }
  261. func (vm *SInstance) ChangeConfig(ctx context.Context, opts *cloudprovider.SManagedVMChangeConfig) error {
  262. input := api.ServerChangeConfigInput{}
  263. input.VmemSize = fmt.Sprintf("%dM", opts.MemoryMB)
  264. input.VcpuCount = &opts.Cpu
  265. input.InstanceType = opts.InstanceType
  266. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "change-config", input)
  267. return err
  268. }
  269. func (vm *SInstance) GetVNCInfo(input *cloudprovider.ServerVncInput) (*cloudprovider.ServerVncOutput, error) {
  270. return vm.host.zone.region.GetInstanceVnc(vm.Id, vm.Name)
  271. }
  272. func (region *SRegion) GetInstanceVnc(id, name string) (*cloudprovider.ServerVncOutput, error) {
  273. s := region.cli.s
  274. resp, err := webconsole.WebConsole.DoServerConnect(s, id, nil)
  275. if err != nil {
  276. return nil, errors.Wrapf(err, "DoServerConnect")
  277. }
  278. result := &cloudprovider.ServerVncOutput{
  279. Protocol: "cloudpods",
  280. InstanceId: id,
  281. InstanceName: name,
  282. Hypervisor: api.HYPERVISOR_DEFAULT,
  283. }
  284. err = resp.Unmarshal(&result)
  285. if err != nil {
  286. return nil, errors.Wrapf(err, "resp.Unmarshal")
  287. }
  288. resp, err = identity.ServicesV3.GetSpecific(s, "common", "config", nil)
  289. if err != nil {
  290. return nil, errors.Wrapf(err, "GetSpecific")
  291. }
  292. result.ApiServer, _ = resp.GetString("config", "default", "api_server")
  293. return result, nil
  294. }
  295. func (vm *SInstance) AttachDisk(ctx context.Context, diskId string) error {
  296. input := api.ServerAttachDiskInput{}
  297. input.DiskId = diskId
  298. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "attachdisk", input)
  299. return err
  300. }
  301. func (vm *SInstance) DetachDisk(ctx context.Context, diskId string) error {
  302. input := api.ServerDetachDiskInput{}
  303. input.DiskId = diskId
  304. input.KeepDisk = true
  305. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "detachdisk", input)
  306. return err
  307. }
  308. func (vm *SInstance) MigrateVM(hostId string) error {
  309. input := api.GuestMigrateInput{}
  310. input.PreferHost = hostId
  311. input.PreferHostId = hostId
  312. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "migrate", input)
  313. return err
  314. }
  315. func (vm *SInstance) LiveMigrateVM(hostId string) error {
  316. input := api.GuestLiveMigrateInput{}
  317. input.PreferHost = hostId
  318. input.PreferHostId = hostId
  319. skipCheck := true
  320. input.SkipCpuCheck = &skipCheck
  321. input.SkipKernelCheck = &skipCheck
  322. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "live-migrate", input)
  323. return err
  324. }
  325. func (vm *SInstance) GetDetails() (*api.ServerDetails, error) {
  326. ret := &api.ServerDetails{}
  327. err := vm.host.zone.region.cli.get(&modules.Servers, vm.Id, nil, ret)
  328. if err != nil {
  329. return nil, err
  330. }
  331. return ret, nil
  332. }
  333. func (vm *SInstance) VMSetStatus(status string) error {
  334. input := apis.PerformStatusInput{}
  335. input.Status = status
  336. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "status", input)
  337. return err
  338. }
  339. func (vm *SInstance) GetError() error {
  340. if utils.IsInStringArray(vm.Status, []string{api.VM_DISK_FAILED, api.VM_SCHEDULE_FAILED, api.VM_NETWORK_FAILED}) {
  341. return fmt.Errorf("vm create failed with status %s", vm.Status)
  342. }
  343. if vm.Status == api.VM_DEPLOY_FAILED {
  344. params := map[string]interface{}{"obj_id": vm.Id, "success": false}
  345. actions := []apis.OpsLogDetails{}
  346. vm.host.zone.region.list(&logger.Actions, params, &actions)
  347. if len(actions) > 0 {
  348. return fmt.Errorf("%s", actions[0].Notes)
  349. }
  350. return fmt.Errorf("vm create failed with status %s", vm.Status)
  351. }
  352. return nil
  353. }
  354. func (vm *SInstance) CreateInstanceSnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudInstanceSnapshot, error) {
  355. return nil, cloudprovider.ErrNotImplemented
  356. }
  357. func (vm *SInstance) GetInstanceSnapshot(idStr string) (cloudprovider.ICloudInstanceSnapshot, error) {
  358. return nil, cloudprovider.ErrNotImplemented
  359. }
  360. func (vm *SInstance) GetInstanceSnapshots() ([]cloudprovider.ICloudInstanceSnapshot, error) {
  361. return nil, cloudprovider.ErrNotImplemented
  362. }
  363. func (vm *SInstance) ResetToInstanceSnapshot(ctx context.Context, idStr string) error {
  364. return cloudprovider.ErrNotImplemented
  365. }
  366. func (vm *SInstance) SaveImage(opts *cloudprovider.SaveImageOptions) (cloudprovider.ICloudImage, error) {
  367. return vm.host.zone.region.SaveImage(vm.Id, opts.Name, opts.Notes)
  368. }
  369. func (region *SRegion) SaveImage(id, imageName, notes string) (*SImage, error) {
  370. input := api.ServerSaveImageInput{}
  371. input.GenerateName = imageName
  372. input.Notes = notes
  373. resp, err := region.perform(&modules.Servers, id, "save-image", input)
  374. if err != nil {
  375. return nil, err
  376. }
  377. imageId, err := resp.GetString("image_id")
  378. if err != nil {
  379. return nil, err
  380. }
  381. caches, err := region.GetStoragecaches()
  382. if err != nil {
  383. return nil, errors.Wrapf(err, "GetStoragecaches")
  384. }
  385. if len(caches) == 0 {
  386. return nil, fmt.Errorf("no storage cache found")
  387. }
  388. caches[0].region = region
  389. image, err := region.GetImage(imageId)
  390. if err != nil {
  391. return nil, err
  392. }
  393. image.cache = &caches[0]
  394. return image, nil
  395. }
  396. func (vm *SInstance) AllocatePublicIpAddress() (string, error) {
  397. return "", cloudprovider.ErrNotImplemented
  398. }
  399. func (host *SHost) GetIVMs() ([]cloudprovider.ICloudVM, error) {
  400. servers, err := host.zone.region.GetInstances(host.Id)
  401. if err != nil {
  402. return nil, err
  403. }
  404. ret := []cloudprovider.ICloudVM{}
  405. for i := range servers {
  406. servers[i].host = host
  407. ret = append(ret, &servers[i])
  408. }
  409. return ret, nil
  410. }
  411. func (host *SHost) GetIVMById(id string) (cloudprovider.ICloudVM, error) {
  412. ins, err := host.zone.region.GetInstance(id)
  413. if err != nil {
  414. return nil, err
  415. }
  416. ins.host = host
  417. return ins, nil
  418. }
  419. func (region *SRegion) GetInstance(id string) (*SInstance, error) {
  420. ins := &SInstance{}
  421. return ins, region.cli.get(&modules.Servers, id, nil, ins)
  422. }
  423. func (region *SRegion) GetInstances(hostId string) ([]SInstance, error) {
  424. params := map[string]interface{}{}
  425. if len(hostId) > 0 {
  426. params["host_id"] = hostId
  427. }
  428. params["filter"] = "hypervisor.in('kvm', 'baremetal', 'pod')"
  429. ret := []SInstance{}
  430. return ret, region.list(&modules.Servers, params, &ret)
  431. }
  432. func (region *SRegion) CreateInstance(hostId, hypervisor string, opts *cloudprovider.SManagedVMCreateConfig) (*SInstance, error) {
  433. input := api.ServerCreateInput{
  434. ServerConfigs: &api.ServerConfigs{},
  435. }
  436. input.GenerateName = opts.Name
  437. input.Hostname = opts.Hostname
  438. input.Description = opts.Description
  439. input.InstanceType = opts.InstanceType
  440. input.VcpuCount = opts.Cpu
  441. input.VmemSize = opts.MemoryMB
  442. input.Password = opts.Password
  443. if len(input.Password) == 0 {
  444. resetPasswd := false
  445. input.ResetPassword = &resetPasswd
  446. }
  447. input.PublicIpBw = opts.PublicIpBw
  448. input.PublicIpChargeType = billing_api.TNetChargeType(opts.PublicIpChargeType)
  449. input.ProjectId = opts.ProjectId
  450. input.Metadata = opts.Tags
  451. input.UserData = opts.UserData
  452. input.PreferHost = hostId
  453. input.Hypervisor = hypervisor
  454. if len(input.UserData) > 0 {
  455. input.EnableCloudInit = true
  456. }
  457. input.Secgroups = opts.ExternalSecgroupIds
  458. if opts.BillingCycle != nil {
  459. input.Duration = opts.BillingCycle.String()
  460. }
  461. image, err := region.GetImage(opts.ExternalImageId)
  462. if err != nil {
  463. return nil, errors.Wrapf(err, "GetImage")
  464. }
  465. imageId := opts.ExternalImageId
  466. if image.DiskFormat == "iso" {
  467. input.Cdrom = opts.ExternalImageId
  468. imageId = ""
  469. }
  470. sysDisk := &api.DiskConfig{
  471. Index: 0,
  472. ImageId: imageId,
  473. DiskType: api.DISK_TYPE_SYS,
  474. SizeMb: opts.SysDisk.SizeGB * 1024,
  475. Backend: opts.SysDisk.StorageType,
  476. Storage: opts.SysDisk.StorageExternalId,
  477. }
  478. if len(opts.SysDisk.Driver) > 0 {
  479. sysDisk.Driver = opts.SysDisk.Driver
  480. }
  481. if len(opts.SysDisk.CacheMode) > 0 {
  482. sysDisk.Cache = opts.SysDisk.CacheMode
  483. }
  484. input.Disks = append(input.Disks, sysDisk)
  485. for idx, disk := range opts.DataDisks {
  486. dataDisk := &api.DiskConfig{
  487. Index: idx + 1,
  488. DiskType: api.DISK_TYPE_DATA,
  489. SizeMb: disk.SizeGB * 1024,
  490. Backend: disk.StorageType,
  491. Storage: disk.StorageExternalId,
  492. }
  493. if len(disk.Driver) > 0 {
  494. dataDisk.Driver = disk.Driver
  495. }
  496. if len(disk.CacheMode) > 0 {
  497. dataDisk.Cache = disk.CacheMode
  498. }
  499. input.Disks = append(input.Disks, dataDisk)
  500. }
  501. input.IsolatedDevices = []*api.IsolatedDeviceConfig{}
  502. for _, dev := range input.IsolatedDevices {
  503. devConfig := &api.IsolatedDeviceConfig{
  504. Id: dev.Id,
  505. }
  506. input.IsolatedDevices = append(input.IsolatedDevices, devConfig)
  507. }
  508. input.Networks = append(input.Networks, &api.NetworkConfig{
  509. Index: 0,
  510. Network: opts.ExternalNetworkId,
  511. Address: opts.IpAddr,
  512. })
  513. ins := &SInstance{}
  514. return ins, region.create(&modules.Servers, input, ins)
  515. }
  516. func (vm *SInstance) CreateDisk(ctx context.Context, opts *cloudprovider.GuestDiskCreateOptions) (string, error) {
  517. diskIds := []string{}
  518. for _, disk := range vm.DisksInfo {
  519. diskIds = append(diskIds, disk.Id)
  520. }
  521. input := jsonutils.Marshal(map[string]interface{}{
  522. "disks": []map[string]interface{}{
  523. {
  524. "size": opts.SizeMb,
  525. "storage_id": opts.StorageId,
  526. "preallocation": opts.Preallocation,
  527. },
  528. },
  529. })
  530. _, err := vm.host.zone.region.perform(&modules.Servers, vm.Id, "createdisk", input)
  531. if err != nil {
  532. return "", err
  533. }
  534. ret := ""
  535. cloudprovider.Wait(time.Second*3, time.Minute*3, func() (bool, error) {
  536. err = vm.Refresh()
  537. if err != nil {
  538. return false, errors.Wrapf(err, "Refresh")
  539. }
  540. for _, disk := range vm.DisksInfo {
  541. if !utils.IsInStringArray(disk.Id, diskIds) {
  542. ret = disk.Id
  543. return true, nil
  544. }
  545. }
  546. return false, nil
  547. })
  548. if len(ret) > 0 {
  549. return ret, nil
  550. }
  551. return "", errors.Wrapf(cloudprovider.ErrNotFound, "after disk created")
  552. }
  553. func (vm *SInstance) GetIsolateDeviceIds() ([]string, error) {
  554. devs, err := vm.host.zone.region.GetIsolatedDevices("", vm.Id)
  555. if err != nil {
  556. return nil, err
  557. }
  558. ret := []string{}
  559. for i := range devs {
  560. ret = append(ret, devs[i].GetGlobalId())
  561. }
  562. return ret, nil
  563. }
  564. func (vm *SInstance) GetContainers() ([]cloudprovider.ICloudContainer, error) {
  565. containers, err := vm.host.zone.region.GetContainers(vm.Id)
  566. if err != nil {
  567. return nil, err
  568. }
  569. ret := []cloudprovider.ICloudContainer{}
  570. for i := range containers {
  571. containers[i].region = vm.host.zone.region
  572. ret = append(ret, &containers[i])
  573. }
  574. return ret, nil
  575. }