Repository: vmware/govmomi
Pull request #2720 (2022-01-27 12:23:58)

Add Appliance access API
Closes: #2716

## Description

Add Appliance access API's described in https://developer.vmware.com/apis/vsphere-automation/latest/appliance/access/

Closes: #2716 

## Type of change

Please mark options that are relevant:

- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to
  not work as expected)
- [X] This change requires a documentation update
- [ ] Build related change

## How Has This Been Tested?

- Tested manually against live vCenter Server
- Added govc tests to ensure changes are working as expected

## Checklist:

- [X] My code follows the CONTRIBUTION [guidelines](./../CONTRIBUTING.md) of
  this project
- [X] I have commented on my code, particularly in hard-to-understand areas
- [X] I have made corresponding changes to the documentation
- [X] I have added tests that prove my fix is effective or that my feature works
- [X] New and existing unit tests pass locally with my changes
- [X] Any dependent changes have been merged

embano1: I'll have @dougm comment on whether/how to use locks in the handlers
pradeep288: New changes are ready to review @embano1, @dougm  
pradeep288: New changes are ready for review  cc @embano1 , @dougm 


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d908347e..ce2ec3b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,47 +1,4 @@
 
-<a name="v0.27.4"></a>
-## [Release v0.27.4](https://github.com/vmware/govmomi/compare/v0.27.3...v0.27.4)
-
-> Release Date: 2022-02-10
-
-### 🐞 Fix
-
-- [285e80cd]	avoid debug trace if http.Request.Body is nil
-- [dde50904]	Ignore concurrent deletes in GetCategories
-- [cbc68fc0]	rest.Client.LoginByToken invalid signature
-
-### 💫 `vcsim` (Simulator)
-
-- [df595d82]	add ssoadmin simulator
-
-### ⚠️ BREAKING
-
-### 📖 Commits
-
-- [285e80cd]	fix: avoid debug trace if http.Request.Body is nil
-- [dde50904]	fix: Ignore concurrent deletes in GetCategories
-- [fc1fce62]	Add PlaceVmsXCluster bindings and simulator
-- [df595d82]	vcsim: add ssoadmin simulator
-- [9ca477aa]	ssoadmin: add IdentitySources API bindings
-- [24fe60f1]	Add BackingDiskObjectId go bindings to CNS API
-- [cbc68fc0]	fix: rest.Client.LoginByToken invalid signature
-
-<a name="v0.27.3"></a>
-## [Release v0.27.3](https://github.com/vmware/govmomi/compare/v0.27.2...v0.27.3)
-
-> Release Date: 2022-02-01
-
-### 🐞 Fix
-
-- [2d7cd133]	Add IPv6 support for signing HTTP request
-
-### ⚠️ BREAKING
-
-### 📖 Commits
-
-- [6b4e2391]	sts: support issuing HoK token using HoK token
-- [2d7cd133]	fix: Add IPv6 support for signing HTTP request
-
 <a name="v0.27.2"></a>
 ## [Release v0.27.2](https://github.com/vmware/govmomi/compare/v0.27.1...v0.27.2)
 
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6af4f695..37d679b2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -109,34 +109,30 @@ $ git push --force-with-lease $USER issue-<number>
 
 ### Updating Pull Requests
 
-If your PR fails to pass CI or needs changes based on code review, it's ok to
-add more commits stating the changes made, e.g. "Address review comments". This
-is to assist the reviewer(s) to easily detect and review the recent changes.
+If your PR fails to pass CI or needs changes based on code review, you'll most
+likely want to squash these changes into existing commits.
 
-In case of small PRs, it's ok to squash and force-push (see further below)
-directly instead.
+If your pull request contains a single commit or your changes are related to the
+most recent commit, you can simply amend the commit.
 
 ```console
-# incorporate review feedback
 $ git add .
-
-# create a fixup commit which will be merged into your (original) <commit>
-$ git commit --fixup <commit>
-$ git push $USER issue-<number>
+$ git commit --amend
+$ git push --force-with-lease $USER issue-<number>
 ```
 
-Be sure to add a comment to the PR indicating your new changes are ready to
-review, as Github does not generate a notification when you git push.
-
-Once the review is complete, squash and push your final commit(s):
+If you need to squash changes into an earlier commit, you can use:
 
 ```console
-# squash all commits into one
-# --autosquash will automatically detect and merge fixup commits
+$ git add .
+$ git commit --fixup <commit>
 $ git rebase -i --autosquash vmware/master
 $ git push --force-with-lease $USER issue-<number>
 ```
 
+Be sure to add a comment to the PR indicating your new changes are ready to
+review, as Github does not generate a notification when you git push.
+
 ### Code Style
 
 The coding style suggested by the Go community is used in `govmomi`. See the
diff --git a/cns/types/types.go b/cns/types/types.go
index c5fb2812..575de000 100644
--- a/cns/types/types.go
+++ b/cns/types/types.go
@@ -394,7 +394,6 @@ type CnsBlockBackingDetails struct {
 
 	BackingDiskId      string `xml:"backingDiskId,omitempty"`
 	BackingDiskUrlPath string `xml:"backingDiskUrlPath,omitempty"`
-	BackingDiskObjectId string `xml:"backingDiskObjectId,omitempty"`
 }
 
 func init() {
diff --git a/examples/tasks/main.go b/examples/tasks/main.go
index 21dad406..a0bbbddb 100644
--- a/examples/tasks/main.go
+++ b/examples/tasks/main.go
@@ -21,7 +21,7 @@ import (
 	"flag"
 	"time"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi/task"
 
diff --git a/go.mod b/go.mod
index 54fe015e..1722e0f5 100644
--- a/go.mod
+++ b/go.mod
@@ -2,12 +2,16 @@ module github.com/vmware/govmomi
 
 go 1.17
 
+replace github.com/davecgh/go-xdr => github.com/rasky/go-xdr v0.0.0-20170217172119-4930550ba2e2
+
+replace github.com/kr/pretty v0.1.0 => github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02
+
 require (
 	github.com/a8m/tree v0.0.0-20210115125333-10a5fd5b637d
-	github.com/rasky/go-xdr v0.0.0-20170217172119-4930550ba2e2
+	github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892
 	github.com/google/uuid v1.2.0
-	github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02
+	github.com/kr/pretty v0.1.0
 	github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728
 )
 
-require	github.com/kr/text v0.1.0 // indirect
+require github.com/kr/text v0.1.0 // indirect
diff --git a/govc/USAGE.md b/govc/USAGE.md
index e52f6b78..039be2a3 100644
--- a/govc/USAGE.md
+++ b/govc/USAGE.md
@@ -270,7 +270,6 @@ but appear via `govc $cmd -h`:
  - [sso.group.ls](#ssogroupls)
  - [sso.group.rm](#ssogrouprm)
  - [sso.group.update](#ssogroupupdate)
- - [sso.idp.ls](#ssoidpls)
  - [sso.service.ls](#ssoservicels)
  - [sso.user.create](#ssousercreate)
  - [sso.user.id](#ssouserid)
@@ -299,12 +298,16 @@ but appear via `govc $cmd -h`:
  - [tree](#tree)
  - [vapp.destroy](#vappdestroy)
  - [vapp.power](#vapppower)
+ - [vcsa.access.consolecli.get](#vcsaaccessconsolecliget)
+ - [vcsa.access.consolecli.set](#vcsaaccessconsolecliset)
+ - [vcsa.access.dcui.get](#vcsaaccessdcuiget)
+ - [vcsa.access.dcui.set](#vcsaaccessdcuiset)
+ - [vcsa.access.shell.get](#vcsaaccessshellget)
+ - [vcsa.access.shell.set](#vcsaaccessshellset)
+ - [vcsa.access.ssh.get](#vcsaaccesssshget)
+ - [vcsa.access.ssh.set](#vcsaaccesssshset)
  - [vcsa.log.forwarding.info](#vcsalogforwardinginfo)
  - [vcsa.net.proxy.info](#vcsanetproxyinfo)
- - [vcsa.shutdown.cancel](#vcsashutdowncancel)
- - [vcsa.shutdown.get](#vcsashutdownget)
- - [vcsa.shutdown.poweroff](#vcsashutdownpoweroff)
- - [vcsa.shutdown.reboot](#vcsashutdownreboot)
  - [version](#version)
  - [vm.change](#vmchange)
  - [vm.clone](#vmclone)
@@ -3722,7 +3725,6 @@ Examples:
     -cluster "Workload-Cluster" \
     -service-cidr 10.96.0.0/23 \
     -pod-cidrs 10.244.0.0/20 \
-    -control-plane-dns 10.10.10.10 \
     -control-plane-dns-names wcp.example.com \
     -workload-network.egress-cidrs 10.0.0.128/26 \
     -workload-network.ingress-cidrs "10.0.0.64/26" \
@@ -4570,20 +4572,6 @@ Options:
   -r=                    Remove user/group from group
 ```
 
-## sso.idp.ls
-
-```
-Usage: govc sso.idp.ls [OPTIONS]
-
-List SSO identity provider sources.
-
-Examples:
-  govc sso.idp.ls
-  govc sso.idp.ls -json
-
-Options:
-```
-
 ## sso.service.ls
 
 ```
@@ -5060,80 +5048,171 @@ Options:
   -vapp.ipath=           Find vapp by inventory path
 ```
 
-## vcsa.log.forwarding.info
+## vcsa.access.consolecli.get
 
 ```
-Usage: govc vcsa.log.forwarding.info [OPTIONS]
+Usage: govc vcsa.access.consolecli.get [OPTIONS]
 
-Retrieve the VC Appliance log forwarding configuration
+Get enabled state of the console-based controlled CLI (TTY1).
+
+Note: This command requires vCenter 7.0.2 or higher.
 
 Examples:
-  govc vcsa.log.forwarding.info
+govc vcsa.access.consolecli.get
 
 Options:
 ```
 
-## vcsa.net.proxy.info
+## vcsa.access.consolecli.set
 
 ```
-Usage: govc vcsa.net.proxy.info [OPTIONS]
+Usage: govc vcsa.access.consolecli.set [OPTIONS]
 
-Retrieve the VC networking proxy configuration
+Set enabled state of the console-based controlled CLI (TTY1).
+
+Note: This command requires vCenter 7.0.2 or higher.
 
 Examples:
-  govc vcsa.net.proxy.info
+# Enable Console CLI
+govc vcsa.access.consolecli.set -enabled=true
+
+# Disable Console CLI
+govc vcsa.access.consolecli.set -enabled=false
 
 Options:
+  -enabled=false         Enable Console CLI.
 ```
 
-## vcsa.shutdown.cancel
+## vcsa.access.dcui.get
 
 ```
-Usage: govc vcsa.shutdown.cancel [OPTIONS]
+Usage: govc vcsa.access.dcui.get [OPTIONS]
+
+Get enabled state of Direct Console User Interface (DCUI TTY2).
+
+Note: This command requires vCenter 7.0.2 or higher.
 
-Cancel pending shutdown action.
 Examples:
-  govc vcsa.shutdown.cancel
+govc vcsa.access.dcui.get
 
 Options:
 ```
 
-## vcsa.shutdown.get
+## vcsa.access.dcui.set
 
 ```
-Usage: govc vcsa.shutdown.get [OPTIONS]
+Usage: govc vcsa.access.dcui.set [OPTIONS]
+
+Set enabled state of Direct Console User Interface (DCUI TTY2).
+
+Note: This command requires vCenter 7.0.2 or higher.
 
-Get details about the pending shutdown action.
 Examples:
-  govc vcsa.shutdown.get
+# Enable DCUI
+govc vcsa.access.dcui.set -enabled=true
+
+# Disable DCUI
+govc vcsa.access.dcui.set -enabled=false
 
 Options:
+  -enabled=false         Enable Direct Console User Interface (DCUI TTY2).
 ```
 
-## vcsa.shutdown.poweroff
+## vcsa.access.shell.get
 
 ```
-Usage: govc vcsa.shutdown.poweroff [OPTIONS] REASON
+Usage: govc vcsa.access.shell.get [OPTIONS]
+
+Get enabled state of BASH, that is, access to BASH from within the controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
 
-Power off the appliance.
 Examples:
-  govc vcsa.shutdown.poweroff -delay 10 "powering off for maintenance"
+govc vcsa.access.shell.get
 
 Options:
-  -delay=0               Minutes after which poweroff should start.
 ```
 
-## vcsa.shutdown.reboot
+## vcsa.access.shell.set
 
 ```
-Usage: govc vcsa.shutdown.reboot [OPTIONS] REASON
+Usage: govc vcsa.access.shell.set [OPTIONS]
+
+Set enabled state of BASH, that is, access to BASH from within the controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
 
-Reboot the appliance.
 Examples:
-  govc vcsa.shutdown.reboot -delay 10 "rebooting for maintenance"
+# Enable Shell
+govc vcsa.access.shell.set -enabled=true -timeout=240
+
+# Disable Shell
+govc vcsa.access.shell.set -enabled=false
+
+Options:
+  -enabled=false         Enable BASH, that is, access to BASH from within the controlled CLI.
+  -timeout=0             The timeout (in seconds) specifies how long you enable the Shell access. The maximum timeout is 86400 seconds(1 day).
+```
+
+## vcsa.access.ssh.get
+
+```
+Usage: govc vcsa.access.ssh.get [OPTIONS]
+
+Get enabled state of the SSH-based controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+govc vcsa.access.ssh.get
+
+Options:
+```
+
+## vcsa.access.ssh.set
+
+```
+Usage: govc vcsa.access.ssh.set [OPTIONS]
+
+Set enabled state of the SSH-based controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+# Enable SSH
+govc vcsa.access.ssh.set -enabled=true
+
+# Disable SSH
+govc vcsa.access.ssh.set -enabled=false
+
+Options:
+  -enabled=false         Enable SSH-based controlled CLI.
+```
+
+## vcsa.log.forwarding.info
+
+```
+Usage: govc vcsa.log.forwarding.info [OPTIONS]
+
+Retrieve the VC Appliance log forwarding configuration
+
+Examples:
+  govc vcsa.log.forwarding.info
+
+Options:
+```
+
+## vcsa.net.proxy.info
+
+```
+Usage: govc vcsa.net.proxy.info [OPTIONS]
+
+Retrieve the VC networking proxy configuration
+
+Examples:
+  govc vcsa.net.proxy.info
 
 Options:
-  -delay=0               Minutes after which reboot should start.
 ```
 
 ## version
diff --git a/govc/flags/debug.go b/govc/flags/debug.go
index 3f5aff87..809ec118 100644
--- a/govc/flags/debug.go
+++ b/govc/flags/debug.go
@@ -31,7 +31,7 @@ import (
 	"text/tabwriter"
 	"time"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi/vim25/debug"
 	"github.com/vmware/govmomi/vim25/soap"
diff --git a/govc/flags/output.go b/govc/flags/output.go
index 565bdd15..aaa3d1bb 100644
--- a/govc/flags/output.go
+++ b/govc/flags/output.go
@@ -29,7 +29,7 @@ import (
 	"sync"
 	"time"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi/task"
 	"github.com/vmware/govmomi/vim25/progress"
diff --git a/govc/importx/spec.go b/govc/importx/spec.go
index e425fe62..514f338c 100644
--- a/govc/importx/spec.go
+++ b/govc/importx/spec.go
@@ -107,7 +107,7 @@ func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error {
 			return fmt.Errorf("invalid file extension %s", path.Ext(fpath))
 		}
 
-		if isRemotePath(f.Arg(0)) {
+		if isRemotePath(fpath) {
 			client, err := cmd.Client()
 			if err != nil {
 				return err
diff --git a/govc/main.go b/govc/main.go
index 28451bce..ff4c9b1e 100644
--- a/govc/main.go
+++ b/govc/main.go
@@ -80,7 +80,6 @@ import (
 	_ "github.com/vmware/govmomi/govc/role"
 	_ "github.com/vmware/govmomi/govc/session"
 	_ "github.com/vmware/govmomi/govc/sso/group"
-	_ "github.com/vmware/govmomi/govc/sso/idp"
 	_ "github.com/vmware/govmomi/govc/sso/service"
 	_ "github.com/vmware/govmomi/govc/sso/user"
 	_ "github.com/vmware/govmomi/govc/storage/policy"
@@ -89,9 +88,12 @@ import (
 	_ "github.com/vmware/govmomi/govc/tags/category"
 	_ "github.com/vmware/govmomi/govc/task"
 	_ "github.com/vmware/govmomi/govc/vapp"
+	_ "github.com/vmware/govmomi/govc/vcsa/access/consolecli"
+	_ "github.com/vmware/govmomi/govc/vcsa/access/dcui"
+	_ "github.com/vmware/govmomi/govc/vcsa/access/shell"
+	_ "github.com/vmware/govmomi/govc/vcsa/access/ssh"
 	_ "github.com/vmware/govmomi/govc/vcsa/log"
 	_ "github.com/vmware/govmomi/govc/vcsa/proxy"
-	_ "github.com/vmware/govmomi/govc/vcsa/shutdown"
 	_ "github.com/vmware/govmomi/govc/version"
 	_ "github.com/vmware/govmomi/govc/vm"
 	_ "github.com/vmware/govmomi/govc/vm/disk"
diff --git a/govc/namespace/cluster/enable.go b/govc/namespace/cluster/enable.go
index 8e5797bf..b67b6722 100644
--- a/govc/namespace/cluster/enable.go
+++ b/govc/namespace/cluster/enable.go
@@ -154,7 +154,6 @@ Examples:
     -cluster "Workload-Cluster" \
     -service-cidr 10.96.0.0/23 \
     -pod-cidrs 10.244.0.0/20 \
-    -control-plane-dns 10.10.10.10 \
     -control-plane-dns-names wcp.example.com \
     -workload-network.egress-cidrs 10.0.0.128/26 \
     -workload-network.ingress-cidrs "10.0.0.64/26" \
@@ -244,7 +243,7 @@ func (cmd *enableCluster) Run(ctx context.Context, f *flag.FlagSet) error {
 	edgeClusterDisplayName := cmd.NcpClusterNetworkSpec.NsxEdgeCluster
 	edgeClusters, err := m.ListCompatibleEdgeClusters(ctx, clusterId, switchId)
 	if err != nil {
-		return fmt.Errorf("error in compatible edge cluster lookup: %s", err)
+		return fmt.Errorf("error in compatible switch lookup: %s", err)
 	}
 
 	matchingEdgeClusters := make([]string, 0)
diff --git a/govc/session/login.go b/govc/session/login.go
index 87e72078..2d0bbeca 100644
--- a/govc/session/login.go
+++ b/govc/session/login.go
@@ -215,13 +215,6 @@ func (cmd *login) loginByToken(ctx context.Context, c *vim25.Client) error {
 		},
 	}
 
-	// something behind the LoginByToken scene requires a version from /sdk/vimServiceVersions.xml
-	// in the SOAPAction header. For example, if vim25.Version is "7.0" but the service version is "6.3",
-	// LoginByToken fails with: 'VersionMismatchFaultCode: Unsupported version URI "urn:vim25/7.0"'
-	if c.Version == vim25.Version {
-		_ = c.UseServiceVersion()
-	}
-
 	return session.NewManager(c).LoginByToken(c.WithHeader(ctx, header))
 }
 
diff --git a/govc/sso/idp/ls.go b/govc/sso/idp/ls.go
deleted file mode 100644
index 1d75355b..00000000
--- a/govc/sso/idp/ls.go
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
-Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-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 idp
-
-import (
-	"context"
-	"flag"
-	"fmt"
-	"io"
-	"strings"
-	"text/tabwriter"
-
-	"github.com/vmware/govmomi/govc/cli"
-	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/govc/sso"
-	"github.com/vmware/govmomi/ssoadmin"
-	"github.com/vmware/govmomi/ssoadmin/types"
-)
-
-type ls struct {
-	*flags.ClientFlag
-	*flags.OutputFlag
-}
-
-func init() {
-	cli.Register("sso.idp.ls", &ls{})
-}
-
-func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
-	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
-	cmd.ClientFlag.Register(ctx, f)
-
-	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
-	cmd.OutputFlag.Register(ctx, f)
-}
-
-func (cmd *ls) Description() string {
-	return `List SSO identity provider sources.
-
-Examples:
-  govc sso.idp.ls
-  govc sso.idp.ls -json`
-}
-
-func (cmd *ls) Process(ctx context.Context) error {
-	if err := cmd.ClientFlag.Process(ctx); err != nil {
-		return err
-	}
-	return cmd.OutputFlag.Process(ctx)
-}
-
-type idpInfo struct {
-	IdentitySources *types.IdentitySources
-}
-
-func (r *idpInfo) Write(w io.Writer) error {
-	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
-
-	type entry struct {
-		name   string
-		url    string
-		kind   string
-		domain string
-		alias  string
-	}
-
-	var entries []entry
-
-	for _, domain := range r.IdentitySources.System.Domains {
-		entries = append(entries, entry{"-", "-", "System Domain", domain.Name, domain.Alias})
-	}
-
-	if r.IdentitySources.LocalOS != nil {
-		for _, domain := range r.IdentitySources.LocalOS.Domains {
-			entries = append(entries, entry{"-", "-", "Local OS", domain.Name, domain.Alias})
-		}
-	}
-
-	if ad := r.IdentitySources.NativeAD; ad != nil {
-		for _, domain := range ad.Domains {
-			entries = append(entries, entry{ad.Name, "-", "Active Directory", domain.Name, domain.Alias})
-		}
-	}
-
-	for _, ldap := range r.IdentitySources.LDAPS {
-		for _, domain := range ldap.Domains {
-			entries = append(entries, entry{ldap.Name, ldap.Details.PrimaryURL, ldap.Type, domain.Name, domain.Alias})
-		}
-	}
-
-	fmt.Fprintln(tw, "Name\tServer URL\tType\tDomain\tAlias")
-
-	for _, e := range entries {
-		fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%s\n", e.name, e.url, e.kind, strings.ToLower(e.domain), e.alias)
-	}
-
-	return tw.Flush()
-}
-
-func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
-	return sso.WithClient(ctx, cmd.ClientFlag, func(c *ssoadmin.Client) error {
-		sources, err := c.IdentitySources(ctx)
-		if err != nil {
-			return err
-		}
-
-		return cmd.WriteResult(&idpInfo{sources})
-	})
-}
diff --git a/govc/vcsa/shutdown/get.go b/govc/vcsa/access/consolecli/get.go
similarity index 64%
rename from govc/vcsa/shutdown/get.go
rename to govc/vcsa/access/consolecli/get.go
index ba71ea6f..3099b6d6 100644
--- a/govc/vcsa/shutdown/get.go
+++ b/govc/vcsa/access/consolecli/get.go
@@ -1,11 +1,11 @@
 /*
 Copyright (c) 2022 VMware, Inc. All Rights Reserved.
 
-Licensed under the Apache License, Version 2.0 (the "License");
+SPDX-License-Identifier: Apache-2.0.
 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
+    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,
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package shutdown
+package consolecli
 
 import (
 	"context"
@@ -25,7 +25,7 @@ import (
 
 	"github.com/vmware/govmomi/govc/cli"
 	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/vapi/appliance/shutdown"
+	"github.com/vmware/govmomi/vapi/appliance/access/consolecli"
 )
 
 type get struct {
@@ -34,7 +34,7 @@ type get struct {
 }
 
 func init() {
-	cli.Register("vcsa.shutdown.get", &get{})
+	cli.Register("vcsa.access.consolecli.get", &get{})
 }
 
 func (cmd *get) Register(ctx context.Context, f *flag.FlagSet) {
@@ -56,13 +56,16 @@ func (cmd *get) Process(ctx context.Context) error {
 }
 
 func (cmd *get) Description() string {
-	return `Get details about the pending shutdown action.
+	return `Get enabled state of the console-based controlled CLI (TTY1).
+
+Note: This command requires vCenter 7.0.2 or higher.
+
 Examples:
-  govc vcsa.shutdown.get`
+govc vcsa.access.consolecli.get`
 }
 
-type shutdownStatus struct {
-	Values shutdown.Config `json:"values"`
+type access struct {
+	Enabled bool `json:"enabled"`
 }
 
 func (cmd *get) Run(ctx context.Context, f *flag.FlagSet) error {
@@ -71,23 +74,20 @@ func (cmd *get) Run(ctx context.Context, f *flag.FlagSet) error {
 		return err
 	}
 
-	s := shutdown.NewManager(c)
+	m := consolecli.NewManager(c)
 
-	r, err := s.Get(ctx)
+	status, err := m.Get(ctx)
 	if err != nil {
 		return err
 	}
 
-	return cmd.WriteResult(shutdownStatus{
-		Values: r,
-	})
+	return cmd.WriteResult(&access{Enabled: status})
 }
 
-func (res shutdownStatus) Write(w io.Writer) error {
-	tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)
-	fmt.Fprintf(tw, "Action:%s\n", res.Values.Action)
-	fmt.Fprintf(tw, "Reason:%s\n", res.Values.Reason)
-	fmt.Fprintf(tw, "ShutDown Time:%s\n", res.Values.ShutdownTime)
+func (res access) Write(w io.Writer) error {
+	tw := tabwriter.NewWriter(w, 10, 4, 0, ' ', 0)
+
+	fmt.Fprintf(tw, "%t\n", res.Enabled)
 
 	return tw.Flush()
 }
diff --git a/govc/vcsa/access/consolecli/set.go b/govc/vcsa/access/consolecli/set.go
new file mode 100644
index 00000000..cebf6cf9
--- /dev/null
+++ b/govc/vcsa/access/consolecli/set.go
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 consolecli
+
+import (
+	"context"
+	"flag"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/consolecli"
+)
+
+type set struct {
+	*flags.ClientFlag
+	enabled bool
+}
+
+func init() {
+	cli.Register("vcsa.access.consolecli.set", &set{})
+}
+
+func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	f.BoolVar(&cmd.enabled,
+		"enabled",
+		false,
+		"Enable Console CLI.")
+}
+
+func (cmd *set) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (cmd *set) Description() string {
+	return `Set enabled state of the console-based controlled CLI (TTY1).
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+# Enable Console CLI
+govc vcsa.access.consolecli.set -enabled=true
+
+# Disable Console CLI
+govc vcsa.access.consolecli.set -enabled=false`
+}
+
+func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := consolecli.NewManager(c)
+
+	input := consolecli.Access{Enabled: cmd.enabled}
+	if err = m.Set(ctx, input); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/govc/vcsa/access/dcui/get.go b/govc/vcsa/access/dcui/get.go
new file mode 100644
index 00000000..21f9b278
--- /dev/null
+++ b/govc/vcsa/access/dcui/get.go
@@ -0,0 +1,93 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 dcui
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"io"
+	"text/tabwriter"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/dcui"
+)
+
+type get struct {
+	*flags.ClientFlag
+	*flags.OutputFlag
+}
+
+func init() {
+	cli.Register("vcsa.access.dcui.get", &get{})
+}
+
+func (cmd *get) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
+}
+
+func (cmd *get) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+	if err := cmd.OutputFlag.Process(ctx); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (cmd *get) Description() string {
+	return `Get enabled state of Direct Console User Interface (DCUI TTY2).
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+govc vcsa.access.dcui.get`
+}
+
+type access struct {
+	Enabled bool `json:"enabled"`
+}
+
+func (cmd *get) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := dcui.NewManager(c)
+
+	status, err := m.Get(ctx)
+	if err != nil {
+		return err
+	}
+
+	return cmd.WriteResult(access{Enabled: status})
+}
+
+func (res access) Write(w io.Writer) error {
+	tw := tabwriter.NewWriter(w, 10, 4, 0, ' ', 0)
+
+	fmt.Fprintf(tw, "%t\n", res.Enabled)
+
+	return tw.Flush()
+}
diff --git a/govc/vcsa/access/dcui/set.go b/govc/vcsa/access/dcui/set.go
new file mode 100644
index 00000000..86857aaa
--- /dev/null
+++ b/govc/vcsa/access/dcui/set.go
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 dcui
+
+import (
+	"context"
+	"flag"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/dcui"
+)
+
+type set struct {
+	*flags.ClientFlag
+	enabled bool
+}
+
+func init() {
+	cli.Register("vcsa.access.dcui.set", &set{})
+}
+
+func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	f.BoolVar(&cmd.enabled,
+		"enabled",
+		false,
+		"Enable Direct Console User Interface (DCUI TTY2).")
+}
+
+func (cmd *set) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (cmd *set) Description() string {
+	return `Set enabled state of Direct Console User Interface (DCUI TTY2).
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+# Enable DCUI
+govc vcsa.access.dcui.set -enabled=true
+
+# Disable DCUI
+govc vcsa.access.dcui.set -enabled=false`
+}
+
+func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := dcui.NewManager(c)
+
+	input := dcui.Access{Enabled: cmd.enabled}
+	if err = m.Set(ctx, input); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/govc/vcsa/access/shell/get.go b/govc/vcsa/access/shell/get.go
new file mode 100644
index 00000000..a7b40ed5
--- /dev/null
+++ b/govc/vcsa/access/shell/get.go
@@ -0,0 +1,94 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 shell
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"io"
+	"text/tabwriter"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/shell"
+)
+
+type get struct {
+	*flags.ClientFlag
+	*flags.OutputFlag
+}
+
+func init() {
+	cli.Register("vcsa.access.shell.get", &get{})
+}
+
+func (cmd *get) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
+}
+
+func (cmd *get) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+	if err := cmd.OutputFlag.Process(ctx); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (cmd *get) Description() string {
+	return `Get enabled state of BASH, that is, access to BASH from within the controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+govc vcsa.access.shell.get`
+}
+
+type access struct {
+	shell.Access
+}
+
+func (cmd *get) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := shell.NewManager(c)
+
+	status, err := m.Get(ctx)
+	if err != nil {
+		return err
+	}
+
+	return cmd.WriteResult(&access{status})
+}
+
+func (res access) Write(w io.Writer) error {
+	tw := tabwriter.NewWriter(w, 0, 4, 0, ' ', 0)
+
+	fmt.Fprintf(tw, "Enabled:%t\n", res.Enabled)
+	fmt.Fprintf(tw, "Timeout:%d\n", res.Timeout)
+
+	return tw.Flush()
+}
diff --git a/govc/vcsa/access/shell/set.go b/govc/vcsa/access/shell/set.go
new file mode 100644
index 00000000..0ad55204
--- /dev/null
+++ b/govc/vcsa/access/shell/set.go
@@ -0,0 +1,90 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 shell
+
+import (
+	"context"
+	"flag"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/shell"
+)
+
+type set struct {
+	*flags.ClientFlag
+	enabled bool
+	timeout int
+}
+
+func init() {
+	cli.Register("vcsa.access.shell.set", &set{})
+}
+
+func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	f.BoolVar(&cmd.enabled,
+		"enabled",
+		false,
+		"Enable BASH, that is, access to BASH from within the controlled CLI.")
+	f.IntVar(&cmd.timeout,
+		"timeout",
+		0,
+		"The timeout (in seconds) specifies how long you enable the Shell access. The maximum timeout is 86400 seconds(1 day).")
+}
+
+func (cmd *set) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (cmd *set) Description() string {
+	return `Set enabled state of BASH, that is, access to BASH from within the controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+# Enable Shell
+govc vcsa.access.shell.set -enabled=true -timeout=240
+
+# Disable Shell
+govc vcsa.access.shell.set -enabled=false`
+}
+
+func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := shell.NewManager(c)
+
+	input := shell.Access{
+		Enabled: cmd.enabled,
+		Timeout: cmd.timeout,
+	}
+	if err = m.Set(ctx, input); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/govc/vcsa/access/ssh/get.go b/govc/vcsa/access/ssh/get.go
new file mode 100644
index 00000000..f87404f2
--- /dev/null
+++ b/govc/vcsa/access/ssh/get.go
@@ -0,0 +1,93 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 ssh
+
+import (
+	"context"
+	"flag"
+	"fmt"
+	"io"
+	"text/tabwriter"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/ssh"
+)
+
+type get struct {
+	*flags.ClientFlag
+	*flags.OutputFlag
+}
+
+func init() {
+	cli.Register("vcsa.access.ssh.get", &get{})
+}
+
+func (cmd *get) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
+	cmd.OutputFlag.Register(ctx, f)
+}
+
+func (cmd *get) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+	if err := cmd.OutputFlag.Process(ctx); err != nil {
+		return err
+	}
+	return nil
+}
+
+func (cmd *get) Description() string {
+	return `Get enabled state of the SSH-based controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+govc vcsa.access.ssh.get`
+}
+
+type access struct {
+	Enabled bool `json:"enabled"`
+}
+
+func (cmd *get) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := ssh.NewManager(c)
+
+	status, err := m.Get(ctx)
+	if err != nil {
+		return err
+	}
+
+	return cmd.WriteResult(&access{Enabled: status})
+}
+
+func (res access) Write(w io.Writer) error {
+	tw := tabwriter.NewWriter(w, 10, 4, 0, ' ', 0)
+
+	fmt.Fprintf(tw, "Enabled:%t\n", res.Enabled)
+
+	return tw.Flush()
+}
diff --git a/govc/vcsa/access/ssh/set.go b/govc/vcsa/access/ssh/set.go
new file mode 100644
index 00000000..413ba28a
--- /dev/null
+++ b/govc/vcsa/access/ssh/set.go
@@ -0,0 +1,82 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 ssh
+
+import (
+	"context"
+	"flag"
+
+	"github.com/vmware/govmomi/govc/cli"
+	"github.com/vmware/govmomi/govc/flags"
+	"github.com/vmware/govmomi/vapi/appliance/access/ssh"
+)
+
+type set struct {
+	*flags.ClientFlag
+	enabled bool
+}
+
+func init() {
+	cli.Register("vcsa.access.ssh.set", &set{})
+}
+
+func (cmd *set) Register(ctx context.Context, f *flag.FlagSet) {
+	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
+	cmd.ClientFlag.Register(ctx, f)
+
+	f.BoolVar(&cmd.enabled,
+		"enabled",
+		false,
+		"Enable SSH-based controlled CLI.")
+}
+
+func (cmd *set) Process(ctx context.Context) error {
+	if err := cmd.ClientFlag.Process(ctx); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (cmd *set) Description() string {
+	return `Set enabled state of the SSH-based controlled CLI.
+
+Note: This command requires vCenter 7.0.2 or higher.
+
+Examples:
+# Enable SSH
+govc vcsa.access.ssh.set -enabled=true
+
+# Disable SSH
+govc vcsa.access.ssh.set -enabled=false`
+}
+
+func (cmd *set) Run(ctx context.Context, f *flag.FlagSet) error {
+	c, err := cmd.RestClient()
+	if err != nil {
+		return err
+	}
+
+	m := ssh.NewManager(c)
+
+	input := ssh.Access{Enabled: cmd.enabled}
+	if err = m.Set(ctx, input); err != nil {
+		return err
+	}
+
+	return nil
+}
diff --git a/govc/vcsa/shutdown/cancel.go b/govc/vcsa/shutdown/cancel.go
deleted file mode 100644
index cb334153..00000000
--- a/govc/vcsa/shutdown/cancel.go
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-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 shutdown
-
-import (
-	"context"
-	"flag"
-
-	"github.com/vmware/govmomi/govc/cli"
-	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/vapi/appliance/shutdown"
-)
-
-type cancel struct {
-	*flags.ClientFlag
-}
-
-func init() {
-	cli.Register("vcsa.shutdown.cancel", &cancel{})
-}
-
-func (cmd *cancel) Register(ctx context.Context, f *flag.FlagSet) {
-	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
-	cmd.ClientFlag.Register(ctx, f)
-}
-
-func (cmd *cancel) Description() string {
-	return `Cancel pending shutdown action.
-Examples:
-  govc vcsa.shutdown.cancel`
-}
-
-func (cmd *cancel) Run(ctx context.Context, f *flag.FlagSet) error {
-	c, err := cmd.RestClient()
-	if err != nil {
-		return err
-	}
-
-	m := shutdown.NewManager(c)
-
-	if err = m.Cancel(ctx); err != nil {
-		return err
-	}
-
-	return nil
-}
diff --git a/govc/vcsa/shutdown/poweroff.go b/govc/vcsa/shutdown/poweroff.go
deleted file mode 100644
index 7d942f31..00000000
--- a/govc/vcsa/shutdown/poweroff.go
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-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 shutdown
-
-import (
-	"context"
-	"flag"
-
-	"github.com/vmware/govmomi/govc/cli"
-	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/vapi/appliance/shutdown"
-)
-
-type powerOff struct {
-	*flags.ClientFlag
-
-	reason string
-	delay  int // in minutes
-}
-
-func init() {
-	cli.Register("vcsa.shutdown.poweroff", &powerOff{})
-}
-
-func (cmd *powerOff) Register(ctx context.Context, f *flag.FlagSet) {
-	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
-	cmd.ClientFlag.Register(ctx, f)
-
-	f.IntVar(&cmd.delay,
-		"delay",
-		0,
-		"Minutes after which poweroff should start.")
-}
-
-func (cmd *powerOff) Usage() string {
-	return "REASON"
-}
-
-func (cmd *powerOff) Description() string {
-	return `Power off the appliance.
-Examples:
-  govc vcsa.shutdown.poweroff -delay 10 "powering off for maintenance"`
-}
-
-func (cmd *powerOff) Run(ctx context.Context, f *flag.FlagSet) error {
-	if f.NArg() != 1 {
-		return flag.ErrHelp
-	}
-
-	c, err := cmd.RestClient()
-	if err != nil {
-		return err
-	}
-
-	m := shutdown.NewManager(c)
-
-	if err = m.PowerOff(ctx, f.Arg(0), cmd.delay); err != nil {
-		return err
-	}
-
-	return nil
-}
diff --git a/govc/vcsa/shutdown/reboot.go b/govc/vcsa/shutdown/reboot.go
deleted file mode 100644
index 2f3bda13..00000000
--- a/govc/vcsa/shutdown/reboot.go
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
-Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-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 shutdown
-
-import (
-	"context"
-	"flag"
-
-	"github.com/vmware/govmomi/govc/cli"
-	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/vapi/appliance/shutdown"
-)
-
-type reboot struct {
-	*flags.ClientFlag
-
-	reason string
-	delay  int // in minutes
-}
-
-func init() {
-	cli.Register("vcsa.shutdown.reboot", &reboot{})
-}
-
-func (cmd *reboot) Register(ctx context.Context, f *flag.FlagSet) {
-	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
-	cmd.ClientFlag.Register(ctx, f)
-
-	var now int
-	f.IntVar(&cmd.delay,
-		"delay",
-		now,
-		"Minutes after which reboot should start.")
-}
-
-func (cmd *reboot) Process(ctx context.Context) error {
-	if err := cmd.ClientFlag.Process(ctx); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (cmd *reboot) Usage() string {
-	return "REASON"
-}
-
-func (cmd *reboot) Description() string {
-	return `Reboot the appliance.
-Examples:
-  govc vcsa.shutdown.reboot -delay 10 "rebooting for maintenance"`
-}
-
-func (cmd *reboot) Run(ctx context.Context, f *flag.FlagSet) error {
-	if f.NArg() != 1 {
-		return flag.ErrHelp
-	}
-
-	c, err := cmd.RestClient()
-	if err != nil {
-		return err
-	}
-
-	m := shutdown.NewManager(c)
-
-	if err = m.Reboot(ctx, f.Arg(0), cmd.delay); err != nil {
-		return err
-	}
-
-	return nil
-}
diff --git a/object/folder.go b/object/folder.go
index 6e0a7649..7a69949f 100644
--- a/object/folder.go
+++ b/object/folder.go
@@ -225,17 +225,3 @@ func (f Folder) MoveInto(ctx context.Context, list []types.ManagedObjectReferenc
 
 	return NewTask(f.c, res.Returnval), nil
 }
-
-func (f Folder) PlaceVmsXCluster(ctx context.Context, spec types.PlaceVmsXClusterSpec) (*types.PlaceVmsXClusterResult, error) {
-	req := types.PlaceVmsXCluster{
-		This:          f.Reference(),
-		PlacementSpec: spec,
-	}
-
-	res, err := methods.PlaceVmsXCluster(ctx, f.c, &req)
-	if err != nil {
-		return nil, err
-	}
-
-	return &res.Returnval, nil
-}
diff --git a/simulator/dvs.go b/simulator/dvs.go
index ec73f06e..05216ef0 100644
--- a/simulator/dvs.go
+++ b/simulator/dvs.go
@@ -268,7 +268,8 @@ func (s *DistributedVirtualSwitch) DestroyTask(ctx *Context, req *types.Destroy_
 	}
 }
 
-func (s *DistributedVirtualSwitch) dvPortgroups(criteria *types.DistributedVirtualSwitchPortCriteria) []types.DistributedVirtualPort {
+func (s *DistributedVirtualSwitch) dvPortgroups(_ *types.DistributedVirtualSwitchPortCriteria) []types.DistributedVirtualPort {
+	// TODO(agui): Filter is not implemented yet
 	res := s.FetchDVPortsResponse.Returnval
 	if len(res) != 0 {
 		return res
@@ -276,120 +277,23 @@ func (s *DistributedVirtualSwitch) dvPortgroups(criteria *types.DistributedVirtu
 
 	for _, ref := range s.Portgroup {
 		pg := Map.Get(ref).(*DistributedVirtualPortgroup)
+		res = append(res, types.DistributedVirtualPort{
+			DvsUuid: s.Uuid,
+			Key:     pg.Key,
+			Config: types.DVPortConfigInfo{
+				Setting: pg.Config.DefaultPortConfig,
+			},
+		})
 
 		for _, key := range pg.PortKeys {
 			res = append(res, types.DistributedVirtualPort{
-				DvsUuid:      s.Uuid,
-				Key:          key,
-				PortgroupKey: pg.Key,
+				DvsUuid: s.Uuid,
+				Key:     key,
 				Config: types.DVPortConfigInfo{
 					Setting: pg.Config.DefaultPortConfig,
 				},
 			})
 		}
 	}
-
-	// filter ports by criteria
-	res = s.filterDVPorts(res, criteria)
-
 	return res
 }
-
-func (s *DistributedVirtualSwitch) filterDVPorts(
-	ports []types.DistributedVirtualPort,
-	criteria *types.DistributedVirtualSwitchPortCriteria,
-) []types.DistributedVirtualPort {
-	if criteria == nil {
-		return ports
-	}
-
-	ports = s.filterDVPortsByPortgroupKey(ports, criteria)
-	ports = s.filterDVPortsByPortKey(ports, criteria)
-	ports = s.filterDVPortsByConnected(ports, criteria)
-
-	return ports
-}
-
-func (s *DistributedVirtualSwitch) filterDVPortsByPortgroupKey(
-	ports []types.DistributedVirtualPort,
-	criteria *types.DistributedVirtualSwitchPortCriteria,
-) []types.DistributedVirtualPort {
-	if len(criteria.PortgroupKey) == 0 || criteria.Inside == nil {
-		return ports
-	}
-
-	// inside portgroup keys
-	if *criteria.Inside {
-		filtered := []types.DistributedVirtualPort{}
-
-		for _, p := range ports {
-			for _, pgk := range criteria.PortgroupKey {
-				if p.PortgroupKey == pgk {
-					filtered = append(filtered, p)
-					break
-				}
-			}
-		}
-		return filtered
-	}
-
-	// outside portgroup keys
-	filtered := []types.DistributedVirtualPort{}
-
-	for _, p := range ports {
-		found := false
-		for _, pgk := range criteria.PortgroupKey {
-			if p.PortgroupKey == pgk {
-				found = true
-				break
-			}
-		}
-
-		if !found {
-			filtered = append(filtered, p)
-		}
-	}
-	return filtered
-}
-
-func (s *DistributedVirtualSwitch) filterDVPortsByPortKey(
-	ports []types.DistributedVirtualPort,
-	criteria *types.DistributedVirtualSwitchPortCriteria,
-) []types.DistributedVirtualPort {
-	if len(criteria.PortKey) == 0 {
-		return ports
-	}
-
-	filtered := []types.DistributedVirtualPort{}
-
-	for _, p := range ports {
-		for _, pk := range criteria.PortKey {
-			if p.Key == pk {
-				filtered = append(filtered, p)
-				break
-			}
-		}
-	}
-
-	return filtered
-}
-
-func (s *DistributedVirtualSwitch) filterDVPortsByConnected(
-	ports []types.DistributedVirtualPort,
-	criteria *types.DistributedVirtualSwitchPortCriteria,
-) []types.DistributedVirtualPort {
-	if criteria.Connected == nil {
-		return ports
-	}
-
-	filtered := []types.DistributedVirtualPort{}
-
-	for _, p := range ports {
-		connected := p.Connectee != nil
-		if connected == *criteria.Connected {
-			filtered = append(filtered, p)
-		}
-	}
-
-	return filtered
-}
diff --git a/simulator/folder.go b/simulator/folder.go
index b0866813..a329112f 100644
--- a/simulator/folder.go
+++ b/simulator/folder.go
@@ -20,7 +20,6 @@ import (
 	"errors"
 	"fmt"
 	"math/rand"
-	"net/url"
 	"path"
 	"strings"
 
@@ -199,11 +198,9 @@ func (f *Folder) CreateFolder(ctx *Context, c *types.CreateFolder) soap.HasFault
 	r := &methods.CreateFolderBody{}
 
 	if folderHasChildType(&f.Folder, "Folder") {
-		name := f.escapeSpecialCharacters(c.Name)
-
-		if obj := ctx.Map.FindByName(name, f.ChildEntity); obj != nil {
+		if obj := ctx.Map.FindByName(c.Name, f.ChildEntity); obj != nil {
 			r.Fault_ = Fault("", &types.DuplicateName{
-				Name:   name,
+				Name:   c.Name,
 				Object: f.Self,
 			})
 
@@ -212,7 +209,7 @@ func (f *Folder) CreateFolder(ctx *Context, c *types.CreateFolder) soap.HasFault
 
 		folder := &Folder{}
 
-		folder.Name = name
+		folder.Name = c.Name
 		folder.ChildType = f.ChildType
 
 		folderPutChild(ctx, &f.Folder, folder)
@@ -227,13 +224,6 @@ func (f *Folder) CreateFolder(ctx *Context, c *types.CreateFolder) soap.HasFault
 	return r
 }
 
-func (f *Folder) escapeSpecialCharacters(name string) string {
-	name = strings.ReplaceAll(name, `%`, strings.ToLower(url.QueryEscape(`%`)))
-	name = strings.ReplaceAll(name, `/`, strings.ToLower(url.QueryEscape(`/`)))
-	name = strings.ReplaceAll(name, `\`, strings.ToLower(url.QueryEscape(`\`)))
-	return name
-}
-
 // StoragePod aka "Datastore Cluster"
 type StoragePod struct {
 	mo.StoragePod
@@ -640,9 +630,8 @@ func (f *Folder) CreateDVSTask(ctx *Context, req *types.CreateDVS_Task) soap.Has
 
 		dvs.AddDVPortgroupTask(ctx, &types.AddDVPortgroup_Task{
 			Spec: []types.DVPortgroupConfigSpec{{
-				Name:     dvs.Name + "-DVUplinks" + strings.TrimPrefix(dvs.Self.Value, "dvs"),
-				Type:     string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
-				NumPorts: 1,
+				Name: dvs.Name + "-DVUplinks" + strings.TrimPrefix(dvs.Self.Value, "dvs"),
+				Type: string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
 				DefaultPortConfig: &types.VMwareDVSPortSetting{
 					Vlan: &types.VmwareDistributedVirtualSwitchTrunkVlanSpec{
 						VlanId: []types.NumericRange{{Start: 0, End: 4094}},
@@ -721,51 +710,3 @@ func (f *Folder) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFaul
 		},
 	}
 }
-
-func (f *Folder) PlaceVmsXCluster(ctx *Context, req *types.PlaceVmsXCluster) soap.HasFault {
-	body := new(methods.PlaceVmsXClusterBody)
-
-	// Reject the request if it is against any folder other than the root folder.
-	if req.This != ctx.Map.content().RootFolder {
-		body.Fault_ = Fault("", new(types.InvalidRequest))
-	}
-
-	body.Res = new(types.PlaceVmsXClusterResponse)
-
-	for _, spec := range req.PlacementSpec.VmPlacementSpecs {
-		pspec := types.PlacementSpec{
-			PlacementType: string(types.PlacementSpecPlacementTypeCreate),
-			ConfigSpec:    &spec.ConfigSpec,
-		}
-
-		pools := req.PlacementSpec.ResourcePools
-		pool := ctx.Map.Get(pools[rand.Intn(len(pools))]).(*ResourcePool)
-		cluster := ctx.Map.Get(pool.Owner).(*ClusterComputeResource)
-
-		res := cluster.PlaceVm(ctx, &types.PlaceVm{
-			This:          f.Self,
-			PlacementSpec: pspec,
-		})
-
-		if res.Fault() != nil {
-			faults := types.PlaceVmsXClusterResultPlacementFaults{
-				VmName:       spec.ConfigSpec.Name,
-				ResourcePool: pool.Self,
-				Faults: []types.LocalizedMethodFault{
-					{
-						Fault: res.Fault().Detail.Fault.(types.BaseMethodFault),
-					},
-				},
-			}
-			body.Res.Returnval.Faults = append(body.Res.Returnval.Faults, faults)
-		} else {
-			placement := types.PlaceVmsXClusterResultPlacementInfo{
-				VmName:         spec.ConfigSpec.Name,
-				Recommendation: res.(*methods.PlaceVmBody).Res.Returnval.Recommendations[0],
-			}
-			body.Res.Returnval.PlacementInfos = append(body.Res.Returnval.PlacementInfos, placement)
-		}
-	}
-
-	return body
-}
diff --git a/simulator/model.go b/simulator/model.go
index d6ace75e..594ed137 100644
--- a/simulator/model.go
+++ b/simulator/model.go
@@ -654,9 +654,8 @@ func (m *Model) Create() error {
 		for npg := 0; npg < m.Portgroup; npg++ {
 			name := m.fmtName(dcName+"_DVPG", npg)
 			spec := types.DVPortgroupConfigSpec{
-				Name:     name,
-				Type:     string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
-				NumPorts: 1,
+				Name: name,
+				Type: string(types.DistributedVirtualPortgroupPortgroupTypeEarlyBinding),
 			}
 
 			task, err := dvs.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{spec})
diff --git a/ssoadmin/client.go b/ssoadmin/client.go
index 88f7d08f..1a03d1e5 100644
--- a/ssoadmin/client.go
+++ b/ssoadmin/client.go
@@ -441,16 +441,3 @@ func (c *Client) RevokeWSTrustRole(ctx context.Context, id types.PrincipalId, ro
 
 	return res.Returnval, nil
 }
-
-func (c *Client) IdentitySources(ctx context.Context) (*types.IdentitySources, error) {
-	req := types.Get{
-		This: c.ServiceContent.IdentitySourceManagementService,
-	}
-
-	res, err := methods.Get(ctx, c, &req)
-	if err != nil {
-		return nil, err
-	}
-
-	return &res.Returnval, nil
-}
diff --git a/ssoadmin/methods/methods.go b/ssoadmin/methods/methods.go
index 8705adff..180a4d48 100644
--- a/ssoadmin/methods/methods.go
+++ b/ssoadmin/methods/methods.go
@@ -743,26 +743,6 @@ func FindUsersInGroup(ctx context.Context, r soap.RoundTripper, req *types.FindU
 	return resBody.Res, nil
 }
 
-type GetBody struct {
-	Req    *types.Get         `xml:"urn:sso Get,omitempty"`
-	Res    *types.GetResponse `xml:"urn:sso GetResponse,omitempty"`
-	Fault_ *soap.Fault        `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
-}
-
-func (b *GetBody) Fault() *soap.Fault { return b.Fault_ }
-
-func Get(ctx context.Context, r soap.RoundTripper, req *types.Get) (*types.GetResponse, error) {
-	var reqBody, resBody GetBody
-
-	reqBody.Req = req
-
-	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
-		return nil, err
-	}
-
-	return resBody.Res, nil
-}
-
 type GetAllCertificatesBody struct {
 	Req    *types.GetAllCertificates         `xml:"urn:sso GetAllCertificates,omitempty"`
 	Res    *types.GetAllCertificatesResponse `xml:"urn:sso GetAllCertificatesResponse,omitempty"`
diff --git a/ssoadmin/simulator/simulator.go b/ssoadmin/simulator/simulator.go
deleted file mode 100644
index e4564840..00000000
--- a/ssoadmin/simulator/simulator.go
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
-   Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-   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 simulator
-
-import (
-	"github.com/vmware/govmomi/simulator"
-	"github.com/vmware/govmomi/ssoadmin"
-	"github.com/vmware/govmomi/ssoadmin/methods"
-	"github.com/vmware/govmomi/ssoadmin/types"
-	"github.com/vmware/govmomi/vim25/soap"
-	vim "github.com/vmware/govmomi/vim25/types"
-)
-
-func init() {
-	simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) {
-		if r.IsVPX() {
-			s.RegisterSDK(New())
-		}
-	})
-}
-
-var content = types.AdminServiceContent{
-	SessionManager:                  vim.ManagedObjectReference{Type: "SsoSessionManager", Value: "ssoSessionManager"},
-	ConfigurationManagementService:  vim.ManagedObjectReference{Type: "SsoAdminConfigurationManagementService", Value: "configurationManagementService"},
-	SmtpManagementService:           vim.ManagedObjectReference{Type: "SsoAdminSmtpManagementService", Value: "smtpManagementService"},
-	PrincipalDiscoveryService:       vim.ManagedObjectReference{Type: "SsoAdminPrincipalDiscoveryService", Value: "principalDiscoveryService"},
-	PrincipalManagementService:      vim.ManagedObjectReference{Type: "SsoAdminPrincipalManagementService", Value: "principalManagementService"},
-	RoleManagementService:           vim.ManagedObjectReference{Type: "SsoAdminRoleManagementService", Value: "roleManagementService"},
-	PasswordPolicyService:           vim.ManagedObjectReference{Type: "SsoAdminPasswordPolicyService", Value: "passwordPolicyService"},
-	LockoutPolicyService:            vim.ManagedObjectReference{Type: "SsoAdminLockoutPolicyService", Value: "lockoutPolicyService"},
-	DomainManagementService:         vim.ManagedObjectReference{Type: "SsoAdminDomainManagementService", Value: "domainManagementService"},
-	IdentitySourceManagementService: vim.ManagedObjectReference{Type: "SsoAdminIdentitySourceManagementService", Value: "identitySourceManagementService"},
-	SystemManagementService:         vim.ManagedObjectReference{Type: "SsoAdminSystemManagementService", Value: "systemManagementService"},
-	DeploymentInformationService:    vim.ManagedObjectReference{Type: "SsoAdminDeploymentInformationService", Value: "deploymentInformationService"},
-	ReplicationService:              vim.ManagedObjectReference{Type: "SsoAdminReplicationService", Value: "replicationService"},
-}
-
-var groupcheckServiceInstance = vim.ManagedObjectReference{
-	Type: "SsoGroupcheckServiceInstance", Value: "ServiceInstance",
-}
-
-var IdentitySources = types.IdentitySources{
-	System: types.IdentitySource{
-		Name:    "vsphere.local",
-		Domains: []types.Domain{{Name: "vsphere.local", Alias: "vmwarem"}},
-	},
-	LocalOS: &types.IdentitySource{
-		Name:    "localos",
-		Domains: []types.Domain{{Name: "localos", Alias: ""}},
-	},
-	NativeAD: nil,
-	LDAPS: []types.LdapIdentitySource{
-		{
-			IdentitySource: types.IdentitySource{
-				Name:    "example.com",
-				Domains: []types.Domain{{Name: "example.com", Alias: "examplex"}},
-			},
-			Type: "ActiveDirectory",
-			Details: types.LdapIdentitySourceDetails{
-				FriendlyName: "foo",
-				UserBaseDn:   "ou=People,dc=example,dc=org",
-				GroupBaseDn:  "ou=People,dc=example,dc=org",
-				PrimaryURL:   "ldap://10.168.194.120:389",
-				FailoverURL:  "",
-			},
-			AuthenticationDetails: types.AuthenticationDetails{
-				AuthenticationType: "PASSWORD",
-				Username:           "cn=admin,dc=example,dc=org",
-			},
-		},
-	},
-}
-
-type ServiceInstance struct {
-	vim.ManagedObjectReference
-}
-
-type GroupcheckServiceInstance struct {
-	vim.ManagedObjectReference
-}
-
-type SessionManager struct {
-	vim.ManagedObjectReference
-}
-
-type IdentitySourceManagementService struct {
-	vim.ManagedObjectReference
-}
-
-func New() *simulator.Registry {
-	r := simulator.NewRegistry()
-	r.Namespace = ssoadmin.Namespace
-	r.Path = ssoadmin.Path
-
-	r.Put(&ServiceInstance{
-		ManagedObjectReference: ssoadmin.ServiceInstance,
-	})
-
-	r.Put(&GroupcheckServiceInstance{
-		ManagedObjectReference: groupcheckServiceInstance,
-	})
-
-	r.Put(&SessionManager{
-		ManagedObjectReference: content.SessionManager,
-	})
-
-	r.Put(&IdentitySourceManagementService{
-		ManagedObjectReference: content.IdentitySourceManagementService,
-	})
-
-	return r
-}
-
-func (s *ServiceInstance) SsoAdminServiceInstance(ctx *simulator.Context, _ *types.SsoAdminServiceInstance) soap.HasFault {
-	return &methods.SsoAdminServiceInstanceBody{
-		Res: &types.SsoAdminServiceInstanceResponse{
-			Returnval: content,
-		},
-	}
-}
-
-func (s *GroupcheckServiceInstance) SsoGroupcheckServiceInstance(ctx *simulator.Context, _ *types.SsoGroupcheckServiceInstance) soap.HasFault {
-	return &methods.SsoGroupcheckServiceInstanceBody{
-		Res: &types.SsoGroupcheckServiceInstanceResponse{
-			Returnval: types.GroupcheckServiceContent{},
-		},
-	}
-}
-
-func (s *SessionManager) Login(ctx *simulator.Context, req *types.Login) soap.HasFault {
-	body := new(methods.LoginBody)
-
-	// TODO: check for Assertion>Subject>NameID as simulator.SessionManager.LoginByToken does
-	body.Res = new(types.LoginResponse)
-
-	return body
-}
-
-func (s *SessionManager) Logout(ctx *simulator.Context, req *types.Logout) soap.HasFault {
-	return &methods.LogoutBody{
-		Res: new(types.LogoutResponse),
-	}
-}
-
-func (s *IdentitySourceManagementService) Get(ctx *simulator.Context, _ *types.Get) soap.HasFault {
-	sources := IdentitySources
-	sources.All = nil
-	sources.All = append(sources.All, sources.System)
-
-	if sources.LocalOS != nil {
-		sources.All = append(sources.All, *sources.LocalOS)
-	}
-
-	if sources.NativeAD != nil {
-		sources.All = append(sources.All, *sources.NativeAD)
-	}
-
-	for _, ldap := range sources.LDAPS {
-		sources.All = append(sources.All, ldap.IdentitySource)
-	}
-
-	return &methods.GetBody{
-		Res: &types.GetResponse{
-			Returnval: sources,
-		},
-	}
-}
diff --git a/ssoadmin/types/types.go b/ssoadmin/types/types.go
index 49e520bc..3608dfff 100644
--- a/ssoadmin/types/types.go
+++ b/ssoadmin/types/types.go
@@ -1038,62 +1038,6 @@ type FindUsersResponse struct {
 	Returnval []AdminUser `xml:"returnval,omitempty"`
 }
 
-type Domain struct {
-	Name  string `xml:"name"`
-	Alias string `xml:"alias,omitempty"`
-}
-
-type IdentitySource struct {
-	Name    string   `xml:"name"`
-	Domains []Domain `xml:"domains"`
-}
-
-type LdapIdentitySourceDetails struct {
-	FriendlyName string `xml:"friendlyName"`
-	UserBaseDn   string `xml:"userBaseDn,omitempty"`
-	GroupBaseDn  string `xml:"groupBaseDn,omitempty"`
-	PrimaryURL   string `xml:"primaryUrl"`
-	FailoverURL  string `xml:"failoverUrl,omitempty"`
-}
-
-type AuthenticationDetails struct {
-	AuthenticationType string `xml:"authenticationType"`
-	Username           string `xml:"username"`
-}
-
-type LdapIdentitySource struct {
-	IdentitySource
-	Type                  string                    `xml:"type"`
-	Details               LdapIdentitySourceDetails `xml:"details"`
-	AuthenticationDetails AuthenticationDetails     `xml:"authenticationDetails"`
-}
-
-type IdentitySources struct {
-	All      []IdentitySource     `xml:"all"`
-	System   IdentitySource       `xml:"system"`
-	LocalOS  *IdentitySource      `xml:"localOS"`
-	NativeAD *IdentitySource      `xml:"nativeAD"`
-	LDAPS    []LdapIdentitySource `xml:"ldaps"`
-}
-
-type Get GetRequestType
-
-func init() {
-	types.Add("sso:Get", reflect.TypeOf((*Get)(nil)).Elem())
-}
-
-type GetRequestType struct {
-	This types.ManagedObjectReference `xml:"_this"`
-}
-
-func init() {
-	types.Add("sso:GetRequestType", reflect.TypeOf((*GetRequestType)(nil)).Elem())
-}
-
-type GetResponse struct {
-	Returnval IdentitySources `xml:"returnval,omitempty"`
-}
-
 type GetAllCertificates GetAllCertificatesRequestType
 
 func init() {
diff --git a/sts/client.go b/sts/client.go
index d98c5609..bcd346b7 100644
--- a/sts/client.go
+++ b/sts/client.go
@@ -71,9 +71,6 @@ func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error {
 
 // TokenRequest parameters for issuing a SAML token.
 // At least one of Userinfo or Certificate must be specified.
-// When `TokenRequest.Certificate` is set, the `tls.Certificate.PrivateKey` field must be set as it is required to sign the request.
-// When the `tls.Certificate.Certificate` field is not set, the request Assertion header is set to that of the TokenRequest.Token.
-// Otherwise `tls.Certificate.Certificate` is used as the BinarySecurityToken in the request.
 type TokenRequest struct {
 	Userinfo    *url.Userinfo    // Userinfo when set issues a Bearer token
 	Certificate *tls.Certificate // Certificate when set issues a HoK token
diff --git a/sts/signer.go b/sts/signer.go
index 6ee0ffde..78cf2046 100644
--- a/sts/signer.go
+++ b/sts/signer.go
@@ -128,28 +128,20 @@ func (s *Signer) Sign(env soap.Envelope) ([]byte, error) {
 			req := x.RequestSecurityToken()
 			c14n = req.C14N()
 			body = req.String()
+			id := newID()
 
-			if len(s.Certificate.Certificate) == 0 {
-				header.Assertion = s.Token
-				if err := s.setTokenReference(&info); err != nil {
-					return nil, err
-				}
-			} else {
-				id := newID()
-
-				header.BinarySecurityToken = &internal.BinarySecurityToken{
-					EncodingType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
-					ValueType:    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
-					ID:           id,
-					Value:        base64.StdEncoding.EncodeToString(s.Certificate.Certificate[0]),
-				}
-
-				info.SecurityTokenReference = &internal.SecurityTokenReference{
-					Reference: &internal.SecurityReference{
-						URI:       "#" + id,
-						ValueType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
-					},
-				}
+			info.SecurityTokenReference = &internal.SecurityTokenReference{
+				Reference: &internal.SecurityReference{
+					URI:       "#" + id,
+					ValueType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
+				},
+			}
+
+			header.BinarySecurityToken = &internal.BinarySecurityToken{
+				EncodingType: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary",
+				ValueType:    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3",
+				ID:           id,
+				Value:        base64.StdEncoding.EncodeToString(s.Certificate.Certificate[0]),
 			}
 		}
 		// When requesting HoK token for interactive user, request will have both priv. key and username/password.
@@ -351,5 +343,5 @@ func isIPv6(s string) bool {
 	if ip == nil {
 		return false
 	}
-	return ip.To4() == nil
+	return len(ip) == net.IPv6len
 }
diff --git a/toolbox/guest_info.go b/toolbox/guest_info.go
index 8abc03a8..fb2eee8b 100644
--- a/toolbox/guest_info.go
+++ b/toolbox/guest_info.go
@@ -21,7 +21,7 @@ import (
 	"fmt"
 	"net"
 
-	xdr "github.com/rasky/go-xdr/xdr2"
+	xdr "github.com/davecgh/go-xdr/xdr2"
 )
 
 // Defs from: open-vm-tools/lib/guestRpc/nicinfo.x
diff --git a/vapi/appliance/access/consolecli/consolecli.go b/vapi/appliance/access/consolecli/consolecli.go
new file mode 100644
index 00000000..2af70aa5
--- /dev/null
+++ b/vapi/appliance/access/consolecli/consolecli.go
@@ -0,0 +1,58 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 consolecli
+
+import (
+	"context"
+	"net/http"
+
+	"github.com/vmware/govmomi/vapi/rest"
+)
+
+const Path = "/api/appliance/access/consolecli"
+
+// Manager provides convenience methods to get/set enabled state of CLI.
+type Manager struct {
+	*rest.Client
+}
+
+// NewManager creates a new Manager with the given client
+func NewManager(client *rest.Client) *Manager {
+	return &Manager{
+		Client: client,
+	}
+}
+
+// Get returns enabled state of the console-based controlled CLI (TTY1).
+func (m *Manager) Get(ctx context.Context) (bool, error) {
+	r := m.Resource(Path)
+
+	var status bool
+	return status, m.Do(ctx, r.Request(http.MethodGet), &status)
+}
+
+// Access represents the value to be set for ConsoleCLI
+type Access struct {
+	Enabled bool `json:"enabled"`
+}
+
+// Set enables state of the console-based controlled CLI (TTY1).
+func (m *Manager) Set(ctx context.Context, inp Access) error {
+	r := m.Resource(Path)
+
+	return m.Do(ctx, r.Request(http.MethodPut, inp), nil)
+}
diff --git a/vapi/appliance/access/dcui/dcui.go b/vapi/appliance/access/dcui/dcui.go
new file mode 100644
index 00000000..8a09d34d
--- /dev/null
+++ b/vapi/appliance/access/dcui/dcui.go
@@ -0,0 +1,60 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 dcui
+
+import (
+	"context"
+	"net/http"
+
+	"github.com/vmware/govmomi/vapi/rest"
+)
+
+const Path = "/api/appliance/access/dcui"
+
+// Manager provides convenience methods to get/set enabled state of DCUI.
+type Manager struct {
+	*rest.Client
+}
+
+// NewManager creates a new Manager with the given client
+func NewManager(client *rest.Client) *Manager {
+	return &Manager{
+		Client: client,
+	}
+}
+
+// Get returns enabled state of Direct Console User Interface (DCUI TTY2).
+func (m *Manager) Get(ctx context.Context) (bool, error) {
+	r := m.Resource(Path)
+
+	var state bool
+	err := m.Do(ctx, r.Request(http.MethodGet), &state)
+
+	return state, err
+}
+
+// Access represents the value to be set for DCUI
+type Access struct {
+	Enabled bool `json:"enabled"`
+}
+
+// Set enables state of Direct Console User Interface (DCUI TTY2).
+func (m *Manager) Set(ctx context.Context, inp Access) error {
+	r := m.Resource(Path)
+
+	return m.Do(ctx, r.Request(http.MethodPut, inp), nil)
+}
diff --git a/vapi/appliance/access/shell/shell.go b/vapi/appliance/access/shell/shell.go
new file mode 100644
index 00000000..b7c013c3
--- /dev/null
+++ b/vapi/appliance/access/shell/shell.go
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 shell
+
+import (
+	"context"
+	"net/http"
+
+	"github.com/vmware/govmomi/vapi/rest"
+)
+
+const Path = "/api/appliance/access/shell"
+
+// Manager provides convenience methods to get/set enabled state of BASH.
+type Manager struct {
+	*rest.Client
+}
+
+// NewManager creates a new Manager with the given client
+func NewManager(client *rest.Client) *Manager {
+	return &Manager{
+		Client: client,
+	}
+}
+
+// Get returns enabled state of BASH, that is, access to BASH from within the controlled CLI.
+func (m *Manager) Get(ctx context.Context) (Access, error) {
+	r := m.Resource(Path)
+
+	var status Access
+	return status, m.Do(ctx, r.Request(http.MethodGet), &status)
+}
+
+// Access represents shell configuration.
+type Access struct {
+	Enabled bool `json:"enabled"`
+	Timeout int  `json:"timeout"`
+}
+
+// Set enables state of BASH, that is access to BASH from within the controlled CLI.
+func (m *Manager) Set(ctx context.Context, inp Access) error {
+	r := m.Resource(Path)
+
+	return m.Do(ctx, r.Request(http.MethodPut, inp), nil)
+}
diff --git a/vapi/appliance/access/ssh/ssh.go b/vapi/appliance/access/ssh/ssh.go
new file mode 100644
index 00000000..f74a6e38
--- /dev/null
+++ b/vapi/appliance/access/ssh/ssh.go
@@ -0,0 +1,60 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0.
+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 ssh
+
+import (
+	"context"
+	"net/http"
+
+	"github.com/vmware/govmomi/vapi/rest"
+)
+
+const Path = "/api/appliance/access/ssh"
+
+// Manager provides convenience methods to get/set enabled state of SSH-based controlled CLI.
+type Manager struct {
+	*rest.Client
+}
+
+// NewManager creates a new Manager with the given client
+func NewManager(client *rest.Client) *Manager {
+	return &Manager{
+		Client: client,
+	}
+}
+
+// Get returns enabled state of the SSH-based controlled CLI.
+func (m *Manager) Get(ctx context.Context) (bool, error) {
+	r := m.Resource(Path)
+
+	var state bool
+	err := m.Do(ctx, r.Request(http.MethodGet), &state)
+
+	return state, err
+}
+
+// Access represents the value to be set for SSH
+type Access struct {
+	Enabled bool `json:"enabled"`
+}
+
+// Set enables state of the SSH-based controlled CLI.
+func (m *Manager) Set(ctx context.Context, inp Access) error {
+	r := m.Resource(Path)
+
+	return m.Do(ctx, r.Request(http.MethodPut, inp), nil)
+}
diff --git a/vapi/appliance/shutdown/shutdown.go b/vapi/appliance/shutdown/shutdown.go
deleted file mode 100644
index f924680a..00000000
--- a/vapi/appliance/shutdown/shutdown.go
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
-Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-SPDX-License-Identifier: Apache-2.0.
-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 shutdown
-
-import (
-	"context"
-	"net/http"
-
-	"github.com/vmware/govmomi/vapi/rest"
-)
-
-const (
-	Path     = "/appliance/shutdown"
-	Action   = "action"
-	Cancel   = "cancel"
-	PowerOff = "poweroff"
-	Reboot   = "reboot"
-)
-
-// Manager provides convenience methods for shutdown Action
-type Manager struct {
-	*rest.Client
-}
-
-// NewManager creates a new Manager
-func NewManager(client *rest.Client) *Manager {
-	return &Manager{
-		Client: client,
-	}
-}
-
-// Cancel cancels pending shutdown action.
-func (m *Manager) Cancel(ctx context.Context) error {
-	r := m.Resource(Path).WithParam(Action, Cancel)
-
-	return m.Do(ctx, r.Request(http.MethodPost), nil)
-}
-
-// Spec represents request body class for an operation.
-type Spec struct {
-	Delay  int    `json:"delay"`
-	Reason string `json:"reason"`
-}
-
-// Config  defines shutdown configuration returned by the Shutdown.get operation
-type Config struct {
-	Action       string `json:"action"`
-	Reason       string `json:"reason"`
-	ShutdownTime string `json:"shutdown_time"`
-}
-
-// Get returns details about the pending shutdown action.
-func (m *Manager) Get(ctx context.Context) (Config, error) {
-	r := m.Resource(Path)
-
-	var c Config
-
-	return c, m.Do(ctx, r.Request(http.MethodGet), &c)
-}
-
-// PowerOff powers off the appliance.
-func (m *Manager) PowerOff(ctx context.Context, powerOffReason string, delay int) error {
-	r := m.Resource(Path).WithParam(Action, PowerOff)
-	s := Spec{
-		Delay:  delay,
-		Reason: powerOffReason,
-	}
-
-	return m.Do(ctx, r.Request(http.MethodPost, s), nil)
-}
-
-// Reboot reboots the appliance
-func (m *Manager) Reboot(ctx context.Context, rebootReason string, delay int) error {
-	r := m.Resource(Path).WithParam(Action, Reboot)
-	s := Spec{
-		Delay:  delay,
-		Reason: rebootReason,
-	}
-
-	return m.Do(ctx, r.Request(http.MethodPost, s), nil)
-}
diff --git a/vapi/appliance/simulator/simulator.go b/vapi/appliance/simulator/simulator.go
new file mode 100644
index 00000000..0027bccb
--- /dev/null
+++ b/vapi/appliance/simulator/simulator.go
@@ -0,0 +1,149 @@
+/*
+Copyright (c) 2022 VMware, Inc. All Rights Reserved.
+
+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 simulator
+
+import (
+	"encoding/json"
+	"log"
+	"net/http"
+	"net/url"
+
+	"github.com/vmware/govmomi/simulator"
+	"github.com/vmware/govmomi/vapi/appliance/access/consolecli"
+	"github.com/vmware/govmomi/vapi/appliance/access/dcui"
+	"github.com/vmware/govmomi/vapi/appliance/access/shell"
+	"github.com/vmware/govmomi/vapi/appliance/access/ssh"
+	vapi "github.com/vmware/govmomi/vapi/simulator"
+)
+
+func init() {
+	simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) {
+		New(s.Listen).Register(s, r)
+	})
+}
+
+// Handler implements the Appliance API simulator
+type Handler struct {
+	URL        *url.URL
+	consolecli consolecli.Access
+	dcui       dcui.Access
+	ssh        ssh.Access
+	shell      shell.Access
+}
+
+// New creates a Handler instance
+func New(u *url.URL) *Handler {
+	return &Handler{
+		URL:        nil,
+		consolecli: consolecli.Access{Enabled: false},
+		dcui:       dcui.Access{Enabled: false},
+		ssh:        ssh.Access{Enabled: false},
+		shell:      shell.Access{Enabled: false, Timeout: 0},
+	}
+}
+
+// Register Appliance Management API paths with the vapi simulator's http.ServeMux
+func (h *Handler) Register(s *simulator.Service, r *simulator.Registry) {
+	s.HandleFunc(consolecli.Path, h.consoleCLIAccess)
+	s.HandleFunc(dcui.Path, h.dcuiAccess)
+	s.HandleFunc(ssh.Path, h.sshAccess)
+	s.HandleFunc(shell.Path, h.shellAccess)
+}
+
+func (h *Handler) decode(r *http.Request, w http.ResponseWriter, val interface{}) bool {
+	return Decode(r, w, val)
+}
+
+// Decode decodes the request Body into val, returns true on success, otherwise false.
+func Decode(request *http.Request, writer http.ResponseWriter, val interface{}) bool {
+	defer request.Body.Close()
+	err := json.NewDecoder(request.Body).Decode(val)
+	if err != nil {
+		log.Printf("%s %s: %s", request.Method, request.RequestURI, err)
+		return false
+	}
+	return true
+}
+
+func (h *Handler) consoleCLIAccess(writer http.ResponseWriter, request *http.Request) {
+	switch request.Method {
+	case http.MethodGet:
+		vapi.StatusOK(writer, h.consolecli.Enabled)
+	case http.MethodPut:
+		var input consolecli.Access
+		if h.decode(request, writer, &input) {
+			h.consolecli.Enabled = input.Enabled
+			writer.WriteHeader(http.StatusNoContent)
+		} else {
+			writer.WriteHeader(http.StatusInternalServerError)
+		}
+	default:
+		http.NotFound(writer, request)
+	}
+}
+
+func (h *Handler) dcuiAccess(writer http.ResponseWriter, request *http.Request) {
+	switch request.Method {
+	case http.MethodGet:
+		vapi.StatusOK(writer, h.dcui.Enabled)
+	case http.MethodPut:
+		var input dcui.Access
+		if h.decode(request, writer, &input) {
+			h.dcui.Enabled = input.Enabled
+			writer.WriteHeader(http.StatusNoContent)
+		} else {
+			writer.WriteHeader(http.StatusInternalServerError)
+		}
+	default:
+		http.NotFound(writer, request)
+	}
+}
+
+func (h *Handler) sshAccess(writer http.ResponseWriter, request *http.Request) {
+	switch request.Method {
+	case http.MethodGet:
+		vapi.StatusOK(writer, h.ssh.Enabled)
+	case http.MethodPut:
+		var input ssh.Access
+		if h.decode(request, writer, &input) {
+			h.ssh.Enabled = input.Enabled
+			writer.WriteHeader(http.StatusNoContent)
+		} else {
+			writer.WriteHeader(http.StatusInternalServerError)
+		}
+	default:
+		http.NotFound(writer, request)
+	}
+}
+
+func (h *Handler) shellAccess(writer http.ResponseWriter, request *http.Request) {
+	switch request.Method {
+	case http.MethodGet:
+		vapi.StatusOK(writer, h.shell)
+	case http.MethodPut:
+		var input shell.Access
+		if h.decode(request, writer, &input) {
+			h.shell.Enabled = input.Enabled
+			h.shell.Timeout = input.Timeout
+			writer.WriteHeader(http.StatusNoContent)
+		} else {
+			writer.WriteHeader(http.StatusInternalServerError)
+		}
+	default:
+		http.NotFound(writer, request)
+	}
+}
diff --git a/vapi/namespace/namespace.go b/vapi/namespace/namespace.go
index c22bfddc..3e1c21d5 100644
--- a/vapi/namespace/namespace.go
+++ b/vapi/namespace/namespace.go
@@ -188,7 +188,7 @@ type EdgeClusterCompatibilitySummary struct {
 func (c *Manager) ListCompatibleEdgeClusters(ctx context.Context, clusterId string, switchId string) (result []EdgeClusterCompatibilitySummary, err error) {
 	listUrl := c.Resource(internal.NamespaceEdgeClusterCompatibility).
 		WithParam("cluster", clusterId).
-		WithParam("compatible", "true").
-		WithPathEncodedParam("distributed_switch", switchId)
+		WithParam("distributed_switch", switchId).
+		WithParam("compatible", "true")
 	return result, c.Do(ctx, listUrl.Request(http.MethodGet), &result)
 }
diff --git a/vapi/namespace/simulator/simulator.go b/vapi/namespace/simulator/simulator.go
index 285a8696..fc773928 100644
--- a/vapi/namespace/simulator/simulator.go
+++ b/vapi/namespace/simulator/simulator.go
@@ -237,6 +237,6 @@ func (h *Handler) getService(w http.ResponseWriter, r *http.Request) {
 				return
 			}
 		}
-		w.WriteHeader(http.StatusNotFound)
+		vapi.Status(w, http.StatusNotFound)
 	}
 }
diff --git a/vapi/rest/client.go b/vapi/rest/client.go
index 3c4b148d..b1cefd0e 100644
--- a/vapi/rest/client.go
+++ b/vapi/rest/client.go
@@ -164,7 +164,7 @@ type RawResponse struct {
 // Do sends the http.Request, decoding resBody if provided.
 func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{}) error {
 	switch req.Method {
-	case http.MethodPost, http.MethodPatch:
+	case http.MethodPost, http.MethodPatch, http.MethodPut:
 		req.Header.Set("Content-Type", "application/json")
 	}
 
diff --git a/vapi/rest/resource.go b/vapi/rest/resource.go
index e6e62749..3004abb8 100644
--- a/vapi/rest/resource.go
+++ b/vapi/rest/resource.go
@@ -51,36 +51,12 @@ func (r *Resource) WithAction(action string) *Resource {
 // WithParam adds one parameter on the URL.RawQuery
 func (r *Resource) WithParam(name string, value string) *Resource {
 	// ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case
-	params, err := url.ParseQuery(r.u.RawQuery)
-	if err != nil {
-		panic(err)
-	}
+	params, _ := url.ParseQuery(r.u.RawQuery)
 	params[name] = append(params[name], value)
 	r.u.RawQuery = params.Encode()
 	return r
 }
 
-// WithPathEncodedParam appends a parameter on the URL.RawQuery,
-// For special cases where URL Path-style encoding is needed
-func (r *Resource) WithPathEncodedParam(name string, value string) *Resource {
-	t := &url.URL{Path: value}
-	encodedValue := t.String()
-	t = &url.URL{Path: name}
-	encodedName := t.String()
-	// ParseQuery handles empty case, and we control access to query string so shouldn't encounter an error case
-	params, err := url.ParseQuery(r.u.RawQuery)
-	if err != nil {
-		panic(err)
-	}
-	// Values.Encode() doesn't escape exactly how we want, so we need to build the query string ourselves
-	if len(params) >= 1 {
-		r.u.RawQuery = r.u.RawQuery + "&" + encodedName + "=" + encodedValue
-	} else {
-		r.u.RawQuery = r.u.RawQuery + encodedName + "=" + encodedValue
-	}
-	return r
-}
-
 // Request returns a new http.Request for the given method.
 // An optional body can be provided for POST and PATCH methods.
 func (r *Resource) Request(method string, body ...interface{}) *http.Request {
diff --git a/vapi/simulator/simulator.go b/vapi/simulator/simulator.go
index 92160a97..493e3c7b 100644
--- a/vapi/simulator/simulator.go
+++ b/vapi/simulator/simulator.go
@@ -43,7 +43,6 @@ import (
 	"github.com/vmware/govmomi/object"
 	"github.com/vmware/govmomi/ovf"
 	"github.com/vmware/govmomi/simulator"
-	"github.com/vmware/govmomi/vapi/appliance/shutdown"
 	"github.com/vmware/govmomi/vapi/internal"
 	"github.com/vmware/govmomi/vapi/library"
 	"github.com/vmware/govmomi/vapi/rest"
@@ -92,7 +91,6 @@ type handler struct {
 	Library     map[string]*content
 	Update      map[string]update
 	Download    map[string]download
-	Config      shutdown.Config
 }
 
 func init() {
@@ -116,7 +114,6 @@ func New(u *url.URL, settings []vim.BaseOptionValue) (string, http.Handler) {
 		Library:     make(map[string]*content),
 		Update:      make(map[string]update),
 		Download:    make(map[string]download),
-		Config:      shutdown.Config{},
 	}
 
 	handlers := []struct {
@@ -158,7 +155,6 @@ func New(u *url.URL, settings []vim.BaseOptionValue) (string, http.Handler) {
 		{internal.VCenterVMTXLibraryItem + "/", s.libraryItemTemplateID},
 		{internal.VCenterVM + "/", s.vmID},
 		{internal.DebugEcho, s.debugEcho},
-		{shutdown.Path, s.shutdown},
 	}
 
 	for i := range handlers {
@@ -295,10 +291,10 @@ func (s *handler) DetachTag(id vim.ManagedObjectReference, tag vim.VslmTagEntry)
 	return nil
 }
 
-// StatusOK responds with http.StatusOK and encodes val, if specified, to JSON
+// Status responds with custom HTTP status and json encoded val if given.
 // For use with "/api" endpoints.
-func StatusOK(w http.ResponseWriter, val ...interface{}) {
-	w.WriteHeader(http.StatusOK)
+func Status(w http.ResponseWriter, httpStatus int, val ...interface{}) {
+	w.WriteHeader(httpStatus)
 	if len(val) == 0 {
 		return
 	}
@@ -310,7 +306,13 @@ func StatusOK(w http.ResponseWriter, val ...interface{}) {
 	}
 }
 
-// OK responds with http.StatusOK and encodes val, if specified, to JSON
+// StatusOK responds with http.StatusOK and json encoded val if given.
+// For use with "/api" endpoints.
+func StatusOK(w http.ResponseWriter, val ...interface{}) {
+	Status(w, http.StatusOK, val...)
+}
+
+// OK responds with http.StatusOK and json encoded val if given.
 // For use with "/rest" endpoints where the response is a "value" wrapped structure.
 func OK(w http.ResponseWriter, val ...interface{}) {
 	if len(val) == 0 {
@@ -2103,48 +2105,3 @@ func (s *handler) vmID(w http.ResponseWriter, r *http.Request) {
 func (s *handler) debugEcho(w http.ResponseWriter, r *http.Request) {
 	r.Write(w)
 }
-
-func (s *handler) shutdown(w http.ResponseWriter, r *http.Request) {
-	delayShutdown := func(delay int) {
-		go time.AfterFunc(time.Duration(delay)*time.Minute, func() {
-			s.Lock()
-			s.Config.ShutdownTime = ""
-			s.Config.Action = ""
-			s.Config.Reason = ""
-			s.Unlock()
-		})
-	}
-
-	switch r.Method {
-	case http.MethodGet:
-		OK(w, s.Config)
-	case http.MethodPost:
-		switch r.URL.Query().Get(shutdown.Action) {
-		case shutdown.Cancel:
-			delayShutdown(0)
-			w.WriteHeader(http.StatusNoContent)
-		case shutdown.Reboot:
-			var spec shutdown.Spec
-			if s.decode(r, w, &spec) {
-				s.Config.ShutdownTime = time.Now().UTC().Add(time.Duration(spec.Delay) * time.Minute).String()
-				s.Config.Reason = spec.Reason
-				s.Config.Action = shutdown.Reboot
-				delayShutdown(spec.Delay)
-				w.WriteHeader(http.StatusNoContent)
-			}
-		case shutdown.PowerOff:
-			var spec shutdown.Spec
-			if s.decode(r, w, &spec) {
-				s.Config.ShutdownTime = time.Now().Local().Add(time.Duration(spec.Delay) * time.Minute).String()
-				s.Config.Reason = spec.Reason
-				s.Config.Action = shutdown.PowerOff
-				delayShutdown(spec.Delay)
-				w.WriteHeader(http.StatusNoContent)
-			}
-		default:
-			http.NotFound(w, r)
-		}
-	default:
-		http.NotFound(w, r)
-	}
-}
diff --git a/vapi/tags/categories.go b/vapi/tags/categories.go
index 64d0b66c..3ad81820 100644
--- a/vapi/tags/categories.go
+++ b/vapi/tags/categories.go
@@ -20,13 +20,11 @@ import (
 	"context"
 	"fmt"
 	"net/http"
-	"strings"
 
 	"github.com/vmware/govmomi/vapi/internal"
 )
 
-// Category provides methods to create, read, update, delete, and enumerate
-// categories.
+// Category provides methods to create, read, update, delete, and enumerate categories.
 type Category struct {
 	ID              string   `json:"id,omitempty"`
 	Name            string   `json:"name,omitempty"`
@@ -94,8 +92,7 @@ func (c *Manager) CreateCategory(ctx context.Context, category *Category) (strin
 	return res, c.Do(ctx, url.Request(http.MethodPost, spec), &res)
 }
 
-// UpdateCategory updates one or more of the AssociableTypes, Cardinality,
-// Description and Name fields.
+// UpdateCategory can update one or more of the AssociableTypes, Cardinality, Description and Name fields.
 func (c *Manager) UpdateCategory(ctx context.Context, category *Category) error {
 	spec := struct {
 		Category Category `json:"update_spec"`
@@ -111,7 +108,7 @@ func (c *Manager) UpdateCategory(ctx context.Context, category *Category) error
 	return c.Do(ctx, url.Request(http.MethodPatch, spec), nil)
 }
 
-// DeleteCategory deletes a category.
+// DeleteCategory deletes an existing category.
 func (c *Manager) DeleteCategory(ctx context.Context, category *Category) error {
 	url := c.Resource(internal.CategoryPath).WithID(category.ID)
 	return c.Do(ctx, url.Request(http.MethodDelete), nil)
@@ -144,7 +141,7 @@ func (c *Manager) ListCategories(ctx context.Context) ([]string, error) {
 	return res, c.Do(ctx, url.Request(http.MethodGet), &res)
 }
 
-// GetCategories fetches a list of category information in the system.
+// GetCategories fetches an array of category information in the system.
 func (c *Manager) GetCategories(ctx context.Context) ([]Category, error) {
 	ids, err := c.ListCategories(ctx)
 	if err != nil {
@@ -155,13 +152,11 @@ func (c *Manager) GetCategories(ctx context.Context) ([]Category, error) {
 	for _, id := range ids {
 		category, err := c.GetCategory(ctx, id)
 		if err != nil {
-			if strings.Contains(err.Error(), http.StatusText(http.StatusNotFound)) {
-				continue // deleted since last fetch
-			}
-			return nil, fmt.Errorf("get category %s: %v", id, err)
+			return nil, fmt.Errorf("get category %s: %s", id, err)
 		}
+
 		categories = append(categories, *category)
-	}
 
+	}
 	return categories, nil
 }
diff --git a/vcsim/main.go b/vcsim/main.go
index 7876ec61..6e11664e 100644
--- a/vcsim/main.go
+++ b/vcsim/main.go
@@ -44,8 +44,8 @@ import (
 	_ "github.com/vmware/govmomi/eam/simulator"
 	_ "github.com/vmware/govmomi/lookup/simulator"
 	_ "github.com/vmware/govmomi/pbm/simulator"
-	_ "github.com/vmware/govmomi/ssoadmin/simulator"
 	_ "github.com/vmware/govmomi/sts/simulator"
+	_ "github.com/vmware/govmomi/vapi/appliance/simulator"
 	_ "github.com/vmware/govmomi/vapi/cluster/simulator"
 	_ "github.com/vmware/govmomi/vapi/namespace/simulator"
 	_ "github.com/vmware/govmomi/vapi/simulator"
diff --git a/vim25/methods/unreleased.go b/vim25/methods/unreleased.go
deleted file mode 100644
index a0ffff8c..00000000
--- a/vim25/methods/unreleased.go
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
-   Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-   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 methods
-
-import (
-	"context"
-
-	"github.com/vmware/govmomi/vim25/soap"
-	"github.com/vmware/govmomi/vim25/types"
-)
-
-type PlaceVmsXClusterBody struct {
-	Req    *types.PlaceVmsXCluster         `xml:"urn:vim25 PlaceVmsXCluster,omitempty"`
-	Res    *types.PlaceVmsXClusterResponse `xml:"PlaceVmsXClusterResponse,omitempty"`
-	Fault_ *soap.Fault                     `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
-}
-
-func (b *PlaceVmsXClusterBody) Fault() *soap.Fault { return b.Fault_ }
-
-func PlaceVmsXCluster(ctx context.Context, r soap.RoundTripper, req *types.PlaceVmsXCluster) (*types.PlaceVmsXClusterResponse, error) {
-	var reqBody, resBody PlaceVmsXClusterBody
-
-	reqBody.Req = req
-
-	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
-		return nil, err
-	}
-
-	return resBody.Res, nil
-}
diff --git a/vim25/soap/debug.go b/vim25/soap/debug.go
index bc5b9020..ab23fd63 100644
--- a/vim25/soap/debug.go
+++ b/vim25/soap/debug.go
@@ -87,9 +87,7 @@ func (d *debugRoundTrip) debugRequest(req *http.Request) string {
 	ext := d.ext(req.Header)
 	// Capture body
 	wc = d.newFile("req." + ext)
-	if req.Body != nil {
-		req.Body = Trace(req.Body, wc, ext)
-	}
+	req.Body = Trace(req.Body, wc, ext)
 
 	// Delay closing until marked done
 	d.cs = append(d.cs, wc)
diff --git a/vim25/types/unreleased.go b/vim25/types/unreleased.go
deleted file mode 100644
index 167184e8..00000000
--- a/vim25/types/unreleased.go
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
-   Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-   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 types
-
-import "reflect"
-
-type ArrayOfPlaceVmsXClusterResultPlacementFaults struct {
-	PlaceVmsXClusterResultPlacementFaults []PlaceVmsXClusterResultPlacementFaults `xml:"PlaceVmsXClusterResultPlacementFaults,omitempty"`
-}
-
-func init() {
-	t["ArrayOfPlaceVmsXClusterResultPlacementFaults"] = reflect.TypeOf((*ArrayOfPlaceVmsXClusterResultPlacementFaults)(nil)).Elem()
-}
-
-type ArrayOfPlaceVmsXClusterResultPlacementInfo struct {
-	PlaceVmsXClusterResultPlacementInfo []PlaceVmsXClusterResultPlacementInfo `xml:"PlaceVmsXClusterResultPlacementInfo,omitempty"`
-}
-
-func init() {
-	t["ArrayOfPlaceVmsXClusterResultPlacementInfo"] = reflect.TypeOf((*ArrayOfPlaceVmsXClusterResultPlacementInfo)(nil)).Elem()
-}
-
-type ArrayOfPlaceVmsXClusterSpecVmPlacementSpec struct {
-	PlaceVmsXClusterSpecVmPlacementSpec []PlaceVmsXClusterSpecVmPlacementSpec `xml:"PlaceVmsXClusterSpecVmPlacementSpec,omitempty"`
-}
-
-func init() {
-	t["ArrayOfPlaceVmsXClusterSpecVmPlacementSpec"] = reflect.TypeOf((*ArrayOfPlaceVmsXClusterSpecVmPlacementSpec)(nil)).Elem()
-}
-
-type PlaceVmsXCluster PlaceVmsXClusterRequestType
-
-func init() {
-	t["PlaceVmsXCluster"] = reflect.TypeOf((*PlaceVmsXCluster)(nil)).Elem()
-}
-
-type PlaceVmsXClusterRequestType struct {
-	This          ManagedObjectReference `xml:"_this"`
-	PlacementSpec PlaceVmsXClusterSpec   `xml:"placementSpec"`
-}
-
-func init() {
-	t["PlaceVmsXClusterRequestType"] = reflect.TypeOf((*PlaceVmsXClusterRequestType)(nil)).Elem()
-}
-
-type PlaceVmsXClusterResponse struct {
-	Returnval PlaceVmsXClusterResult `xml:"returnval"`
-}
-
-type PlaceVmsXClusterResult struct {
-	DynamicData
-
-	PlacementInfos []PlaceVmsXClusterResultPlacementInfo   `xml:"placementInfos,omitempty"`
-	Faults         []PlaceVmsXClusterResultPlacementFaults `xml:"faults,omitempty"`
-}
-
-func init() {
-	t["PlaceVmsXClusterResult"] = reflect.TypeOf((*PlaceVmsXClusterResult)(nil)).Elem()
-}
-
-type PlaceVmsXClusterResultPlacementFaults struct {
-	DynamicData
-
-	ResourcePool ManagedObjectReference `xml:"resourcePool"`
-	VmName       string                 `xml:"vmName"`
-	Faults       []LocalizedMethodFault `xml:"faults,omitempty"`
-}
-
-func init() {
-	t["PlaceVmsXClusterResultPlacementFaults"] = reflect.TypeOf((*PlaceVmsXClusterResultPlacementFaults)(nil)).Elem()
-}
-
-type PlaceVmsXClusterResultPlacementInfo struct {
-	DynamicData
-
-	VmName         string                `xml:"vmName"`
-	Recommendation ClusterRecommendation `xml:"recommendation"`
-}
-
-func init() {
-	t["PlaceVmsXClusterResultPlacementInfo"] = reflect.TypeOf((*PlaceVmsXClusterResultPlacementInfo)(nil)).Elem()
-}
-
-type PlaceVmsXClusterSpec struct {
-	DynamicData
-
-	ResourcePools    []ManagedObjectReference              `xml:"resourcePools,omitempty"`
-	VmPlacementSpecs []PlaceVmsXClusterSpecVmPlacementSpec `xml:"vmPlacementSpecs,omitempty"`
-}
-
-func init() {
-	t["PlaceVmsXClusterSpec"] = reflect.TypeOf((*PlaceVmsXClusterSpec)(nil)).Elem()
-}
-
-type PlaceVmsXClusterSpecVmPlacementSpec struct {
-	DynamicData
-
-	ConfigSpec VirtualMachineConfigSpec `xml:"configSpec"`
-}
-
-func init() {
-	t["PlaceVmsXClusterSpecVmPlacementSpec"] = reflect.TypeOf((*PlaceVmsXClusterSpecVmPlacementSpec)(nil)).Elem()
-}


Test patch:
diff --git a/cns/client_test.go b/cns/client_test.go
index 1d3592a9..01e58053 100644
--- a/cns/client_test.go
+++ b/cns/client_test.go
@@ -24,7 +24,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi/find"
 	"github.com/vmware/govmomi/object"
@@ -262,35 +262,6 @@ func TestClient(t *testing.T) {
 		}
 	}
 
-	// Test BackingDiskObjectId field only for vVol or vSAN volume type
-	var queryFilterBackingDiskObjectIdTest cnstypes.CnsQueryFilter
-	var volumeIDListBackingDiskObjectIdTest []cnstypes.CnsVolumeId
-	volumeIDListBackingDiskObjectIdTest = append(volumeIDListBackingDiskObjectIdTest, cnstypes.CnsVolumeId{Id: volumeId})
-	queryFilterBackingDiskObjectIdTest.VolumeIds = volumeIDListBackingDiskObjectIdTest
-	t.Logf("Calling QueryVolume using queryFilter: %+v", pretty.Sprint(queryFilterBackingDiskObjectIdTest))
-	queryResultBackingDiskObjectIdTest, err := cnsClient.QueryVolume(ctx, queryFilterBackingDiskObjectIdTest)
-	if err != nil {
-		t.Errorf("Failed to query all volumes. Error: %+v \n", err)
-		t.Fatal(err)
-	}
-	t.Logf("Successfully Queried Volumes. queryResultBackingDiskObjectIdTest: %+v", pretty.Sprint(queryResultBackingDiskObjectIdTest))
-	t.Log("Checking backingDiskObjectId retieved")
-	datastoreType, err := ds.Type(ctx)
-	if err != nil {
-		t.Errorf("Failed to get datastore type. Error: %+v \n", err)
-		t.Fatal(err)
-	}
-	for _, vol := range queryResultBackingDiskObjectIdTest.Volumes {
-		// BackingDiskObjectId is only for vsan/vvol, for other type this field is empty but test should not fail
-		backingDiskObjectId := vol.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails).BackingDiskObjectId
-		if backingDiskObjectId == "" {
-			if datastoreType == vim25types.HostFileSystemVolumeFileSystemTypeVsan || datastoreType == vim25types.HostFileSystemVolumeFileSystemTypeVVOL {
-				t.Errorf("Failed to get BackingDiskObjectId")
-				t.FailNow()
-			}
-		}
-	}
-
 	// Test QuerySnapshots API on 7.0 U3 or above
 	var snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter
 	var querySnapshotsTaskResult *cnstypes.CnsSnapshotQueryResult
diff --git a/govc/test/import.bats b/govc/test/import.bats
index 7550fad8..3d714614 100755
--- a/govc/test/import.bats
+++ b/govc/test/import.bats
@@ -22,9 +22,6 @@ load test_helper
   run govc import.spec "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ovf"
   assert_success
 
-  run govc import.spec "https://$(govc env GOVC_URL)/folder/$TTYLINUX_NAME.ova"
-  assert_success
-
   proto=$(jq -r .IPProtocol <<<"$output")
   assert_equal IPv4 "$proto"
 
diff --git a/govc/test/sso.bats b/govc/test/sso.bats
index d03c34e9..ff67ddb1 100755
--- a/govc/test/sso.bats
+++ b/govc/test/sso.bats
@@ -45,18 +45,4 @@ load test_helper
   govc sso.service.ls -p com.vmware.cis -t cs.identity -P wsTrust -T com.vmware.cis.cs.identity.sso -l | grep wsTrust
   govc sso.service.ls -P vmomi | grep vcenterserver | grep -v https:
   govc sso.service.ls -P vmomi -l | grep https:
-}
-
-@test "sso.idp.ls" {
-  vcsim_env
-
-  run govc sso.idp.ls -json
-  assert_success
-
-  run govc sso.idp.ls
-  assert_success
-  [ ${#lines[@]} -eq 4 ]
-  assert_matches "System Domain"
-  assert_matches "Local OS"
-  assert_matches "ActiveDirectory"
-}
+}
\ No newline at end of file
diff --git a/govc/test/vcsa_access_consolecli.bats b/govc/test/vcsa_access_consolecli.bats
new file mode 100755
index 00000000..e199898e
--- /dev/null
+++ b/govc/test/vcsa_access_consolecli.bats
@@ -0,0 +1,35 @@
+#!/usr/bin/env bats
+
+load test_helper
+
+@test "vcsa.access.consolecli.get" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.consolecli.get
+  assert_success
+
+  run govc vcsa.access.consolecli.get -json=True
+  assert_success
+
+  run govc vcsa.access.consolecli.get -xml=True
+  assert_success
+}
+
+@test "vcsa.access.consolecli.set" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.consolecli.set
+  status=$(govc vcsa.access.consolecli.get| grep "false"| awk '{print $1}')
+  assert_equal $status 'false'
+
+  run govc vcsa.access.consolecli.set -enabled=true
+  status=$(govc vcsa.access.consolecli.get | grep "true"| awk '{print $0}')
+  assert_equal $status 'true'
+
+  run govc vcsa.access.consolecli.set -enabled=false
+  status=$(govc vcsa.access.consolecli.get | grep "false"| awk '{print $1}')
+  assert_equal $status 'false'
+
+}
diff --git a/govc/test/vcsa_access_dcui.bats b/govc/test/vcsa_access_dcui.bats
new file mode 100755
index 00000000..321c1dc3
--- /dev/null
+++ b/govc/test/vcsa_access_dcui.bats
@@ -0,0 +1,35 @@
+#!/usr/bin/env bats
+
+load test_helper
+
+@test "vcsa.access.dcui.get" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.dcui.get
+  assert_success
+
+  run govc vcsa.access.dcui.get -json=True
+  assert_success
+
+  run govc vcsa.access.dcui.get -xml=True
+  assert_success
+}
+
+@test "vcsa.access.dcui.set" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.dcui.set
+  status=$(govc vcsa.access.dcui.get| grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+
+  run govc vcsa.access.dcui.set -enabled=true
+  status=$(govc vcsa.access.dcui.get | grep -ow "true"| awk '{print $1}')
+  assert_equal $status 'true'
+
+  run govc vcsa.access.dcui.set -enabled=false
+  status=$(govc vcsa.access.dcui.get | grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+  
+}
diff --git a/govc/test/vcsa_access_shell.bats b/govc/test/vcsa_access_shell.bats
new file mode 100755
index 00000000..487a8ff7
--- /dev/null
+++ b/govc/test/vcsa_access_shell.bats
@@ -0,0 +1,34 @@
+#!/usr/bin/env bats
+
+load test_helper
+
+@test "vcsa.access.shell.get" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.shell.get
+  assert_success
+
+  run govc vcsa.access.shell.get -json=True
+  assert_success
+
+  run govc vcsa.access.shell.get -xml=True
+  assert_success
+}
+
+@test "vcsa.access.shell.set" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.shell.set
+  status=$(govc vcsa.access.shell.get| grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+
+  run govc vcsa.access.shell.set -enabled=true -timeout=240
+  status=$(govc vcsa.access.shell.get | grep -ow "true"| awk '{print $1}')
+  assert_equal $status 'true'
+
+  run govc vcsa.access.shell.set -enabled=false
+  status=$(govc vcsa.access.shell.get | grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+}
diff --git a/govc/test/vcsa_access_ssh.bats b/govc/test/vcsa_access_ssh.bats
new file mode 100755
index 00000000..242798fb
--- /dev/null
+++ b/govc/test/vcsa_access_ssh.bats
@@ -0,0 +1,34 @@
+#!/usr/bin/env bats
+
+load test_helper
+
+@test "vcsa.access.ssh.get" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.ssh.get
+  assert_success
+
+  run govc vcsa.access.ssh.get -json=True
+  assert_success
+
+  run govc vcsa.access.ssh.get -xml=True
+  assert_success
+}
+
+@test "vcsa.access.ssh.set" {
+  vcsim_env
+  local output
+
+  run govc vcsa.access.ssh.set
+  status=$(govc vcsa.access.ssh.get| grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+
+  run govc vcsa.access.ssh.set -enabled=true
+  status=$(govc vcsa.access.ssh.get | grep -ow "true"| awk '{print $1}')
+  assert_equal $status 'true'
+
+  run govc vcsa.access.ssh.set -enabled=false
+  status=$(govc vcsa.access.ssh.get | grep -ow "false"| awk '{print $1}')
+  assert_equal $status 'false'
+}
diff --git a/govc/test/vcsa_shutdown.bats b/govc/test/vcsa_shutdown.bats
deleted file mode 100755
index 13c06894..00000000
--- a/govc/test/vcsa_shutdown.bats
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/usr/bin/env bats
-
-load test_helper
-
-@test "vcsa.shutdown.poweroff" {
-  vcsim_env
-  local output
-
-  run govc vcsa.shutdown.poweroff -delay 50 "powering off for maintenance"
-  assert_success
-
-  status=$(govc vcsa.shutdown.get| grep -ow "poweroff"| awk '{print $1}')
-  assert_equal $status 'poweroff'
-   
-  run govc vcsa.shutdown.poweroff -delay 50 "powering off for maintenance"
-  assert_success
-
-  status=$(govc vcsa.shutdown.get| grep -ow "poweroff"| awk '{print $1}')
-  assert_equal $status 'poweroff'
-
-  run govc vcsa.shutdown.poweroff
-  assert_failure
-
-}
-
-@test "vcsa.shutdown.reboot" {
-  vcsim_env
-  local output
-
-  run govc vcsa.shutdown.reboot -delay 50 "rebooting for maintenance"
-  assert_success
-
-  status=$(govc vcsa.shutdown.get| grep -ow "reboot"| awk '{print $1}')
-  assert_equal $status 'reboot'
-
-  run govc vcsa.shutdown.reboot -delay 50 "rebooting for maintenance"
-  assert_success
-
-  status=$(govc vcsa.shutdown.get| grep -ow "reboot"| awk '{print $1}')
-  assert_equal $status 'reboot'
-
-  run govc vcsa.shutdown.reboot
-  assert_failure
-
-}
-
-
-@test "vcsa.shutdown.get" {
-  vcsim_env
-  local output
-
-  run govc vcsa.shutdown.get
-  assert_success
-
-  run govc vcsa.shutdown.get -json
-  assert_success
-
-  run govc vcsa.shutdown.status -yaml
-  assert_failure
-}
-
-
-@test "vcsa.shutdown.cancel" {
-  vcsim_env
-  local output
-
-  run govc vcsa.shutdown.cancel
-  assert_success
-
-  run govc vcsa.shutdown.reboot -delay 50 "rebooting for maintenance"
-  assert_success
-  run govc vcsa.shutdown.cancel
-  status=$(govc vcsa.shutdown.get| grep -i "Action"| awk '{print $2}')
-  assert_equal $status ''
-  status=$(govc vcsa.shutdown.get| grep -i "ShutDownTime"| awk '{print $2}')
-  assert_equal $status ''
-  status=$(govc vcsa.shutdown.get| grep -i "Reason"| awk '{print $2}')
-  
-
-  run govc vcsa.shutdown.cancel -reason "cancelling shutdown"
-  assert_failure
-}
diff --git a/simulator/dvs_test.go b/simulator/dvs_test.go
index 64fc1d90..6fcb2716 100644
--- a/simulator/dvs_test.go
+++ b/simulator/dvs_test.go
@@ -124,9 +124,7 @@ func TestDVS(t *testing.T) {
 		} else {
 			switch test.op {
 			case types.ConfigSpecOperationAdd:
-				dtask, err = dswitch.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{
-					{Name: test.pg, NumPorts: 1},
-				})
+				dtask, err = dswitch.AddPortgroup(ctx, []types.DVPortgroupConfigSpec{{Name: test.pg}})
 			}
 		}
 
@@ -170,112 +168,3 @@ func TestDVS(t *testing.T) {
 		t.Fatal(err)
 	}
 }
-
-func TestFetchDVPortsCriteria(t *testing.T) {
-	m := VPX()
-
-	defer m.Remove()
-
-	err := m.Create()
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	ctx := context.Background()
-	c := m.Service.client
-
-	finder := find.NewFinder(c, false)
-	dc, _ := finder.DatacenterList(ctx, "*")
-	finder.SetDatacenter(dc[0])
-	vswitch := Map.Any("DistributedVirtualSwitch").(*DistributedVirtualSwitch)
-	dvs0 := object.NewDistributedVirtualSwitch(c, vswitch.Reference())
-	pgs := vswitch.Portgroup
-	if len(pgs) != 2 {
-		t.Fatalf("expected 2 portgroups in DVS; got %d", len(pgs))
-	}
-
-	tests := []struct {
-		name     string
-		criteria *types.DistributedVirtualSwitchPortCriteria
-		expected []types.DistributedVirtualPort
-	}{
-		{
-			"empty criteria",
-			&types.DistributedVirtualSwitchPortCriteria{},
-			[]types.DistributedVirtualPort{
-				{PortgroupKey: pgs[0].Value, Key: "0"},
-				{PortgroupKey: pgs[1].Value, Key: "0"},
-			},
-		},
-		{
-			"inside PortgroupKeys",
-			&types.DistributedVirtualSwitchPortCriteria{
-				PortgroupKey: []string{pgs[0].Value},
-				Inside:       types.NewBool(true),
-			},
-			[]types.DistributedVirtualPort{
-				{PortgroupKey: pgs[0].Value, Key: "0"},
-			},
-		},
-		{
-			"outside PortgroupKeys",
-			&types.DistributedVirtualSwitchPortCriteria{
-				PortgroupKey: []string{pgs[0].Value},
-				Inside:       types.NewBool(false),
-			},
-			[]types.DistributedVirtualPort{
-				{PortgroupKey: pgs[1].Value, Key: "0"},
-			},
-		},
-		{
-			"PortKeys",
-			&types.DistributedVirtualSwitchPortCriteria{
-				PortKey: []string{"1"},
-			},
-			[]types.DistributedVirtualPort{},
-		},
-		{
-			"connected",
-			&types.DistributedVirtualSwitchPortCriteria{
-				Connected: types.NewBool(true),
-			},
-			[]types.DistributedVirtualPort{},
-		},
-		{
-			"not connected",
-			&types.DistributedVirtualSwitchPortCriteria{
-				Connected: types.NewBool(false),
-			},
-			[]types.DistributedVirtualPort{
-				{PortgroupKey: pgs[0].Value, Key: "0"},
-				{PortgroupKey: pgs[1].Value, Key: "0"},
-			},
-		},
-	}
-
-	for _, test := range tests {
-		t.Run(test.name, func(t *testing.T) {
-			actual, err := dvs0.FetchDVPorts(context.TODO(), test.criteria)
-
-			if err != nil {
-				t.Fatal(err)
-			}
-
-			if len(actual) != len(test.expected) {
-				t.Fatalf("expected %d ports; got %d", len(test.expected), len(actual))
-			}
-
-			for i, p := range actual {
-				if p.Key != test.expected[i].Key {
-					t.Errorf("ports[%d]: expected Key `%s`; got `%s`",
-						i, test.expected[i].Key, p.Key)
-				}
-
-				if p.PortgroupKey != test.expected[i].PortgroupKey {
-					t.Errorf("ports[%d]: expected PortgroupKey `%s`; got `%s`",
-						i, test.expected[i].PortgroupKey, p.PortgroupKey)
-				}
-			}
-		})
-	}
-}
diff --git a/simulator/folder_test.go b/simulator/folder_test.go
index c898fbc9..a84c7c64 100644
--- a/simulator/folder_test.go
+++ b/simulator/folder_test.go
@@ -26,7 +26,6 @@ import (
 	"github.com/vmware/govmomi/object"
 	"github.com/vmware/govmomi/simulator/esx"
 	"github.com/vmware/govmomi/simulator/vpx"
-	"github.com/vmware/govmomi/vim25"
 	"github.com/vmware/govmomi/vim25/methods"
 	"github.com/vmware/govmomi/vim25/mo"
 	"github.com/vmware/govmomi/vim25/soap"
@@ -215,50 +214,6 @@ func TestFolderVC(t *testing.T) {
 	}
 }
 
-func TestFolderSpecialCharaters(t *testing.T) {
-	content := vpx.ServiceContent
-	s := New(NewServiceInstance(SpoofContext(), content, vpx.RootFolder))
-
-	ts := s.NewServer()
-	defer ts.Close()
-
-	ctx := context.Background()
-	c, err := govmomi.NewClient(ctx, ts.URL, true)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	f := object.NewRootFolder(c.Client)
-
-	tests := []struct {
-		name     string
-		expected string
-	}{
-		{`/`, `%2f`},
-		{`\`, `%5c`},
-		{`%`, `%25`},
-		// multiple special characters
-		{`%%`, `%25%25`},
-	}
-
-	for _, test := range tests {
-		ff, err := f.CreateFolder(ctx, test.name)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		o := Map.Get(ff.Reference())
-		if o == nil {
-			t.Fatalf("failed to find %#v", ff)
-		}
-
-		e := o.(mo.Entity).Entity()
-		if e.Name != test.expected {
-			t.Errorf("expected %s, got %s", test.expected, e.Name)
-		}
-	}
-}
-
 func TestFolderFaults(t *testing.T) {
 	f := Folder{}
 	f.ChildType = []string{"VirtualMachine"}
@@ -609,39 +564,3 @@ func TestFolderCreateDVS(t *testing.T) {
 		t.Error("expected error")
 	}
 }
-
-func TestPlaceVmsXCluster(t *testing.T) {
-	vpx := VPX()
-	vpx.Cluster = 3
-
-	Test(func(ctx context.Context, c *vim25.Client) {
-		finder := find.NewFinder(c, false)
-
-		spec := types.PlaceVmsXClusterSpec{}
-
-		pools, err := finder.ResourcePoolList(ctx, "/DC0/host/DC0_C*/*")
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		for _, pool := range pools {
-			spec.ResourcePools = append(spec.ResourcePools, pool.Reference())
-		}
-
-		spec.VmPlacementSpecs = []types.PlaceVmsXClusterSpecVmPlacementSpec{{
-			ConfigSpec: types.VirtualMachineConfigSpec{
-				Name: "test-vm",
-			},
-		}}
-
-		folder := object.NewRootFolder(c)
-		res, err := folder.PlaceVmsXCluster(ctx, spec)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		if len(res.PlacementInfos) != len(spec.VmPlacementSpecs) {
-			t.Errorf("%d PlacementInfos vs %d VmPlacementSpecs", len(res.PlacementInfos), len(spec.VmPlacementSpecs))
-		}
-	}, vpx)
-}
diff --git a/sts/client_test.go b/sts/client_test.go
index 3b49b1ad..03014039 100644
--- a/sts/client_test.go
+++ b/sts/client_test.go
@@ -30,7 +30,6 @@ import (
 	"github.com/vmware/govmomi/session"
 	"github.com/vmware/govmomi/ssoadmin"
 	"github.com/vmware/govmomi/ssoadmin/types"
-	"github.com/vmware/govmomi/vapi/rest"
 	"github.com/vmware/govmomi/vim25"
 	"github.com/vmware/govmomi/vim25/methods"
 	"github.com/vmware/govmomi/vim25/soap"
@@ -123,7 +122,6 @@ func TestIssueHOK(t *testing.T) {
 	if err != nil {
 		log.Fatal(err)
 	}
-	_ = c.UseServiceVersion()
 
 	if !c.IsVC() {
 		t.SkipNow()
@@ -161,81 +159,6 @@ func TestIssueHOK(t *testing.T) {
 	}
 
 	log.Printf("current time=%s", now)
-
-	rc := rest.NewClient(c)
-	err = rc.LoginByToken(rc.WithSigner(ctx, s))
-	if err != nil {
-		t.Fatal(err)
-	}
-}
-
-func TestIssueTokenByToken(t *testing.T) {
-	ctx := context.Background()
-	url := os.Getenv("GOVC_TEST_URL")
-	if url == "" {
-		t.SkipNow()
-	}
-
-	u, err := soap.ParseURL(url)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	vc1, err := vim25.NewClient(ctx, soap.NewClient(u, true))
-	if err != nil {
-		log.Fatal(err)
-	}
-	_ = vc1.UseServiceVersion()
-
-	if !vc1.IsVC() {
-		t.SkipNow()
-	}
-
-	vc2, err := vim25.NewClient(ctx, soap.NewClient(u, true))
-	if err != nil {
-		log.Fatal(err)
-	}
-	_ = vc2.UseServiceVersion()
-
-	sts1, err := NewClient(ctx, vc1)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if err = solutionUserCreate(ctx, u.User, sts1, vc1); err != nil {
-		t.Fatal(err)
-	}
-
-	sts2, err := NewClient(ctx, vc2)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	req1 := TokenRequest{
-		Certificate: solutionUserCert(),
-		Delegatable: true,
-	}
-
-	signer1, err := sts1.Issue(ctx, req1)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	req2 := signer1.NewRequest()
-	// use Assertion header instead of BinarySecurityToken
-	req2.Certificate = &tls.Certificate{PrivateKey: req1.Certificate.PrivateKey}
-
-	signer2, err := sts2.Issue(ctx, req2)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	header := soap.Header{Security: signer2}
-
-	err = session.NewManager(vc2).LoginByToken(vc2.WithHeader(ctx, header))
-	if err != nil {
-		t.Fatal(err)
-	}
 }
 
 func TestIssueBearer(t *testing.T) {
@@ -254,7 +177,6 @@ func TestIssueBearer(t *testing.T) {
 	if err != nil {
 		log.Fatal(err)
 	}
-	_ = c.UseServiceVersion()
 
 	if !c.IsVC() {
 		t.SkipNow()
@@ -311,7 +233,6 @@ func TestIssueActAs(t *testing.T) {
 	if err != nil {
 		log.Fatal(err)
 	}
-	_ = c.UseServiceVersion()
 
 	if !c.IsVC() {
 		t.SkipNow()
diff --git a/sts/signer_test.go b/sts/signer_test.go
index 6acacc51..f857b612 100644
--- a/sts/signer_test.go
+++ b/sts/signer_test.go
@@ -140,20 +140,3 @@ func TestSigner(t *testing.T) {
 		t.Fatal(err)
 	}
 }
-
-func TestIsIPv6(t *testing.T) {
-	tests := []struct {
-		ip string
-		v6 bool
-	}{
-		{"0:0:0:0:0:0:0:1", true},
-		{"10.0.0.42", false},
-	}
-
-	for _, test := range tests {
-		v6 := isIPv6(test.ip)
-		if v6 != test.v6 {
-			t.Errorf("%s: expected %t, got %t", test.ip, test.v6, v6)
-		}
-	}
-}
diff --git a/vapi/rest/resource_test.go b/vapi/rest/resource_test.go
index 5ee40d66..31778321 100644
--- a/vapi/rest/resource_test.go
+++ b/vapi/rest/resource_test.go
@@ -51,34 +51,3 @@ func TestResource_WithParam(t *testing.T) {
 		}
 	})
 }
-
-func TestResource_WithPathEncodedParam(t *testing.T) {
-	simulator.Test(func(ctx context.Context, vc *vim25.Client) {
-		c := rest.NewClient(vc)
-
-		// path is correctly formatted when Path-Encoded param is first
-		url := c.Resource("api/some/resource").
-			WithPathEncodedParam("key1", "value 1")
-		expectedPath := "api/some/resource?key1=value%201"
-		if !strings.Contains(url.String(), expectedPath) {
-			t.Errorf("First path-encoded param incorrectly added to resource, URL %q, expected path %q", url.String(), expectedPath)
-		}
-
-		// path is correctly formatted when Path-Encoded param is last
-		url = c.Resource("api/some/resource").
-			WithParam("key1", "value 1").
-			WithPathEncodedParam("key2", "value 2")
-		expectedPath = "api/some/resource?key1=value+1&key2=value%202"
-		if !strings.Contains(url.String(), expectedPath) {
-			t.Errorf("Last path-encoded param incorrectly added to resource, URL %q, expected path %q", url.String(), expectedPath)
-		}
-
-		// if WithParam is used again, it will re-encode the Path-Encoded value
-		url = url.WithParam("key3", "value 3")
-		expectedPath = "api/some/resource?key1=value+1&key2=value+2&key3=value+3"
-		if !strings.Contains(url.String(), expectedPath) {
-			t.Errorf("Middle path-encoded param not endcoded as expected, URL %q, expected path %q", url.String(), expectedPath)
-		}
-
-	})
-}
diff --git a/vapi/tags/categories_test.go b/vapi/tags/categories_test.go
deleted file mode 100644
index 66494856..00000000
--- a/vapi/tags/categories_test.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package tags
-
-import (
-	"context"
-	"fmt"
-	"net/http"
-	"strings"
-	"testing"
-
-	"github.com/vmware/govmomi/simulator"
-	"github.com/vmware/govmomi/vapi/rest"
-	"github.com/vmware/govmomi/vim25"
-)
-
-func TestManager_GetCategories(t *testing.T) {
-	simulator.Run(func(ctx context.Context, client *vim25.Client) error {
-		rc := rest.NewClient(client)
-
-		tr := testRoundTripper{
-			t:         t,
-			transport: rc.Client.Client.Transport,
-		}
-		rc.Client.Client.Transport = &tr
-
-		err := rc.Login(ctx, simulator.DefaultLogin)
-		if err != nil {
-			t.Fatalf("VAPI login: %v", err)
-		}
-
-		tm := NewManager(rc)
-
-		// categories to createCount and (concurrently) delete while retrieving categories
-		const (
-			createCount = 5
-			deleteCount = 2
-		)
-
-		var created []string
-		for i := 1; i <= createCount; i++ {
-			cat, err := tm.CreateCategory(ctx, &Category{
-				Name: fmt.Sprintf("testcat-%d", i),
-			})
-			if err != nil {
-				t.Fatalf("createCount category: %v", err)
-			}
-			created = append(created, cat)
-		}
-
-		for i := 0; i < deleteCount; i++ {
-			tr.deleted = append(tr.deleted, created[i])
-		}
-
-		got, err := tm.GetCategories(ctx)
-		if err != nil {
-			t.Fatalf("get categories: %v", err)
-		}
-
-		if len(got) != createCount-deleteCount {
-			t.Errorf("category count mismatch: got=%d, want=%d", len(got), createCount-deleteCount)
-		}
-
-		return nil
-	})
-}
-
-// testRoundTripper returns 404 for all categories in deleted
-type testRoundTripper struct {
-	t *testing.T
-
-	deleted   []string
-	transport http.RoundTripper
-}
-
-func (tr *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
-	for _, id := range tr.deleted {
-		if strings.Contains(req.URL.Path, id) {
-			return &http.Response{
-				StatusCode: http.StatusNotFound,
-				Status:     http.StatusText(http.StatusNotFound),
-				Body:       nil,
-				Request:    req.Clone(context.Background()),
-			}, nil
-		}
-	}
-
-	return tr.transport.RoundTrip(req)
-}
diff --git a/vim25/debug/debug_test.go b/vim25/debug/debug_test.go
deleted file mode 100644
index 2c36fead..00000000
--- a/vim25/debug/debug_test.go
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
-   Copyright (c) 2022 VMware, Inc. All Rights Reserved.
-
-   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 debug_test
-
-import (
-	"context"
-	"net/http"
-	"sync"
-	"testing"
-
-	"github.com/vmware/govmomi/find"
-	"github.com/vmware/govmomi/simulator"
-	"github.com/vmware/govmomi/vapi/rest"
-	"github.com/vmware/govmomi/vim25"
-	"github.com/vmware/govmomi/vim25/debug"
-
-	_ "github.com/vmware/govmomi/vapi/simulator"
-)
-
-func TestSetProvider(t *testing.T) {
-	p := debug.FileProvider{
-		Path: t.TempDir(),
-	}
-	debug.SetProvider(&p)
-
-	simulator.Test(func(ctx context.Context, c *vim25.Client) {
-		var wg sync.WaitGroup
-		rc := rest.NewClient(c)
-
-		// hit the debug package with some concurrency (see PR #2469)
-		for i := 0; i < 5; i++ {
-			wg.Add(1)
-			go func() {
-				defer wg.Done()
-				finder := find.NewFinder(c)
-
-				_, err := finder.VirtualMachineList(ctx, "*")
-				if err != nil {
-					t.Error(err)
-				}
-			}()
-		}
-
-		wg.Wait()
-
-		// send an http request with a nil Body to ensure debug trace doesn't panic in this case
-		u := rc.URL().String() + "/com/vmware/cis/session"
-
-		req, err := http.NewRequest(http.MethodPost, u, nil)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		req.SetBasicAuth("user", "pass")
-		var id string
-		if err = rc.Do(ctx, req, &id); err != nil {
-			t.Fatal(err)
-		}
-	})
-}
diff --git a/vsan/client_test.go b/vsan/client_test.go
index cb3326b4..68408d14 100644
--- a/vsan/client_test.go
+++ b/vsan/client_test.go
@@ -20,7 +20,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi"
 	"github.com/vmware/govmomi/find"
diff --git a/vslm/client_test.go b/vslm/client_test.go
index 12aaa938..2814dd16 100644
--- a/vslm/client_test.go
+++ b/vslm/client_test.go
@@ -20,7 +20,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/dougm/pretty"
+	"github.com/kr/pretty"
 
 	"github.com/vmware/govmomi"
 	"github.com/vmware/govmomi/cns"