5 minute read

For one of the courses that I am tutoring, I thought it wouldn’t hurt having a Windows VM remotely and showing WSL2 to make the students familiar with the nice POSIX-compliant environment. I’m leaving a note on how to set up a Windows 10 VM on a working OpenNebula platform.

Setting

  • Server: HPE ProLiant DL360 Gen10
  • CPU: Intel(R) Xeon(R) Gold 5315Y CPU @ 3.20GHz
  • Host OS: Ubuntu 20.04.5 LTS
  • OpenNebula: Version 6.4.0 with KVM

Walkthrough

A Windows 10 VM on OpenNebula reached through RDP

1. Enable the nested virtualization to use WSL2 on Windows instances – this should better be done first as we need to reload the kernel.

2. Install OpenNebula 6.4.0 on Ubuntu 20.04.5 LTS machine

  • The official document is nicely written and contains all the information you need. This time, I installed both the frontend (Sunstone) and the KVM Node on the same machine.
  • OpenNebula Installation
  • KVM Node Deployment
  • Bridged Networking
    • I configured to use one of the NIC to be attached as a bridge; however, Netfilter on Ubuntu 20.04 drops he packet on a bridge interface by default. To work around this, you need the following persistent rule:
      % sudo sysctl -p /etc/sysctl.conf
      net.bridge.bridge-nf-call-ip6tables = 0
      net.bridge.bridge-nf-call-iptables = 0
      net.bridge.bridge-nf-call-arptables = 0
      

3. Prepare the Windows 10 VM image from the Windows 10 Enterprise Evaluation Copy ISO

There’s a quite straightforward tutorial even with a YouTube screen recording: How to Build an Image for Windows Virtual Machines.

The tutorial is for OpenNebula: 5.10, but it also worked just fine for the current stable 6.4.0. I tried for Windows 11, but I was warned that the machine is not meeting hardware requirements at the installation screen – perhaps we need to wait for the virtio driver to be updated.

Anyway, I’m summarizing the steps below.

3a. Download the Windows 10 Enterprize Evaluation Copy from Windows 10 Enterprise

I selected the 64-bit edition of Enterprise ISO and am calling it win10-64bit-21h2.iso.

3b. Download the Stable virtio-win ISO

At the time of writing, the stable version of VirtIO Drivers for Windows is virtio-win-0.1.221.iso.

3c. Build the OpenNebula Windows VM Contextualization package ISO for 6.4.0

At the time of writing, the Windows contexualization package was not published in the Releases, so I decided to build one on my own. On a Debian host for example:

# Install wixl (msitools)
% sudo apt install -y wixl
# Clone the repository
% git clone https://github.com/OpenNebula/addon-context-windows.git && cd addon-context-windows
% env VERSION=6.4.0 ./generate-all.sh
Info: Using the binary: nssm/win32/nssm.exe

(wixl:221764): wixl-CRITICAL **: 11:17:18.576: wixl_wix_builder_install_mode_to_event: assertion 'modeString != NULL' failed
one-context-6.4.0.msi
Total translation table size: 0
Total rockridge attributes bytes: 262
Total directory bytes: 380
Path table size(bytes): 10
Max brk space used 0
250 extents written (0 MB)
one-context-6.4.0.iso

The packages are here:
--------------------------------------------------------------------------------
out/one-context-6.4.0.iso
out/one-context-6.4.0.msi

3d. Create Images in the Datastore from the ISO files

Putting the ISOs in /var/tmp (the default SAFE_DIRS for System Datastore), and login as the oneadmin user on the OpenNebula host:

% oneimage create -d 1 --name "Windows 10 ISO" --path /var/tmp/win10-64bit-21h2.iso --type CDROM
% oneimage create -d 1 --name "Virtio Windows Drivers ISO" --path /var/tmp/virtio-win-0.1.221.iso --type CDROM
% oneimage create -d 1 --name "ONE Windows Context ISO" --path /var/tmp/one-context-6.4.0.iso --type CDROM

3e. Create a DATABLOCK for Windows 10 to be installed

I created an empty 100GB disk.

% oneimage create -d 1 --name "Windows 10" --type DATABLOCK --size 100G --persistent

3f. Create a VM Template

Note that the <cpu mode='host-passthrough'/> KVM raw data section enables nested virtualization by passing-through the CPUs.

% cat /tmp/win10-vm-template.txt
NAME = "Windows 10"
MEMORY = "16384"
MEMORY_UNIT_COST = "MB"
CPU = "4"
VCPU = "4"

DISK = [
  IMAGE = "Windows 10 ISO",
  IMAGE_UNAME = "oneadmin" ]
DISK = [
  IMAGE = "Virtio Windows Drivers ISO",
  IMAGE_UNAME = "oneadmin" ]
DISK = [
  IMAGE = "ONE Windows Context ISO",
  IMAGE_UNAME = "oneadmin" ]
DISK = [
  DEV_PREFIX = "vd",
  IMAGE = "Windows 10",
  IMAGE_UNAME = "oneadmin" ]

NIC = [
  NETWORK = "vnet",
  NETWORK_UNAME = "oneadmin",
  SECURITY_GROUPS = "0" ]
NIC_DEFAULT = [
  MODEL = "virtio" ]

GRAPHICS = [
  LISTEN = "0.0.0.0",
  TYPE = "VNC" ]

INPUT = [
  BUS = "usb",
  TYPE = "tablet" ]

OS = [
  BOOT = "disk0" ]
RAW = [
  DATA = "<cpu mode='host-passthrough'/>",
  TYPE = "kvm",
  VALIDATE = "YES" ]
% onetemplate create /tmp/win10-vm-template.txt

3g. Instantiate the VM Windows 10 Installation and install Windows 10 on the disk

The Sunstone Web UI would be easier from this step as you need VNC/Virt Viewer to complete the installation. During the Windows Setup: - “Which type of installation do you want?”: Choose “Custom: Install Windows only (advanced)” - “Where do you want to install Windows?”: [Load driver] -> Select all the compatible drivers on the VirtIO driver CD-ROM and install them -> You should be able to see the empty (100GB) disk

3h. Install VirtIO drivers for peripherals

Once you sign in to the freshly installed Windows, open Device Manager and install drivers from the VirtIO driver CD-ROM for

  • Other devices -> Ethernet Controller -> [Update driver] -> [Browse my computer for driver software] -> [virtio-win-0.1.221]
  • Other devices -> PCI Device -> [Update driver] -> [Browse my computer for driver software] -> [virtio-win-0.1.221]

3i. Terminate the VM instance

Terminate the Windows 10 VM.

3j. Update the Windows 10 Image

Change Type from DATABLOCK to OS and change Persistent from yes to no.

3k. Update the Windows 10 VM Template

Remove all the disks from Storage except for the Windows 10 OS Image.

4. Deploy the VM from the VM Template Windows 10

It is recommended to enable Remote Desktop – otherwise you need to interact with the Windows VM via VNC/Virt Viewer.

5. (Optional) Expose the RDP port of the VM

Since I didn’t want to remove the firewall at the gateway router, I’m port-forwarding ingress packets for xx.yy.zz.1:aa/tcp to xx.yy.zz.101:389/tcp.

6. Install WSL2 on the VM

Open PowerShell as Administrator, follow the official instruction: Install Linux on Windows with WSL, and restart Windows. wsl --install should install Ubuntu for WSL”2” by default. A screenshot showing wsl --install and Ubuntu with WSL2 via RDP

Leave a comment