Comments (16)
The actual problem with the TypedParams is that the size an individual TypedParam varies depending on the type, so you have to look at the so-called discriminant (which is just an integer that identifies the actual type contained in the TypedParam) at the beginning of a TypedParam value in order to tell how long the value is. The workaround in the generated code does this and then hands the xdr library typed params of a particular type, like TypedParamInt, to unmarshal the value into. The logic that does this is in a routine called decodeTypedParams. Your workaround will need to call this routine on the array of TypedParams embedded in the struct.
I will be looking at this problem this week, finally. I will push a fix as soon as I can.
from go-libvirt.
This is caused by libvirt's TypedParam types. Specifically, the xdr decoding library we're using to unpack the replies from libvirt doesn't understand them (rightly so - they're not part of the xdr spec). The code generator works around this by inserting some special case code for these types. That code looks at the discriminant for the TypedParam to identify what type it is, and then pushes an instance of that type to the xdr decoder so it's unpacking into a known type.
But that doesn't work when the TypedParam is contained in another struct, as in this case.
To fix this without making a mess, we'll need to pull in and modify the xdr library, and add code to its type engine that understands the libvirt TypedParam types. With that done, the code generator won't need to special-case these types anymore, and they'll work no matter how deeply nested they are in the message.
from go-libvirt.
do you have some plans to fix this? Now i'm use my own generated libvirt binding that works with dbus, but also i'm need plain libvirt package to connect to remote libvirt instance
from go-libvirt.
I'll see what I can do. It's not a difficult fix.
from go-libvirt.
sorry, any news?
from go-libvirt.
I'm also experiencing the issue, are there any workarounds?
from go-libvirt.
...gentle ping...
from go-libvirt.
This issue is still on my todo list, but I haven't gotten to it yet.
It is possible to build a workaround for this. You'd need to modify the generated code for the ConnectGetAllDomainStats function and manually call decodeTypedParams on the embedded TypedParams.
from go-libvirt.
What do you think about patching it directly in master until the issue is fixed the proper way?
from go-libvirt.
@trapgate Could you please provide a snippet for the parsing workaround? I've tried to implement it, but I'm still getting only domain info, params are not parsed properly at times or just altogether.
Thank you.
from go-libvirt.
@vtolstov Any progress from your side, maybe?
from go-libvirt.
Ok, I've been able to hack the decoder a little, but only by replacing a byte slice with a hardcoded length instead of []TypedParam slice in DomainStatsRecord and calling xdr.Unmarshal
instead of decode. Otherwise (when I replaced []TypedParam with []byte), unmarshal was taking only first 37 bytes of the payload part that contains params and values.
After manually finding out the length of that chunk (~1200 bytes) and hardcoding it in the data structure, I was able to call decodeTypedParams and receive meaningful values out of it.
@trapgate, since you have experience with xdr, do you know how can I complete the workaround? Specifically, which structure instead of []TypedParam will allow for safe unmarshaling and can be used to then decode typed params from itself?
Thank you.
from go-libvirt.
Yep, I've seen decodeTypedParams. The issue appears prior to that though. The payload is expected to be parsed to a slice of structs {Domain, []TypedParam}, so there's not only typed params there. I was wondering how to do the initial parsing, e.g. where to put the bytes representing params initially, before I can call decodeTypedParams on those parts...
It's awesome that you have some time to resolve the issue, I'd like to see how the solution looks like :)
from go-libvirt.
This should be fixed now. A brief summary:
TypedParams are a struct:
// TypedParam is libvirt's remote_typed_param
type TypedParam struct {
Field string
Value TypedParamValue
}
So far, no problem. But TypedParamValue is where things get interesting:
// TypedParamValue is a discriminated union.
type TypedParamValue struct {
D uint32
I interface{}
}
D
is the "discriminant", which just tells you the type stored in the I
member. From an xdr standpoint, in order to decode a TypedParamValue off the wire, the decoder needs to look at the value of D
, create the appropriate type variable to store the value in, and then decode into that variable.
Prior to this change, there was code in every handler to check whether a TypedParam was part of the return values from a call to libvirt; if it was, some special code got called to do the above. That didn't work when the TypedParam was part of another struct, though, because the result handlers don't recurse down through the contents of the returned types - the xdr library itself did that.
To fix this without introducing a circular dependency, I altered the xdr decoding library to let the caller pass in a list of special types, each with a decode handler. When the xdr library detects one of those types (by type name, not by type introspection - otherwise there would be a circular dependency) it calls the provided decode handler. The only special type we need for the libvirt interface is the TypedParam; all other types were complete and needed no special handling.
Hopefully this clarifies things a bit.
from go-libvirt.
thanks!
from go-libvirt.
you're welcome. :)
from go-libvirt.
Related Issues (20)
- Make error public, to allow more fine grained control for clients HOT 4
- Disk usage shown by ConnectGetAllDomainStats is incorrect HOT 3
- Support for connection URIs HOT 6
- Tunnel via SSH? HOT 3
- Migrate Operations missing HOT 1
- Document minimum (or maximum) supported toolchain requirements
- Mentioned method Disconnected() does not exist HOT 1
- libvirttest.MockLibvirt does not implement net.Conn HOT 2
- Broken link to libvirt RPC knowledgebase HOT 1
- Inability to subscribe `metdata-change`, `device-added` and `device-removed` events HOT 5
- Support for QEMU Agent Command HOT 4
- CI occasionally times out HOT 1
- Can libvirt arm platform run X86 system? HOT 1
- Support for modular libvirt daemons HOT 4
- suggested breaking change: add context.Context support to API HOT 1
- cannot use 2147483648 (untyped int constant) as * value in constant declaration (overflows) HOT 4
- Connecting to Libvirt
- Deadlock if Stream Shutdown races with Push
- Q: What is the meaning of `NeedResults`? HOT 1
- Qemu special api
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-libvirt.