feat: support snapshot of esxi

This commit is contained in:
rainzm
2020-11-09 13:54:45 +08:00
parent 4653e46ec9
commit 7bdcf95524
3 changed files with 248 additions and 9 deletions
+63 -1
View File
@@ -130,7 +130,7 @@ func init() {
Cpu: args.CpuNum,
Mem: args.MemSize,
}
vm, err := host.CloneVM(context.Background(), temVm, idss[0].(*esxi.SDatastore), createParams)
vm, err := host.CloneVM(context.Background(), temVm, nil, idss[0].(*esxi.SDatastore), createParams)
if err != nil {
return errors.Wrap(err, "SHost.CloneVMFromTemplate")
}
@@ -198,6 +198,68 @@ func init() {
return nil
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-snapshots", "Show vm snapshots details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
vm, err := getVM(cli, args)
if err != nil {
return err
}
vmsps, err := vm.GetInstanceSnapshots()
if err != nil {
return err
}
printList(vmsps, []string{})
return nil
})
type VirtualMachineSnapshotCreateOptions struct {
VirtualMachineShowOptions
NAME string `help:"Name of snapshot"`
Desc string `help:"Description of snapshot"`
}
shellutils.R(&VirtualMachineSnapshotCreateOptions{}, "vm-snapshot-create", "Create vm snapshot", func(cli *esxi.SESXiClient, args *VirtualMachineSnapshotCreateOptions) error {
vm, err := getVM(cli, &args.VirtualMachineShowOptions)
if err != nil {
return err
}
sp, err := vm.CreateInstanceSnapshot(context.Background(), args.NAME, args.Desc)
if err != nil {
return err
}
printObject(sp)
return nil
})
type VirtualMachineSnapshotOptions struct {
VirtualMachineShowOptions
ID string `help:"ID of snapshot"`
}
shellutils.R(&VirtualMachineSnapshotOptions{}, "vm-snapshot-delete", "Delete vm snapshot", func(cli *esxi.SESXiClient, args *VirtualMachineSnapshotOptions) error {
vm, err := getVM(cli, &args.VirtualMachineShowOptions)
if err != nil {
return err
}
sp, err := vm.GetInstanceSnapshot(args.ID)
if err != nil {
return err
}
err = sp.Delete()
if err != nil {
return err
}
return nil
})
shellutils.R(&VirtualMachineSnapshotOptions{}, "vm-snapshot-reset", "Reset vm to snapshot", func(cli *esxi.SESXiClient, args *VirtualMachineSnapshotOptions) error {
vm, err := getVM(cli, &args.VirtualMachineShowOptions)
if err != nil {
return err
}
err = vm.ResetToInstanceSnapshot(context.Background(), args.ID)
if err != nil {
return err
}
return nil
})
shellutils.R(&VirtualMachineShowOptions{}, "vm-disks", "Show vm disks details", func(cli *esxi.SESXiClient, args *VirtualMachineShowOptions) error {
vm, err := getVM(cli, args)
if err != nil {
+89
View File
@@ -0,0 +1,89 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package esxi
import (
"fmt"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
)
type SVirtualMachineSnapshot struct {
snapshotTree types.VirtualMachineSnapshotTree
vm *SVirtualMachine
}
func NewSnapshot(st types.VirtualMachineSnapshotTree) *SVirtualMachineSnapshot {
return &SVirtualMachineSnapshot{
snapshotTree: st,
}
}
func (s *SVirtualMachineSnapshot) GetId() string {
return moRefId(s.snapshotTree.Snapshot)
}
func (s *SVirtualMachineSnapshot) GetName() string {
return s.snapshotTree.Name
}
func (s *SVirtualMachineSnapshot) GetDescription() string {
return s.snapshotTree.Description
}
func (s *SVirtualMachineSnapshot) GetGlobalId() string {
return fmt.Sprintf("%s-%d", s.vm.GetGlobalId(), s.snapshotTree.Id)
}
func (s *SVirtualMachineSnapshot) GetStatus() string {
return api.INSTANCE_SNAPSHOT_READY
}
func (s *SVirtualMachineSnapshot) Refresh() error {
return nil
}
func (s *SVirtualMachineSnapshot) IsEmulated() bool {
return false
}
func (s *SVirtualMachineSnapshot) GetMetadata() *jsonutils.JSONDict {
return nil
}
func (s *SVirtualMachineSnapshot) GetProjectId() string {
return s.vm.GetProjectId()
}
func (s *SVirtualMachineSnapshot) Delete() error {
cTrue := true
req := types.RemoveSnapshot_Task{
This: s.snapshotTree.Snapshot.Reference(),
RemoveChildren: false,
Consolidate: &cTrue,
}
res, err := methods.RemoveSnapshot_Task(s.vm.manager.context, s.vm.manager.client.Client, &req)
if err != nil {
return errors.Wrap(err, "RemoveSnapshot_Task")
}
return object.NewTask(s.vm.manager.client.Client, res.Returnval).Wait(s.vm.manager.context)
}
+96 -8
View File
@@ -24,6 +24,7 @@ import (
"github.com/vmware/govmomi/nfc"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/soap"
"github.com/vmware/govmomi/vim25/types"
@@ -48,18 +49,19 @@ import (
"yunion.io/x/onecloud/pkg/util/version"
)
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary", "config", "guest", "resourcePool", "layoutEx"}
var VIRTUAL_MACHINE_PROPS = []string{"name", "parent", "runtime", "summary", "config", "guest", "resourcePool", "layoutEx", "snapshot"}
type SVirtualMachine struct {
multicloud.SInstanceBase
SManagedObject
vnics []SVirtualNIC
vdisks []SVirtualDisk
vga SVirtualVGA
cdroms []SVirtualCdrom
devs map[int32]SVirtualDevice
ihost cloudprovider.ICloudHost
vnics []SVirtualNIC
vdisks []SVirtualDisk
vga SVirtualVGA
cdroms []SVirtualCdrom
devs map[int32]SVirtualDevice
ihost cloudprovider.ICloudHost
snapshots []SVirtualMachineSnapshot
guestIps map[string]string
}
@@ -253,7 +255,7 @@ func (self *SVirtualMachine) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
func (self *SVirtualMachine) GetIDiskById(idStr string) (cloudprovider.ICloudDisk, error) {
for i := 0; i < len(self.vdisks); i += 1 {
if self.vdisks[i].GetGlobalId() == idStr {
if self.vdisks[i].MatchId(idStr) {
return &self.vdisks[i], nil
}
}
@@ -1357,3 +1359,89 @@ func (self *SVirtualMachine) IsTemplate() bool {
}
return movm.Config != nil && movm.Config.Template
}
func (self *SVirtualMachine) fetchSnapshots() {
movm := self.getVirtualMachine()
if movm.Snapshot == nil {
return
}
self.snapshots = self.extractSnapshots(movm.Snapshot.RootSnapshotList, make([]SVirtualMachineSnapshot, 0, len(movm.Snapshot.RootSnapshotList)))
}
func (self *SVirtualMachine) extractSnapshots(tree []types.VirtualMachineSnapshotTree, snapshots []SVirtualMachineSnapshot) []SVirtualMachineSnapshot {
for i := range tree {
snapshots = append(snapshots, SVirtualMachineSnapshot{
snapshotTree: tree[i],
vm: self,
})
snapshots = self.extractSnapshots(tree[i].ChildSnapshotList, snapshots)
}
return snapshots
}
func (self *SVirtualMachine) GetInstanceSnapshots() ([]cloudprovider.ICloudInstanceSnapshot, error) {
if self.snapshots == nil {
self.fetchSnapshots()
}
ret := make([]cloudprovider.ICloudInstanceSnapshot, 0, len(self.snapshots))
for i := range self.snapshots {
ret = append(ret, &self.snapshots[i])
}
return ret, nil
}
func (self *SVirtualMachine) GetInstanceSnapshot(idStr string) (cloudprovider.ICloudInstanceSnapshot, error) {
if self.snapshots == nil {
self.fetchSnapshots()
}
for i := range self.snapshots {
if self.snapshots[i].GetGlobalId() == idStr {
// copyone
sp := self.snapshots[i]
return &sp, nil
}
}
return nil, errors.ErrNotFound
}
func (self *SVirtualMachine) CreateInstanceSnapshot(ctx context.Context, name string, desc string) (cloudprovider.ICloudInstanceSnapshot, error) {
ovm := self.getVmObj()
task, err := ovm.CreateSnapshot(ctx, name, desc, false, false)
if err != nil {
return nil, errors.Wrap(err, "CreateSnapshot")
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return nil, errors.Wrap(err, "task.Wait")
}
sp := info.Result.(types.ManagedObjectReference)
err = self.Refresh()
if err != nil {
return nil, errors.Wrap(err, "create successfully")
}
self.fetchSnapshots()
for i := range self.snapshots {
if self.snapshots[i].snapshotTree.Snapshot == sp {
// copyone
sp := self.snapshots[i]
return &sp, nil
}
}
return nil, errors.Wrap(errors.ErrNotFound, "create successfully")
}
func (self *SVirtualMachine) ResetToInstanceSnapshot(ctx context.Context, idStr string) error {
cloudIsp, err := self.GetInstanceSnapshot(idStr)
if err != nil {
return errors.Wrap(err, "GetInstanceSnapshot")
}
isp := cloudIsp.(*SVirtualMachineSnapshot)
req := types.RevertToSnapshot_Task{
This: isp.snapshotTree.Snapshot.Reference(),
}
res, err := methods.RevertToSnapshot_Task(ctx, self.manager.client.Client, &req)
if err != nil {
return errors.Wrap(err, "RevertToSnapshot_Task")
}
return object.NewTask(self.manager.client.Client, res.Returnval).Wait(ctx)
}