On Fri, Feb 08, 2008 at 05:31:42PM +0900, S.Sakamoto wrote: > > > virt-manager can display only the bridge of the physics network device now > > > when add a device and make a guest domain newly. > > > A bridge of bonding and Tag VLAN is not displayed. > > > > > > So, I make the patch that a bridge of bonding and Tag VLAN came to be displayed. > > > Do not getout from processing specific linux... > > > but can use a bridge of bonding and the tag VLAN. > > > > I'd definitely welcome code to deal with VLANs - and we're already Linux > > specific in this code, so that's not a problem. > > > > We can't use the 'rhpl*' python libraries though - these are Red Hat > > specific libraries, so if we use them, virt-manager won't be able to run > > on Debian/SUSE/etc > > > > If you can adapt the code to remove use of 'import rhpl' then that'd be > > good. > > I remake the patch to remove use of 'import rhpl'. After much testing on some horrible different networking configs, here is an updated patch which I think should work correctly. - Instead of using /etc/modprobe.conf, it reads /sys/class/net/bonding_masters to get an accurate list of bonding devices - It doesn't use the HAL linux.sysfs_path patch when looking for VLANs because that is /sys/devices/pci0000:00/0000:00:1e.0/0000:01:00.0/net/eth0 but the VLANs are only visible under /sys/class/net/eth0.* - It filters out any physical devices that are part of a bonding master so they don't appear in the list twice I've tested with: - eth0 as bridge, and peth0 as physical device - br0 as bridge and eth0 as physical device - bond0 with eth0 as slave, and brbond0 as bridge - eth0.5 vlan with breth05 as bridge Which I think covers the use cases your patch was trying to address. The algorithm it uses is thus: - Find all bonding master devices - Add them to netdev list - Mark shared if in a bridge - Find all physical devices from HAL - Skip if a slave in a bonding device - Check if renamed from ethN -> pethN - Add them to netdev list - Mark shared if in a bridge - For all VLANs associated with physical device - Add them to netdev list - Mark shared if in a bridge Let me know if this patch shows the correct lists for you - if not the /root/.virt-manager/virt-manager.log file should contain useful debug output diff -r 1892867ca5c7 src/virtManager/connection.py --- a/src/virtManager/connection.py Thu Jan 31 11:39:10 2008 -0500 +++ b/src/virtManager/connection.py Fri Feb 15 13:18:56 2008 -0500 @@ -22,6 +22,7 @@ import libvirt import libvirt import logging import os, sys +import glob import traceback from time import time import logging @@ -29,6 +30,7 @@ import dbus import dbus import threading import gtk +import string from virtManager.domain import vmmDomain from virtManager.network import vmmNetwork @@ -134,9 +136,7 @@ class vmmConnection(gobject.GObject): self.record = [] self.hostinfo = None - self.detect_network_devices() - - def detect_network_devices(self): + # Probe for network devices try: # Get a connection to the SYSTEM bus self.bus = dbus.SystemBus() @@ -145,12 +145,21 @@ class vmmConnection(gobject.GObject): self.hal_iface = dbus.Interface(hal_object, 'org.freedesktop.Hal.Manager') # Track device add/removes so we can detect newly inserted CD media - self.hal_iface.connect_to_signal("DeviceAdded", self._device_added) - self.hal_iface.connect_to_signal("DeviceRemoved", self._device_removed) - - # Find info about all current present media + self.hal_iface.connect_to_signal("DeviceAdded", self._net_phys_device_added) + self.hal_iface.connect_to_signal("DeviceRemoved", self._net_phys_device_removed) + + # find all bonding master devices and register them + # XXX bonding stuff is linux specific + bondMasters = self._net_get_bonding_masters() + for bond in bondMasters: + sysfspath = "/sys/class/net/" + bond + mac = self._net_get_mac_address(bond, sysfspath) + self._net_device_added(bond, mac, sysfspath) + + # Find info about all current present physical net devices + # This is OS portable... for path in self.hal_iface.FindDeviceByCapability("net"): - self._device_added(path) + self._net_phys_device_added(path) except: (type, value, stacktrace) = sys.exc_info () logging.error("Unable to connect to HAL to list network devices: '%s'" + \ @@ -159,56 +168,70 @@ class vmmConnection(gobject.GObject): self.bus = None self.hal_iface = None - def _device_added(self, path): + def _net_phys_device_added(self, path): + logging.debug("Got physical device %s" % path) obj = self.bus.get_object("org.freedesktop.Hal", path) if obj.QueryCapability("net"): name = obj.GetPropertyString("net.interface") + # XXX ...but this is Linux specific again - patches welcomed + #sysfspath = obj.GetPropertyString("linux.sysfs_path") + # XXX hal gives back paths to /sys/devices/pci0000:00/0000:00:1e.0/0000:01:00.0/net/eth0 + # which doesnt' work so well - we want this: + sysfspath = "/sys/class/net/" + name + + # If running a device in bridged mode, there's a reasonable + # chance that the actual ethernet device has been renamed to + # something else. ethN -> pethN + psysfspath = sysfspath[0:len(sysfspath)-len(name)] + "p" + name + if os.path.exists(psysfspath): + logging.debug("Device %s named to p%s" % (name, name)) + name = "p" + name + sysfspath = psysfspath + + # Ignore devices that are slaves of a bond + if self._net_is_bonding_slave(name, sysfspath): + logging.debug("Skipping device %s in bonding slave" % name) + return + mac = obj.GetPropertyString("net.address") - # Now magic to determine if the device is part of a bridge - shared = False - bridge = None - try: - # XXX Linux specific - needs porting for other OS - patches - # welcomed... - sysfspath = obj.GetPropertyString("linux.sysfs_path") - - # If running a device in bridged mode, there's a reasonable - # chance that the actual ethernet device has been renamed to - # something else. ethN -> pethN - psysfspath = sysfspath[0:len(sysfspath)-len(name)] + "p" + name - if os.path.exists(psysfspath): - name = "p" + name - sysfspath = psysfspath - - brportpath = os.path.join(sysfspath, "brport") - - if os.path.exists(brportpath): - shared = True - brlinkpath = os.path.join(brportpath, "bridge") - dest = os.readlink(brlinkpath) - (head,tail) = os.path.split(dest) - bridge = tail - except: - (type, value, stacktrace) = sys.exc_info () - logging.error("Unable to determine if device is shared:" + - str(type) + " " + str(value) + "\n" + \ - traceback.format_exc (stacktrace)) - - if self.netdevs.has_key(path): - currDev = self.netdevs[path] - if currDev.get_info() == (name, mac, shared, bridge): - return - del self.netdevs[path] - dev = vmmNetDevice(self.config, self, name, mac, shared, bridge) - self.netdevs[path] = dev - self.emit("netdev-added", dev.get_name()) - - def _device_removed(self, path): - if self.netdevs.has_key(path): - dev = self.netdevs[path] + # Add the main NIC + self._net_device_added(name, mac, sysfspath) + + # Add any associated VLANs + logging.debug("Checking for VLANs on %s" % sysfspath) + for vlanpath in glob.glob(sysfspath + ".*"): + if os.path.exists(vlanpath): + logging.debug("Process VLAN %s" % vlanpath) + vlanmac = self._net_get_mac_address(name, vlanpath) + (ignore,vlanname) = os.path.split(vlanpath) + self._net_device_added(vlanname, vlanmac, vlanpath) + + def _net_device_added(self, name, mac, sysfspath): + # Race conditions mean we can occassionally see device twice + if self.netdevs.has_key(name): + return + + bridge = self._net_get_bridge_owner(name, sysfspath) + shared = False + if bridge is not None: + shared = True + + logging.debug("Adding net device %s %s %s bridge %s" % (name, mac, sysfspath, str(bridge))) + + dev = vmmNetDevice(self.config, self, name, mac, shared, bridge) + self.netdevs[name] = dev + self.emit("netdev-added", dev.get_name()) + + def _net_phys_device_removed(self, path): + obj = self.bus.get_object("org.freedesktop.Hal", path) + if obj.QueryCapability("net"): + name = obj.GetPropertyString("net.interface") + + if self.netdevs.has_key(name): + dev = self.netdevs[name] self.emit("netdev-removed", dev.get_name()) - del self.netdevs[path] + del self.netdevs[name] def is_read_only(self): return self.readOnly @@ -545,13 +568,6 @@ class vmmConnection(gobject.GObject): newInactiveNetNames = self.vmm.listDefinedNetworks() except: logging.warn("Unable to list inactive networks") - - # check of net devices - newPaths = [] - if self.hal_iface: - newPaths = self.hal_iface.FindDeviceByCapability("net") - for newPath in newPaths: - self._device_added(newPath) for name in newActiveNetNames: net = self.vmm.networkLookupByName(name) @@ -847,5 +863,47 @@ class vmmConnection(gobject.GObject): else: return _("Unknown") + def _net_get_bridge_owner(self, name, sysfspath): + # Now magic to determine if the device is part of a bridge + brportpath = os.path.join(sysfspath, "brport") + try: + if os.path.exists(brportpath): + brlinkpath = os.path.join(brportpath, "bridge") + dest = os.readlink(brlinkpath) + (ignore,bridge) = os.path.split(dest) + return bridge + except: + (type, value, stacktrace) = sys.exc_info () + logging.error("Unable to determine if device is shared:" + + str(type) + " " + str(value) + "\n" + \ + traceback.format_exc (stacktrace)) + + return None + + def _net_get_mac_address(self, name, sysfspath): + mac = None + addrpath = sysfspath + "/address" + if os.path.exists(addrpath): + df = open(addrpath, 'r') + mac = df.readline() + df.close() + return mac.strip(" \n\t") + + def _net_get_bonding_masters(self): + masters = [] + f = open("/sys/class/net/bonding_masters") + while True: + rline = f.readline() + if not rline: break + if rline == "\x00": continue + masters.append(rline.strip(" \n\t")) + return masters + + def _net_is_bonding_slave(self, name, sysfspath): + masterpath = sysfspath + "/master" + if os.path.exists(masterpath): + return True + return False + gobject.type_register(vmmConnection) Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=| _______________________________________________ et-mgmt-tools mailing list et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools