ia64/xen-unstable

changeset 19365:f81467ad1356

xend: Accept udev events and update physical resource information

When a udev event is received, udevevent.py parses the udev data and
tells XendNode.py to update the physical resource information.
This patch also add a boolean parameter 'xend-udev-event-server', to
let users indicate whether we should enable this function or not.

Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 17 10:40:47 2009 +0000 (2009-03-17)
parents 57327f3334b4
children 6e3e841f0259
files tools/examples/xend-config.sxp tools/python/xen/xend/XendNode.py tools/python/xen/xend/XendOptions.py tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/udevevent.py
line diff
     1.1 --- a/tools/examples/xend-config.sxp	Tue Mar 17 10:38:06 2009 +0000
     1.2 +++ b/tools/examples/xend-config.sxp	Tue Mar 17 10:40:47 2009 +0000
     1.3 @@ -64,6 +64,7 @@
     1.4  #(xend-relocation-server no)
     1.5  (xend-relocation-server yes)
     1.6  #(xend-relocation-ssl-server no)
     1.7 +#(xend-udev-event-server no)
     1.8  
     1.9  #(xend-unix-path /var/lib/xend/xend-socket)
    1.10  
     2.1 --- a/tools/python/xen/xend/XendNode.py	Tue Mar 17 10:38:06 2009 +0000
     2.2 +++ b/tools/python/xen/xend/XendNode.py	Tue Mar 17 10:40:47 2009 +0000
     2.3 @@ -146,6 +146,18 @@ class XendNode:
     2.4  
     2.5          self.srs = {}
     2.6  
     2.7 +        self._init_networks()
     2.8 +        self._init_PIFs()
     2.9 +
    2.10 +        self._init_SRs()
    2.11 +        self._init_PBDs()
    2.12 +
    2.13 +        self._init_PPCIs()
    2.14 +
    2.15 +        self._init_PSCSIs()
    2.16 +
    2.17 +
    2.18 +    def _init_networks(self):
    2.19          # Initialise networks
    2.20          # First configure ones off disk
    2.21          saved_networks = self.state_store.load_state('network')
    2.22 @@ -179,6 +191,7 @@ class XendNode:
    2.23              if unconfigured_bridge != 'tmpbridge':
    2.24                  XendNetwork.create_phy(unconfigured_bridge)
    2.25  
    2.26 +    def _init_PIFs(self):
    2.27          # Initialise PIFs
    2.28          # First configure ones off disk
    2.29          saved_pifs = self.state_store.load_state('pif')
    2.30 @@ -221,7 +234,8 @@ class XendNode:
    2.31                      log.debug("Cannot find network for bridge %s "
    2.32                                "when configuring PIF %s",
    2.33                                (bridge_name, name))     
    2.34 -        
    2.35 +
    2.36 +    def _init_SRs(self):
    2.37          # initialise storage
    2.38          saved_srs = self.state_store.load_state('sr')
    2.39          if saved_srs:
    2.40 @@ -240,6 +254,7 @@ class XendNode:
    2.41              qcow_sr_uuid = uuid.createString()
    2.42              self.srs[qcow_sr_uuid] = XendQCoWStorageRepo(qcow_sr_uuid)
    2.43  
    2.44 +    def _init_PBDs(self):
    2.45          saved_pbds = self.state_store.load_state('pbd')
    2.46          if saved_pbds:
    2.47              for pbd_uuid, pbd_cfg in saved_pbds.items():
    2.48 @@ -248,8 +263,7 @@ class XendNode:
    2.49                  except CreateUnspecifiedAttributeError:
    2.50                      log.warn("Error recreating PBD %s", pbd_uuid) 
    2.51  
    2.52 -
    2.53 -        # Initialise PPCIs
    2.54 +    def _init_PPCIs(self):
    2.55          saved_ppcis = self.state_store.load_state('ppci')
    2.56          saved_ppci_table = {}
    2.57          if saved_ppcis:
    2.58 @@ -282,7 +296,7 @@ class XendNode:
    2.59              ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
    2.60              XendPPCI(ppci_uuid, ppci_record)
    2.61  
    2.62 -
    2.63 +    def _init_PSCSIs(self):
    2.64          # Initialise PSCSIs
    2.65          saved_pscsis = self.state_store.load_state('pscsi')
    2.66          saved_pscsi_table = {}
    2.67 @@ -301,6 +315,75 @@ class XendNode:
    2.68                  XendPSCSI(pscsi_uuid, pscsi_record)
    2.69  
    2.70  
    2.71 +    def add_network(self, interface):
    2.72 +        # TODO
    2.73 +        log.debug("add_network(): Not implemented.")
    2.74 +
    2.75 +
    2.76 +    def remove_network(self, interface):
    2.77 +        # TODO
    2.78 +        log.debug("remove_network(): Not implemented.")
    2.79 +
    2.80 +
    2.81 +    def add_PPCI(self, pci_name):
    2.82 +        # Update lspci info
    2.83 +        PciUtil.create_lspci_info()
    2.84 +
    2.85 +        # Initialise the PPCI
    2.86 +        saved_ppcis = self.state_store.load_state('ppci')
    2.87 +        saved_ppci_table = {}
    2.88 +        if saved_ppcis:
    2.89 +            for ppci_uuid, ppci_record in saved_ppcis.items():
    2.90 +                try:
    2.91 +                    saved_ppci_table[ppci_record['name']] = ppci_uuid
    2.92 +                except KeyError:
    2.93 +                    pass
    2.94 +
    2.95 +        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
    2.96 +        pci_dev = PciUtil.PciDevice(domain, bus, slot, func)
    2.97 +        ppci_record = {
    2.98 +            'domain':                   pci_dev.domain,
    2.99 +            'bus':                      pci_dev.bus,
   2.100 +            'slot':                     pci_dev.slot,
   2.101 +            'func':                     pci_dev.func,
   2.102 +            'vendor_id':                pci_dev.vendor,
   2.103 +            'vendor_name':              pci_dev.vendorname,
   2.104 +            'device_id':                pci_dev.device,
   2.105 +            'device_name':              pci_dev.devicename,
   2.106 +            'revision_id':              pci_dev.revision,
   2.107 +            'class_code':               pci_dev.classcode,
   2.108 +            'class_name':               pci_dev.classname,
   2.109 +            'subsystem_vendor_id':      pci_dev.subvendor,
   2.110 +            'subsystem_vendor_name':    pci_dev.subvendorname,
   2.111 +            'subsystem_id':             pci_dev.subdevice,
   2.112 +            'subsystem_name':           pci_dev.subdevicename,
   2.113 +            'driver':                   pci_dev.driver
   2.114 +            }
   2.115 +        # If saved uuid exists, use it. Otherwise create one.
   2.116 +        ppci_uuid = saved_ppci_table.get(pci_dev.name, uuid.createString())
   2.117 +        XendPPCI(ppci_uuid, ppci_record)
   2.118 +
   2.119 +
   2.120 +    def remove_PPCI(self, pci_name):
   2.121 +        # Update lspci info
   2.122 +        PciUtil.create_lspci_info()
   2.123 +
   2.124 +        # Remove the PPCI
   2.125 +        (domain, bus, slot, func) = PciUtil.parse_pci_name(pci_name)
   2.126 +        ppci_ref = XendPPCI.get_by_sbdf(domain, bus, slot, func)
   2.127 +        XendAPIStore.get(ppci_ref, "PPCI").destroy()
   2.128 +
   2.129 +
   2.130 +    def add_PSCSI(self):
   2.131 +        # TODO
   2.132 +        log.debug("add_network(): Not implemented.")
   2.133 +
   2.134 +
   2.135 +    def remove_PSCSI(self):
   2.136 +        # TODO
   2.137 +        log.debug("add_network(): Not implemented.")
   2.138 +
   2.139 +
   2.140  ##    def network_destroy(self, net_uuid):
   2.141   ##       del self.networks[net_uuid]
   2.142    ##      self.save_networks()
     3.1 --- a/tools/python/xen/xend/XendOptions.py	Tue Mar 17 10:38:06 2009 +0000
     3.2 +++ b/tools/python/xen/xend/XendOptions.py	Tue Mar 17 10:40:47 2009 +0000
     3.3 @@ -75,6 +75,9 @@ class XendOptions:
     3.4      """Default for the flag indicating whether xend should run a ssl relocation server."""
     3.5      xend_relocation_ssl_server_default = 'no'
     3.6  
     3.7 +    """Default for the flag indicating whether xend should run a udev event server."""
     3.8 +    xend_udev_event_server_default = 'no'
     3.9 +
    3.10      """Default interface address the xend relocation server listens at. """
    3.11      xend_relocation_address_default = ''
    3.12  
    3.13 @@ -216,6 +219,10 @@ class XendOptions:
    3.14      def get_xend_relocation_server_ssl_cert_file(self):
    3.15          return self.get_config_string("xend-relocation-server-ssl-cert-file")
    3.16  
    3.17 +    def get_xend_udev_event_server(self):
    3.18 +        return self.get_config_bool("xend-udev-event-server",
    3.19 +                                    self.xend_udev_event_server_default)
    3.20 +
    3.21      def get_xend_port(self):
    3.22          """Get the port xend listens at for its HTTP interface.
    3.23          """
     4.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Tue Mar 17 10:38:06 2009 +0000
     4.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Tue Mar 17 10:40:47 2009 +0000
     4.3 @@ -24,6 +24,7 @@ from xen.xend import osdep
     4.4  from xen.util import mkdir
     4.5  
     4.6  import relocate
     4.7 +import udevevent
     4.8  import SrvServer
     4.9  from params import *
    4.10  
    4.11 @@ -336,6 +337,7 @@ class Daemon:
    4.12              del xc
    4.13  
    4.14              relocate.listenRelocation()
    4.15 +            udevevent.listenUdevEvent()
    4.16              servers = SrvServer.create()
    4.17              servers.start(status)
    4.18              del servers
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/python/xen/xend/server/udevevent.py	Tue Mar 17 10:40:47 2009 +0000
     5.3 @@ -0,0 +1,68 @@
     5.4 +import socket
     5.5 +
     5.6 +from xen.web import protocol, unix
     5.7 +
     5.8 +from xen.xend.XendLogging import log
     5.9 +from xen.xend import XendNode
    5.10 +from xen.xend import XendOptions
    5.11 +
    5.12 +UDEV_EVENT_PATH = '\0/org/xen/xend/udev_event'
    5.13 +
    5.14 +class UdevEventProtocol(protocol.Protocol):
    5.15 +
    5.16 +    def __init__(self):
    5.17 +        protocol.Protocol.__init__(self)
    5.18 +
    5.19 +    def dataReceived(self, data):
    5.20 +        udev_event = {}
    5.21 +        for entry in data.split('\0'):
    5.22 +            try:
    5.23 +                opt, val = entry.split("=")
    5.24 +                udev_event[opt] = val
    5.25 +            except (TypeError, ValueError):
    5.26 +                pass
    5.27 +        if udev_event.get('ACTION', None) is None:
    5.28 +            log.warn("Invalid udev event received")
    5.29 +            return
    5.30 +
    5.31 +        log.debug("udev event received: %s", udev_event)
    5.32 +
    5.33 +        self._process_event(udev_event)
    5.34 +
    5.35 +    def _process_event(self, udev_event):
    5.36 +        try:
    5.37 +            if (udev_event.get('SUBSYSTEM', None) == 'pci'):
    5.38 +                pci_name = udev_event.get('PCI_SLOT_NAME', None)
    5.39 +                if (udev_event['ACTION'] == 'add'):
    5.40 +                    log.info("Adding pci device %s", pci_name)
    5.41 +                    XendNode.instance().add_PPCI(pci_name)
    5.42 +                elif (udev_event['ACTION'] == 'remove'):
    5.43 +                    log.info("Removing pci device %s", pci_name)
    5.44 +                    XendNode.instance().remove_PPCI(pci_name)
    5.45 +
    5.46 +            elif (udev_event.get('SUBSYSTEMS', None) == 'scsi'):
    5.47 +                if (udev_event['ACTION'] == 'add'):
    5.48 +                    log.info("Adding scsi device")
    5.49 +                    XendNode.instance().add_PSCSI()
    5.50 +                elif (udev_event['ACTION'] == 'remove'):
    5.51 +                    log.info("Removing scci device")
    5.52 +                    XendNode.instance().remove_PSCSI()
    5.53 +
    5.54 +            elif (udev_event.get('SUBSYSTEM', None) == 'net'):
    5.55 +                interface = udev_event.get('INTERFACE', None)
    5.56 +                if (udev_event['ACTION'] == 'add'):
    5.57 +                    log.info("Adding net device %s", interface)
    5.58 +                    XendNode.instance().add_network(interface)
    5.59 +                elif (udev_event['ACTION'] == 'remove'):
    5.60 +                    log.info("Removing net device %s", interface)
    5.61 +                    XendNode.instance().remove_network(interface)
    5.62 +
    5.63 +        except Exception, e:
    5.64 +            log.warn("error while processing udev event(): %s" % str(e))
    5.65 +
    5.66 +
    5.67 +def listenUdevEvent():
    5.68 +    xoptions = XendOptions.instance()
    5.69 +    if xoptions.get_xend_udev_event_server():
    5.70 +        unix.UnixDgramListener(UDEV_EVENT_PATH, UdevEventProtocol)
    5.71 +