virtual_machine.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838
  1. /*
  2. Copyright (c) 2015-2017 VMware, Inc. All Rights Reserved.
  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. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package object
  14. import (
  15. "context"
  16. "errors"
  17. "fmt"
  18. "net"
  19. "path"
  20. "github.com/vmware/govmomi/nfc"
  21. "github.com/vmware/govmomi/property"
  22. "github.com/vmware/govmomi/vim25"
  23. "github.com/vmware/govmomi/vim25/methods"
  24. "github.com/vmware/govmomi/vim25/mo"
  25. "github.com/vmware/govmomi/vim25/types"
  26. )
  27. const (
  28. PropRuntimePowerState = "summary.runtime.powerState"
  29. )
  30. type VirtualMachine struct {
  31. Common
  32. }
  33. func NewVirtualMachine(c *vim25.Client, ref types.ManagedObjectReference) *VirtualMachine {
  34. return &VirtualMachine{
  35. Common: NewCommon(c, ref),
  36. }
  37. }
  38. func (v VirtualMachine) PowerState(ctx context.Context) (types.VirtualMachinePowerState, error) {
  39. var o mo.VirtualMachine
  40. err := v.Properties(ctx, v.Reference(), []string{PropRuntimePowerState}, &o)
  41. if err != nil {
  42. return "", err
  43. }
  44. return o.Summary.Runtime.PowerState, nil
  45. }
  46. func (v VirtualMachine) PowerOn(ctx context.Context) (*Task, error) {
  47. req := types.PowerOnVM_Task{
  48. This: v.Reference(),
  49. }
  50. res, err := methods.PowerOnVM_Task(ctx, v.c, &req)
  51. if err != nil {
  52. return nil, err
  53. }
  54. return NewTask(v.c, res.Returnval), nil
  55. }
  56. func (v VirtualMachine) PowerOff(ctx context.Context) (*Task, error) {
  57. req := types.PowerOffVM_Task{
  58. This: v.Reference(),
  59. }
  60. res, err := methods.PowerOffVM_Task(ctx, v.c, &req)
  61. if err != nil {
  62. return nil, err
  63. }
  64. return NewTask(v.c, res.Returnval), nil
  65. }
  66. func (v VirtualMachine) PutUsbScanCodes(ctx context.Context, spec types.UsbScanCodeSpec) (int32, error) {
  67. req := types.PutUsbScanCodes{
  68. This: v.Reference(),
  69. Spec: spec,
  70. }
  71. res, err := methods.PutUsbScanCodes(ctx, v.c, &req)
  72. if err != nil {
  73. return 0, err
  74. }
  75. return res.Returnval, nil
  76. }
  77. func (v VirtualMachine) Reset(ctx context.Context) (*Task, error) {
  78. req := types.ResetVM_Task{
  79. This: v.Reference(),
  80. }
  81. res, err := methods.ResetVM_Task(ctx, v.c, &req)
  82. if err != nil {
  83. return nil, err
  84. }
  85. return NewTask(v.c, res.Returnval), nil
  86. }
  87. func (v VirtualMachine) Suspend(ctx context.Context) (*Task, error) {
  88. req := types.SuspendVM_Task{
  89. This: v.Reference(),
  90. }
  91. res, err := methods.SuspendVM_Task(ctx, v.c, &req)
  92. if err != nil {
  93. return nil, err
  94. }
  95. return NewTask(v.c, res.Returnval), nil
  96. }
  97. func (v VirtualMachine) ShutdownGuest(ctx context.Context) error {
  98. req := types.ShutdownGuest{
  99. This: v.Reference(),
  100. }
  101. _, err := methods.ShutdownGuest(ctx, v.c, &req)
  102. return err
  103. }
  104. func (v VirtualMachine) RebootGuest(ctx context.Context) error {
  105. req := types.RebootGuest{
  106. This: v.Reference(),
  107. }
  108. _, err := methods.RebootGuest(ctx, v.c, &req)
  109. return err
  110. }
  111. func (v VirtualMachine) Destroy(ctx context.Context) (*Task, error) {
  112. req := types.Destroy_Task{
  113. This: v.Reference(),
  114. }
  115. res, err := methods.Destroy_Task(ctx, v.c, &req)
  116. if err != nil {
  117. return nil, err
  118. }
  119. return NewTask(v.c, res.Returnval), nil
  120. }
  121. func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string, config types.VirtualMachineCloneSpec) (*Task, error) {
  122. req := types.CloneVM_Task{
  123. This: v.Reference(),
  124. Folder: folder.Reference(),
  125. Name: name,
  126. Spec: config,
  127. }
  128. res, err := methods.CloneVM_Task(ctx, v.c, &req)
  129. if err != nil {
  130. return nil, err
  131. }
  132. return NewTask(v.c, res.Returnval), nil
  133. }
  134. func (v VirtualMachine) Customize(ctx context.Context, spec types.CustomizationSpec) (*Task, error) {
  135. req := types.CustomizeVM_Task{
  136. This: v.Reference(),
  137. Spec: spec,
  138. }
  139. res, err := methods.CustomizeVM_Task(ctx, v.c, &req)
  140. if err != nil {
  141. return nil, err
  142. }
  143. return NewTask(v.c, res.Returnval), nil
  144. }
  145. func (v VirtualMachine) Relocate(ctx context.Context, config types.VirtualMachineRelocateSpec, priority types.VirtualMachineMovePriority) (*Task, error) {
  146. req := types.RelocateVM_Task{
  147. This: v.Reference(),
  148. Spec: config,
  149. Priority: priority,
  150. }
  151. res, err := methods.RelocateVM_Task(ctx, v.c, &req)
  152. if err != nil {
  153. return nil, err
  154. }
  155. return NewTask(v.c, res.Returnval), nil
  156. }
  157. func (v VirtualMachine) Reconfigure(ctx context.Context, config types.VirtualMachineConfigSpec) (*Task, error) {
  158. req := types.ReconfigVM_Task{
  159. This: v.Reference(),
  160. Spec: config,
  161. }
  162. res, err := methods.ReconfigVM_Task(ctx, v.c, &req)
  163. if err != nil {
  164. return nil, err
  165. }
  166. return NewTask(v.c, res.Returnval), nil
  167. }
  168. func (v VirtualMachine) RefreshStorageInfo(ctx context.Context) error {
  169. req := types.RefreshStorageInfo{
  170. This: v.Reference(),
  171. }
  172. _, err := methods.RefreshStorageInfo(ctx, v.c, &req)
  173. return err
  174. }
  175. func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) {
  176. var ip string
  177. p := property.DefaultCollector(v.c)
  178. err := property.Wait(ctx, p, v.Reference(), []string{"guest.ipAddress"}, func(pc []types.PropertyChange) bool {
  179. for _, c := range pc {
  180. if c.Name != "guest.ipAddress" {
  181. continue
  182. }
  183. if c.Op != types.PropertyChangeOpAssign {
  184. continue
  185. }
  186. if c.Val == nil {
  187. continue
  188. }
  189. ip = c.Val.(string)
  190. return true
  191. }
  192. return false
  193. })
  194. if err != nil {
  195. return "", err
  196. }
  197. return ip, nil
  198. }
  199. // WaitForNetIP waits for the VM guest.net property to report an IP address for all VM NICs.
  200. // Only consider IPv4 addresses if the v4 param is true.
  201. // By default, wait for all NICs to get an IP address, unless 1 or more device is given.
  202. // A device can be specified by the MAC address or the device name, e.g. "ethernet-0".
  203. // Returns a map with MAC address as the key and IP address list as the value.
  204. func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...string) (map[string][]string, error) {
  205. macs := make(map[string][]string)
  206. eths := make(map[string]string)
  207. p := property.DefaultCollector(v.c)
  208. // Wait for all NICs to have a MacAddress, which may not be generated yet.
  209. err := property.Wait(ctx, p, v.Reference(), []string{"config.hardware.device"}, func(pc []types.PropertyChange) bool {
  210. for _, c := range pc {
  211. if c.Op != types.PropertyChangeOpAssign {
  212. continue
  213. }
  214. devices := VirtualDeviceList(c.Val.(types.ArrayOfVirtualDevice).VirtualDevice)
  215. for _, d := range devices {
  216. if nic, ok := d.(types.BaseVirtualEthernetCard); ok {
  217. mac := nic.GetVirtualEthernetCard().MacAddress
  218. if mac == "" {
  219. return false
  220. }
  221. macs[mac] = nil
  222. eths[devices.Name(d)] = mac
  223. }
  224. }
  225. }
  226. return true
  227. })
  228. if len(device) != 0 {
  229. // Only wait for specific NIC(s)
  230. macs = make(map[string][]string)
  231. for _, mac := range device {
  232. if eth, ok := eths[mac]; ok {
  233. mac = eth // device name, e.g. "ethernet-0"
  234. }
  235. macs[mac] = nil
  236. }
  237. }
  238. err = property.Wait(ctx, p, v.Reference(), []string{"guest.net"}, func(pc []types.PropertyChange) bool {
  239. for _, c := range pc {
  240. if c.Op != types.PropertyChangeOpAssign {
  241. continue
  242. }
  243. nics := c.Val.(types.ArrayOfGuestNicInfo).GuestNicInfo
  244. for _, nic := range nics {
  245. mac := nic.MacAddress
  246. if mac == "" || nic.IpConfig == nil {
  247. continue
  248. }
  249. for _, ip := range nic.IpConfig.IpAddress {
  250. if _, ok := macs[mac]; !ok {
  251. continue // Ignore any that don't correspond to a VM device
  252. }
  253. if v4 && net.ParseIP(ip.IpAddress).To4() == nil {
  254. continue // Ignore non IPv4 address
  255. }
  256. macs[mac] = append(macs[mac], ip.IpAddress)
  257. }
  258. }
  259. }
  260. for _, ips := range macs {
  261. if len(ips) == 0 {
  262. return false
  263. }
  264. }
  265. return true
  266. })
  267. if err != nil {
  268. return nil, err
  269. }
  270. return macs, nil
  271. }
  272. // Device returns the VirtualMachine's config.hardware.device property.
  273. func (v VirtualMachine) Device(ctx context.Context) (VirtualDeviceList, error) {
  274. var o mo.VirtualMachine
  275. err := v.Properties(ctx, v.Reference(), []string{"config.hardware.device", "summary.runtime.connectionState"}, &o)
  276. if err != nil {
  277. return nil, err
  278. }
  279. // Quoting the SDK doc:
  280. // The virtual machine configuration is not guaranteed to be available.
  281. // For example, the configuration information would be unavailable if the server
  282. // is unable to access the virtual machine files on disk, and is often also unavailable
  283. // during the initial phases of virtual machine creation.
  284. if o.Config == nil {
  285. return nil, fmt.Errorf("%s Config is not available, connectionState=%s",
  286. v.Reference(), o.Summary.Runtime.ConnectionState)
  287. }
  288. return VirtualDeviceList(o.Config.Hardware.Device), nil
  289. }
  290. func (v VirtualMachine) HostSystem(ctx context.Context) (*HostSystem, error) {
  291. var o mo.VirtualMachine
  292. err := v.Properties(ctx, v.Reference(), []string{"summary.runtime.host"}, &o)
  293. if err != nil {
  294. return nil, err
  295. }
  296. host := o.Summary.Runtime.Host
  297. if host == nil {
  298. return nil, errors.New("VM doesn't have a HostSystem")
  299. }
  300. return NewHostSystem(v.c, *host), nil
  301. }
  302. func (v VirtualMachine) ResourcePool(ctx context.Context) (*ResourcePool, error) {
  303. var o mo.VirtualMachine
  304. err := v.Properties(ctx, v.Reference(), []string{"resourcePool"}, &o)
  305. if err != nil {
  306. return nil, err
  307. }
  308. rp := o.ResourcePool
  309. if rp == nil {
  310. return nil, errors.New("VM doesn't have a resourcePool")
  311. }
  312. return NewResourcePool(v.c, *rp), nil
  313. }
  314. func (v VirtualMachine) configureDevice(ctx context.Context, op types.VirtualDeviceConfigSpecOperation, fop types.VirtualDeviceConfigSpecFileOperation, devices ...types.BaseVirtualDevice) error {
  315. spec := types.VirtualMachineConfigSpec{}
  316. for _, device := range devices {
  317. config := &types.VirtualDeviceConfigSpec{
  318. Device: device,
  319. Operation: op,
  320. }
  321. if disk, ok := device.(*types.VirtualDisk); ok {
  322. config.FileOperation = fop
  323. // Special case to attach an existing disk
  324. if op == types.VirtualDeviceConfigSpecOperationAdd && disk.CapacityInKB == 0 {
  325. childDisk := false
  326. if b, ok := disk.Backing.(*types.VirtualDiskFlatVer2BackingInfo); ok {
  327. childDisk = b.Parent != nil
  328. }
  329. if !childDisk {
  330. config.FileOperation = "" // existing disk
  331. }
  332. }
  333. }
  334. spec.DeviceChange = append(spec.DeviceChange, config)
  335. }
  336. task, err := v.Reconfigure(ctx, spec)
  337. if err != nil {
  338. return err
  339. }
  340. return task.Wait(ctx)
  341. }
  342. // AddDevice adds the given devices to the VirtualMachine
  343. func (v VirtualMachine) AddDevice(ctx context.Context, device ...types.BaseVirtualDevice) error {
  344. return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationAdd, types.VirtualDeviceConfigSpecFileOperationCreate, device...)
  345. }
  346. // EditDevice edits the given (existing) devices on the VirtualMachine
  347. func (v VirtualMachine) EditDevice(ctx context.Context, device ...types.BaseVirtualDevice) error {
  348. return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationEdit, types.VirtualDeviceConfigSpecFileOperationReplace, device...)
  349. }
  350. // RemoveDevice removes the given devices on the VirtualMachine
  351. func (v VirtualMachine) RemoveDevice(ctx context.Context, keepFiles bool, device ...types.BaseVirtualDevice) error {
  352. fop := types.VirtualDeviceConfigSpecFileOperationDestroy
  353. if keepFiles {
  354. fop = ""
  355. }
  356. return v.configureDevice(ctx, types.VirtualDeviceConfigSpecOperationRemove, fop, device...)
  357. }
  358. // BootOptions returns the VirtualMachine's config.bootOptions property.
  359. func (v VirtualMachine) BootOptions(ctx context.Context) (*types.VirtualMachineBootOptions, error) {
  360. var o mo.VirtualMachine
  361. err := v.Properties(ctx, v.Reference(), []string{"config.bootOptions"}, &o)
  362. if err != nil {
  363. return nil, err
  364. }
  365. return o.Config.BootOptions, nil
  366. }
  367. // SetBootOptions reconfigures the VirtualMachine with the given options.
  368. func (v VirtualMachine) SetBootOptions(ctx context.Context, options *types.VirtualMachineBootOptions) error {
  369. spec := types.VirtualMachineConfigSpec{}
  370. spec.BootOptions = options
  371. task, err := v.Reconfigure(ctx, spec)
  372. if err != nil {
  373. return err
  374. }
  375. return task.Wait(ctx)
  376. }
  377. // Answer answers a pending question.
  378. func (v VirtualMachine) Answer(ctx context.Context, id, answer string) error {
  379. req := types.AnswerVM{
  380. This: v.Reference(),
  381. QuestionId: id,
  382. AnswerChoice: answer,
  383. }
  384. _, err := methods.AnswerVM(ctx, v.c, &req)
  385. if err != nil {
  386. return err
  387. }
  388. return nil
  389. }
  390. func (v VirtualMachine) AcquireTicket(ctx context.Context, kind string) (*types.VirtualMachineTicket, error) {
  391. req := types.AcquireTicket{
  392. This: v.Reference(),
  393. TicketType: kind,
  394. }
  395. res, err := methods.AcquireTicket(ctx, v.c, &req)
  396. if err != nil {
  397. return nil, err
  398. }
  399. return &res.Returnval, nil
  400. }
  401. // CreateSnapshot creates a new snapshot of a virtual machine.
  402. func (v VirtualMachine) CreateSnapshot(ctx context.Context, name string, description string, memory bool, quiesce bool) (*Task, error) {
  403. req := types.CreateSnapshot_Task{
  404. This: v.Reference(),
  405. Name: name,
  406. Description: description,
  407. Memory: memory,
  408. Quiesce: quiesce,
  409. }
  410. res, err := methods.CreateSnapshot_Task(ctx, v.c, &req)
  411. if err != nil {
  412. return nil, err
  413. }
  414. return NewTask(v.c, res.Returnval), nil
  415. }
  416. // RemoveAllSnapshot removes all snapshots of a virtual machine
  417. func (v VirtualMachine) RemoveAllSnapshot(ctx context.Context, consolidate *bool) (*Task, error) {
  418. req := types.RemoveAllSnapshots_Task{
  419. This: v.Reference(),
  420. Consolidate: consolidate,
  421. }
  422. res, err := methods.RemoveAllSnapshots_Task(ctx, v.c, &req)
  423. if err != nil {
  424. return nil, err
  425. }
  426. return NewTask(v.c, res.Returnval), nil
  427. }
  428. type snapshotMap map[string][]types.ManagedObjectReference
  429. func (m snapshotMap) add(parent string, tree []types.VirtualMachineSnapshotTree) {
  430. for i, st := range tree {
  431. sname := st.Name
  432. names := []string{sname, st.Snapshot.Value}
  433. if parent != "" {
  434. sname = path.Join(parent, sname)
  435. // Add full path as an option to resolve duplicate names
  436. names = append(names, sname)
  437. }
  438. for _, name := range names {
  439. m[name] = append(m[name], tree[i].Snapshot)
  440. }
  441. m.add(sname, st.ChildSnapshotList)
  442. }
  443. }
  444. // FindSnapshot supports snapshot lookup by name, where name can be:
  445. // 1) snapshot ManagedObjectReference.Value (unique)
  446. // 2) snapshot name (may not be unique)
  447. // 3) snapshot tree path (may not be unique)
  448. func (v VirtualMachine) FindSnapshot(ctx context.Context, name string) (*types.ManagedObjectReference, error) {
  449. var o mo.VirtualMachine
  450. err := v.Properties(ctx, v.Reference(), []string{"snapshot"}, &o)
  451. if err != nil {
  452. return nil, err
  453. }
  454. if o.Snapshot == nil || len(o.Snapshot.RootSnapshotList) == 0 {
  455. return nil, errors.New("No snapshots for this VM")
  456. }
  457. m := make(snapshotMap)
  458. m.add("", o.Snapshot.RootSnapshotList)
  459. s := m[name]
  460. switch len(s) {
  461. case 0:
  462. return nil, fmt.Errorf("snapshot %q not found", name)
  463. case 1:
  464. return &s[0], nil
  465. default:
  466. return nil, fmt.Errorf("%q resolves to %d snapshots", name, len(s))
  467. }
  468. }
  469. // RemoveSnapshot removes a named snapshot
  470. func (v VirtualMachine) RemoveSnapshot(ctx context.Context, name string, removeChildren bool, consolidate *bool) (*Task, error) {
  471. snapshot, err := v.FindSnapshot(ctx, name)
  472. if err != nil {
  473. return nil, err
  474. }
  475. req := types.RemoveSnapshot_Task{
  476. This: snapshot.Reference(),
  477. RemoveChildren: removeChildren,
  478. Consolidate: consolidate,
  479. }
  480. res, err := methods.RemoveSnapshot_Task(ctx, v.c, &req)
  481. if err != nil {
  482. return nil, err
  483. }
  484. return NewTask(v.c, res.Returnval), nil
  485. }
  486. // RevertToCurrentSnapshot reverts to the current snapshot
  487. func (v VirtualMachine) RevertToCurrentSnapshot(ctx context.Context, suppressPowerOn bool) (*Task, error) {
  488. req := types.RevertToCurrentSnapshot_Task{
  489. This: v.Reference(),
  490. SuppressPowerOn: types.NewBool(suppressPowerOn),
  491. }
  492. res, err := methods.RevertToCurrentSnapshot_Task(ctx, v.c, &req)
  493. if err != nil {
  494. return nil, err
  495. }
  496. return NewTask(v.c, res.Returnval), nil
  497. }
  498. // RevertToSnapshot reverts to a named snapshot
  499. func (v VirtualMachine) RevertToSnapshot(ctx context.Context, name string, suppressPowerOn bool) (*Task, error) {
  500. snapshot, err := v.FindSnapshot(ctx, name)
  501. if err != nil {
  502. return nil, err
  503. }
  504. req := types.RevertToSnapshot_Task{
  505. This: snapshot.Reference(),
  506. SuppressPowerOn: types.NewBool(suppressPowerOn),
  507. }
  508. res, err := methods.RevertToSnapshot_Task(ctx, v.c, &req)
  509. if err != nil {
  510. return nil, err
  511. }
  512. return NewTask(v.c, res.Returnval), nil
  513. }
  514. // IsToolsRunning returns true if VMware Tools is currently running in the guest OS, and false otherwise.
  515. func (v VirtualMachine) IsToolsRunning(ctx context.Context) (bool, error) {
  516. var o mo.VirtualMachine
  517. err := v.Properties(ctx, v.Reference(), []string{"guest.toolsRunningStatus"}, &o)
  518. if err != nil {
  519. return false, err
  520. }
  521. return o.Guest.ToolsRunningStatus == string(types.VirtualMachineToolsRunningStatusGuestToolsRunning), nil
  522. }
  523. // Wait for the VirtualMachine to change to the desired power state.
  524. func (v VirtualMachine) WaitForPowerState(ctx context.Context, state types.VirtualMachinePowerState) error {
  525. p := property.DefaultCollector(v.c)
  526. err := property.Wait(ctx, p, v.Reference(), []string{PropRuntimePowerState}, func(pc []types.PropertyChange) bool {
  527. for _, c := range pc {
  528. if c.Name != PropRuntimePowerState {
  529. continue
  530. }
  531. if c.Val == nil {
  532. continue
  533. }
  534. ps := c.Val.(types.VirtualMachinePowerState)
  535. if ps == state {
  536. return true
  537. }
  538. }
  539. return false
  540. })
  541. return err
  542. }
  543. func (v VirtualMachine) MarkAsTemplate(ctx context.Context) error {
  544. req := types.MarkAsTemplate{
  545. This: v.Reference(),
  546. }
  547. _, err := methods.MarkAsTemplate(ctx, v.c, &req)
  548. if err != nil {
  549. return err
  550. }
  551. return nil
  552. }
  553. func (v VirtualMachine) MarkAsVirtualMachine(ctx context.Context, pool ResourcePool, host *HostSystem) error {
  554. req := types.MarkAsVirtualMachine{
  555. This: v.Reference(),
  556. Pool: pool.Reference(),
  557. }
  558. if host != nil {
  559. ref := host.Reference()
  560. req.Host = &ref
  561. }
  562. _, err := methods.MarkAsVirtualMachine(ctx, v.c, &req)
  563. if err != nil {
  564. return err
  565. }
  566. return nil
  567. }
  568. func (v VirtualMachine) Migrate(ctx context.Context, pool *ResourcePool, host *HostSystem, priority types.VirtualMachineMovePriority, state types.VirtualMachinePowerState) (*Task, error) {
  569. req := types.MigrateVM_Task{
  570. This: v.Reference(),
  571. Priority: priority,
  572. State: state,
  573. }
  574. if pool != nil {
  575. ref := pool.Reference()
  576. req.Pool = &ref
  577. }
  578. if host != nil {
  579. ref := host.Reference()
  580. req.Host = &ref
  581. }
  582. res, err := methods.MigrateVM_Task(ctx, v.c, &req)
  583. if err != nil {
  584. return nil, err
  585. }
  586. return NewTask(v.c, res.Returnval), nil
  587. }
  588. func (v VirtualMachine) Unregister(ctx context.Context) error {
  589. req := types.UnregisterVM{
  590. This: v.Reference(),
  591. }
  592. _, err := methods.UnregisterVM(ctx, v.Client(), &req)
  593. return err
  594. }
  595. // QueryEnvironmentBrowser is a helper to get the environmentBrowser property.
  596. func (v VirtualMachine) QueryConfigTarget(ctx context.Context) (*types.ConfigTarget, error) {
  597. var vm mo.VirtualMachine
  598. err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm)
  599. if err != nil {
  600. return nil, err
  601. }
  602. req := types.QueryConfigTarget{
  603. This: vm.EnvironmentBrowser,
  604. }
  605. res, err := methods.QueryConfigTarget(ctx, v.Client(), &req)
  606. if err != nil {
  607. return nil, err
  608. }
  609. return res.Returnval, nil
  610. }
  611. func (v VirtualMachine) MountToolsInstaller(ctx context.Context) error {
  612. req := types.MountToolsInstaller{
  613. This: v.Reference(),
  614. }
  615. _, err := methods.MountToolsInstaller(ctx, v.Client(), &req)
  616. return err
  617. }
  618. func (v VirtualMachine) UnmountToolsInstaller(ctx context.Context) error {
  619. req := types.UnmountToolsInstaller{
  620. This: v.Reference(),
  621. }
  622. _, err := methods.UnmountToolsInstaller(ctx, v.Client(), &req)
  623. return err
  624. }
  625. func (v VirtualMachine) UpgradeTools(ctx context.Context, options string) (*Task, error) {
  626. req := types.UpgradeTools_Task{
  627. This: v.Reference(),
  628. InstallerOptions: options,
  629. }
  630. res, err := methods.UpgradeTools_Task(ctx, v.Client(), &req)
  631. if err != nil {
  632. return nil, err
  633. }
  634. return NewTask(v.c, res.Returnval), nil
  635. }
  636. func (v VirtualMachine) Export(ctx context.Context) (*nfc.Lease, error) {
  637. req := types.ExportVm{
  638. This: v.Reference(),
  639. }
  640. res, err := methods.ExportVm(ctx, v.Client(), &req)
  641. if err != nil {
  642. return nil, err
  643. }
  644. return nfc.NewLease(v.c, res.Returnval), nil
  645. }
  646. func (v VirtualMachine) UpgradeVM(ctx context.Context, version string) (*Task, error) {
  647. req := types.UpgradeVM_Task{
  648. This: v.Reference(),
  649. Version: version,
  650. }
  651. res, err := methods.UpgradeVM_Task(ctx, v.Client(), &req)
  652. if err != nil {
  653. return nil, err
  654. }
  655. return NewTask(v.c, res.Returnval), nil
  656. }
  657. // UUID is a helper to get the UUID of the VirtualMachine managed object.
  658. // This method returns an empty string if an error occurs when retrieving UUID from the VirtualMachine object.
  659. func (v VirtualMachine) UUID(ctx context.Context) string {
  660. var o mo.VirtualMachine
  661. err := v.Properties(ctx, v.Reference(), []string{"config.uuid"}, &o)
  662. if err != nil {
  663. return ""
  664. }
  665. return o.Config.Uuid
  666. }