Beispiel #1
0
// ObjectContentToType loads an ObjectContent value into the value it
// represents. If the ObjectContent value has a non-empty 'MissingSet' field,
// it returns the first fault it finds there as error. If the 'MissingSet'
// field is empty, it returns a pointer to a reflect.Value. It handles contain
// nested properties, such as 'guest.ipAddress' or 'config.hardware'.
func ObjectContentToType(o types.ObjectContent) (interface{}, error) {
	// Expect no properties in the missing set
	for _, p := range o.MissingSet {
		if ignoreMissingProperty(o.Obj, p) {
			continue
		}

		return nil, soap.WrapVimFault(p.Fault.Fault)
	}

	ti := typeInfoForType(o.Obj.Type)
	v, err := ti.LoadFromObjectContent(o)
	if err != nil {
		return nil, err
	}

	return v.Elem().Interface(), nil
}
Beispiel #2
0
// TestSoapFaults covers the various soap fault checking paths
func TestSoapFaults(t *testing.T) {
	ctx := context.Background()

	// Nothing VC specific in this test, so we use the simpler ESX model
	model := simulator.ESX()
	defer model.Remove()
	err := model.Create()
	if err != nil {
		t.Fatal(err)
	}

	server := model.Service.NewServer()
	defer server.Close()

	client, err := govmomi.NewClient(ctx, server.URL, true)
	if err != nil {
		t.Fatal(err)
	}

	// Any VM will do
	finder := find.NewFinder(client.Client, false)
	vm, err := finder.VirtualMachine(ctx, "/ha-datacenter/vm/*_VM0")
	if err != nil {
		t.Fatal(err)
	}

	// Test the success path
	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		return vm.PowerOn(ctx)
	})
	if err != nil {
		t.Fatal(err)
	}

	// Wrap existing vm MO with faultyVirtualMachine
	ref := simulator.Map.Get(vm.Reference())
	fvm := &faultyVirtualMachine{*ref.(*simulator.VirtualMachine), nil}
	simulator.Map.Put(fvm)

	// Inject TaskInProgress fault
	fvm.fault = new(types.TaskInProgress)
	task, err := vm.PowerOff(ctx)
	if err != nil {
		t.Fatal(err)
	}

	// Test the task.Error path
	res, err := task.WaitForResult(ctx, nil)
	if !isTaskInProgress(err) {
		t.Error(err)
	}

	// Test the soap.IsVimFault() path
	if !isTaskInProgress(soap.WrapVimFault(res.Error.Fault)) {
		t.Errorf("fault=%#v", res.Error.Fault)
	}

	// Test the soap.IsSoapFault() path
	err = vm.MarkAsTemplate(ctx)
	if !isTaskInProgress(err) {
		t.Error(err)
	}

	// Test a fault other than TaskInProgress
	fvm.fault = &types.QuestionPending{
		Text: "now why would you want to do such a thing?",
	}

	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		return vm.PowerOff(ctx)
	})
	if err == nil {
		t.Error("expected error")
	}
	if isTaskInProgress(err) {
		t.Error(err)
	}

	// Test with retry
	fvm.fault = new(types.TaskInProgress)
	called := 0

	err = Wait(ctx, func(ctx context.Context) (Task, error) {
		called++
		if called > 1 {
			simulator.Map.Put(ref) // remove fault injection
		}

		return vm.PowerOff(ctx)
	})
	if err != nil {
		t.Error(err)
	}
	if called != 2 {
		t.Errorf("called=%d", called)
	}
}