lukedyue

Introduction

Project Goal

The test driver (as accessed via the test:/// URI scheme) is a fake virt driver designed to let applications test against libvirt with fake data and not have any effect on the host. As can be seen from the API coverage report http://libvirt.org/hvsupport.html there are quite a few APIs not yet implemented in the test driver. Ideally, the test driver would have 100% API coverage, and so the goal of the project is to address gaps in the API coverage.

And my work is trying to expand API coverage as much as possible.

Why do we have to implement these things?

With the test driver, we don't have to run a daemon, we don't have to care about what virtualization tech does current system support, we can just test libvirt's APIs with virsh or other tools and get to know what the API behavior is. And when the test driver shares some common code with other drivers, when can test the code using the test driver and don't have to create a real virtual machine with that virtualization tech, that's pretty convenient. At the same time, the API implementations of the test driver are also references for other drivers, as the test driver's implementation does not have all the unrelated handling. So far, there are a lot of APIs remain unimplemented, so we have to expand the API coverage.

What I've done

In the past 10 weeks, I have implemented 19 APIs, 6 of them merged and 13 of them still need review or adjustment. They are listed below

All (19)

GitLab link

Merged (12)

Not merged yet (6)

Blogs about GSoC and Libvirt

Planning to write another or more blogs to describe how to implement one test API in the future.

Conclusion & Acknowledgments

In the past 10 weeks, I learned a lot about libvirt's codebase and how the community runs, I have to say that the project is not as easy as I thought weeks ago. We need to keep the code clear and de-duplicate some code so that we can reuse them. We also have to write a lot of tests, that ensure everything runs correctly and once there is something wrong, we can quickly find it. And memory safe is pretty important too. I have to care about all these things when submitting patches to the community, and try to write some high-quality code really improves my C skill. Sometimes I thought I was careful enough, but when my mentors review my patches, they can always find some shortcomings, thank them, and that teaches me the importance of review and cooperation, also reminds me that I have a lot to learn.

So, what's next? First, I would like to complete my current patches and make them merged. Though the GSoC has ended, I will still contribute to libvirt and implement more test driver APIs in the future, I think it's a pretty nice experience to work with the libvirt community, and I'm also interested in implementing these APIs.

I really appreciate my mentors, Martin Kletzander and Michal Prívozník, thank them for answering my questions, spending time reviewing my patches, and sharing their knowledge with me, without their help, I won't complete these works. I also would like to express my gratitude towards other devs, I learned a lot from them too.

Configure your environment

Before diving into libvirt's codebase, you may need to configure your system and IDE to assist your development. If you are familiar with these things, you can just start to read codes or write some codes right now. And according to libvirt's contributing guidance, there are a lot of things we have to comply with.

Configure git send-mail

As you may notice, people are sending patches to the mailing lists, and they are not copying-pasting patches to mail clients and send, they are using git send-mail, so you have to configure it before we send patches. You have to configure an SMTP client before we start to configure git send-mail, and I'm using msmtp here, you can choose your own one. Here is my ~/.msmtprc config without my privacy info.

# Set default values for all following accounts.
defaults
auth           oauthbearer
tls            on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile        ~/.msmtp.log

# Gmail
account        gmail
host           smtp.gmail.com
# If you need a proxy
# proxy_host     127.0.0.1
# proxy_port     7891
port           587
from           youraddr@gmail.com
user           youraddr@gmail.com
passwordeval   "Your own script to renew Gmail OAuth tokens"

account default : gmail

For more info, please check out ArchWiki. And just like what I said in the previous post, if you are in China and you insist to use Gmail, you may need a proxy to use it normally, and configure that on your own. Note that Gmail won't support login with password unless you adjust some settings, or you should write or search for a script to do OAuth login. After testing your msmtp config works, you can now add these to your git config file.

[sendemail]
        from = Your Name <youraddr@gmail.com>
        smtpuser =
        smtpserver = "/usr/bin/msmtp"
        smtpencryption = tls

Test config with git send-email --confirm=always --to=someaddr@gmail.com master, edit the mails according to the comments, send emails, and see if you receive them, if not, fix your configs, if you receive patches, congratulations! You are done with this part. Remember to comply with libvirt's advice, and there are a lot of git send-email options you can adjust, like --suppress-cc=all if you don't want to cc the mail to someone by accident.

Configure your IDE

To have a better development experience, I suggest you developing libvirt in Linux instead of other systems, because we would have a package manager to install some libs which we need to compile the libvirt. Of course, you can use Windows / FreeBSD / macOS or some other systems if you know how to solve problems (and luckily, for developing the test driver, we don't need to care about which virtualization tech does the OS support).

You can choose your favorite IDE or text editor, I'm using Virtual Studio Code so I will show how I configure it below.

Compile

First, you have to install dependencies before compiling libvirt, you can look for them in your system's libvirt package file. For example, I am using Arch Linux, so I can head to PKGBUILD for libvirt

depends=('libpciaccess' 'yajl' 'fuse2' 'gnutls' 'parted' 'libssh' 'libxml2' 'numactl' 'polkit')
makedepends=('meson' 'libxslt' 'python-docutils' 'lvm2' 'open-iscsi' 'libiscsi' 'ceph-libs' 'glusterfs' 'bash-completion' 'rpcsvc-proto' 'dnsmasq' 'iproute2' 'qemu-headless')
optdepends=('libvirt-storage-gluster: Gluster storage backend'
            'libvirt-storage-iscsi-direct: iSCSI-direct storage backend'
            'libvirt-storage-rbd: RBD storage backend'
            'gettext: required for libvirt-guests.service'
            'openbsd-netcat: for remote management over ssh'
            'dmidecode: DMI system info support'
            'dnsmasq: required for default NAT/DHCP for guests'
            'radvd: IPv6 RAD support'
            'ebtables: required for default NAT networking'
            'qemu: QEMU/KVM support'
            'lvm2: Logical Volume Manager support'
            'open-iscsi: iSCSI support via iscsiadm')

So just install packages in depends and makedepends with pacman, don't forget to install gcc or clang as a compiler, and we can start to compile.

Libvirt's website also gives some examples on how to compile here, you can follow them.

Now we have self-compiled virsh binary in /path/to/your/source/build/tools/virsh, if you only want to develop the test driver, we don't need to run a daemon, just debug with virsh is enough.

Debug

Now, we have codes, we have binaries, but how can we debug? With VSCode, we can use the cpptools plugin in the official market, and make a new dir called .vscode in your source code dir, place a launch.json file in it.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "cppdbg",
            "request": "launch",
            "program": "/path/to/your/source/code/build/tools/virsh",
            "args": [
                "-c", "test:///path/to/your/source/code/examples/xml/test/testnode.xml",
            ],
            "cwd": "${workspaceRoot}",
            "MiMode": "gdb",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
        }
    ]
}

And a c_cpp_properties.json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "compileCommands": "${workspaceFolder}/build/compile_commands.json"
        }
    ],
    "version": 4
}

Then you can use the VSCode's debug option in the sidebar, begin the debug, add breakpoints, checkout call stacks, inspect variables, it's pretty convenient. If you have known gdb or lldb well, it's also pretty nice to run them in cli.

Memory leak?

Normally, I am using

$ valgrind --tool=memcheck --leak-check=full --track-origins=yes --keep-stacktraces=alloc-and-free -s ./build/tools/virsh -c test:///path/to/your/source/examples/xml/test/testnode.xml

and execute some commands to see if there are memory leaks, if you know how to adjust valgrind options and find out these options are not good enough, please tell me, thanks :). You don't have to debug with valgrind though, cause running the program with valgrind is pretty slow, just check it before your commit.

Now, you can start to code, and submit your patches, don't forget to run ninja -C build test before your commit (or you can add git hooks) and you can also fork the libvirt repo in GitLab, so you could have CI (for FreeBSD and macOS CI, you have to configure it according to ci/README.rst) to help you find if there are any problems. Commit messages sometimes are pretty important, if your code uses some tricks or changed something, you'd better state them clearly in your commit message, you can look at how other people do.

Some advice

  • If you add new APIs to your test driver, you'd better add some tests to /path/to/your/source/tests/virshtest.c
  • If you have some common codes between drivers, you can extract them to /path/to/your/source/src/conf/domain_conf.c or /path/to/your/source/src/hypervisor/domain_driver.c, or somewhere else suitable enough.

Happy coding! :)

I'm very happy and honored that I was admitted to participate in the GSoC 2021, to work with libvirt community.

I will record and share some experience here, if you also would like to participate in GSoC, work with Open Source communities, or just for fun, then go on.

English is not my mother tongue, so you may find an offensive “tone” in the article where no offense is meant.

First step

Do you enjoy writing codes? Do you love open source? Do you have enough time in the summer holiday? Or if you just want to enrich yourself, You can take GSoC into account.

After ensuring that you have enough motivation to work 45 days (GSoC 2021 halves the time), then you need to select a community and a project to contribute to, that's pretty important.

There are a lot of communities in GSoC, if you are familiar with some, you can just head to them and find the projects you are interested in. But if you are a newbie, then you may look into them one by one. There are tags for every community, but please don't ignore a community just because the tags don't fit your skills, cause sometimes tags are not consistent with the projects. For example, a community may have a tag C++, but all the projects are not related with C++.

And do note that some communities require the previous contributions or pass some tests before submit your proposal (to pass some students). Normally, you can get the requirements from the community official sites, such as libvirt's GSoC FAQ, please read these carefully to save both you and your mentors' time.

Contact communities

After selecting the projects you take interest in, you should now contact communities, and remember that, the earlier, the better. You may need to use IRC, Email, Slack, Telegram, or something else to contact the community.

  • For IRC, I'd recommend running WeeChat , The Lounge, or Quassel on the server side, and use a client to connect to the server, so you can always stay online and won't miss any messages.
  • For email, you can use your favorite email providers like Gmail, Outlook, or ProtonMail... but remember that sometimes your mail will go to the mentor's junk folder, so if the mentor doesn't reply to you, you should find another method to contact him. And if you are in China, you'd better choose an email provider that you can always connect to, or you should have a good proxy :)

Now you find the best method to contact communities, so don't hesitate to introduce yourself and show your abilities :), and remember to be polite.

Write proposals

If you think the communication between you and your mentor is pretty good and you finally decide to choose the project (or just choose the project directly), you can start to write your proposals now (don't forget that you should meet the communities requirement as I said in the First Step). Introduce yourself, write down your ideas about the project, organize a detailed schedule, anyway, try to make your proposal look nice. And don't forget to share your draft with the community, so community members can give some advice to make your proposal better. Though you can submit multiple proposals, I believe most people will just submit one, cause time is pretty limited.

Contribute and wait

Contributing to the project you take interest in is pretty important. First, you can get familiar with the code, and the workflow of the project. Second, the community members will get to know you. Third, the contribution you make, to some extent, shows your determination to take part in the project. Even though you may not be the selected one, contributing to communities deserves to be encouraged.

So, after so many preparations, you are good to go. Submit your proposals, attend the interview arranged by the community, and, wait for good news. Good luck ;)