Giter Club home page Giter Club logo

Comments (16)

trapgate avatar trapgate commented on July 3, 2024 1

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.

trapgate avatar trapgate commented on July 3, 2024

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.

vtolstov avatar vtolstov commented on July 3, 2024

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.

trapgate avatar trapgate commented on July 3, 2024

I'll see what I can do. It's not a difficult fix.

from go-libvirt.

vtolstov avatar vtolstov commented on July 3, 2024

sorry, any news?

from go-libvirt.

Abashinos avatar Abashinos commented on July 3, 2024

I'm also experiencing the issue, are there any workarounds?

from go-libvirt.

vtolstov avatar vtolstov commented on July 3, 2024

...gentle ping...

from go-libvirt.

trapgate avatar trapgate commented on July 3, 2024

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.

Abashinos avatar Abashinos commented on July 3, 2024

What do you think about patching it directly in master until the issue is fixed the proper way?

from go-libvirt.

Abashinos avatar Abashinos commented on July 3, 2024

@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.

Abashinos avatar Abashinos commented on July 3, 2024

@vtolstov Any progress from your side, maybe?

from go-libvirt.

Abashinos avatar Abashinos commented on July 3, 2024

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.

Abashinos avatar Abashinos commented on July 3, 2024

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.

trapgate avatar trapgate commented on July 3, 2024

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.

vtolstov avatar vtolstov commented on July 3, 2024

thanks!

from go-libvirt.

trapgate avatar trapgate commented on July 3, 2024

you're welcome. :)

from go-libvirt.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.