github.com/vmware/govmomi@v0.43.0/simulator/session_manager_test.go (about)

     1  /*
     2  Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package simulator
    18  
    19  import (
    20  	"context"
    21  	"crypto/tls"
    22  	"log"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/vmware/govmomi"
    27  	"github.com/vmware/govmomi/object"
    28  	"github.com/vmware/govmomi/property"
    29  	"github.com/vmware/govmomi/session"
    30  	"github.com/vmware/govmomi/simulator/vpx"
    31  	"github.com/vmware/govmomi/vim25/methods"
    32  	"github.com/vmware/govmomi/vim25/mo"
    33  	"github.com/vmware/govmomi/vim25/soap"
    34  	"github.com/vmware/govmomi/vim25/types"
    35  )
    36  
    37  func isNotAuthenticated(err error) bool {
    38  	if soap.IsSoapFault(err) {
    39  		switch soap.ToSoapFault(err).VimFault().(type) {
    40  		case types.NotAuthenticated:
    41  			return true
    42  		}
    43  	}
    44  	return false
    45  }
    46  
    47  func TestSessionManagerAuth(t *testing.T) {
    48  	ctx := context.Background()
    49  
    50  	m := VPX()
    51  
    52  	defer m.Remove()
    53  
    54  	err := m.Create()
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  
    59  	s := m.Service.NewServer()
    60  	defer s.Close()
    61  
    62  	u := s.URL.User
    63  	s.URL.User = nil // skip Login()
    64  
    65  	c, err := govmomi.NewClient(ctx, s.URL, true)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	session, err := c.SessionManager.UserSession(ctx)
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	if session != nil {
    76  		t.Error("expected nil session")
    77  	}
    78  
    79  	opts := object.NewOptionManager(c.Client, *c.ServiceContent.Setting)
    80  	var content []types.ObjectContent
    81  	err = opts.Properties(ctx, opts.Reference(), []string{"setting"}, &content)
    82  	if err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	if len(content) != 1 {
    87  		t.Error("expected content len=1")
    88  	}
    89  
    90  	if len(content[0].PropSet) != 0 {
    91  		t.Error("non-empty PropSet")
    92  	}
    93  
    94  	if len(content[0].MissingSet) != 1 {
    95  		t.Error("expected MissingSet len=1")
    96  	}
    97  
    98  	if _, ok := content[0].MissingSet[0].Fault.Fault.(*types.NotAuthenticated); !ok {
    99  		t.Error("expected NotAuthenticated")
   100  	}
   101  
   102  	_, err = methods.GetCurrentTime(ctx, c)
   103  	if !isNotAuthenticated(err) {
   104  		t.Error("expected NotAuthenticated")
   105  	}
   106  
   107  	err = c.SessionManager.Login(ctx, u)
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	c.UserAgent = "vcsim/x.x"
   113  
   114  	session, err = c.SessionManager.UserSession(ctx)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  
   119  	if session == nil {
   120  		t.Error("expected session")
   121  	}
   122  
   123  	if session.UserAgent != c.UserAgent {
   124  		t.Errorf("UserAgent=%s", session.UserAgent)
   125  	}
   126  
   127  	active, err := c.SessionManager.SessionIsActive(ctx)
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  
   132  	if active == false {
   133  		t.Error("not active")
   134  	}
   135  
   136  	{
   137  		req := types.SessionIsActive{
   138  			This:      c.SessionManager.Reference(),
   139  			SessionID: "enoent",
   140  			UserName:  "",
   141  		}
   142  
   143  		active, err := methods.SessionIsActive(ctx, c, &req)
   144  		if err != nil {
   145  			t.Fatal(err)
   146  		}
   147  
   148  		if active.Returnval {
   149  			t.Error("active")
   150  		}
   151  	}
   152  
   153  	{
   154  		req := types.SessionIsActive{
   155  			This:      c.SessionManager.Reference(),
   156  			SessionID: session.Key,
   157  			UserName:  "enoent",
   158  		}
   159  
   160  		active, err := methods.SessionIsActive(ctx, c, &req)
   161  		if err != nil {
   162  			t.Fatal(err)
   163  		}
   164  
   165  		if active.Returnval {
   166  			t.Error("active")
   167  		}
   168  	}
   169  
   170  	content = nil
   171  	err = opts.Properties(ctx, opts.Reference(), []string{"setting"}, &content)
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  
   176  	if len(content) != 1 {
   177  		t.Error("expected content len=1")
   178  	}
   179  
   180  	if len(content[0].PropSet) != 1 {
   181  		t.Error("PropSet len=1")
   182  	}
   183  
   184  	if len(content[0].MissingSet) != 0 {
   185  		t.Error("expected MissingSet len=0")
   186  	}
   187  
   188  	last := session.LastActiveTime
   189  
   190  	_, err = methods.GetCurrentTime(ctx, c)
   191  	if err != nil {
   192  		t.Error(err)
   193  	}
   194  
   195  	pc, err := property.DefaultCollector(c.Client).Create(ctx)
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  
   200  	session, _ = c.SessionManager.UserSession(ctx)
   201  
   202  	if session.LastActiveTime.Equal(last) {
   203  		t.Error("LastActiveTime was not updated")
   204  	}
   205  
   206  	if !strings.Contains(pc.Reference().Value, session.Key) {
   207  		t.Errorf("invalid ref=%s", pc.Reference())
   208  	}
   209  
   210  	ticket, err := c.SessionManager.AcquireCloneTicket(ctx)
   211  	if err != nil {
   212  		t.Fatal(err)
   213  	}
   214  
   215  	c, err = govmomi.NewClient(ctx, s.URL, true)
   216  	if err != nil {
   217  		t.Fatal(err)
   218  	}
   219  
   220  	err = c.SessionManager.CloneSession(ctx, ticket)
   221  	if err != nil {
   222  		t.Fatal(err)
   223  	}
   224  
   225  	err = c.SessionManager.CloneSession(ctx, ticket)
   226  	if err == nil {
   227  		t.Error("expected error")
   228  	}
   229  
   230  	_, err = methods.GetCurrentTime(ctx, c)
   231  	if err != nil {
   232  		t.Error(err)
   233  	}
   234  }
   235  
   236  func TestSessionManagerLoginExtension(t *testing.T) {
   237  	ctx := context.Background()
   238  
   239  	s := New(NewServiceInstance(SpoofContext(), vpx.ServiceContent, vpx.RootFolder))
   240  	s.TLS = new(tls.Config)
   241  	ts := s.NewServer()
   242  	defer ts.Close()
   243  
   244  	if terr := ts.StartTunnel(); terr != nil {
   245  		t.Fatal(terr)
   246  	}
   247  
   248  	u := ts.URL.User
   249  	ts.URL.User = nil // skip Login()
   250  
   251  	c, err := govmomi.NewClient(ctx, ts.URL, true)
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  	err = session.NewManager(c.Client).LoginExtensionByCertificate(ctx, u.Username())
   257  	if err == nil {
   258  		t.Error("expected error") // client cert not set
   259  	}
   260  
   261  	c.SetCertificate(ts.TLS.Certificates[0]) // any cert is ok with vcsim
   262  	err = session.NewManager(c.Client).LoginExtensionByCertificate(ctx, u.Username())
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	_, err = methods.GetCurrentTime(ctx, c)
   268  	if err != nil {
   269  		t.Error(err)
   270  	}
   271  }
   272  
   273  // Test WaitForUpdates against the PropertyCollector singleton.
   274  // Includes test for issue 1172, where a 2nd session use of the PropertyCollector singleton followed by Logout()
   275  // unregistered the 1st session's update listener as the PC singleton has the same moref regardless of session instance.
   276  func TestSessionManagerPropertyCollector(t *testing.T) {
   277  	ctx := context.Background()
   278  
   279  	m := VPX()
   280  
   281  	defer m.Remove()
   282  
   283  	err := m.Create()
   284  	if err != nil {
   285  		t.Fatal(err)
   286  	}
   287  
   288  	s := m.Service.NewServer()
   289  	defer s.Close()
   290  
   291  	c, err := govmomi.NewClient(ctx, s.URL, true)
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	pc := property.DefaultCollector(c.Client)
   297  	root := object.NewRootFolder(c.Client)
   298  
   299  	filter := types.CreateFilter{
   300  		This: pc.Reference(),
   301  		Spec: types.PropertyFilterSpec{
   302  			PropSet: []types.PropertySpec{
   303  				{
   304  					Type:    "Datacenter",
   305  					All:     types.NewBool(false),
   306  					PathSet: []string{"name"},
   307  				},
   308  			},
   309  			ObjectSet: []types.ObjectSpec{
   310  				{
   311  					Obj:  root.Reference(),
   312  					Skip: (*bool)(nil),
   313  					SelectSet: []types.BaseSelectionSpec{
   314  						&types.TraversalSpec{
   315  							SelectionSpec: types.SelectionSpec{
   316  								Name: "folder2childEntity",
   317  							},
   318  							Type: "Folder",
   319  							Path: "childEntity",
   320  							Skip: types.NewBool(false),
   321  							SelectSet: []types.BaseSelectionSpec{
   322  								&types.SelectionSpec{
   323  									Name: "folder2childEntity",
   324  								},
   325  							},
   326  						},
   327  					},
   328  				},
   329  			},
   330  			ReportMissingObjectsInResults: (*bool)(nil),
   331  		},
   332  		PartialUpdates: true,
   333  	}
   334  
   335  	if _, err = pc.CreateFilter(ctx, filter); err != nil {
   336  		t.Fatal(err)
   337  	}
   338  
   339  	updates, _ := pc.WaitForUpdates(ctx, "") // disregard first result
   340  	// add DC and poll
   341  	dc, _ := root.CreateDatacenter(ctx, "DC-A")
   342  	updates, _ = pc.WaitForUpdates(ctx, updates.Version)
   343  	set := updates.FilterSet[0].ObjectSet[0]
   344  	if set.Obj.Type != "Datacenter" {
   345  		t.Errorf("obj=%s", set.Obj)
   346  	}
   347  	if set.Kind != types.ObjectUpdateKindEnter {
   348  		t.Errorf("kind=%s", set.Kind)
   349  	}
   350  
   351  	// create a new session and a call to the PropertyCollector singleton
   352  	c2, err := govmomi.NewClient(ctx, s.URL, true)
   353  	if err != nil {
   354  		log.Fatal(err)
   355  	}
   356  	var folder mo.Folder
   357  	property.DefaultCollector(c2.Client).RetrieveOne(ctx, root.Reference(), []string{"name"}, &folder)
   358  	_ = c2.Logout(ctx)
   359  
   360  	// remove DC and poll
   361  	_, _ = dc.Destroy(ctx)
   362  	updates, _ = pc.WaitForUpdates(ctx, updates.Version)
   363  	set = updates.FilterSet[0].ObjectSet[0]
   364  	if set.Obj.Type != "Datacenter" {
   365  		t.Errorf("obj=%s", set.Obj)
   366  	}
   367  	if set.Kind != types.ObjectUpdateKindLeave {
   368  		t.Errorf("kind=%s", set.Kind)
   369  	}
   370  }