Saturday, February 16, 2008

The (virtual) Windows-on-Linux desktop

It's kinda weird to start a blog about the Linux desktop with a post about virtualization, but here's the deal: I know that virtualization is the next big thing (or the current big thing) when it comes to servers. I think that it can also be the next big thing on the desktop.

Many times people don't like using Windows. They don't like having to buy a new computer to use a new operating system, they don't like having to reinstall the operating system to solve problems. You know, all those things that one is pretty much forced to do when one uses Windows. However, they don't switch. I honestly believe there are GNU/Linux distributions that are ready for the desktop. So, why won't they switch?

Why?

Well, people don't use operating systems. People use applications, and rely on operating systems to run applications. When you suggest someone to switch to Linux, the first thing they tend to ask is "Will X work with it?". A huge number of times, X is a program. The best answer one can give is "Well, you can use Y to do that".

That's not good enough for them.

Our answer should be "Yeah, don't worry about that program, you can still use it". And I'm not talking about Office. I'm talking about Photoshop. Corel Draw. Or that crazy internal app that the office uses to do that weird thing that they need to do because they are doing business in that niche area.

We can already migrate most of the desktop functionality to open source alternatives. Hell, we can already introduce those alternatives in Windows, and then move people to a new operating system when they are familiar with the new applications. But we cannot migrate all the functionality. The bad news is that most of the times that's a deal breaker.

(Everything should look gloomy and hopeless now.)

Luckily, the arms race engaged by CPU makers and fueled by Microsoft operating systems and gamers has given us machines with ridiculous amounts of processing power. We can run two operating systems on one machine.

Yes, we can. Even if one of those is one from Microsoft. Just make sure is not the last one, and you'll be fine. OK, you can even make it the last one, I've actually tried that. And that's why I think virtualization has such a bright future in the desktop. Parallels Desktop and VMware Fusion are an example of this. They cut the tether between application and operating system. You can run the operating system you like, not the one you are forced to run because of one single applicating that you need to run.

Enough of this chit-chat. Let's look at an example: Argentina's tax software is only available for Windows. I need to run it on my Ubuntu laptop. I'm going to use KVM and rdesktop to run the application in a Windows virtual machine and use it without having to see the full Windows desktop.

KVM makes use of hardware virtualization extensions present in recent Intel and AMD processors. To know if your CPU supports KVM, just do:

$ cat /proc/cpuinfo | grep "vmx\|svm"

If anything shows up, you have a compatible processor. If not, you may still have a compatible processor but the extensions might be disabled in the BIOS. The KVM FAQ has suggestions on how to deal with this.

In the case that your processor doesn't have virtualization extensions, you can use other programs such as VirtualBox (which is mostly open source) or VMware (which is not, and therefore doesn't get a link =P). These programs use other trickery to run unmodified guest operating systems in x86 boxes. As long as you can open a network connection between guest and host, you should be able to use the last part of this post to run Windows programs directly on your Linux desktop.

First we have to compile and install KVM. KVM is already shipped with most distros (it's shipped with Ubuntu) but the packaged versions tend to be quite old, especially for a young project like KVM which still moves pretty fast. Just follow the download link from the main site and get the current version tarball (kvm-60.tar.gz as of this).

If you are using an Ubuntu or Debian system, you can now do:

$ sudo apt-get build-dep kvm

To get all needed dependencies.

Unpack the tarball to your usual folder (I use something like /home//local) and do:

$ ./configure --enable-alsa
$ make

KVM uses QEMU to provide the virtual machine with devices, so we need to make sure that KVM compiles QEMU with ALSA support if we want to get decent sound from the guest.

If you weren't able to check dependencies, the configure script probably complained. Use your favourite package manager to check for the missing packages or (God help) download and install the necessary tarballs. The easiest way is to have your package manager do a search for the name of the missing library in the name and description of available packages (and maybe add "dev" to the search so it shows development packages).

After a while everything should be built and you can do:

$ sudo make install

And KVM should be installed.

Now we have to install the guest operating system. You can use any flavour of Windows, but Windows Server 2003 (or anyone with Terminal Services) will give us the possibility of having just the window of the application we want on our Linux desktop. You will see. Of course, it should be a Windows version for which you have a valid license (we are trying to move away from Windows, but in a legal way).

Before performing the actual install, we have to create a disk image. What's this? It's just a file on disk that represents a real HDD for the guest operating system. We can do:

$ qemu-img create 2003.img -f qcow2 10G

That will create a 10-gig image file using the QCOW2 format (the native QEMU image file format) in the current directory. The cool thing about the image is that it "streches" to fit the data the guest writes to it. Right now, just created, the 10-gig image file occupies a mere 50 KB in my machine.

Before we install the system, we should make sure that we can run KVM without having to be root. There's a file in the scripts folder of the KVM tarball called
65-kvm.rules. Just copy it to /etc/udev/rules.d/, make sure to add a kvm group to your system, and add your user to that group.

KVM works as a kernel module, so we should load the appropiate kernel module before starting. My laptop has a Intel Core 2 Duo processor so I will use the kvm-intel module. Homework: give the name of the module to load if you have and AMD processor.

$ sudo modprobe kvm-intel

Now, let's say I have a Windows Server 2003 ISO in /home//stuff/iso/win2003_sp2.iso:

$ qemu-system-x86_64 -cdrom /home//stuff/iso/win2003_sp2.iso -m 512 2003.img -boot d


Will boot the ISO as a CDROM and start the installation. The command-line options are pretty self explanatory, and the QEMU command-line help is good otherwise. I'm giving 512 megs of RAM to my Windows guest.


That's how the install looks as a virtual machine. The title of the window says "QEMU/KVM", that's how we know that the KVM module is loaded and being used. The install will go on as a normal Windows install. Finally, after another reboot, we will get a login prompt.

I always choose to create a user right away. One good thing to do (that the great QCOW2 image file format allows us to do) is to shut down the machine after the install is done and make our image file read only. Then we can create another image file:

$ qemu-img create win.img -b 2003.img -f qcow2

The -b switch says that the new image will look like the old one, and just store the changes. In this way, if we fuck up from here onwards we can always have a clean Windows install available (which won't get modified even if we want as we have made it read-only). Neat, huh?

After you create a user, you might want to do some configuration (probably ramp up the sad 640x480 default screen size) and install the software you need (in this case Argentina's tax software). You should have a working network connection, so you should be able to download the programs you want. QEMU documentation shows ways of sharing directories between guest and host, but that's for another post. Argentina's tax software is downloadable, so I don't need to do any of that =).

Then we have to enable Remote Desktop. Right click on My Computer (you can find it in the Start menu, does not seem to show on the desktop by default), Properties, Remote, "Enable Remote Desktop for this computer". Check that your user has access and you are done. Don't forget to write down the full path to your application's executable, we are going to need it.

We don't need rdesktop to actually use our application. However, the default screen we get with KVM has some caveats, the biggest one being not having cut-and-paste and having to let the window grab the mouse to get mouse events in the guest.

rdesktop should be packaged for your distribution. Once you have it installed, restart your Windows guest with the following command line:

$ qemu-system-x86_64 -m 512 win.img -redir tcp:3389::3389 -redir udp:3389::3389

That will allow rdesktop to connect to the guest. QEMU enables by default a networking mode known as "user mode networking". This basically means that the QEMU process fakes a router that lets you use your guest as if it was behind a really paranoid firewall blocking every inbound connection, but allowing things to go out. In this way the guest can access everything that the host can access (for example the Internet) as long as the guest starts the connection. It has a DHCP server and everything so networking should really come up automagically in the guest.

Finally, we launch rdesktop:

$ rdesktop localhost -s "C:\Program Files\S.I.Ap\AFIP\siap.exe" -S standard -D

The -s switch allows us to run someting else than the normal shell, the (in)famous explorer.exe. The -S switch tells rdesktop to listen to minimize events in the guest window and replay them in the host (this will let us minimize the Windows application clicking on the Windows minimize button). Finally, the -D switch takes away window manager decorations, so we finally have:


Like I promised, a Windows window (pun intended) over a Linux desktop, with full cut-and-paste and no Windows desktop in sight. Cool!

I've been meaning to write a simple application that will automate this process but I cannot seem to get the scope right. I don't want to reinvent the wheel and end up with a full virtual machine management tool like the half-dozen or so that are already available. I want something simple that will let people use their Windows programs in Linux without having to go through this post. Broad scope and functionality suggestions are welcome.

No comments: