Skip to content

Commit 49947e5

Browse files
authored
Merge pull request #3784 from dougm/vcsim-session-timeout
vcsim: Use OptionManager to configure session timeout duration
2 parents 0cb5102 + 6af11fc commit 49947e5

File tree

9 files changed

+95
-32
lines changed

9 files changed

+95
-32
lines changed

cli/host/option/set.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ func (cmd *set) Description() string {
4646
4747
Examples:
4848
govc host.option.set Config.HostAgent.plugins.solo.enableMob true
49-
govc host.option.set Config.HostAgent.log.level verbose`
49+
govc host.option.set Config.HostAgent.log.level verbose
50+
govc host.option.set Config.HostAgent.vmacore.soap.sessionTimeout 90`
5051
}
5152

5253
func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {

cli/option/set.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ func (cmd *Set) Description() string {
4747
return SetDescription + `
4848
4949
Examples:
50+
# Change log levels
5051
govc option.set log.level info
51-
govc option.set logger.Vsan verbose`
52+
govc option.set logger.Vsan verbose
53+
# Increase vCenter session timeout to 90 minutes
54+
govc option.set config.vmacore.soap.sessionTimeout 90`
5255
}
5356

5457
func (cmd *Set) Update(ctx context.Context, f *flag.FlagSet, m *object.OptionManager) error {

govc/USAGE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,7 @@ Set option NAME to VALUE.
34603460
Examples:
34613461
govc host.option.set Config.HostAgent.plugins.solo.enableMob true
34623462
govc host.option.set Config.HostAgent.log.level verbose
3463+
govc host.option.set Config.HostAgent.vmacore.soap.sessionTimeout 90
34633464
34643465
Options:
34653466
-host= Host system [GOVC_HOST]
@@ -5296,8 +5297,11 @@ Usage: govc option.set [OPTIONS] NAME VALUE
52965297
Set option NAME to VALUE.
52975298
52985299
Examples:
5300+
# Change log levels
52995301
govc option.set log.level info
53005302
govc option.set logger.Vsan verbose
5303+
# Increase vCenter session timeout to 90 minutes
5304+
govc option.set config.vmacore.soap.sessionTimeout 90
53015305
53025306
Options:
53035307
```

session/keepalive/example_test.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import (
1010
"log"
1111
"time"
1212

13-
"github.com/vmware/govmomi/session"
13+
"github.com/vmware/govmomi"
1414
"github.com/vmware/govmomi/session/keepalive"
1515
"github.com/vmware/govmomi/simulator"
16+
"github.com/vmware/govmomi/simulator/sim25"
1617
"github.com/vmware/govmomi/vapi/rest"
1718
"github.com/vmware/govmomi/vim25"
1819
)
@@ -23,14 +24,21 @@ var (
2324
keepAliveIdle = sessionIdleTimeout / 2
2425
)
2526

26-
func init() {
27-
simulator.SessionIdleTimeout = sessionIdleTimeout
28-
}
29-
3027
func ExampleHandlerSOAP() {
31-
simulator.Run(func(ctx context.Context, c *vim25.Client) error {
32-
// No need for initial Login() here as simulator.Run already has
33-
m := session.NewManager(c)
28+
simulator.Run(func(ctx context.Context, vc *vim25.Client) error {
29+
// Using the authenticated vc client, timeout will apply to new sessions.
30+
sim25.SetSessionTimeout(ctx, vc, sessionIdleTimeout)
31+
32+
c, err := govmomi.NewClient(ctx, vc.URL(), true)
33+
if err != nil {
34+
return err
35+
}
36+
m := c.SessionManager
37+
38+
err = m.Login(ctx, simulator.DefaultLogin) // New session
39+
if err != nil {
40+
return err
41+
}
3442

3543
// check twice if session is valid, sleeping > SessionIdleTimeout in between
3644
check := func() {
@@ -53,7 +61,7 @@ func ExampleHandlerSOAP() {
5361
// this starts the keep alive handler when Login is called, and stops the handler when Logout is called
5462
c.RoundTripper = keepalive.NewHandlerSOAP(c.RoundTripper, keepAliveIdle, nil)
5563

56-
err := m.Login(ctx, simulator.DefaultLogin)
64+
err = m.Login(ctx, simulator.DefaultLogin)
5765
if err != nil {
5866
return err
5967
}
@@ -82,8 +90,11 @@ func ExampleHandlerSOAP() {
8290

8391
func ExampleHandlerREST() {
8492
simulator.Run(func(ctx context.Context, vc *vim25.Client) error {
93+
// Using the authenticated vc client, timeout will apply to new sessions.
94+
sim25.SetSessionTimeout(ctx, vc, sessionIdleTimeout)
95+
8596
c := rest.NewClient(vc)
86-
err := c.Login(ctx, simulator.DefaultLogin)
97+
err := c.Login(ctx, simulator.DefaultLogin) // New session
8798
if err != nil {
8899
return err
89100
}

simulator/option_manager.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ type OptionManager struct {
2727
mirror *[]types.BaseOptionValue
2828
}
2929

30-
func asOptionManager(ctx *Context, obj mo.Reference) (*OptionManager, bool) {
31-
om, ok := ctx.Map.Get(obj.Reference()).(*OptionManager)
32-
return om, ok
33-
}
34-
3530
// NewOptionManager constructs the type. If mirror is non-nil it takes precedence over settings, and settings is ignored.
3631
// Args:
3732
// - ref - used to set OptionManager.Self if non-nil

simulator/session_manager.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ func (m *SessionManager) init(*Registry) {
4343
}
4444

4545
var (
46-
// SessionIdleTimeout duration used to expire idle sessions
47-
SessionIdleTimeout time.Duration
48-
4946
sessionMutex sync.Mutex
5047

5148
// secureCookies enables Set-Cookie.Secure=true
@@ -361,12 +358,12 @@ func (c *Context) mapSession() {
361358
}
362359
}
363360

364-
func (m *SessionManager) expiredSession(id string, now time.Time) bool {
361+
func (m *SessionManager) expiredSession(id string, now time.Time, timeout time.Duration) bool {
365362
expired := true
366363

367364
s, ok := m.getSession(id)
368365
if ok {
369-
expired = now.Sub(s.LastActiveTime) > SessionIdleTimeout
366+
expired = now.Sub(s.LastActiveTime) > timeout
370367
if expired {
371368
m.delSession(id)
372369
}
@@ -375,23 +372,29 @@ func (m *SessionManager) expiredSession(id string, now time.Time) bool {
375372
return expired
376373
}
377374

378-
// SessionIdleWatch starts a goroutine that calls func expired() at SessionIdleTimeout intervals.
375+
// SessionIdleWatch starts a goroutine that calls func expired() at timeout intervals.
379376
// The goroutine exits if the func returns true.
380-
func SessionIdleWatch(ctx context.Context, id string, expired func(string, time.Time) bool) {
381-
if SessionIdleTimeout == 0 {
377+
func SessionIdleWatch(ctx *Context, id string, expired func(string, time.Time, time.Duration) bool) {
378+
opt := ctx.Map.OptionManager().find("config.vmacore.soap.sessionTimeout")
379+
if opt == nil {
382380
return
383381
}
384382

383+
timeout, err := time.ParseDuration(opt.Value.(string))
384+
if err != nil {
385+
panic(err)
386+
}
387+
385388
go func() {
386-
for t := time.NewTimer(SessionIdleTimeout); ; {
389+
for t := time.NewTimer(timeout); ; {
387390
select {
388391
case <-ctx.Done():
389392
return
390393
case now := <-t.C:
391-
if expired(id, now) {
394+
if expired(id, now, timeout) {
392395
return
393396
}
394-
t.Reset(SessionIdleTimeout)
397+
t.Reset(timeout)
395398
}
396399
}
397400
}()
@@ -423,7 +426,7 @@ func (c *Context) SetSession(session Session, login bool) {
423426
Locale: session.Locale,
424427
})
425428

426-
SessionIdleWatch(c.Context, session.Key, m.expiredSession)
429+
SessionIdleWatch(c, session.Key, m.expiredSession)
427430
}
428431
}
429432

simulator/sim25/client.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// © Broadcom. All Rights Reserved.
2+
// The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package sim25
6+
7+
import (
8+
"context"
9+
"time"
10+
11+
"github.com/vmware/govmomi/vim25"
12+
"github.com/vmware/govmomi/vim25/methods"
13+
"github.com/vmware/govmomi/vim25/types"
14+
)
15+
16+
// SetSessionTimeout changes the default session timeout.
17+
func SetSessionTimeout(ctx context.Context, c *vim25.Client, timeout time.Duration) error {
18+
// Note that real vCenter supports the same OptionValue Key, but only with a Value of whole seconds.
19+
req := types.UpdateOptions{
20+
This: *c.ServiceContent.Setting,
21+
ChangedValue: []types.BaseOptionValue{
22+
&types.OptionValue{
23+
Key: "config.vmacore.soap.sessionTimeout",
24+
Value: timeout.String(),
25+
},
26+
},
27+
}
28+
29+
_, err := methods.UpdateOptions(ctx, c, &req)
30+
return err
31+
}

simulator/sim25/doc.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// © Broadcom. All Rights Reserved.
2+
// The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
/*
6+
Package sim25 contains vim25.Client helpers intended for use with vcsim.
7+
*/
8+
package sim25

vapi/simulator/simulator.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -524,12 +524,12 @@ func Decode(r *http.Request, w http.ResponseWriter, val any) bool {
524524
return true
525525
}
526526

527-
func (s *handler) expiredSession(id string, now time.Time) bool {
527+
func (s *handler) expiredSession(id string, now time.Time, timeout time.Duration) bool {
528528
expired := true
529529
s.Lock()
530530
session, ok := s.Session[id]
531531
if ok {
532-
expired = now.Sub(session.LastAccessed) > simulator.SessionIdleTimeout
532+
expired = now.Sub(session.LastAccessed) > timeout
533533
if expired {
534534
delete(s.Session, id)
535535
}
@@ -538,6 +538,13 @@ func (s *handler) expiredSession(id string, now time.Time) bool {
538538
return expired
539539
}
540540

541+
func (s *handler) newContext() *simulator.Context {
542+
return &simulator.Context{
543+
Context: context.Background(),
544+
Map: s.Map,
545+
}
546+
}
547+
541548
func (s *handler) session(w http.ResponseWriter, r *http.Request) {
542549
id := r.Header.Get(internal.SessionCookieName)
543550
useHeaderAuthn := strings.ToLower(r.Header.Get(internal.UseHeaderAuthn))
@@ -560,7 +567,7 @@ func (s *handler) session(w http.ResponseWriter, r *http.Request) {
560567
id = uuid.New().String()
561568
now := time.Now()
562569
s.Session[id] = &rest.Session{User: user, Created: now, LastAccessed: now}
563-
simulator.SessionIdleWatch(context.Background(), id, s.expiredSession)
570+
simulator.SessionIdleWatch(s.newContext(), id, s.expiredSession)
564571
if useHeaderAuthn != "true" {
565572
http.SetCookie(w, &http.Cookie{
566573
Name: internal.SessionCookieName,

0 commit comments

Comments
 (0)