Here's our second blog post on our journey to introduce Rust to the Xen Project. In case you didn't catch the opening post, you can find it right here:
Understanding Guest Tools
Before delving into our Rust prototype, let's first clarify what we're talking about! We're referring to an agent installed within the VM that facilitates communication with Dom0. Essentially, they enable the collection of various OS data, such as memory usage, OS version, IP addresses, and more, which are then stored in a key/value database known as Xenstore.
For example, that's how you can see a VM IP address reported in Xen Orchestra:
Right now, the agent used by XCP-ng for Linux guests is written in Go, hosted in a XenServer repository. FreeBSD guests use a shell script, forked from a previous version of this agent predating its rewrite in Go.
Why we replace it
There are various reasons for which we decided to replace the existing tools by a new one. Regarding the choice of Rust itself for a rewrite, it was explained in our initial blog post. But why a rewrite?
Project and Community Aspects
The existing project isn't hosted on Xen Git or Gitlab platform; instead, it resides under the XenServer banner on Github, which is acceptable but not ideal.
Contributing to the project is challenging due to complex communication with the existing team and issues with the current code base.
Moreover, the project isn't pro-active on building distro packages, leaving distro maintainers doing all the work. It's OK, but we aim to do better by working with popular distros to make packages easily available, simplifying the installation process.
The current code base has room for improvement in terms of code quality and design. While technical issues could be addressed through contributions, the aforementioned community aspects make it more difficult to fix.
Most notably, it is essentially a rewrite in Go of the older shell-script version, keeping the shell-like "run a bunch of commands every minute to parse their output", when most of the information it monitors could be received as they occur. This consumes more VCPU time in the guest, and dom0 only gets the state changes after a delay.
Our goal is to create a future-proof solution by considering the possibility of going beyond existing interfaces and xenstore key/values, ultimately becoming a genuine upstream contributor.
Our first prototype
We successfully developed our initial prototype, utilizing the same key/values as the existing Go tools. This approach allowed us to establish the proof of concept while examining short-term challenges and plotting the future roadmap.
The prototype is already functional, and reveals itself through the "Management agent" string:
Designed for modularity and extensibility, the prototype can be adapted according to the requirements of other downstream users such as XenServer, Amazon, and others.
Why it's better
This new tool is designed from the start to listen to system events, for example to be notified when the network configuration changes. On Linux this is done using a Netlink socket; FreeBSD is gaining Netlink support in upcoming v13.2; Windows has its own API to get notified of address changes, and we're thinking about having a look at that.
Using the native APIs instead of launching external processes to collect information will also make it easier to integrate in minimal guest OSes like Talos Linux.
We designed it not to be tied to the
libxenstore API, so it could be easily be modified to use a different communication channel if needed, or extended to use the WMI API to Xenstore to make it useful in Windows guests too.
We're looking forward to get it packaged for major OSes, to make it easier for everyone to use it.
This prototype is still not 100% complete, for example not reporting network info about SR-IOV NICs. Error handling and logging is also not what will be expected of a finished software product.
There is room for improvement in terms of modularity: certain platform-specific features (such as Netlink support for Linux guests) that depend on specific crates are effectively managed through compile-time choices. However, several other features were also associated with compile-time choices simply to keep the prototype straightforward, and these would benefit from runtime configuration.
While Linux guests are well-supported, other operating systems frequently run as XCP-ng guests (notably FreeBSD) and will require support as well. It is also worth considering whether Windows could be supported by the same core tool, in order to avoid having two separate tools performing similar tasks.
And proper build instructions will be useful 😉