Adding an e1000 NIC in XenServer 7

*Note: This is not officially supported – do this at your own risk.*

Sometimes, virtual appliances or other random VMs in your lab need a simple, widely supported NIC and just wont boot (or install) without one. XenServer uses a Realtek RTL8139 10/100 card when you don’t have integration services installed. This is usually not an issue…but it certainly can be.

In older versions of XenServer, there was a patch available as mentioned in this thread that allowed you to use a custom field to apply the e1000 NIC to individual VMs rather than every single VM – the patch is available here. (read the thread first for instructions)

Now that XenServer 7 is publicly available, the patch above no longer works and throws the following error:

So, it looks like it can’t find the qemu-dm-wrapper file – because it is in a different location in XS7. That being said, I have not re-written the patch to look in the correct location (my python-fu is not what it should be) but I will tell you how to get it working, and you will still need the code from the patch.

We are going to manually modify the qemu-dm-wrapper file – if you don’t feel comfortable doing that, DON’T. I’m not responsible for you hosing up your Dom0…you’ve been warned. 🙂

in XS7, the file is located here:

/usr/libexec/xenopsd/qemu-dm-wrapper

So SSH into your XenServer and fire up your favorite text editor on the above file. We need to add two things:

  1. The e1000_enabled_os function
  2. The if statement in the main function

You can type these in by hand, but you will be using the source from the original patch – you should end up with this:

Capture

Then you will need to add the ‘NicEmulation’ custom field into the VMs and populate it with the string ‘e1000’ to get an e1000 NIC on your virtual machine.

 

Original Patch Code (Thanks to WANSec)

>>>PATCH START<<<

--- /opt/xensource/libexec/qemu-dm-wrapper-orig 2014-01-08 00:39:55.000000000 -0600
+++ /opt/xensource/libexec/qemu-dm-wrapper      2014-01-08 00:41:59.000000000 -0600
@@ -75,9 +75,31 @@
        setrlimit(RLIMIT_CORE, (limit, oldlimits[1]))
        return limit

+def e1000_enabled_os(argv):
+        import re
+        import os
+
+        res = re.search('((?:[A-Fa-f\d]{1,2}(?:[-:])?){6})', ' '.join(argv))
+        my_mac = res.group()
+
+        #print 'vif_uuid = xe vif-list MAC=' + my_mac + ' --minimal'
+        vif_uuid = os.popen('xe vif-list MAC=' + my_mac + ' --minimal').read().rstrip()
+
+        #print 'vm_uuid = xe vif-param-get uuid=' + vif_uuid + ' param-name=vm-uuid'
+        vm_uuid = os.popen('xe vif-param-get uuid=' + vif_uuid + ' param-name=vm-uuid').read().rstrip()
+
+        #print 'result = xe vm-param-get param-name=other-config param-key=XenCenter.CustomFields.NicEmulation uuid=' + vm_uuid
+        result = os.popen('xe vm-param-get param-name=other-config param-key=XenCenter.CustomFields.NicEmulation uuid=' + vm_uuid).read().rstrip()
+        if (result == 'e1000'):
+                return True
+        return False
+
 def main(argv):
        import os

+       if e1000_enabled_os(argv):
+               argv = [arg.replace('rtl8139','e1000') for arg in argv]
+
        qemu_env = os.environ
        qemu_dm = '/usr/lib/xen/bin/qemu-dm'
        domid = int(argv[1])

>>>PATCH END<<<

Once you have patched the file in Dom0, you need to add a Custom Field to the VM and enter the string ‘e1000’ to emulate an e1000 NIC, otherwise the Realtek NIC will be used.

Capture

 

18 thoughts on “Adding an e1000 NIC in XenServer 7”

  1. Hi I did what you described but I can’t boot the vm anymore. I receive an error “An Emulator required to run this VM failed to start”. Any idea how to fix?

    Reply
    • Han,

      I can’t say I’ve run into that before – have done this successfully numerous times. The only thing I can think of is to not copy directly from webpage to put into text editor as Unicode != ASCII, etc. Or if hand typed, make 100% sure it is correct.

      Reply
    • Same Problem here. patch was working fine actually. but stupidly applied some patches which overwrite the file and now cant get it to work even with the manual code posted down in the comments.

      Reply
  2. I have ran through the tutorial and have come up with a strange issue. I was able to get the hack to work with great success, but the problem is I am unable to migrate VMs between systems or move storage between local and NFS I receive Storage_interface.Does_not_exist(_). Tried lots of things like restarting the toolstack, rebooting the system, nothing helps. The only thing that works is when I change qemu-dm-wrapper back, I am then able to migrate machines. Any ideas?

    Reply
    • I cannot say that I have run into this issue and really wouldn’t know how to address it. That said, the hack is not supported nor should it be used in production environments.

      Reply
  3. Hi Jake, Great article. I understand why this hack isn’t supported in a production environment but do you know why Citrix is so loathed not to include “NIC choice” in Xenserver? I realise you can’t answer for Citrix (or would want to), I am just curious about this and the possible reasons, as “Xen Tools” is not always an option (as seen by demand for this fix). A lot of us want to also virtualise “closed boxes” like firewall appliances and without being able to choose the hardware presented to the VM, we’ll need to continue to look at other Hypervisors, which is a shame. Thanks for your time, regards, Darrin.

    Reply
  4. Hi Jacob,

    thanks for the fix and excellent post, I’ve tried this on XenServer 7.1 and it works.

    using vi editor as mentioned in the post. copy paste into vi editor and save your changes, dont use winscp or notepad to edit where I was seeing the same errors as above

    Reply
  5. Got this working for 7.1 ***BUT*** the switch using NicEmulation didn’t work, so just I just added one line to qemu-wrapper-dm:

    def main(argv):
    import os
    import sys

    argv = [arg.replace(‘rtl8139′,’e1000’) for arg in argv]

    qemu_env = os.environ
    qemu_dm_list =[]
    loc1 = ‘/usr/lib/xen/bin/qemu-dm’
    loc2 = ‘/usr/lib64/xen/bin/qemu-dm’
    loc3 = ‘/usr/lib/xen-4.1/bin/qemu-dm’
    loc4 = ‘/usr/lib/xen-4.2/bin/qemu-dm’
    loc5 = ‘/usr/lib/xen-4.4/bin/qemu-dm’

    It means you always get e1000, but for my case I’m not too worried.

    Reply
  6. Work in 7.2 !!

    def e1000_enabled_os(argv):
    import re
    import os

    res = re.search(‘((?:[A-Fa-f\d]{1,2}(?:[-:])?){6})’, ‘ ‘.join(argv))
    my_mac = res.group()

    vif_uuid = os.popen(‘xe vif-list MAC=’ + my_mac + ‘ –minimal’).read().rstrip()

    vm_uuid = os.popen(‘xe vif-param-get uuid=’ + vif_uuid + ‘ param-name=vm-uuid’).read().rstrip()

    result = os.popen(‘xe vm-param-get param-name=other-config param-key=XenCenter.CustomFields.NicEmulation uuid=’ + vm_uuid).read().rstrip()
    if (result == ‘e1000’):
    return True
    return False

    And in main:

    def main(argv):
    if e1000_enabled_os(argv):
    argv = [arg.replace(‘rtl8139′,’e1000’) for arg in argv]
    qemu_env = os.environ
    domid = int(argv[1])

    After boot :

    qemu-dm-769 –syslog -d 769 -m 1024 -boot -serial pty -vcpus 2 -videoram 4 -vncunused -vnc 127.0.0.1:1 -usb -usbdevice tablet -net nic,vlan=0,macaddr=56:95:01:bc:74:73,model=e1000 -net tap,vlan=0,bridge=xapi0,ifname=tap769.0 -net nic,vlan=1,macaddr=8e:fc:0f:37:81:75,model=e1000 -net tap,vlan=1,bridge=xapi0,ifname=tap769.1 -net nic,vlan=2,macaddr=92:78:3a:c9:e1:33,model=e1000 -net tap,vlan=2,bridge=xapi0,ifname=tap769.2 -net nic,vlan=3,macaddr=36:bd:bd:5f:e7:3f,model=e1000 -net tap,vlan=3,bridge=xapi0,ifname=tap769.3 -net nic,vlan=4,macaddr=aa:65:ba:f2:c8:20,model=e1000 -net tap,vlan=4,bridge=xapi0,ifname=tap769.4 -net nic,vlan=5,macaddr=fe:4a:a1:b8:40:de,model=e1000 -net tap,vlan=5,bridge=xapi0,ifname=tap769.5 -net nic,vlan=6,macaddr=5a:c5:2e:f4:01:a7,model=e1000 -net tap,vlan=6,bridge=xapi0,ifname=tap769.6 -acpi -monitor null

    Reply
  7. Found a problem with the patch if you have more than one vif nic then you can get UUID,UUID for vif_uuid which causes and error I added this in 7.1 and 7.2 and it worked great!

    #print ‘QERR vif_uuid = xe vif-list MAC=’ + my_mac + ‘ –minimal’
    vif_uuid = os.popen(‘xe vif-list MAC=’ + my_mac + ‘ –minimal’).read().rstrip()
    vif_uuid = vif_uuid.split(‘,’)[0]

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.