Update vmware/govmomi vendor: add vapi package
Zones implementation for vSphere cloud provider needs dependencies which are not included in current vmware/govmomi vendor. So this update added "vapi" package to support zones.
This commit is contained in:
6
vendor/github.com/vmware/govmomi/simulator/dvs.go
generated
vendored
6
vendor/github.com/vmware/govmomi/simulator/dvs.go
generated
vendored
@@ -106,11 +106,10 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(req *types.ReconfigureDvs_
|
||||
|
||||
switch types.ConfigSpecOperation(member.Operation) {
|
||||
case types.ConfigSpecOperationAdd:
|
||||
if FindReference(host.Network, s.Self) != nil {
|
||||
if FindReference(s.Summary.HostMember, member.Host) != nil {
|
||||
return nil, &types.AlreadyExists{Name: host.Name}
|
||||
}
|
||||
|
||||
Map.AppendReference(host, &host.Network, s.Self)
|
||||
Map.AppendReference(host, &host.Network, s.Portgroup...)
|
||||
s.Summary.HostMember = append(s.Summary.HostMember, member.Host)
|
||||
|
||||
@@ -129,8 +128,7 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(req *types.ReconfigureDvs_
|
||||
}
|
||||
}
|
||||
|
||||
Map.RemoveReference(host, &host.Network, s.Self)
|
||||
RemoveReference(&s.Summary.HostMember, s.Self)
|
||||
RemoveReference(&s.Summary.HostMember, member.Host)
|
||||
case types.ConfigSpecOperationEdit:
|
||||
return nil, &types.NotSupported{}
|
||||
}
|
||||
|
||||
6
vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go
generated
vendored
6
vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go
generated
vendored
@@ -161,6 +161,12 @@ var EventInfo = []types.EventDescriptionEventDetail{
|
||||
Category: "info",
|
||||
FullFormat: "{{.Vm.Name}} on host {{.Host.Name}} in {{.Datacenter.Name}} is starting",
|
||||
},
|
||||
{
|
||||
Key: "VmStoppingEvent",
|
||||
Description: "VM stopping",
|
||||
Category: "info",
|
||||
FullFormat: "{{.Vm.Name}} on host {{.Host.Name}} in {{.Datacenter.Name}} is stopping",
|
||||
},
|
||||
{
|
||||
Key: "VmSuspendingEvent",
|
||||
Description: "VM being suspended",
|
||||
|
||||
13
vendor/github.com/vmware/govmomi/simulator/event_manager.go
generated
vendored
13
vendor/github.com/vmware/govmomi/simulator/event_manager.go
generated
vendored
@@ -157,15 +157,18 @@ func (m *EventManager) PostEvent(ctx *Context, req *types.PostEvent) soap.HasFau
|
||||
event.CreatedTime = time.Now()
|
||||
event.UserName = ctx.Session.UserName
|
||||
|
||||
m.page = m.page.Next()
|
||||
m.page = m.page.Prev()
|
||||
m.page.Value = req.EventToPost
|
||||
m.formatMessage(req.EventToPost)
|
||||
|
||||
for _, c := range m.collectors {
|
||||
if c.eventMatches(req.EventToPost) {
|
||||
c.page = c.page.Next()
|
||||
c.page.Value = event
|
||||
}
|
||||
ctx.WithLock(c, func() {
|
||||
if c.eventMatches(req.EventToPost) {
|
||||
c.page = c.page.Prev()
|
||||
c.page.Value = req.EventToPost
|
||||
Map.Update(c, []types.PropertyChange{{Name: "latestPage", Val: c.GetLatestPage()}})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return &methods.PostEventBody{
|
||||
|
||||
6
vendor/github.com/vmware/govmomi/simulator/os_unix.go
generated
vendored
6
vendor/github.com/vmware/govmomi/simulator/os_unix.go
generated
vendored
@@ -29,12 +29,10 @@ func (ds *Datastore) stat() error {
|
||||
return err
|
||||
}
|
||||
|
||||
bsize := uint64(stat.Bsize) / 512
|
||||
|
||||
info.FreeSpace = int64(stat.Bfree*bsize) >> 1
|
||||
info.FreeSpace = int64(stat.Bfree * uint64(stat.Bsize))
|
||||
|
||||
ds.Summary.FreeSpace = info.FreeSpace
|
||||
ds.Summary.Capacity = int64(stat.Blocks*bsize) >> 1
|
||||
ds.Summary.Capacity = int64(stat.Blocks * uint64(stat.Bsize))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
228
vendor/github.com/vmware/govmomi/simulator/property_collector.go
generated
vendored
228
vendor/github.com/vmware/govmomi/simulator/property_collector.go
generated
vendored
@@ -17,11 +17,14 @@ limitations under the License.
|
||||
package simulator
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
@@ -32,6 +35,11 @@ import (
|
||||
|
||||
type PropertyCollector struct {
|
||||
mo.PropertyCollector
|
||||
|
||||
nopLocker
|
||||
updates []types.ObjectUpdate
|
||||
mu sync.Mutex
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewPropertyCollector(ref types.ManagedObjectReference) object.Reference {
|
||||
@@ -72,6 +80,10 @@ func getObject(ctx *Context, ref types.ManagedObjectReference) (reflect.Value, b
|
||||
obj = o.Get()
|
||||
}
|
||||
|
||||
return getManagedObject(obj), true
|
||||
}
|
||||
|
||||
func getManagedObject(obj mo.Reference) reflect.Value {
|
||||
rval := reflect.ValueOf(obj).Elem()
|
||||
rtype := rval.Type()
|
||||
|
||||
@@ -82,26 +94,21 @@ func getObject(ctx *Context, ref types.ManagedObjectReference) (reflect.Value, b
|
||||
// for the case where the type has a field of the same name, for example:
|
||||
// mo.ResourcePool.ResourcePool
|
||||
for {
|
||||
if path.Base(rtype.PkgPath()) != "mo" {
|
||||
if rtype.Kind() != reflect.Struct || rtype.NumField() == 0 {
|
||||
log.Printf("%#v does not have an embedded mo type", ref)
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
rval = rval.Field(0)
|
||||
rtype = rval.Type()
|
||||
} else {
|
||||
if path.Base(rtype.PkgPath()) == "mo" {
|
||||
break
|
||||
}
|
||||
if rtype.Kind() != reflect.Struct || rtype.NumField() == 0 {
|
||||
log.Panicf("%#v does not have an embedded mo type", obj.Reference())
|
||||
}
|
||||
rval = rval.Field(0)
|
||||
rtype = rval.Type()
|
||||
}
|
||||
|
||||
return rval, true
|
||||
return rval
|
||||
}
|
||||
|
||||
func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{} {
|
||||
if rval.Kind() == reflect.Ptr {
|
||||
rval = rval.Elem()
|
||||
}
|
||||
|
||||
// wrapValue converts slice types to the appropriate ArrayOf type used in property collector responses.
|
||||
func wrapValue(rval reflect.Value, rtype reflect.Type) interface{} {
|
||||
pval := rval.Interface()
|
||||
|
||||
if rval.Kind() == reflect.Slice {
|
||||
@@ -128,7 +135,7 @@ func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{}
|
||||
Long: v,
|
||||
}
|
||||
default:
|
||||
kind := f.Type.Elem().Name()
|
||||
kind := rtype.Elem().Name()
|
||||
// Remove govmomi interface prefix name
|
||||
if strings.HasPrefix(kind, "Base") {
|
||||
kind = kind[4:]
|
||||
@@ -143,6 +150,14 @@ func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{}
|
||||
return pval
|
||||
}
|
||||
|
||||
func fieldValueInterface(f reflect.StructField, rval reflect.Value) interface{} {
|
||||
if rval.Kind() == reflect.Ptr {
|
||||
rval = rval.Elem()
|
||||
}
|
||||
|
||||
return wrapValue(rval, f.Type)
|
||||
}
|
||||
|
||||
func fieldValue(rval reflect.Value, p string) (interface{}, error) {
|
||||
var value interface{}
|
||||
fields := strings.Split(p, ".")
|
||||
@@ -401,7 +416,9 @@ func (pc *PropertyCollector) collect(ctx *Context, r *types.RetrievePropertiesEx
|
||||
// Select object references
|
||||
for _, spec := range r.SpecSet {
|
||||
for _, o := range spec.ObjectSet {
|
||||
rval, ok := getObject(ctx, o.Obj)
|
||||
var rval reflect.Value
|
||||
ok := false
|
||||
ctx.WithLock(o.Obj, func() { rval, ok = getObject(ctx, o.Obj) })
|
||||
if !ok {
|
||||
if isFalse(spec.ReportMissingObjectsInResults) {
|
||||
return nil, &types.ManagedObjectNotFound{Obj: o.Obj}
|
||||
@@ -420,7 +437,7 @@ func (pc *PropertyCollector) collect(ctx *Context, r *types.RetrievePropertiesEx
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
rr.collect(ctx, ref)
|
||||
ctx.WithLock(ref, func() { rr.collect(ctx, ref) })
|
||||
}
|
||||
|
||||
return rr.RetrieveResult, nil
|
||||
@@ -429,7 +446,10 @@ func (pc *PropertyCollector) collect(ctx *Context, r *types.RetrievePropertiesEx
|
||||
func (pc *PropertyCollector) CreateFilter(ctx *Context, c *types.CreateFilter) soap.HasFault {
|
||||
body := &methods.CreateFilterBody{}
|
||||
|
||||
filter := &PropertyFilter{pc: pc}
|
||||
filter := &PropertyFilter{
|
||||
pc: pc,
|
||||
refs: make(map[types.ManagedObjectReference]struct{}),
|
||||
}
|
||||
filter.PartialUpdates = c.PartialUpdates
|
||||
filter.Spec = c.Spec
|
||||
|
||||
@@ -455,14 +475,17 @@ func (pc *PropertyCollector) CreatePropertyCollector(ctx *Context, c *types.Crea
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) DestroyPropertyCollector(ctx *Context, c *types.DestroyPropertyCollector) soap.HasFault {
|
||||
pc.CancelWaitForUpdates(&types.CancelWaitForUpdates{This: c.This})
|
||||
|
||||
body := &methods.DestroyPropertyCollectorBody{}
|
||||
|
||||
for _, ref := range pc.Filter {
|
||||
filter := ctx.Session.Get(ref).(*PropertyFilter)
|
||||
filter.DestroyPropertyFilter(&types.DestroyPropertyFilter{This: ref})
|
||||
filter.DestroyPropertyFilter(ctx, &types.DestroyPropertyFilter{This: ref})
|
||||
}
|
||||
|
||||
ctx.Session.Remove(c.This)
|
||||
ctx.Map.Remove(c.This)
|
||||
|
||||
body.Res = &types.DestroyPropertyCollectorResponse{}
|
||||
|
||||
@@ -519,24 +542,46 @@ func (pc *PropertyCollector) RetrieveProperties(ctx *Context, r *types.RetrieveP
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) CancelWaitForUpdates(r *types.CancelWaitForUpdates) soap.HasFault {
|
||||
pc.mu.Lock()
|
||||
if pc.cancel != nil {
|
||||
pc.cancel()
|
||||
}
|
||||
pc.mu.Unlock()
|
||||
|
||||
return &methods.CancelWaitForUpdatesBody{Res: new(types.CancelWaitForUpdatesResponse)}
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpdatesEx) soap.HasFault {
|
||||
body := &methods.WaitForUpdatesExBody{}
|
||||
func (pc *PropertyCollector) update(u types.ObjectUpdate) {
|
||||
pc.mu.Lock()
|
||||
pc.updates = append(pc.updates, u)
|
||||
pc.mu.Unlock()
|
||||
}
|
||||
|
||||
// At the moment we need to support Task completion. Handlers can simply set the Task
|
||||
// state before returning and the non-incremental update is enough for the client.
|
||||
// We can wait for incremental updates to simulate timeouts, etc.
|
||||
if r.Version != "" {
|
||||
body.Fault_ = Fault("incremental updates not supported yet", &types.NotSupported{})
|
||||
return body
|
||||
}
|
||||
func (pc *PropertyCollector) PutObject(o mo.Reference) {
|
||||
pc.update(types.ObjectUpdate{
|
||||
Obj: o.Reference(),
|
||||
Kind: types.ObjectUpdateKindEnter,
|
||||
ChangeSet: nil,
|
||||
})
|
||||
}
|
||||
|
||||
update := &types.UpdateSet{
|
||||
Version: "-",
|
||||
}
|
||||
func (pc *PropertyCollector) UpdateObject(o mo.Reference, changes []types.PropertyChange) {
|
||||
pc.update(types.ObjectUpdate{
|
||||
Obj: o.Reference(),
|
||||
Kind: types.ObjectUpdateKindModify,
|
||||
ChangeSet: changes,
|
||||
})
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) RemoveObject(ref types.ManagedObjectReference) {
|
||||
pc.update(types.ObjectUpdate{
|
||||
Obj: ref,
|
||||
Kind: types.ObjectUpdateKindLeave,
|
||||
ChangeSet: nil,
|
||||
})
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) apply(ctx *Context, update *types.UpdateSet) types.BaseMethodFault {
|
||||
for _, ref := range pc.Filter {
|
||||
filter := ctx.Session.Get(ref).(*PropertyFilter)
|
||||
|
||||
@@ -545,8 +590,7 @@ func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpda
|
||||
|
||||
res, fault := pc.collect(ctx, r)
|
||||
if fault != nil {
|
||||
body.Fault_ = Fault("", fault)
|
||||
return body
|
||||
return fault
|
||||
}
|
||||
|
||||
fu := types.PropertyFilterUpdate{
|
||||
@@ -554,6 +598,10 @@ func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpda
|
||||
}
|
||||
|
||||
for _, o := range res.Objects {
|
||||
if _, ok := filter.refs[o.Obj]; ok {
|
||||
continue
|
||||
}
|
||||
filter.refs[o.Obj] = struct{}{}
|
||||
ou := types.ObjectUpdate{
|
||||
Obj: o.Obj,
|
||||
Kind: types.ObjectUpdateKindEnter,
|
||||
@@ -570,14 +618,122 @@ func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpda
|
||||
fu.ObjectSet = append(fu.ObjectSet, ou)
|
||||
}
|
||||
|
||||
update.FilterSet = append(update.FilterSet, fu)
|
||||
if len(fu.ObjectSet) != 0 {
|
||||
update.FilterSet = append(update.FilterSet, fu)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pc *PropertyCollector) WaitForUpdatesEx(ctx *Context, r *types.WaitForUpdatesEx) soap.HasFault {
|
||||
wait, cancel := context.WithCancel(context.Background())
|
||||
if r.Options != nil {
|
||||
if max := r.Options.MaxWaitSeconds; max != nil {
|
||||
wait, cancel = context.WithTimeout(context.Background(), time.Second*time.Duration(*max))
|
||||
}
|
||||
}
|
||||
pc.mu.Lock()
|
||||
pc.cancel = cancel
|
||||
pc.mu.Unlock()
|
||||
|
||||
body := &methods.WaitForUpdatesExBody{}
|
||||
|
||||
set := &types.UpdateSet{
|
||||
Version: r.Version,
|
||||
}
|
||||
|
||||
body.Res = &types.WaitForUpdatesExResponse{
|
||||
Returnval: update,
|
||||
Returnval: set,
|
||||
}
|
||||
|
||||
return body
|
||||
apply := func() bool {
|
||||
if fault := pc.apply(ctx, set); fault != nil {
|
||||
body.Fault_ = Fault("", fault)
|
||||
body.Res = nil
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
if r.Version == "" {
|
||||
apply() // Collect current state
|
||||
set.Version = "-" // Next request with Version set will wait via loop below
|
||||
ctx.Map.AddHandler(pc) // Listen for create, update, delete of managed objects
|
||||
return body
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(250 * time.Millisecond) // allow for updates to accumulate
|
||||
defer ticker.Stop()
|
||||
// Start the wait loop, returning on one of:
|
||||
// - Client calls CancelWaitForUpdates
|
||||
// - MaxWaitSeconds was specified and has been exceeded
|
||||
// - We have updates to send to the client
|
||||
for {
|
||||
select {
|
||||
case <-wait.Done():
|
||||
body.Res.Returnval = nil
|
||||
switch wait.Err() {
|
||||
case context.Canceled:
|
||||
log.Printf("%s: WaitForUpdates canceled", pc.Self)
|
||||
body.Fault_ = Fault("", new(types.RequestCanceled)) // CancelWaitForUpdates was called
|
||||
body.Res = nil
|
||||
case context.DeadlineExceeded:
|
||||
log.Printf("%s: WaitForUpdates MaxWaitSeconds exceeded", pc.Self)
|
||||
}
|
||||
|
||||
return body
|
||||
case <-ticker.C:
|
||||
pc.mu.Lock()
|
||||
updates := pc.updates
|
||||
pc.updates = nil // clear updates collected by the managed object CRUD listeners
|
||||
pc.mu.Unlock()
|
||||
if len(updates) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Printf("%s: applying %d updates to %d filters", pc.Self, len(updates), len(pc.Filter))
|
||||
|
||||
for _, f := range pc.Filter {
|
||||
filter := ctx.Session.Get(f).(*PropertyFilter)
|
||||
fu := types.PropertyFilterUpdate{Filter: f}
|
||||
|
||||
for _, update := range updates {
|
||||
switch update.Kind {
|
||||
case types.ObjectUpdateKindEnter: // Create
|
||||
if !apply() {
|
||||
return body
|
||||
}
|
||||
case types.ObjectUpdateKindModify: // Update
|
||||
log.Printf("%s has %d changes", update.Obj, len(update.ChangeSet))
|
||||
if !apply() { // An update may apply to collector traversal specs
|
||||
return body
|
||||
}
|
||||
if _, ok := filter.refs[update.Obj]; ok {
|
||||
// This object has already been applied by the filter,
|
||||
// now check if the property spec applies for this update.
|
||||
update = filter.apply(ctx, update)
|
||||
if len(update.ChangeSet) != 0 {
|
||||
fu.ObjectSet = append(fu.ObjectSet, update)
|
||||
}
|
||||
}
|
||||
case types.ObjectUpdateKindLeave: // Delete
|
||||
if _, ok := filter.refs[update.Obj]; !ok {
|
||||
continue
|
||||
}
|
||||
delete(filter.refs, update.Obj)
|
||||
fu.ObjectSet = append(fu.ObjectSet, update)
|
||||
}
|
||||
}
|
||||
|
||||
if len(fu.ObjectSet) != 0 {
|
||||
set.FilterSet = append(set.FilterSet, fu)
|
||||
}
|
||||
}
|
||||
if len(set.FilterSet) != 0 {
|
||||
return body
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForUpdates is deprecated, but pyvmomi is still using it at the moment.
|
||||
|
||||
63
vendor/github.com/vmware/govmomi/simulator/property_filter.go
generated
vendored
63
vendor/github.com/vmware/govmomi/simulator/property_filter.go
generated
vendored
@@ -17,6 +17,9 @@ limitations under the License.
|
||||
package simulator
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/vmware/govmomi/vim25/methods"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/soap"
|
||||
@@ -26,17 +29,71 @@ import (
|
||||
type PropertyFilter struct {
|
||||
mo.PropertyFilter
|
||||
|
||||
pc *PropertyCollector
|
||||
pc *PropertyCollector
|
||||
refs map[types.ManagedObjectReference]struct{}
|
||||
}
|
||||
|
||||
func (f *PropertyFilter) DestroyPropertyFilter(c *types.DestroyPropertyFilter) soap.HasFault {
|
||||
func (f *PropertyFilter) DestroyPropertyFilter(ctx *Context, c *types.DestroyPropertyFilter) soap.HasFault {
|
||||
body := &methods.DestroyPropertyFilterBody{}
|
||||
|
||||
RemoveReference(&f.pc.Filter, c.This)
|
||||
|
||||
Map.Remove(c.This)
|
||||
ctx.Session.Remove(c.This)
|
||||
|
||||
body.Res = &types.DestroyPropertyFilterResponse{}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
// matches returns true if the change matches one of the filter Spec.PropSet
|
||||
func (f *PropertyFilter) matches(ctx *Context, ref types.ManagedObjectReference, change *types.PropertyChange) bool {
|
||||
for _, p := range f.Spec.PropSet {
|
||||
if p.Type != ref.Type {
|
||||
continue
|
||||
}
|
||||
|
||||
if isTrue(p.All) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, name := range p.PathSet {
|
||||
if name == change.Name {
|
||||
return true
|
||||
}
|
||||
|
||||
// strings.HasPrefix("runtime.powerState", "runtime") == parent field matches
|
||||
if strings.HasPrefix(change.Name, name) {
|
||||
if obj := ctx.Map.Get(ref); obj != nil { // object may have since been deleted
|
||||
change.Name = name
|
||||
change.Val, _ = fieldValue(reflect.ValueOf(obj), name)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// apply the PropertyFilter.Spec to the given ObjectUpdate
|
||||
func (f *PropertyFilter) apply(ctx *Context, change types.ObjectUpdate) types.ObjectUpdate {
|
||||
parents := make(map[string]bool)
|
||||
set := change.ChangeSet
|
||||
change.ChangeSet = nil
|
||||
|
||||
for i, p := range set {
|
||||
if f.matches(ctx, change.Obj, &p) {
|
||||
if p.Name != set[i].Name {
|
||||
// update matches a parent field from the spec.
|
||||
if parents[p.Name] {
|
||||
continue // only return 1 instance of the parent
|
||||
}
|
||||
parents[p.Name] = true
|
||||
}
|
||||
change.ChangeSet = append(change.ChangeSet, p)
|
||||
}
|
||||
}
|
||||
|
||||
return change
|
||||
}
|
||||
|
||||
90
vendor/github.com/vmware/govmomi/simulator/registry.go
generated
vendored
90
vendor/github.com/vmware/govmomi/simulator/registry.go
generated
vendored
@@ -23,6 +23,7 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/vmware/govmomi/vim25"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
@@ -46,10 +47,11 @@ var refValueMap = map[string]string{
|
||||
// Map is the default Registry instance.
|
||||
var Map = NewRegistry()
|
||||
|
||||
// RegisterObject interface supports callbacks when objects are added and removed from the Registry
|
||||
// RegisterObject interface supports callbacks when objects are created, updated and deleted from the Registry
|
||||
type RegisterObject interface {
|
||||
mo.Reference
|
||||
PutObject(mo.Reference)
|
||||
UpdateObject(mo.Reference, []types.PropertyChange)
|
||||
RemoveObject(types.ManagedObjectReference)
|
||||
}
|
||||
|
||||
@@ -59,7 +61,7 @@ type Registry struct {
|
||||
objects map[types.ManagedObjectReference]mo.Reference
|
||||
handlers map[types.ManagedObjectReference]RegisterObject
|
||||
locks map[types.ManagedObjectReference]sync.Locker
|
||||
counter int
|
||||
counter int64
|
||||
|
||||
Namespace string
|
||||
Path string
|
||||
@@ -112,8 +114,8 @@ func (r *Registry) newReference(item mo.Reference) types.ManagedObjectReference
|
||||
}
|
||||
|
||||
if ref.Value == "" {
|
||||
r.counter++
|
||||
ref.Value = fmt.Sprintf("%s-%d", valuePrefix(ref.Type), r.counter)
|
||||
n := atomic.AddInt64(&r.counter, 1)
|
||||
ref.Value = fmt.Sprintf("%s-%d", valuePrefix(ref.Type), n)
|
||||
}
|
||||
|
||||
return ref
|
||||
@@ -126,7 +128,9 @@ func (r *Registry) setReference(item mo.Reference, ref types.ManagedObjectRefere
|
||||
|
||||
// AddHandler adds a RegisterObject handler to the Registry.
|
||||
func (r *Registry) AddHandler(h RegisterObject) {
|
||||
r.m.Lock()
|
||||
r.handlers[h.Reference()] = h
|
||||
r.m.Unlock()
|
||||
}
|
||||
|
||||
// NewEntity sets Entity().Self with a new, unique Value.
|
||||
@@ -173,10 +177,23 @@ func (r *Registry) Any(kind string) mo.Entity {
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyHandlers calls the given func for each r.handlers
|
||||
func (r *Registry) applyHandlers(f func(o RegisterObject)) {
|
||||
r.m.Lock()
|
||||
handlers := make([]RegisterObject, 0, len(r.handlers))
|
||||
for _, handler := range r.handlers {
|
||||
handlers = append(handlers, handler)
|
||||
}
|
||||
r.m.Unlock()
|
||||
|
||||
for i := range handlers {
|
||||
f(handlers[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Put adds a new object to Registry, generating a ManagedObjectReference if not already set.
|
||||
func (r *Registry) Put(item mo.Reference) mo.Reference {
|
||||
r.m.Lock()
|
||||
defer r.m.Unlock()
|
||||
|
||||
ref := item.Reference()
|
||||
if ref.Type == "" || ref.Value == "" {
|
||||
@@ -192,25 +209,50 @@ func (r *Registry) Put(item mo.Reference) mo.Reference {
|
||||
|
||||
r.objects[ref] = item
|
||||
|
||||
for _, h := range r.handlers {
|
||||
h.PutObject(item)
|
||||
}
|
||||
r.m.Unlock()
|
||||
|
||||
r.applyHandlers(func(o RegisterObject) {
|
||||
o.PutObject(item)
|
||||
})
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
// Remove removes an object from the Registry.
|
||||
func (r *Registry) Remove(item types.ManagedObjectReference) {
|
||||
r.applyHandlers(func(o RegisterObject) {
|
||||
o.RemoveObject(item)
|
||||
})
|
||||
|
||||
r.m.Lock()
|
||||
defer r.m.Unlock()
|
||||
|
||||
for _, h := range r.handlers {
|
||||
h.RemoveObject(item)
|
||||
}
|
||||
|
||||
delete(r.objects, item)
|
||||
delete(r.handlers, item)
|
||||
delete(r.locks, item)
|
||||
r.m.Unlock()
|
||||
}
|
||||
|
||||
// Update dispatches object property changes to RegisterObject handlers,
|
||||
// such as any PropertyCollector instances with in-progress WaitForUpdates calls.
|
||||
// The changes are also applied to the given object via mo.ApplyPropertyChange,
|
||||
// so there is no need to set object fields directly.
|
||||
func (r *Registry) Update(obj mo.Reference, changes []types.PropertyChange) {
|
||||
for i := range changes {
|
||||
if changes[i].Op == "" {
|
||||
changes[i].Op = types.PropertyChangeOpAssign
|
||||
}
|
||||
if changes[i].Val != nil {
|
||||
rval := reflect.ValueOf(changes[i].Val)
|
||||
changes[i].Val = wrapValue(rval, rval.Type())
|
||||
}
|
||||
}
|
||||
|
||||
val := getManagedObject(obj).Addr().Interface().(mo.Reference)
|
||||
|
||||
mo.ApplyPropertyChange(val, changes)
|
||||
|
||||
r.applyHandlers(func(o RegisterObject) {
|
||||
o.UpdateObject(val, changes)
|
||||
})
|
||||
}
|
||||
|
||||
// getEntityParent traverses up the inventory and returns the first object of type kind.
|
||||
@@ -417,11 +459,23 @@ func (r *Registry) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
func (r *Registry) locker(obj mo.Reference) sync.Locker {
|
||||
var ref types.ManagedObjectReference
|
||||
|
||||
switch x := obj.(type) {
|
||||
case types.ManagedObjectReference:
|
||||
ref = x
|
||||
obj = r.Get(ref) // to check for sync.Locker
|
||||
case *types.ManagedObjectReference:
|
||||
ref = *x
|
||||
obj = r.Get(ref) // to check for sync.Locker
|
||||
default:
|
||||
ref = obj.Reference()
|
||||
}
|
||||
|
||||
if mu, ok := obj.(sync.Locker); ok {
|
||||
return mu
|
||||
}
|
||||
|
||||
ref := obj.Reference()
|
||||
r.m.Lock()
|
||||
mu, ok := r.locks[ref]
|
||||
if !ok {
|
||||
@@ -444,3 +498,9 @@ func (r *Registry) WithLock(obj mo.Reference, f func()) {
|
||||
}
|
||||
f()
|
||||
}
|
||||
|
||||
// nopLocker can be embedded to opt-out of auto-locking (see Registry.WithLock)
|
||||
type nopLocker struct{}
|
||||
|
||||
func (*nopLocker) Lock() {}
|
||||
func (*nopLocker) Unlock() {}
|
||||
|
||||
22
vendor/github.com/vmware/govmomi/simulator/search_index.go
generated
vendored
22
vendor/github.com/vmware/govmomi/simulator/search_index.go
generated
vendored
@@ -57,15 +57,18 @@ func (s *SearchIndex) FindByDatastorePath(r *types.FindByDatastorePath) soap.Has
|
||||
func (s *SearchIndex) FindByInventoryPath(req *types.FindByInventoryPath) soap.HasFault {
|
||||
body := &methods.FindByInventoryPathBody{Res: new(types.FindByInventoryPathResponse)}
|
||||
|
||||
path := strings.Split(req.InventoryPath, "/")
|
||||
if len(path) <= 1 {
|
||||
split := func(c rune) bool {
|
||||
return c == '/'
|
||||
}
|
||||
path := strings.FieldsFunc(req.InventoryPath, split)
|
||||
if len(path) < 1 {
|
||||
return body
|
||||
}
|
||||
|
||||
root := Map.content().RootFolder
|
||||
o := &root
|
||||
|
||||
for _, name := range path[1:] {
|
||||
for _, name := range path {
|
||||
f := s.FindChild(&types.FindChild{Entity: *o, Name: name})
|
||||
|
||||
o = f.(*methods.FindChildBody).Res.Returnval
|
||||
@@ -132,9 +135,16 @@ func (s *SearchIndex) FindByUuid(req *types.FindByUuid) soap.HasFault {
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if vm.Config.Uuid == req.Uuid {
|
||||
body.Res.Returnval = &ref
|
||||
break
|
||||
if req.InstanceUuid != nil && *req.InstanceUuid {
|
||||
if vm.Config.InstanceUuid == req.Uuid {
|
||||
body.Res.Returnval = &ref
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if vm.Config.Uuid == req.Uuid {
|
||||
body.Res.Returnval = &ref
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
6
vendor/github.com/vmware/govmomi/simulator/session_manager.go
generated
vendored
6
vendor/github.com/vmware/govmomi/simulator/session_manager.go
generated
vendored
@@ -138,6 +138,12 @@ func (s *SessionManager) Logout(ctx *Context, _ *types.Logout) soap.HasFault {
|
||||
session := ctx.Session
|
||||
delete(s.sessions, session.Key)
|
||||
|
||||
for ref, obj := range ctx.Session.Registry.objects {
|
||||
if _, ok := obj.(RegisterObject); ok {
|
||||
ctx.Map.Remove(ref) // Remove RegisterObject handlers
|
||||
}
|
||||
}
|
||||
|
||||
ctx.postEvent(&types.UserLogoutSessionEvent{
|
||||
IpAddress: session.IpAddress,
|
||||
UserAgent: session.UserAgent,
|
||||
|
||||
2
vendor/github.com/vmware/govmomi/simulator/simulator.go
generated
vendored
2
vendor/github.com/vmware/govmomi/simulator/simulator.go
generated
vendored
@@ -390,7 +390,7 @@ func (s *Service) findDatastore(query url.Values) (*Datastore, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
finder := find.NewFinder(s.client, false)
|
||||
dc, err := finder.DatacenterOrDefault(ctx, query.Get("dcName"))
|
||||
dc, err := finder.DatacenterOrDefault(ctx, query.Get("dcPath"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
35
vendor/github.com/vmware/govmomi/simulator/task.go
generated
vendored
35
vendor/github.com/vmware/govmomi/simulator/task.go
generated
vendored
@@ -55,18 +55,19 @@ func CreateTask(e mo.Reference, name string, run func(*Task) (types.AnyType, typ
|
||||
Execute: run,
|
||||
}
|
||||
|
||||
Map.Put(task)
|
||||
|
||||
task.Self = Map.newReference(task)
|
||||
task.Info.Key = task.Self.Value
|
||||
task.Info.Task = task.Self
|
||||
task.Info.Name = ucFirst(name)
|
||||
task.Info.DescriptionId = fmt.Sprintf("%s.%s", ref.Type, id)
|
||||
task.Info.Entity = &ref
|
||||
task.Info.EntityName = ref.Value
|
||||
|
||||
task.Info.Reason = &types.TaskReasonUser{UserName: "vcsim"} // TODO: Context.Session.User
|
||||
task.Info.QueueTime = time.Now()
|
||||
task.Info.State = types.TaskInfoStateQueued
|
||||
|
||||
Map.Put(task)
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
@@ -78,25 +79,31 @@ type TaskRunner interface {
|
||||
|
||||
func (t *Task) Run() types.ManagedObjectReference {
|
||||
now := time.Now()
|
||||
t.Info.StartTime = &now
|
||||
|
||||
t.Info.State = types.TaskInfoStateRunning
|
||||
Map.Update(t, []types.PropertyChange{
|
||||
{Name: "info.startTime", Val: now},
|
||||
{Name: "info.state", Val: types.TaskInfoStateRunning},
|
||||
})
|
||||
|
||||
res, err := t.Execute(t)
|
||||
|
||||
now = time.Now()
|
||||
t.Info.CompleteTime = &now
|
||||
|
||||
state := types.TaskInfoStateSuccess
|
||||
var fault interface{}
|
||||
if err != nil {
|
||||
t.Info.State = types.TaskInfoStateError
|
||||
t.Info.Error = &types.LocalizedMethodFault{
|
||||
state = types.TaskInfoStateError
|
||||
fault = types.LocalizedMethodFault{
|
||||
Fault: err,
|
||||
LocalizedMessage: fmt.Sprintf("%T", err),
|
||||
}
|
||||
} else {
|
||||
t.Info.Result = res
|
||||
t.Info.State = types.TaskInfoStateSuccess
|
||||
}
|
||||
|
||||
now = time.Now()
|
||||
|
||||
Map.Update(t, []types.PropertyChange{
|
||||
{Name: "info.completeTime", Val: now},
|
||||
{Name: "info.state", Val: state},
|
||||
{Name: "info.result", Val: res},
|
||||
{Name: "info.error", Val: fault},
|
||||
})
|
||||
|
||||
return t.Self
|
||||
}
|
||||
|
||||
19
vendor/github.com/vmware/govmomi/simulator/task_manager.go
generated
vendored
19
vendor/github.com/vmware/govmomi/simulator/task_manager.go
generated
vendored
@@ -17,6 +17,8 @@ limitations under the License.
|
||||
package simulator
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/vmware/govmomi/object"
|
||||
"github.com/vmware/govmomi/vim25/mo"
|
||||
"github.com/vmware/govmomi/vim25/types"
|
||||
@@ -26,6 +28,7 @@ var recentTaskMax = 200 // the VC limit
|
||||
|
||||
type TaskManager struct {
|
||||
mo.TaskManager
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func NewTaskManager(ref types.ManagedObjectReference) object.Reference {
|
||||
@@ -41,12 +44,16 @@ func (m *TaskManager) PutObject(obj mo.Reference) {
|
||||
return
|
||||
}
|
||||
|
||||
m.RecentTask = append(m.RecentTask, ref)
|
||||
|
||||
if len(m.RecentTask) > recentTaskMax {
|
||||
m.RecentTask = m.RecentTask[1:]
|
||||
m.Lock()
|
||||
recent := append(m.RecentTask, ref)
|
||||
if len(recent) > recentTaskMax {
|
||||
recent = recent[1:]
|
||||
}
|
||||
|
||||
Map.Update(m, []types.PropertyChange{{Name: "recentTask", Val: recent}})
|
||||
m.Unlock()
|
||||
}
|
||||
|
||||
func (m *TaskManager) RemoveObject(_ types.ManagedObjectReference) {
|
||||
}
|
||||
func (*TaskManager) RemoveObject(types.ManagedObjectReference) {}
|
||||
|
||||
func (*TaskManager) UpdateObject(mo.Reference, []types.PropertyChange) {}
|
||||
|
||||
83
vendor/github.com/vmware/govmomi/simulator/view_manager.go
generated
vendored
83
vendor/github.com/vmware/govmomi/simulator/view_manager.go
generated
vendored
@@ -137,7 +137,8 @@ type ContainerView struct {
|
||||
types map[string]bool
|
||||
}
|
||||
|
||||
func (v *ContainerView) DestroyView(c *types.DestroyView) soap.HasFault {
|
||||
func (v *ContainerView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault {
|
||||
ctx.Session.Remove(c.This)
|
||||
return destroyView(c.This)
|
||||
}
|
||||
|
||||
@@ -192,3 +193,83 @@ func (v *ContainerView) add(root mo.Reference, seen map[types.ManagedObjectRefer
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (m *ViewManager) CreateListView(ctx *Context, req *types.CreateListView) soap.HasFault {
|
||||
body := new(methods.CreateListViewBody)
|
||||
list := new(ListView)
|
||||
|
||||
if err := list.add(req.Obj); err != nil {
|
||||
body.Fault_ = Fault("", err)
|
||||
return body
|
||||
}
|
||||
|
||||
ctx.Session.Put(list)
|
||||
|
||||
body.Res = &types.CreateListViewResponse{
|
||||
Returnval: list.Self,
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
type ListView struct {
|
||||
mo.ListView
|
||||
}
|
||||
|
||||
func (v *ListView) update() {
|
||||
Map.Update(v, []types.PropertyChange{{Name: "view", Val: v.View}})
|
||||
}
|
||||
|
||||
func (v *ListView) add(refs []types.ManagedObjectReference) *types.ManagedObjectNotFound {
|
||||
for _, ref := range refs {
|
||||
obj := Map.Get(ref)
|
||||
if obj == nil {
|
||||
return &types.ManagedObjectNotFound{Obj: ref}
|
||||
}
|
||||
v.View = append(v.View, ref)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *ListView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault {
|
||||
ctx.Session.Remove(c.This)
|
||||
return destroyView(c.This)
|
||||
}
|
||||
|
||||
func (v *ListView) ModifyListView(req *types.ModifyListView) soap.HasFault {
|
||||
body := new(methods.ModifyListViewBody)
|
||||
|
||||
for _, ref := range req.Remove {
|
||||
RemoveReference(&v.View, ref)
|
||||
}
|
||||
|
||||
if err := v.add(req.Add); err != nil {
|
||||
body.Fault_ = Fault("", err)
|
||||
return body
|
||||
}
|
||||
|
||||
body.Res = new(types.ModifyListViewResponse)
|
||||
|
||||
if len(req.Remove) != 0 || len(req.Add) != 0 {
|
||||
v.update()
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func (v *ListView) ResetListView(req *types.ResetListView) soap.HasFault {
|
||||
body := new(methods.ResetListViewBody)
|
||||
|
||||
v.View = nil
|
||||
|
||||
if err := v.add(req.Obj); err != nil {
|
||||
body.Fault_ = Fault("", err)
|
||||
return body
|
||||
}
|
||||
|
||||
body.Res = new(types.ResetListViewResponse)
|
||||
|
||||
v.update()
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
7
vendor/github.com/vmware/govmomi/simulator/virtual_disk_manager.go
generated
vendored
7
vendor/github.com/vmware/govmomi/simulator/virtual_disk_manager.go
generated
vendored
@@ -210,3 +210,10 @@ func (m *VirtualDiskManager) QueryVirtualDiskUuid(req *types.QueryVirtualDiskUui
|
||||
|
||||
return body
|
||||
}
|
||||
|
||||
func (m *VirtualDiskManager) SetVirtualDiskUuid(req *types.SetVirtualDiskUuid) soap.HasFault {
|
||||
body := new(methods.SetVirtualDiskUuidBody)
|
||||
// TODO: validate uuid format and persist
|
||||
body.Res = new(types.SetVirtualDiskUuidResponse)
|
||||
return body
|
||||
}
|
||||
|
||||
117
vendor/github.com/vmware/govmomi/simulator/virtual_machine.go
generated
vendored
117
vendor/github.com/vmware/govmomi/simulator/virtual_machine.go
generated
vendored
@@ -444,6 +444,13 @@ func numberToString(n int64, sep rune) string {
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func getDiskSize(disk *types.VirtualDisk) int64 {
|
||||
if disk.CapacityInBytes == 0 {
|
||||
return disk.CapacityInKB * 1024
|
||||
}
|
||||
return disk.CapacityInBytes
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) configureDevice(devices object.VirtualDeviceList, spec *types.VirtualDeviceConfigSpec) types.BaseMethodFault {
|
||||
device := spec.Device
|
||||
d := device.GetVirtualDevice()
|
||||
@@ -518,9 +525,16 @@ func (vm *VirtualMachine) configureDevice(devices object.VirtualDeviceList, spec
|
||||
p, _ := parseDatastorePath(info.FileName)
|
||||
|
||||
host := Map.Get(*vm.Runtime.Host).(*HostSystem)
|
||||
ds := Map.FindByName(p.Datastore, host.Datastore).Reference()
|
||||
|
||||
info.Datastore = &ds
|
||||
entity := Map.FindByName(p.Datastore, host.Datastore)
|
||||
ref := entity.Reference()
|
||||
info.Datastore = &ref
|
||||
|
||||
ds := entity.(*Datastore)
|
||||
|
||||
// XXX: compare disk size and free space until windows stat is supported
|
||||
ds.Summary.FreeSpace -= getDiskSize(x)
|
||||
ds.Info.GetDatastoreInfo().FreeSpace = ds.Summary.FreeSpace
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,6 +570,15 @@ func (vm *VirtualMachine) removeDevice(devices object.VirtualDeviceList, spec *t
|
||||
switch b := device.Backing.(type) {
|
||||
case types.BaseVirtualDeviceFileBackingInfo:
|
||||
file = b.GetVirtualDeviceFileBackingInfo().FileName
|
||||
|
||||
p, _ := parseDatastorePath(file)
|
||||
|
||||
host := Map.Get(*vm.Runtime.Host).(*HostSystem)
|
||||
|
||||
ds := Map.FindByName(p.Datastore, host.Datastore).(*Datastore)
|
||||
|
||||
ds.Summary.FreeSpace += getDiskSize(device)
|
||||
ds.Info.GetDatastoreInfo().FreeSpace = ds.Summary.FreeSpace
|
||||
}
|
||||
|
||||
if file != "" {
|
||||
@@ -686,15 +709,9 @@ func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
|
||||
}
|
||||
}
|
||||
|
||||
c.VirtualMachine.Runtime.PowerState = c.state
|
||||
c.VirtualMachine.Summary.Runtime.PowerState = c.state
|
||||
|
||||
bt := &c.VirtualMachine.Summary.Runtime.BootTime
|
||||
var boot types.AnyType
|
||||
if c.state == types.VirtualMachinePowerStatePoweredOn {
|
||||
now := time.Now()
|
||||
*bt = &now
|
||||
} else {
|
||||
*bt = nil
|
||||
boot = time.Now()
|
||||
}
|
||||
|
||||
event := c.event()
|
||||
@@ -705,9 +722,23 @@ func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) {
|
||||
&types.VmPoweredOnEvent{VmEvent: event},
|
||||
)
|
||||
case types.VirtualMachinePowerStatePoweredOff:
|
||||
c.ctx.postEvent(&types.VmPoweredOffEvent{VmEvent: event})
|
||||
c.ctx.postEvent(
|
||||
&types.VmStoppingEvent{VmEvent: event},
|
||||
&types.VmPoweredOffEvent{VmEvent: event},
|
||||
)
|
||||
case types.VirtualMachinePowerStateSuspended:
|
||||
c.ctx.postEvent(
|
||||
&types.VmSuspendingEvent{VmEvent: event},
|
||||
&types.VmSuspendedEvent{VmEvent: event},
|
||||
)
|
||||
}
|
||||
|
||||
Map.Update(c.VirtualMachine, []types.PropertyChange{
|
||||
{Name: "runtime.powerState", Val: c.state},
|
||||
{Name: "summary.runtime.powerState", Val: c.state},
|
||||
{Name: "summary.runtime.bootTime", Val: boot},
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -739,6 +770,37 @@ func (vm *VirtualMachine) PowerOffVMTask(ctx *Context, c *types.PowerOffVM_Task)
|
||||
}
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) SuspendVMTask(ctx *Context, req *types.SuspendVM_Task) soap.HasFault {
|
||||
runner := &powerVMTask{vm, types.VirtualMachinePowerStateSuspended, ctx}
|
||||
task := CreateTask(runner.Reference(), "suspend", runner.Run)
|
||||
|
||||
return &methods.SuspendVM_TaskBody{
|
||||
Res: &types.SuspendVM_TaskResponse{
|
||||
Returnval: task.Run(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ResetVMTask(ctx *Context, req *types.ResetVM_Task) soap.HasFault {
|
||||
task := CreateTask(vm, "reset", func(task *Task) (types.AnyType, types.BaseMethodFault) {
|
||||
res := vm.PowerOffVMTask(ctx, &types.PowerOffVM_Task{This: vm.Self})
|
||||
ctask := Map.Get(res.(*methods.PowerOffVM_TaskBody).Res.Returnval).(*Task)
|
||||
if ctask.Info.Error != nil {
|
||||
return nil, ctask.Info.Error.Fault
|
||||
}
|
||||
|
||||
_ = vm.PowerOnVMTask(ctx, &types.PowerOnVM_Task{This: vm.Self})
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
return &methods.ResetVM_TaskBody{
|
||||
Res: &types.ResetVM_TaskResponse{
|
||||
Returnval: task.Run(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ReconfigVMTask(ctx *Context, req *types.ReconfigVM_Task) soap.HasFault {
|
||||
task := CreateTask(vm, "reconfigVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
|
||||
err := vm.configure(&req.Spec)
|
||||
@@ -771,6 +833,11 @@ func (vm *VirtualMachine) DestroyTask(ctx *Context, req *types.Destroy_Task) soa
|
||||
return nil, r.Fault().VimFault().(types.BaseMethodFault)
|
||||
}
|
||||
|
||||
// Remove all devices
|
||||
devices := object.VirtualDeviceList(vm.Config.Hardware.Device)
|
||||
spec, _ := devices.ConfigSpec(types.VirtualDeviceConfigSpecOperationRemove)
|
||||
vm.configureDevices(&types.VirtualMachineConfigSpec{DeviceChange: spec})
|
||||
|
||||
// Delete VM files from the datastore (ignoring result for now)
|
||||
m := Map.FileManager()
|
||||
dc := Map.getEntityDatacenter(vm).Reference()
|
||||
@@ -907,29 +974,36 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa
|
||||
|
||||
func (vm *VirtualMachine) RelocateVMTask(req *types.RelocateVM_Task) soap.HasFault {
|
||||
task := CreateTask(vm, "relocateVm", func(t *Task) (types.AnyType, types.BaseMethodFault) {
|
||||
var changes []types.PropertyChange
|
||||
|
||||
if ref := req.Spec.Datastore; ref != nil {
|
||||
ds := Map.Get(*ref).(*Datastore)
|
||||
Map.RemoveReference(ds, &ds.Vm, *ref)
|
||||
|
||||
vm.Datastore = []types.ManagedObjectReference{*ref}
|
||||
|
||||
// TODO: migrate vm.Config.Files (and vm.Summary.Config.VmPathName)
|
||||
|
||||
changes = append(changes, types.PropertyChange{Name: "datastore", Val: []types.ManagedObjectReference{*ref}})
|
||||
}
|
||||
|
||||
if ref := req.Spec.Pool; ref != nil {
|
||||
pool := Map.Get(*ref).(*ResourcePool)
|
||||
Map.RemoveReference(pool, &pool.Vm, *ref)
|
||||
|
||||
vm.ResourcePool = ref
|
||||
changes = append(changes, types.PropertyChange{Name: "resourcePool", Val: *ref})
|
||||
}
|
||||
|
||||
if ref := req.Spec.Host; ref != nil {
|
||||
host := Map.Get(*ref).(*HostSystem)
|
||||
Map.RemoveReference(host, &host.Vm, *ref)
|
||||
|
||||
vm.Runtime.Host = ref
|
||||
changes = append(changes,
|
||||
types.PropertyChange{Name: "runtime.host", Val: *ref},
|
||||
types.PropertyChange{Name: "summary.runtime.host", Val: *ref},
|
||||
)
|
||||
}
|
||||
|
||||
Map.Update(vm, changes)
|
||||
|
||||
return nil, nil
|
||||
})
|
||||
|
||||
@@ -1032,7 +1106,7 @@ func (vm *VirtualMachine) RemoveAllSnapshotsTask(req *types.RemoveAllSnapshots_T
|
||||
}
|
||||
}
|
||||
|
||||
func (vm *VirtualMachine) ShutdownGuest(c *types.ShutdownGuest) soap.HasFault {
|
||||
func (vm *VirtualMachine) ShutdownGuest(ctx *Context, c *types.ShutdownGuest) soap.HasFault {
|
||||
r := &methods.ShutdownGuestBody{}
|
||||
// should be poweron
|
||||
if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOff {
|
||||
@@ -1047,6 +1121,17 @@ func (vm *VirtualMachine) ShutdownGuest(c *types.ShutdownGuest) soap.HasFault {
|
||||
vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
|
||||
vm.Summary.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff
|
||||
|
||||
event := vm.event()
|
||||
ctx.postEvent(
|
||||
&types.VmGuestShutdownEvent{VmEvent: event},
|
||||
&types.VmPoweredOffEvent{VmEvent: event},
|
||||
)
|
||||
|
||||
Map.Update(vm, []types.PropertyChange{
|
||||
{Name: "runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff},
|
||||
{Name: "summary.runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff},
|
||||
})
|
||||
|
||||
r.Res = new(types.ShutdownGuestResponse)
|
||||
|
||||
return r
|
||||
|
||||
Reference in New Issue
Block a user