Automatische Vergabe von Mac-Adressen in DomUs
Wenn man die Konfiguration von Xen-DomUs in Textdateien ablegt, die an das xm create-Kommando verfüttert werden, so würfelt Xen mit jedem Kaltstart einer DomU eine neue Mac-Adresse für die virtuelle Netzwerkkarte aus. Im Zusammenspiel mit dem udev-Paket aus Debian Etch und Lenny (4.0 und 5.0) führt das dazu, dass die Netzwerkkarte "wandert": beim ersten Start heißt sie eth0, beim zweiten wegen der geänderten Mac-Adresse eth1 und so weiter. Da die Netzwerkkonfiguration in der DomU aber in der Regel an den Namen geknüpft ist, verliert die DomU beim zweiten Start den Zugang zum Netz.
Abhilfe ist leicht zu schaffen, erfordert aber, dass man beim ersten Start die Mac-Adresse in der DomU ausliest und in der Kofigurationsdatei außerhalb, also in der Dom0 nachträgt. Das ist auf die Dauer, besonders wenn man häufig neue DomUs per ctdomubuilder erzeugt, recht umständlich. In einem Ticket waren schon einige Lösungswege aufgezeigt, die wir nunmehr auch umgesetzt haben. In c't 19/08 war ein Prototyp des Python-Skripts veröffentlicht, das die Konfigurationsdateien in Art einer Include-Datei ergänzt. Hier ist eine etwas elegantere Form, die die Mac-Adressen in einer Text-Datei, statt einer binären Datenbank ablegt, sodass man von Hand auch mal aufräumen kann. Das Skript ersetzt die von ctdomubuilder angelegte Datei /etc/xen/ctsrvcommon:
# Hack to make Xen re-use MAC addresses (instead of constantly creating new
# ones)
# This file is supposed to be execfile()d
def selectMacAddress(name):
CONF_FILE='/etc/xen/macaddrs'
SECTION='MAC addresses'
EMPTY_CONF_FILE='''
# Virtual machines remember their MAC addresses using this file. If Xen
# doesn't find a machine here, it generates a random MAC address and appends
# it to the list below.
'''
import sys
from os import access, R_OK, W_OK
from os.path import dirname
from ConfigParser import SafeConfigParser
xenpath=dirname(dirname(sys.argv[0])) # parent dir of dir
if not name:
print 'Missing domU name, abort'
sys.exit(1)
macs=SafeConfigParser()
macs.read(CONF_FILE)
# If config file doesn't exist, create an empty one
if not access(CONF_FILE, R_OK | W_OK):
open(CONF_FILE, 'a').write('%s\n[%s]\n' % (EMPTY_CONF_FILE, SECTION))
if macs.has_option(SECTION, name):
mymac=macs.get(SECTION, name)
else:
from random import randint
print 'Generating random MAC address ...' ,
mac=[0x00, 0x16, 0x3e,
randint(0x00, 0x7f),
randint(0x00, 0xff),
randint(0x00, 0xff) ]
# convert to hex separated by colons
mymac=':'.join('%02x' % m for m in mac)
open(CONF_FILE, 'a').write('%s = %s\n' % (name, mymac))
print 'Using MAC address %s' % mymac
return (xenpath, mymac)
xenpath, mymac=selectMacAddress(name)
Die demnächst per Update erhältliche Version 2.1 des ctdomubuilder wird das Skript enthalten und neue DomU-Konfigurationsdateien von sich aus so schreiben, dass die Festlegung der name-Variable und das Einlesen des Skript in der richtigen Reihenfolge geschieht - so wie im Artikel in c't 19/08 dokumentiert.