Background: Im using govmomi for configuration collection for vmware. I'm currently in the process of getting the datastore info I require. One of the fields I need is the disk Naa. This can be found in the VmfsDatastoreInfo struct under the Vmfs field.
Issue: I am looping through a range and I believed Ds.Info to be of the VmfsDatastoreInfo type so in theory I could get the info I needed by going through Ds.Info.Vmfs. When I reference this I get the error:
ds.Info.Vmfs undefined (type types.BaseDatastoreInfo has no field or method Vmfs)
Out of curiosity I explored using reflection and did the following:
fmt.Println(reflect.TypeOf(ds.Info))
output was
*types.VmfsDatastoreInfo
Im trying to understand why the same object is showing as two different types?
Edit: Getting to ds :
c, err := govmomi.NewClient(ctx, u, true)
//Check if the connection was successful
if err != nil {
fmt.Println(err)
}
// Create view of Datastore objects
m := view.NewManager(c.Client)
d, _ := m.CreateContainerView(ctx, c.ServiceContent.RootFolder, []string{"Datastore"}, true)
if err != nil {
log.Fatal(err)
}
defer d.Destroy(ctx)
//Retrieve a list of all Virtual Machines including their summary and runtime
var dss []mo.Datastore
err = d.Retrieve(ctx, []string{"Datastore"}, []string{"info", "host"}, &dss)
if err != nil {
log.Fatal(err)
}
for _, ds := range dss {
fmt.Println(reflect.TypeOf(ds.Info))
s := reflect.ValueOf(ds.Info).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Println(i, typeOfT.Field(i).Name, f.Type(), f.Interface())
}
}
ds is a Datastore type :
type Datastore struct {
ManagedEntity
Info types.BaseDatastoreInfo `mo:"info"`
Summary types.DatastoreSummary `mo:"summary"`
Host []types.DatastoreHostMount `mo:"host"`
Vm []types.ManagedObjectReference `mo:"vm"`
Browser types.ManagedObjectReference `mo:"browser"`
Capability types.DatastoreCapability `mo:"capability"`
IormConfiguration *types.StorageIORMInfo `mo:"iormConfiguration"`
}
Following through the Govmomi package info I found the following
type BaseDatastoreInfo interface {
GetDatastoreInfo() *DatastoreInfo
}
func (b *DatastoreInfo) GetDatastoreInfo() *DatastoreInfo
type DatastoreInfo struct {
DynamicData
Name string `xml:"name"`
Url string `xml:"url"`
FreeSpace int64 `xml:"freeSpace"`
MaxFileSize int64 `xml:"maxFileSize"`
MaxVirtualDiskCapacity int64 `xml:"maxVirtualDiskCapacity,omitempty"`
MaxMemoryFileSize int64 `xml:"maxMemoryFileSize,omitempty"`
Timestamp *time.Time `xml:"timestamp"`
ContainerId string `xml:"containerId,omitempty"`
}
Im trying to understand why the same object is showing as two different types?
It is not.
I believed Ds.Info to be of the VmfsDatastoreInfo type
No. if ds
is a Datastore
than ds.Info
is of type BaseDatastoreInfo
which is a interface and as such has only one method GetDatastoreInfo()
. That's why you see the error
ds.Info.Vmfs undefined (type types.BaseDatastoreInfo has no field or method Vmfs)
Now read the whole package documentation of package reflect and the documentation of reflect.TypoOf. Now read https://blog.golang.org/laws-of-reflection.
Your reflect.TypeOf(ds.Info)
resolves the dynamic type of ds.Info (its static type is BaseDatastoreInfo). For a simple example see https://play.golang.org/p/kgDYXv4i63T.
reflect.TypeOf
looks inside of its argument (which is interface {}
); if it would not but report always the static type, reflect.TypeOf would always report interface{}
).
Probably you just should use the interface without reflection:
ds.Info.GetDatastoreInfo()
and use that information. No need to reflect here.