Repository: vmware/govmomi
Pull request #2080 (2020-08-07 11:27:37)

vSAN methods QueryVsanObjects and VsanQueryObjectIdentities has been added 
Added couple of vsan api interface which is required for my e2e-test automation

Testing Done:
go test -v

```
=== RUN   TestClient
--- PASS: TestClient (4.04s)
=== RUN   TestVsanQueryObjectIdentities
    TestVsanQueryObjectIdentities: client_test.go:128: Printing clusterConfig:
         &types.VsanObjectIdentityAndHealth{
            Health:       (*types.VsanObjectOverallHealth)(nil),
            Identities:   &types.VsanObjectIdentity{Uuid:"84c65a5f-46ed-c821-dedf-02005e6ac5d0"},
            RawData:      "",
            SpaceSummary: nil,
        }
--- PASS: TestVsanQueryObjectIdentities (4.71s)
PASS
ok      github.com/vmware/govmomi/vsan  8.770s
```

vmwclabot: @marunachalam, you must sign our contributor license agreement before your changes are merged. Click [here](https://cla.vmware.com/cla/32624a9bb1c745e8bde43619290d0cf2) to sign the agreement. If you are a VMware employee, read [this](https://cla.vmware.com/employee) for further instruction.
divyenpatel: @marunachalam Can you please squash all your commits.

I see you have not updated `vsan/client.go`. How are you planning to call these methods?

Can you share testing done for these methods? Can you implement some tests and add it to `vsan/client_test.go`.

marunachalam: > @marunachalam Can you please squash all your commits.
> 
> I see you have not updated `vsan/client.go`. How are you planning to call these methods?
> 
> Can you share testing done for these methods? Can you implement some tests and add it to `vsan/client_test.go`.

I have added the client and test methods

Test Result -

=== RUN   TestClient
--- PASS: TestClient (4.94s)
=== RUN   TestVsanQueryObjectIdentities
    TestVsanQueryObjectIdentities: client_test.go:128: Printing clusterConfig:
         &types.VsanObjectIdentityAndHealth{
            Health:       (*types.VsanObjectOverallHealth)(nil),
            Identities:   &types.VsanObjectIdentity{Uuid:"b004315f-d6d8-771f-8ef9-020055b45c1b"},
            RawData:      "",
            SpaceSummary: nil,
        }
--- PASS: TestVsanQueryObjectIdentities (6.29s)
=== RUN   TestQueryVsanObjects
    TestQueryVsanObjects: client_test.go:183: No vSAN objects found
--- PASS: TestQueryVsanObjects (5.36s)
PASS
ok      github.com/vmware/govmomi/vsan  16.622s






divyenpatel: @marunachalam Thanks for addressing all review comments. Can you please squash all commits in this PR?
marunachalam: > @marunachalam Thanks for addressing all review comments. Can you please squash all commits in this PR?

Thanks for looking into it @divyenpatel , I have squashed my commits.
divyenpatel: /lgtm
divyenpatel: @dougm Can you help review this PR?
vmwclabot: @marunachalam, your company's legal contact did not review your signed contributor license agreement within the 14 day limit. The merge can not proceed. Click [here](https://cla.vmware.com/cla/32624a9bb1c745e8bde43619290d0cf2) to resign the agreement.
divyenpatel: @marunachalam change looks good to me. Can you please squash all your commit?
divyenpatel: @marunachalam Can you add a test execution log in the PR description?
marunachalam: Testing Done:
go test -v
```
=== RUN   TestClient
--- PASS: TestClient (4.04s)
=== RUN   TestVsanQueryObjectIdentities
    TestVsanQueryObjectIdentities: client_test.go:128: Printing clusterConfig:
         &types.VsanObjectIdentityAndHealth{
            Health:       (*types.VsanObjectOverallHealth)(nil),
            Identities:   &types.VsanObjectIdentity{Uuid:"84c65a5f-46ed-c821-dedf-02005e6ac5d0"},
            RawData:      "",
            SpaceSummary: nil,
        }
--- PASS: TestVsanQueryObjectIdentities (4.71s)
PASS
ok      github.com/vmware/govmomi/vsan  8.770s
```

Patch:
diff --git a/vsan/client.go b/vsan/client.go
index 3648da29..6d50f7c7 100644
--- a/vsan/client.go
+++ b/vsan/client.go
@@ -84,3 +84,28 @@ func (c *Client) VsanPerfQueryPerf(ctx context.Context, cluster *vimtypes.Manage
 	}
 	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{
+		This:    VsanQueryObjectIdentitiesInstance,
+		Cluster: cluster,
+	}
+
+	res, err := methods.VsanQueryObjectIdentities(ctx, c.serviceClient, &req)
+
+	if err != nil {
+		return nil, err
+	}
+
+	return &res.Returnval, nil
+
+}
diff --git a/vsan/methods/methods.go b/vsan/methods/methods.go
index a94d5c5e..732c5961 100644
--- a/vsan/methods/methods.go
+++ b/vsan/methods/methods.go
@@ -44,6 +44,29 @@ func VsanPerfGetSupportedEntityTypes(ctx context.Context, r soap.RoundTripper, r
 	return resBody.Res, nil
 }
 
+//Object Identities
+
+type VsanQueryObjectIdentitiesBody struct {
+	Req    *types.VsanQueryObjectIdentities         `xml:"urn:vsan VsanQueryObjectIdentities,omitempty"`
+	Res    *types.VsanQueryObjectIdentitiesResponse `xml:"urn:vsan VsanQueryObjectIdentitiesResponse,omitempty"`
+	Fault_ *soap.Fault                              `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *VsanQueryObjectIdentitiesBody) Fault() *soap.Fault { return b.Fault_ }
+
+func VsanQueryObjectIdentities(ctx context.Context, r soap.RoundTripper, req *types.VsanQueryObjectIdentities) (*types.VsanQueryObjectIdentitiesResponse, error) {
+	var reqBody, resBody VsanQueryObjectIdentitiesBody
+
+	reqBody.Req = req
+
+	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+		return nil, err
+	}
+
+	return resBody.Res, nil
+
+}
+
 // Health summary
 type VsanQueryVcClusterHealthSummaryBody struct {
 	Req    *types.VsanQueryVcClusterHealthSummary         `xml:"urn:vsan VsanQueryVcClusterHealthSummary,omitempty"`
@@ -147,3 +170,23 @@ func VsanClusterGetConfig(ctx context.Context, r soap.RoundTripper, req *types.V
 
 	return resBody.Res, nil
 }
+
+type QueryVsanObjectsBody struct {
+	Req    *types.QueryVsanObjects         `xml:"urn:vsan QueryVsanObjects,omitempty"`
+	Res    *types.QueryVsanObjectsResponse `xml:"urn:vsan QueryVsanObjectsResponse,omitempty"`
+	Fault_ *soap.Fault                     `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"`
+}
+
+func (b *QueryVsanObjectsBody) Fault() *soap.Fault { return b.Fault_ }
+
+func QueryVsanObjects(ctx context.Context, r soap.RoundTripper, req *types.QueryVsanObjects) (*types.QueryVsanObjectsResponse, error) {
+	var reqBody, resBody QueryVsanObjectsBody
+
+	reqBody.Req = req
+
+	if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil {
+		return nil, err
+	}
+
+	return resBody.Res, nil
+}
diff --git a/vsan/types/types.go b/vsan/types/types.go
index 48c151fb..b950edd1 100644
--- a/vsan/types/types.go
+++ b/vsan/types/types.go
@@ -83,6 +83,52 @@ func init() {
 	t["VsanPerfThreshold"] = reflect.TypeOf((*VsanPerfThreshold)(nil)).Elem()
 }
 
+// Vsan Query Object Identies
+type VsanQueryObjectIdentities VsanQueryObjectIdentitiesRequestType
+
+func init() {
+	t["VsanQueryObjectIdentities"] = reflect.TypeOf((*VsanQueryObjectIdentities)(nil)).Elem()
+}
+
+type VsanQueryObjectIdentitiesRequestType struct {
+	This                types.ManagedObjectReference `xml:"_this"`
+	Cluster             types.ManagedObjectReference `xml:"cluster"`
+	ObjTypes            []string                     `xml:"objTypes,omitempty"`
+	ObjUuids            []string                     `xml:"objUuids,omitempty"`
+	IncludeObjIdentity  *bool                        `xml:"includeObjIdentity"`
+	IncludeHealth       *bool                        `xml:"includeHealth,omitempty"`
+	IncludeSpaceSummary *bool                        `xml:"includeSpaceSummary"`
+}
+
+func init() {
+	t["VsanQueryObjectIdentitiesRequestType"] = reflect.TypeOf((*VsanQueryObjectIdentitiesRequestType)(nil)).Elem()
+}
+
+type VsanQueryObjectIdentitiesResponse struct {
+	Returnval VsanObjectIdentityAndHealth `xml:"returnval"`
+}
+
+type VsanObjectIdentityAndHealth struct {
+	DynamicData
+
+	Health       *VsanObjectOverallHealth `xml:"health,omitempty"`
+	Identities   *VsanObjectIdentity      `xml:"identities,omitempty"`
+	RawData      string                   `xml:"rawData,omitempty"`
+	SpaceSummary []VsanObjectSpaceSummary `xml:"spaceSummary,omitempty"`
+}
+
+func init() {
+	t["VsanObjectIdentityAndHealth"] = reflect.TypeOf((*VsanObjectIdentityAndHealth)(nil)).Elem()
+}
+
+type VsanObjectIdentity struct {
+	Uuid string `xml:"uuid,omitempty"`
+}
+
+func init() {
+	t["VsanObjectIdentity"] = reflect.TypeOf((*VsanObjectIdentity)(nil)).Elem()
+}
+
 // Cluster health summary
 type VsanQueryVcClusterHealthSummary VsanQueryVcClusterHealthSummaryRequestType
 
@@ -1409,6 +1455,25 @@ type VsanClusterGetConfigResponse struct {
 	Returnval VsanConfigInfoEx `xml:"returnval"`
 }
 
+type QueryVsanObjectsRequestType struct {
+	This  types.ManagedObjectReference `xml:"_this"`
+	Uuids []string                     `xml:"uuids"`
+}
+
+func init() {
+	types.Add("QueryVsanObjecstRequestType", reflect.TypeOf((*QueryVsanObjectsRequestType)(nil)).Elem())
+}
+
+type QueryVsanObjects QueryVsanObjectsRequestType
+
+func init() {
+	types.Add("QueryVsanObjects", reflect.TypeOf((*QueryVsanObjects)(nil)).Elem())
+}
+
+type QueryVsanObjectsResponse struct {
+	Returnval string `xml:"returnval"`
+}
+
 type VsanConfigInfoEx struct {
 	VsanClusterConfigInfo
 


Test patch:
diff --git a/vsan/client_test.go b/vsan/client_test.go
index 6ba8852a..47091441 100644
--- a/vsan/client_test.go
+++ b/vsan/client_test.go
@@ -81,3 +81,51 @@ func TestClient(t *testing.T) {
 		t.Logf("Printing one of the clusterConfig where file service is enabled:\n %+v", pretty.Sprint(clusterConfigToPrint))
 	}
 }
+
+func TestVsanQueryObjectIdentities(t *testing.T) {
+	url := os.Getenv("VC_URL")            // example: export VC_URL='https://username:password@vc-ip/sdk'
+	datacenter := os.Getenv("DATACENTER") // example: export DATACENTER='name-of-datacenter'
+	if url == "" || datacenter == "" {
+		t.Skip("VC_URL or DATACENTER is not set")
+	}
+
+	u, err := soap.ParseURL(url)
+	if err != nil {
+		t.Fatal(err)
+	}
+	ctx := context.Background()
+
+	c, err := govmomi.NewClient(ctx, u, true)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	vsanHealthClient, err := NewClient(ctx, c.Client)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	finder := find.NewFinder(vsanHealthClient.vim25Client, false)
+	dc, err := finder.Datacenter(ctx, datacenter)
+	if err != nil {
+		t.Fatal(err)
+	}
+	finder.SetDatacenter(dc)
+
+	clusterComputeResource, err := finder.ClusterComputeResourceList(ctx, "*")
+
+	if err != nil {
+		t.Logf("Error occurred while getting clusterComputeResource %+v", err.Error())
+		t.Fatal(err)
+	}
+
+	for _, cluster := range clusterComputeResource {
+		clusterConfig, err := vsanHealthClient.VsanQueryObjectIdentities(ctx, cluster.Reference())
+		if err != nil {
+			t.Logf("Error occurred: %+v", err.Error())
+			t.Fatal(err)
+		}
+		t.Logf("Printing clusterConfig:\n %+s", pretty.Sprint(clusterConfig))
+	}
+
+}