Repository: vmware/govmomi
Pull request #2205 (2020-12-11 09:08:31)

Add function to get vsan host config
VsanHostConfigInfoEx is a property of HostVsanSystem in "vsan" namespace, which is an extension of vim25types.VsanHostConfigInfo.
Adding function to retrieve this property from given vsanSystem.


Patch:
diff --git a/cns/client.go b/cns/client.go
index e43d0fac..d680eff6 100644
--- a/cns/client.go
+++ b/cns/client.go
@@ -192,16 +192,3 @@ func (c *Client) RelocateVolume(ctx context.Context, relocateSpecs ...cnstypes.B
 	}
 	return object.NewTask(c.vim25Client, res.Returnval), nil
 }
-
-// ConfigureVolumeACLs calls the CNS Configure ACL API.
-func (c *Client) ConfigureVolumeACLs(ctx context.Context, aclConfigSpecs ...cnstypes.CnsVolumeACLConfigureSpec) (*object.Task, error) {
-	req := cnstypes.CnsConfigureVolumeACLs{
-		This:           CnsVolumeManagerInstance,
-		ACLConfigSpecs: aclConfigSpecs,
-	}
-	res, err := methods.CnsConfigureVolumeACLs(ctx, c.serviceClient, &req)
-	if err != nil {
-		return nil, err
-	}
-	return object.NewTask(c.vim25Client, res.Returnval), nil
-}
diff --git a/cns/methods/methods.go b/cns/methods/methods.go
index 9daecdc7..567f21e6 100644
--- a/cns/methods/methods.go
+++ b/cns/methods/methods.go
@@ -220,23 +220,3 @@ func CnsRelocateVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsR
 
 	return resBody.Res, nil
 }
-
-type CnsConfigureVolumeACLsBody struct {
-	Req    *types.CnsConfigureVolumeACLs         `xml:"urn:vsan CnsConfigureVolumeACLs,omitempty"`
-	Res    *types.CnsConfigureVolumeACLsResponse `xml:"urn:vsan CnsConfigureVolumeACLsResponse,omitempty"`
-	Fault_ *soap.Fault                           `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
-}
-
-func (b *CnsConfigureVolumeACLsBody) Fault() *soap.Fault { return b.Fault_ }
-
-func CnsConfigureVolumeACLs(ctx context.Context, r soap.RoundTripper, req *types.CnsConfigureVolumeACLs) (*types.CnsConfigureVolumeACLsResponse, error) {
-	var reqBody, resBody CnsConfigureVolumeACLsBody
-
-	reqBody.Req = req
-
-	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
-		return nil, err
-	}
-
-	return resBody.Res, nil
-}
diff --git a/cns/types/types.go b/cns/types/types.go
index 40c75742..905fbf0b 100644
--- a/cns/types/types.go
+++ b/cns/types/types.go
@@ -594,46 +594,3 @@ type CnsAlreadyRegisteredFault struct {
 func init() {
 	types.Add("CnsAlreadyRegisteredFault", reflect.TypeOf((*CnsAlreadyRegisteredFault)(nil)).Elem())
 }
-
-type CnsConfigureVolumeACLs CnsConfigureVolumeACLsRequestType
-
-func init() {
-	types.Add("vsan:CnsConfigureVolumeACLs", reflect.TypeOf((*CnsConfigureVolumeACLs)(nil)).Elem())
-}
-
-type CnsConfigureVolumeACLsRequestType struct {
-	This           types.ManagedObjectReference `xml:"_this"`
-	ACLConfigSpecs []CnsVolumeACLConfigureSpec  `xml:"ACLConfigSpecs"`
-}
-
-func init() {
-	types.Add("vsan:CnsConfigureVolumeACLsRequestType", reflect.TypeOf((*CnsConfigureVolumeACLsRequestType)(nil)).Elem())
-}
-
-type CnsConfigureVolumeACLsResponse struct {
-	Returnval types.ManagedObjectReference `xml:"returnval"`
-}
-
-type CnsVolumeACLConfigureSpec struct {
-	types.DynamicData
-
-	VolumeId              CnsVolumeId                `xml:"volumeId"`
-	AccessControlSpecList []BaseCnsAccessControlSpec `xml:"accessControlSpecList,typeattr"`
-}
-
-func init() {
-	types.Add("vsan:CnsVolumeACLConfigureSpec", reflect.TypeOf((*CnsVolumeACLConfigureSpec)(nil)).Elem())
-}
-func (b *CnsAccessControlSpec) GetCnsAccessControlSpec() *CnsAccessControlSpec { return b }
-
-type BaseCnsAccessControlSpec interface {
-	GetCnsAccessControlSpec() *CnsAccessControlSpec
-}
-
-type CnsAccessControlSpec struct {
-	types.DynamicData
-}
-
-func init() {
-	types.Add("vsan:CnsAccessControlSpec", reflect.TypeOf((*CnsAccessControlSpec)(nil)).Elem())
-}
diff --git a/govc/USAGE.md b/govc/USAGE.md
index f08548af..0f1d6a65 100644
--- a/govc/USAGE.md
+++ b/govc/USAGE.md
@@ -287,7 +287,6 @@ but appear via `govc $cmd -h`:
  - [vm.disk.create](#vmdiskcreate)
  - [vm.guest.tools](#vmguesttools)
  - [vm.info](#vminfo)
- - [vm.instantclone](#vminstantclone)
  - [vm.ip](#vmip)
  - [vm.keystrokes](#vmkeystrokes)
  - [vm.markastemplate](#vmmarkastemplate)
@@ -4831,50 +4830,6 @@ Options:
   -waitip=false          Wait for VM to acquire IP address
 ```
 
-## vm.instantclone
-
-```
-Usage: govc vm.instantclone [OPTIONS] NAME
-
-Instant Clone VM to NAME. 
-
-Examples:
-  govc vm.instantclone -vm source-vm new-vm
-  # Configure ExtraConfig variables on a guest VM:
-  govc vm.instantclone -vm source-vm -e guestinfo.ipaddress=192.168.0.1 -e guestinfo.netmask=255.255.255.0 new-vm
-  # Read the variable set above inside the guest:
-  vmware-rpctool "info-get guestinfo.ipaddress"
-  vmware-rpctool "info-get guestinfo.netmask"
-
-Options:
-  -cert=                 Certificate [GOVC_CERTIFICATE]
-  -dc=                   Datacenter [GOVC_DATACENTER]
-  -debug=false           Store debug logs [GOVC_DEBUG]
-  -ds=                   Datastore [GOVC_DATASTORE]
-  -dump=false            Enable Go output
-  -e=[]                  ExtraConfig. <key>=<value>
-  -folder=               Inventory folder [GOVC_FOLDER]
-  -json=false            Enable JSON output
-  -k=false               Skip verification of server certificate [GOVC_INSECURE]
-  -key=                  Private key [GOVC_PRIVATE_KEY]
-  -net=                  Network [GOVC_NETWORK]
-  -net.adapter=e1000     Network adapter type
-  -net.address=          Network hardware address
-  -persist-session=true  Persist session to disk [GOVC_PERSIST_SESSION]
-  -pool=                 Resource pool [GOVC_RESOURCE_POOL]
-  -tls-ca-certs=         TLS CA certificates file [GOVC_TLS_CA_CERTS]
-  -tls-known-hosts=      TLS known hosts file [GOVC_TLS_KNOWN_HOSTS]
-  -u=                    ESX or vCenter URL [GOVC_URL]
-  -vim-namespace=vim25   Vim namespace [GOVC_VIM_NAMESPACE]
-  -vim-version=6.7       Vim version [GOVC_VIM_VERSION]
-  -vm=                   Virtual machine [GOVC_VM]
-  -vm.dns=               Find VM by FQDN
-  -vm.ip=                Find VM by IP address
-  -vm.ipath=             Find VM by inventory path
-  -vm.path=              Find VM by path to .vmx file
-  -vm.uuid=              Find VM by UUID
-```
-
 ## vm.ip
 
 ```
diff --git a/govc/flags/datastore.go b/govc/flags/datastore.go
index 8030a6e0..bbe7e8c7 100644
--- a/govc/flags/datastore.go
+++ b/govc/flags/datastore.go
@@ -76,10 +76,6 @@ func (f *DatastoreFlag) Process(ctx context.Context) error {
 	})
 }
 
-func (flag *DatastoreFlag) IsSet() bool {
-	return flag.Name != ""
-}
-
 func (f *DatastoreFlag) Args(args []string) []object.DatastorePath {
 	var files []object.DatastorePath
 
diff --git a/govc/flags/folder.go b/govc/flags/folder.go
index da17bfa7..a84266a8 100644
--- a/govc/flags/folder.go
+++ b/govc/flags/folder.go
@@ -67,10 +67,6 @@ func (flag *FolderFlag) Process(ctx context.Context) error {
 	})
 }
 
-func (flag *FolderFlag) IsSet() bool {
-	return flag.name != ""
-}
-
 func (flag *FolderFlag) Folder() (*object.Folder, error) {
 	if flag.folder != nil {
 		return flag.folder, nil
diff --git a/govc/flags/resource_pool.go b/govc/flags/resource_pool.go
index b3d87b71..e60b5ee3 100644
--- a/govc/flags/resource_pool.go
+++ b/govc/flags/resource_pool.go
@@ -68,10 +68,6 @@ func (flag *ResourcePoolFlag) Process(ctx context.Context) error {
 	})
 }
 
-func (flag *ResourcePoolFlag) IsSet() bool {
-	return flag.name != ""
-}
-
 func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) {
 	if flag.pool != nil {
 		return flag.pool, nil
diff --git a/govc/vm/instantclone.go b/govc/vm/instantclone.go
deleted file mode 100644
index de52e074..00000000
--- a/govc/vm/instantclone.go
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
-Copyright (c) 2014-2016 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 vm
-
-import (
-	"context"
-	"flag"
-	"fmt"
-
-	"github.com/vmware/govmomi/govc/cli"
-	"github.com/vmware/govmomi/govc/flags"
-	"github.com/vmware/govmomi/object"
-	"github.com/vmware/govmomi/vim25"
-	"github.com/vmware/govmomi/vim25/types"
-)
-
-type instantclone struct {
-	*flags.ClientFlag
-	*flags.DatacenterFlag
-	*flags.DatastoreFlag
-	*flags.ResourcePoolFlag
-	*flags.NetworkFlag
-	*flags.FolderFlag
-	*flags.VirtualMachineFlag
-
-	name        string
-	extraConfig extraConfig
-
-	Client         *vim25.Client
-	Datacenter     *object.Datacenter
-	Datastore      *object.Datastore
-	ResourcePool   *object.ResourcePool
-	Folder         *object.Folder
-	VirtualMachine *object.VirtualMachine
-}
-
-func init() {
-	cli.Register("vm.instantclone", &instantclone{})
-}
-
-func (cmd *instantclone) Register(ctx context.Context, f *flag.FlagSet) {
-	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
-	cmd.ClientFlag.Register(ctx, f)
-
-	cmd.DatacenterFlag, ctx = flags.NewDatacenterFlag(ctx)
-	cmd.DatacenterFlag.Register(ctx, f)
-
-	cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
-	cmd.DatastoreFlag.Register(ctx, f)
-
-	cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx)
-	cmd.ResourcePoolFlag.Register(ctx, f)
-
-	cmd.NetworkFlag, ctx = flags.NewNetworkFlag(ctx)
-	cmd.NetworkFlag.Register(ctx, f)
-
-	cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx)
-	cmd.FolderFlag.Register(ctx, f)
-
-	cmd.VirtualMachineFlag, ctx = flags.NewVirtualMachineFlag(ctx)
-	cmd.VirtualMachineFlag.Register(ctx, f)
-
-	f.Var(&cmd.extraConfig, "e", "ExtraConfig. <key>=<value>")
-}
-
-func (cmd *instantclone) Usage() string {
-	return "NAME"
-}
-
-func (cmd *instantclone) Description() string {
-	return `Instant Clone VM to NAME. 
-
-Examples:
-  govc vm.instantclone -vm source-vm new-vm
-  # Configure ExtraConfig variables on a guest VM:
-  govc vm.instantclone -vm source-vm -e guestinfo.ipaddress=192.168.0.1 -e guestinfo.netmask=255.255.255.0 new-vm
-  # Read the variable set above inside the guest:
-  vmware-rpctool "info-get guestinfo.ipaddress"
-  vmware-rpctool "info-get guestinfo.netmask"`
-}
-
-func (cmd *instantclone) Process(ctx context.Context) error {
-	if err := cmd.ClientFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.DatacenterFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.DatastoreFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.ResourcePoolFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.NetworkFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.FolderFlag.Process(ctx); err != nil {
-		return err
-	}
-	if err := cmd.VirtualMachineFlag.Process(ctx); err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (cmd *instantclone) Run(ctx context.Context, f *flag.FlagSet) error {
-	var err error
-
-	if len(f.Args()) != 1 {
-		return flag.ErrHelp
-	}
-
-	cmd.name = f.Arg(0)
-	if cmd.name == "" {
-		return flag.ErrHelp
-	}
-
-	cmd.Client, err = cmd.ClientFlag.Client()
-	if err != nil {
-		return err
-	}
-
-	cmd.Datacenter, err = cmd.DatacenterFlag.Datacenter()
-	if err != nil {
-		return err
-	}
-
-	cmd.Datastore, err = cmd.DatastoreFlag.Datastore()
-	if err != nil {
-		return err
-	}
-
-	cmd.Folder, err = cmd.FolderFlag.Folder()
-	if err != nil {
-		return err
-	}
-
-	cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool()
-	if err != nil {
-		return err
-	}
-
-	cmd.VirtualMachine, err = cmd.VirtualMachineFlag.VirtualMachine()
-	if err != nil {
-		return err
-	}
-
-	if cmd.VirtualMachine == nil {
-		return flag.ErrHelp
-	}
-
-	_, err = cmd.instantcloneVM(ctx)
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func (cmd *instantclone) instantcloneVM(ctx context.Context) (*object.VirtualMachine, error) {
-	relocateSpec := types.VirtualMachineRelocateSpec{}
-
-	if cmd.NetworkFlag.IsSet() {
-		devices, err := cmd.VirtualMachine.Device(ctx)
-		if err != nil {
-			return nil, err
-		}
-
-		// prepare virtual device config spec for network card
-		configSpecs := []types.BaseVirtualDeviceConfigSpec{}
-
-		op := types.VirtualDeviceConfigSpecOperationAdd
-		card, derr := cmd.NetworkFlag.Device()
-		if derr != nil {
-			return nil, derr
-		}
-		// search for the first network card of the source
-		for _, device := range devices {
-			if _, ok := device.(types.BaseVirtualEthernetCard); ok {
-				op = types.VirtualDeviceConfigSpecOperationEdit
-				// set new backing info
-				cmd.NetworkFlag.Change(device, card)
-				card = device
-				break
-			}
-		}
-
-		configSpecs = append(configSpecs, &types.VirtualDeviceConfigSpec{
-			Operation: op,
-			Device:    card,
-		})
-
-		relocateSpec.DeviceChange = configSpecs
-	}
-
-	if cmd.FolderFlag.IsSet() {
-		folderref := cmd.Folder.Reference()
-		relocateSpec.Folder = &folderref
-	}
-
-	if cmd.ResourcePoolFlag.IsSet() {
-		poolref := cmd.ResourcePool.Reference()
-		relocateSpec.Pool = &poolref
-	}
-
-	if cmd.DatastoreFlag.IsSet() {
-		datastoreref := cmd.Datastore.Reference()
-		relocateSpec.Datastore = &datastoreref
-	}
-
-	instantcloneSpec := &types.VirtualMachineInstantCloneSpec{
-		Name:     cmd.name,
-		Location: relocateSpec,
-	}
-
-	if len(cmd.extraConfig) > 0 {
-		instantcloneSpec.Config = cmd.extraConfig
-	}
-
-	task, err := cmd.VirtualMachine.InstantClone(ctx, *instantcloneSpec)
-	if err != nil {
-		return nil, err
-	}
-
-	logger := cmd.ProgressLogger(fmt.Sprintf("Instant Cloning %s to %s...", cmd.VirtualMachine.InventoryPath, cmd.name))
-	defer logger.Wait()
-
-	info, err := task.WaitForResult(ctx, logger)
-	if err != nil {
-		return nil, err
-	}
-
-	return object.NewVirtualMachine(cmd.Client, info.Result.(types.ManagedObjectReference)), nil
-}
diff --git a/govc/volume/ls.go b/govc/volume/ls.go
index f12c8685..4785149a 100644
--- a/govc/volume/ls.go
+++ b/govc/volume/ls.go
@@ -29,12 +29,10 @@ import (
 	"github.com/vmware/govmomi/govc/cli"
 	"github.com/vmware/govmomi/govc/flags"
 	"github.com/vmware/govmomi/units"
-	vim "github.com/vmware/govmomi/vim25/types"
 )
 
 type ls struct {
 	*flags.ClientFlag
-	*flags.DatastoreFlag
 	*flags.OutputFlag
 
 	types.CnsQueryFilter
@@ -52,9 +50,6 @@ func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
 	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
 	cmd.ClientFlag.Register(ctx, f)
 
-	cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx)
-	cmd.DatastoreFlag.Register(ctx, f)
-
 	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
 	cmd.OutputFlag.Register(ctx, f)
 
@@ -67,9 +62,6 @@ func (cmd *ls) Process(ctx context.Context) error {
 	if err := cmd.ClientFlag.Process(ctx); err != nil {
 		return err
 	}
-	if err := cmd.DatastoreFlag.Process(ctx); err != nil {
-		return err
-	}
 	return cmd.OutputFlag.Process(ctx)
 }
 
@@ -83,7 +75,6 @@ func (cmd *ls) Description() string {
 Examples:
   govc volume.ls
   govc volume.ls -l
-  govc volume.ls -ds vsanDatastore
   govc volume.ls df86393b-5ae0-4fca-87d0-b692dbc67d45
   govc disk.ls -l $(govc volume.ls -L pvc-9744a4ff-07f4-43c4-b8ed-48ea7a528734)`
 }
@@ -142,15 +133,6 @@ func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
 	}
 	_ = vc.UseServiceVersion("vsan")
 
-	ds, err := cmd.DatastoreIfSpecified()
-	if err != nil {
-		return err
-	}
-
-	if ds != nil {
-		cmd.Datastores = []vim.ManagedObjectReference{ds.Reference()}
-	}
-
 	c, err := cns.NewClient(ctx, vc)
 	if err != nil {
 		return err
diff --git a/object/virtual_machine.go b/object/virtual_machine.go
index 2f002280..d20d0e6d 100644
--- a/object/virtual_machine.go
+++ b/object/virtual_machine.go
@@ -181,20 +181,6 @@ func (v VirtualMachine) Clone(ctx context.Context, folder *Folder, name string,
 	return NewTask(v.c, res.Returnval), nil
 }
 
-func (v VirtualMachine) InstantClone(ctx context.Context, config types.VirtualMachineInstantCloneSpec) (*Task, error) {
-	req := types.InstantClone_Task{
-		This: v.Reference(),
-		Spec: config,
-	}
-
-	res, err := methods.InstantClone_Task(ctx, v.c, &req)
-	if err != nil {
-		return nil, err
-	}
-
-	return NewTask(v.c, res.Returnval), nil
-}
-
 func (v VirtualMachine) Customize(ctx context.Context, spec types.CustomizationSpec) (*Task, error) {
 	req := types.CustomizeVM_Task{
 		This: v.Reference(),
diff --git a/simulator/container.go b/simulator/container.go
index e1656660..e0298980 100644
--- a/simulator/container.go
+++ b/simulator/container.go
@@ -226,11 +226,7 @@ func (c *container) start(vm *VirtualMachine) {
 	cmd := exec.Command(shell, "-c", strings.Join(args, " "))
 	out, err := cmd.Output()
 	if err != nil {
-		stderr := ""
-		if xerr, ok := err.(*exec.ExitError); ok {
-			stderr = string(xerr.Stderr)
-		}
-		log.Printf("%s %s: %s %s", vm.Name, cmd.Args, err, stderr)
+		log.Printf("%s %s: %s", vm.Name, cmd.Args, err)
 		return
 	}
 
diff --git a/vsan/client.go b/vsan/client.go
index 91b55337..36869d2f 100644
--- a/vsan/client.go
+++ b/vsan/client.go
@@ -18,6 +18,7 @@ package vsan
 
 import (
 	"context"
+	"errors"
 
 	"github.com/vmware/govmomi/vim25"
 	"github.com/vmware/govmomi/vim25/soap"
@@ -42,18 +43,27 @@ var (
 		Type:  "VsanPerformanceManager",
 		Value: "vsan-performance-manager",
 	}
+	VsanQueryObjectIdentitiesInstance = vimtypes.ManagedObjectReference{
+		Type:  "VsanObjectSystem",
+		Value: "vsan-cluster-object-system",
+	}
+	VsanPropertyCollectorInstance = vimtypes.ManagedObjectReference{
+		Type:  "PropertyCollector",
+		Value: "vsan-property-collector",
+	}
 )
 
 // Client used for accessing vsan health APIs.
 type Client struct {
-	vim25Client   *vim25.Client
-	serviceClient *soap.Client
+	*soap.Client
+
+	Vim25Client *vim25.Client
 }
 
 // NewClient creates a new VsanHealth client
 func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) {
 	sc := c.Client.NewServiceClient(Path, Namespace)
-	return &Client{c, sc}, nil
+	return &Client{sc, c}, nil
 }
 
 // VsanClusterGetConfig calls the Vsan health's VsanClusterGetConfig API.
@@ -63,7 +73,7 @@ func (c *Client) VsanClusterGetConfig(ctx context.Context, cluster vimtypes.Mana
 		Cluster: cluster,
 	}
 
-	res, err := methods.VsanClusterGetConfig(ctx, c.serviceClient, &req)
+	res, err := methods.VsanClusterGetConfig(ctx, c, &req)
 	if err != nil {
 		return nil, err
 	}
@@ -78,21 +88,13 @@ func (c *Client) VsanPerfQueryPerf(ctx context.Context, cluster *vimtypes.Manage
 		QuerySpecs: qSpecs,
 	}
 
-	res, err := methods.VsanPerfQueryPerf(ctx, c.serviceClient, &req)
+	res, err := methods.VsanPerfQueryPerf(ctx, c, &req)
 	if err != nil {
 		return nil, err
 	}
 	return res.Returnval, nil
 }
 
-// Creates the vsan object identities instance. This is to be queried from vsan health.
-var (
-	VsanQueryObjectIdentitiesInstance = vimtypes.ManagedObjectReference{
-		Type:  "VsanObjectSystem",
-		Value: "vsan-cluster-object-system",
-	}
-)
-
 // VsanQueryObjectIdentities return host uuid
 func (c *Client) VsanQueryObjectIdentities(ctx context.Context, cluster vimtypes.ManagedObjectReference) (*vsantypes.VsanObjectIdentityAndHealth, error) {
 	req := vsantypes.VsanQueryObjectIdentities{
@@ -100,12 +102,49 @@ func (c *Client) VsanQueryObjectIdentities(ctx context.Context, cluster vimtypes
 		Cluster: &cluster,
 	}
 
-	res, err := methods.VsanQueryObjectIdentities(ctx, c.serviceClient, &req)
+	res, err := methods.VsanQueryObjectIdentities(ctx, c, &req)
 
 	if err != nil {
 		return nil, err
 	}
 
 	return res.Returnval, nil
+}
+
+// VsanHostGetConfig returns the config of host's vSAN system.
+func (c *Client) VsanHostGetConfig(ctx context.Context, vsanSystem vimtypes.ManagedObjectReference) (*vsantypes.VsanHostConfigInfoEx, error) {
+	req := vimtypes.RetrievePropertiesEx{
+		SpecSet: []vimtypes.PropertyFilterSpec{{
+			ObjectSet: []vimtypes.ObjectSpec{{
+				Obj: vsanSystem}},
+			PropSet: []vimtypes.PropertySpec{{
+				Type:    "HostVsanSystem",
+				PathSet: []string{"config"}}}}},
+		This: VsanPropertyCollectorInstance}
+
+	res, err := methods.RetrievePropertiesEx(ctx, c, &req)
+	if err != nil {
+		return nil, err
+	}
 
+	var property vimtypes.DynamicProperty
+	if res != nil && res.Returnval != nil {
+		for _, obj := range res.Returnval.Objects {
+			for _, prop := range obj.PropSet {
+				if prop.Name == "config" {
+					property = prop
+					break
+				}
+			}
+		}
+	}
+
+	switch cfg := property.Val.(type) {
+	case vimtypes.VsanHostConfigInfo:
+		return &vsantypes.VsanHostConfigInfoEx{VsanHostConfigInfo: cfg}, nil
+	case vsantypes.VsanHostConfigInfoEx:
+		return &cfg, nil
+	default:
+		return nil, errors.New("host vSAN config not found")
+	}
 }


Test patch:
diff --git a/vsan/client_test.go b/vsan/client_test.go
index 47091441..47c76e4c 100644
--- a/vsan/client_test.go
+++ b/vsan/client_test.go
@@ -51,7 +51,7 @@ func TestClient(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	finder := find.NewFinder(vsanHealthClient.vim25Client, false)
+	finder := find.NewFinder(vsanHealthClient.Vim25Client, false)
 	dc, err := finder.Datacenter(ctx, datacenter)
 	if err != nil {
 		t.Fatal(err)
@@ -80,6 +80,26 @@ func TestClient(t *testing.T) {
 	if isFileServiceEnabled {
 		t.Logf("Printing one of the clusterConfig where file service is enabled:\n %+v", pretty.Sprint(clusterConfigToPrint))
 	}
+
+	hosts, _ := finder.HostSystemList(ctx, "*")
+	if err != nil {
+		t.Logf("Error occurred while getting hostSystem %+v", err.Error())
+		t.Fatal(err)
+	}
+
+	for _, host := range hosts {
+		vsanSystem, _ := host.ConfigManager().VsanInternalSystem(ctx)
+		if err != nil {
+			t.Logf("Error occurred: %+v", err.Error())
+			t.Fatal(err)
+		}
+		hostConfig, err := vsanHealthClient.VsanHostGetConfig(ctx, vsanSystem.Reference())
+		if err != nil {
+			t.Logf("Error occurred: %+v", err.Error())
+			t.Fatal(err)
+		}
+		t.Logf("Printing hostConfig:\n %+s", pretty.Sprint(hostConfig))
+	}
 }
 
 func TestVsanQueryObjectIdentities(t *testing.T) {
@@ -105,7 +125,7 @@ func TestVsanQueryObjectIdentities(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	finder := find.NewFinder(vsanHealthClient.vim25Client, false)
+	finder := find.NewFinder(vsanHealthClient.Vim25Client, false)
 	dc, err := finder.Datacenter(ctx, datacenter)
 	if err != nil {
 		t.Fatal(err)