Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vcsim: workaround xml ns issue with pyvsphere #958

Merged
merged 1 commit into from
Dec 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions simulator/property_collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,3 +891,167 @@ func TestPropertyCollectorSelectionSpec(t *testing.T) {
t.Fatalf("len(content)=%d", len(content))
}
}

func TestIssue945(t *testing.T) {
// pyvsphere request
xml := `<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ZSI="http://www.zolera.com/schemas/ZSI/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SOAP-ENV:Header />
<SOAP-ENV:Body xmlns:ns1="urn:vim25">
<ns1:RetrievePropertiesEx xsi:type="ns1:RetrievePropertiesExRequestType">
<ns1:_this type="PropertyCollector">propertyCollector</ns1:_this>
<ns1:specSet>
<ns1:propSet>
<ns1:type>VirtualMachine</ns1:type>
<ns1:pathSet>name</ns1:pathSet>
</ns1:propSet>
<ns1:objectSet>
<ns1:obj type="Folder">group-d1</ns1:obj>
<ns1:skip>false</ns1:skip>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>visitFolders</ns1:name>
<ns1:type>Folder</ns1:type>
<ns1:path>childEntity</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>visitFolders</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>dcToHf</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>dcToVmf</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>crToH</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>crToRp</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>dcToDs</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>hToVm</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>rpToVm</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>dcToVmf</ns1:name>
<ns1:type>Datacenter</ns1:type>
<ns1:path>vmFolder</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>visitFolders</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>dcToDs</ns1:name>
<ns1:type>Datacenter</ns1:type>
<ns1:path>datastore</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>visitFolders</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>dcToHf</ns1:name>
<ns1:type>Datacenter</ns1:type>
<ns1:path>hostFolder</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>visitFolders</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>crToH</ns1:name>
<ns1:type>ComputeResource</ns1:type>
<ns1:path>host</ns1:path>
<ns1:skip>false</ns1:skip>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>crToRp</ns1:name>
<ns1:type>ComputeResource</ns1:type>
<ns1:path>resourcePool</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>rpToRp</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>rpToVm</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>rpToRp</ns1:name>
<ns1:type>ResourcePool</ns1:type>
<ns1:path>resourcePool</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>rpToRp</ns1:name>
</ns1:selectSet>
<ns1:selectSet>
<ns1:name>rpToVm</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>hToVm</ns1:name>
<ns1:type>HostSystem</ns1:type>
<ns1:path>vm</ns1:path>
<ns1:skip>false</ns1:skip>
<ns1:selectSet>
<ns1:name>visitFolders</ns1:name>
</ns1:selectSet>
</ns1:selectSet>
<ns1:selectSet xsi:type="ns1:TraversalSpec">
<ns1:name>rpToVm</ns1:name>
<ns1:type>ResourcePool</ns1:type>
<ns1:path>vm</ns1:path>
<ns1:skip>false</ns1:skip>
</ns1:selectSet>
</ns1:objectSet>
</ns1:specSet>
<ns1:options />
</ns1:RetrievePropertiesEx>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>`

method, err := UnmarshalBody([]byte(xml))
if err != nil {
t.Fatal(err)
}

req := method.Body.(*types.RetrievePropertiesEx)

ctx := context.Background()

m := VPX()

defer m.Remove()

err = m.Create()
if err != nil {
t.Fatal(err)
}

s := m.Service.NewServer()
defer s.Close()

client, err := govmomi.NewClient(ctx, s.URL, true)
if err != nil {
t.Fatal(err)
}

res, err := methods.RetrievePropertiesEx(ctx, client, req)
if err != nil {
t.Fatal(err)
}

content := res.Returnval.Objects
count := m.Count()

if len(content) != count.Machine {
t.Fatalf("len(content)=%d", len(content))
}
}
18 changes: 17 additions & 1 deletion simulator/simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,23 @@ func (s *Server) Close() {
}
}

var typeFunc = types.TypeFunc()
var (
vim25MapType = types.TypeFunc()
typeFunc = defaultMapType
)

func defaultMapType(name string) (reflect.Type, bool) {
typ, ok := vim25MapType(name)
if !ok {
// See TestIssue945, in which case Go does not resolve the namespace and name == "ns1:TraversalSpec"
// Without this hack, the SelectSet would be all nil's
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to take a closer look. feels hacky. seems like we are trimming only vim25: as namespace here:

name = strings.TrimPrefix(name, "vim25:")

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a hack, like the comment says. We've only hit this with pyvsphere (not pyvmomi or other clients). I don't want to spend time messing with our fork of the xml package at the moment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not the xml fork. just TypeFunc in types/registry.go. If you replace the TrimPrefix with SplitN, it should work as well. or maybe we can have a TypeFunc that only trims vim25, and anther that trims all namespaces.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I didn't want to put the hack in the types package. The vim25 check there is valid. But the hack above we shouldn't need at all, as the xml package should be properly resolving the namespace alias.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, i see, there is this: <SOAP-ENV:Body xmlns:ns1="urn:vim25"> missed that.

kind := strings.SplitN(name, ":", 2)
if len(kind) == 2 {
typ, ok = vim25MapType(kind[1])
}
}
return typ, ok
}

// UnmarshalBody extracts the Body from a soap.Envelope and unmarshals to the corresponding govmomi type
func UnmarshalBody(data []byte) (*Method, error) {
Expand Down
2 changes: 1 addition & 1 deletion simulator/simulator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func TestUnmarshalError(t *testing.T) {
}

defer func() {
typeFunc = types.TypeFunc() // reset
typeFunc = defaultMapType // reset
}()

ttypes := map[string]reflect.Type{
Expand Down