# HG changeset patch # User plc@xxxxxxxxxxxxxxxxxxxxx # Date 1182539263 21600 # Node ID fa6ec13addb49f7054c364a90bbcbfae1d79fea8 # Parent 362adec0c4592f130ba17304126656b40f1b0324 CDROM removable media-present attribute plus handling code diff -r 362adec0c459 -r fa6ec13addb4 linux-2.6-xen-sparse/drivers/xen/blkback/Makefile --- a/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Fri Jun 22 13:02:23 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/Makefile Fri Jun 22 13:07:43 2007 -0600 @@ -1,3 +1,3 @@ obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkb obj-$(CONFIG_XEN_BLKDEV_BACKEND) := blkbk.o -blkbk-y := blkback.o xenbus.o interface.o vbd.o +blkbk-y := blkback.o xenbus.o interface.o vbd.o cdrom.o diff -r 362adec0c459 -r fa6ec13addb4 linux-2.6-xen-sparse/drivers/xen/blkback/cdrom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/cdrom.c Fri Jun 22 13:07:43 2007 -0600 @@ -0,0 +1,169 @@ +/****************************************************************************** + * blkback/cdrom.c + * + * Routines for managing cdrom watch and media-present attribute of a + * cdrom type virtual block device (VBD). + * + * Copyright (c) 2003-2005, Keir Fraser & Steve Hand + * Copyright (c) 2007 Pat Campbell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation; or, when distributed + * separately from the Linux kernel or incorporated into other + * software packages, subject to the following license: + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this source file (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, + * merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "common.h" + +#undef DPRINTK +#define DPRINTK(_f, _a...) \ + printk("(%s() file=%s, line=%d) " _f "\n", \ + __PRETTY_FUNCTION__, __FILE__ , __LINE__ , ##_a ) + + +#define MEDIA_PRESENT "media-present" + +static void cdrom_media_changed(struct xenbus_watch *, const char **, unsigned int); + +/** + * Writes media-present=1 attribute for the given vbd device if not + * already there + */ +static int cdrom_xenstore_write_media_present(struct backend_info *be) +{ + struct xenbus_device *dev = be->dev; + struct xenbus_transaction xbt; + int err; + int media_present; + + DPRINTK(" "); + + err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d", + &media_present); + if ( 0 < err) { + DPRINTK("already written err%d", err); + return(0); + } + media_present = 1; + +again: + err = xenbus_transaction_start(&xbt); + if (err) { + xenbus_dev_fatal(dev, err, "starting transaction"); + return(-1); + } + + err = xenbus_printf(xbt, dev->nodename, MEDIA_PRESENT, "%d", media_present ); + if (err) { + xenbus_dev_fatal(dev, err, "writing %s/%s", + dev->nodename, MEDIA_PRESENT); + goto abort; + } + err = xenbus_transaction_end(xbt, 0); + if (err == -EAGAIN) + goto again; + if (err) + xenbus_dev_fatal(dev, err, "ending transaction"); + return(0); + abort: + xenbus_transaction_end(xbt, 1); + return(-1); +} + +/** + * + */ +int cdrom_is_type(struct backend_info *be) +{ + DPRINTK( "type:%x", be->blkif->vbd.type ); + if ( be->blkif->vbd.type & VDISK_CDROM && be->blkif->vbd.type & GENHD_FL_REMOVABLE){ + return(1); + } + return(0); +} + +/** + * + */ +void cdrom_add_media_watch(struct backend_info *be) +{ + struct xenbus_device *dev = be->dev; + int err; + + DPRINTK( "nodename:%s", dev->nodename); + if (cdrom_is_type(be)) { + DPRINTK("is a cdrom"); + if ( cdrom_xenstore_write_media_present(be) == 0 ) { + DPRINTK( "xenstore wrote OK"); + err = xenbus_watch_path2(dev, dev->nodename, MEDIA_PRESENT, + &be->backend_cdrom_watch, cdrom_media_changed); + if (err) { + DPRINTK( "media_present watch add failed" ); + } + } + } +} + +/** + * Callback received when the "media_present" xenstore node is changed + */ +static void cdrom_media_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + int err; + unsigned media_present; + struct backend_info *be + = container_of(watch, struct backend_info, backend_cdrom_watch); + struct xenbus_device *dev = be->dev; + + DPRINTK(" "); + + if ( !(cdrom_is_type(be))) { + DPRINTK("callback not for a cdrom" ); + return; + } + + err = xenbus_scanf(XBT_NIL, dev->nodename, MEDIA_PRESENT, "%d", + &media_present); + if (err == 0 || err == -ENOENT) { + DPRINTK("xenbus_read of cdrom media_present node error:%d",err); + return; + } + + if (media_present == 0) { + vbd_free(&be->blkif->vbd); + } + else { + char *p = strrchr(dev->otherend, '/') + 1; + long handle = simple_strtoul(p, NULL, 0); + + if (be->blkif->vbd.bdev == NULL) { + err = vbd_create(be->blkif, handle, be->major, be->minor, + (NULL == strchr(be->mode, 'w'))); + if (err) { + be->major = be->minor = 0; + xenbus_dev_fatal(dev, err, "creating vbd structure"); + return; + } + } + } +} diff -r 362adec0c459 -r fa6ec13addb4 linux-2.6-xen-sparse/drivers/xen/blkback/common.h --- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Jun 22 13:02:23 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Fri Jun 22 13:07:43 2007 -0600 @@ -96,6 +96,17 @@ typedef struct blkif_st { grant_ref_t shmem_ref; } blkif_t; +struct backend_info +{ + struct xenbus_device *dev; + blkif_t *blkif; + struct xenbus_watch backend_watch; + struct xenbus_watch backend_cdrom_watch; + unsigned major; + unsigned minor; + char *mode; +}; + blkif_t *blkif_alloc(domid_t domid); void blkif_disconnect(blkif_t *blkif); void blkif_free(blkif_t *blkif); @@ -136,4 +147,8 @@ int blkback_barrier(struct xenbus_transa int blkback_barrier(struct xenbus_transaction xbt, struct backend_info *be, int state); +/* cdrom media change */ +int cdrom_is_type(struct backend_info *be); +void cdrom_add_media_watch(struct backend_info *be); + #endif /* __BLKIF__BACKEND__COMMON_H__ */ diff -r 362adec0c459 -r fa6ec13addb4 linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Jun 22 13:02:23 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Fri Jun 22 13:07:43 2007 -0600 @@ -106,6 +106,9 @@ int vbd_translate(struct phys_req *req, if ((operation != READ) && vbd->readonly) goto out; + if (vbd->bdev == NULL) + goto out; + if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd))) goto out; diff -r 362adec0c459 -r fa6ec13addb4 linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Jun 22 13:02:23 2007 -0600 +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Fri Jun 22 13:07:43 2007 -0600 @@ -26,16 +26,6 @@ #define DPRINTK(fmt, args...) \ pr_debug("blkback/xenbus (%s:%d) " fmt ".\n", \ __FUNCTION__, __LINE__, ##args) - -struct backend_info -{ - struct xenbus_device *dev; - blkif_t *blkif; - struct xenbus_watch backend_watch; - unsigned major; - unsigned minor; - char *mode; -}; static void connect(struct backend_info *); static int connect_ring(struct backend_info *); @@ -179,6 +169,12 @@ static int blkback_remove(struct xenbus_ be->backend_watch.node = NULL; } + if (be->backend_cdrom_watch.node) { + unregister_xenbus_watch(&be->backend_cdrom_watch); + kfree(be->backend_cdrom_watch.node); + be->backend_cdrom_watch.node = NULL; + } + if (be->blkif) { blkif_disconnect(be->blkif); vbd_free(&be->blkif->vbd); @@ -330,6 +326,9 @@ static void backend_changed(struct xenbu /* We're potentially connected now */ update_blkif_status(be->blkif); + + /* Add watch for cdrom media status if necessay */ + cdrom_add_media_watch(be); } } diff -r 362adec0c459 -r fa6ec13addb4 tools/ioemu/block.c --- a/tools/ioemu/block.c Fri Jun 22 13:02:23 2007 -0600 +++ b/tools/ioemu/block.c Fri Jun 22 13:07:43 2007 -0600 @@ -185,6 +185,13 @@ static BlockDriver *find_image_format(co uint8_t *buf; size_t bufsize = 1024; + if ( strcmp(filename, "/dev/cdrom") == 0) { + drv = bdrv_find_format("raw"); + if (drv != NULL) { + return(drv); + } + } + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); if (fd < 0) { buf = NULL; @@ -531,19 +538,9 @@ int bdrv_is_read_only(BlockDriverState * return bs->read_only; } -int bdrv_is_inserted(BlockDriverState *bs) -{ - return bs->inserted; -} - int bdrv_is_locked(BlockDriverState *bs) { return bs->locked; -} - -void bdrv_set_locked(BlockDriverState *bs, int locked) -{ - bs->locked = locked; } void bdrv_set_change_cb(BlockDriverState *bs, @@ -692,8 +689,10 @@ static int raw_open(BlockDriverState *bs fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); if (fd < 0) { fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); - if (fd < 0) - return -1; + if (fd < 0 && strstart(filename, "/dev/cd", NULL)) + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE | O_NONBLOCK ); + if (fd < 0) + return -1; bs->read_only = 1; } #ifdef _BSD @@ -764,7 +763,93 @@ static void raw_close(BlockDriverState * BDRVRawState *s = bs->opaque; bs->total_sectors = 0; close(s->fd); -} + s->fd = -1; +} + +#include +#include +static int raw_is_inserted(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + int ret; + + switch(bs->removable) { + case BDRV_TYPE_CDROM: + ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); + if (ret == CDS_DISC_OK) { + return 1; + } + else { + return 0; + } + break; + default: + return 1; + } +} + +static int raw_media_changed(BlockDriverState *bs) +{ + int ret = 0; + + switch(bs->removable) { + case BDRV_TYPE_CDROM: + { + if( bs->media_changed == 1 ) + { + ret = 1; + bs->media_changed = 0; + } + return ret; + } + default: + return -ENOTSUP; + } +} + + +static int raw_eject(BlockDriverState *bs, int eject_flag) +{ + char cmd[sizeof(bs->device_name) + 32]; + + switch(bs->removable) { + case BDRV_TYPE_CDROM: + if (eject_flag) { + sprintf(cmd, "eject %s", bs->filename); + if (system(cmd) == -1) { + perror("CDROMEJECT"); + } + } else { + sprintf(cmd, "eject -t %s", bs->filename); + if (system(cmd) == -1) { + perror("CDROMCLOSETRAY"); + } + } + break; + default: + return -ENOTSUP; + } + return 0; +} + +static int raw_set_locked(BlockDriverState *bs, int locked) +{ + BDRVRawState *s = bs->opaque; + + switch(bs->removable) { + case BDRV_TYPE_CDROM: + if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) { + /* Note: an error can happen if the distribution automatically + mounts the CD-ROM */ + // perror("CDROM_LOCKDOOR"); + } + break; + default: + return -ENOTSUP; + } + return 0; +} + #ifdef _WIN32 #include @@ -845,6 +930,12 @@ BlockDriver bdrv_raw = { raw_close, raw_create, raw_flush, + + /* removable device support */ + .bdrv_is_inserted = raw_is_inserted, + .bdrv_media_changed = raw_media_changed, + .bdrv_eject = raw_eject, + .bdrv_set_locked = raw_set_locked, }; void bdrv_init(void) @@ -861,3 +952,96 @@ void bdrv_init(void) bdrv_register(&bdrv_vpc); bdrv_register(&bdrv_vvfat); } + +/**************************************************************/ +/* removable device support */ + +/** + * Return TRUE if the media is present + */ +int bdrv_is_inserted(BlockDriverState *bs) +{ + BlockDriver *drv = bs->drv; + int ret; + if (!drv) + return 0; + if (!drv->bdrv_is_inserted) + return 1; + ret = drv->bdrv_is_inserted(bs); + return ret; +} + +/** + * Return TRUE if the media changed since the last call to this + * function. + */ +int bdrv_media_changed(BlockDriverState *bs) +{ + BlockDriver *drv = bs->drv; + int ret; + + if (!drv || !drv->bdrv_media_changed) + ret = -ENOTSUP; + else + ret = drv->bdrv_media_changed(bs); + if (ret == -ENOTSUP) + ret = bs->media_changed; + bs->media_changed = 0; + return ret; +} + + +/** + * If eject_flag is TRUE, eject the media. Otherwise, close the tray + */ +void bdrv_eject(BlockDriverState *bs, int eject_flag) +{ + + int ret = 0; + char cmd[sizeof(bs->device_name) + 32]; + BlockDriver *drv = bs->drv; + + switch(bs->removable) { + case BDRV_TYPE_CDROM: + if (eject_flag) { + sprintf(cmd, "eject %s", bs->filename); + if (system(cmd) == -1) { + perror("CDROMEJECT"); + ret = -ENOTSUP; + } + } else { + sprintf(cmd, "eject -t %s", bs->filename); + if (system(cmd) == -1) { + perror("CDROMCLOSETRAY"); + ret = -ENOTSUP; + } + } + break; + default: + if (!drv || !drv->bdrv_eject) { + ret = -ENOTSUP; + } else { + ret = drv->bdrv_eject(bs, eject_flag); + } + if (ret == -ENOTSUP) { + if (eject_flag) + bdrv_close(bs); + } + } + //return ret; +} + +/** + * Lock or unlock the media (if it is locked, the user won't be able + * to eject it manually). + */ +void bdrv_set_locked(BlockDriverState *bs, int locked) +{ + BlockDriver *drv = bs->drv; + + bs->locked = locked; + if (drv && drv->bdrv_set_locked) { + drv->bdrv_set_locked(bs, locked); + } +} + diff -r 362adec0c459 -r fa6ec13addb4 tools/ioemu/block_int.h --- a/tools/ioemu/block_int.h Fri Jun 22 13:02:23 2007 -0600 +++ b/tools/ioemu/block_int.h Fri Jun 22 13:07:43 2007 -0600 @@ -41,6 +41,13 @@ struct BlockDriver { int nb_sectors, int *pnum); int (*bdrv_set_key)(BlockDriverState *bs, const char *key); int (*bdrv_make_empty)(BlockDriverState *bs); + + /* removable device specific */ + int (*bdrv_is_inserted)(BlockDriverState *bs); + int (*bdrv_media_changed)(BlockDriverState *bs); + int (*bdrv_eject)(BlockDriverState *bs, int eject_flag); + int (*bdrv_set_locked)(BlockDriverState *bs, int locked); + struct BlockDriver *next; }; @@ -65,6 +72,7 @@ struct BlockDriverState { char backing_file[1024]; /* if non zero, the image is a diff of this file image */ int is_temporary; + int media_changed; BlockDriverState *backing_hd; diff -r 362adec0c459 -r fa6ec13addb4 tools/ioemu/hw/ide.c --- a/tools/ioemu/hw/ide.c Fri Jun 22 13:02:23 2007 -0600 +++ b/tools/ioemu/hw/ide.c Fri Jun 22 13:07:43 2007 -0600 @@ -278,6 +278,7 @@ #define ASC_ILLEGAL_OPCODE 0x20 #define ASC_LOGICAL_BLOCK_OOR 0x21 #define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIA_CHANGED 0x28 #define ASC_MEDIUM_NOT_PRESENT 0x3a #define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 @@ -393,6 +394,7 @@ typedef struct PCIIDEState { } PCIIDEState; #define DMA_MULTI_THREAD +#undef DMA_MULTI_THREAD #ifdef DMA_MULTI_THREAD @@ -1341,7 +1343,6 @@ static void ide_atapi_cmd(IDEState *s) } else { ide_atapi_cmd_error(s, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - xenstore_check_new_media_present(1000); } break; case GPCMD_MODE_SENSE_10: @@ -1530,7 +1531,10 @@ static void ide_atapi_cmd(IDEState *s) if (eject && !start) { /* eject the disk */ - bdrv_close(s->bs); + bdrv_eject(s->bs, 1); + } else if (eject && start) { + /* close the tray */ + bdrv_eject(s->bs, 0); } ide_atapi_cmd_ok(s); } diff -r 362adec0c459 -r fa6ec13addb4 tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Fri Jun 22 13:02:23 2007 -0600 +++ b/tools/ioemu/xenstore.c Fri Jun 22 13:07:43 2007 -0600 @@ -82,7 +82,7 @@ void xenstore_parse_domain_config(int do char **e = NULL; char *buf = NULL, *path; char *fpath = NULL, *bpath = NULL, - *dev = NULL, *params = NULL, *type = NULL; + *dev = NULL, *params = NULL, *type = NULL, *media_present = NULL; int i, is_scsi; unsigned int len, num, hd_index; @@ -168,8 +168,12 @@ void xenstore_parse_domain_config(int do /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); - if (pasprintf(&buf, "%s/params", bpath) != -1) - xs_watch(xsh, buf, dev); + xs_watch(xsh, buf, dev); + if (pasprintf(&buf, "%s/media-present", bpath) != -1) { + free(media_present); + media_present = xs_read(xsh, XBT_NULL, buf, &len); + xs_watch(xsh, buf, "media_present"); + } } /* open device now if media present */ if (params[0]) { @@ -313,7 +317,7 @@ void xenstore_process_logdirty_event(voi void xenstore_process_event(void *opaque) { - char **vec, *image = NULL; + char **vec, *image = NULL, *media_present = NULL; unsigned int len, num, hd_index; vec = xs_read_watch(xsh, &num); @@ -322,6 +326,40 @@ void xenstore_process_event(void *opaque if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { xenstore_process_logdirty_event(); + goto out; + } + + if (!strcmp(vec[XS_WATCH_TOKEN], "media_present")) { + media_present = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len); + if (media_present) { + BlockDriverState *bs; + char *buf = NULL, *cp = NULL, *path = NULL, *dev = NULL; + + path = strdup(vec[XS_WATCH_PATH]); + cp = strstr(path, "media-present"); + if (cp){ + *(cp-1) = '\0'; + pasprintf(&buf, "%s/dev", path); + dev = xs_read(xsh, XBT_NULL, buf, &len); + if (dev) { + bs = bdrv_find(dev); + if (!bs) { + term_printf("device not found\n"); + goto out; + } + if (strcmp(media_present, "0") == 0 && bs) { + bdrv_close(bs); + } + else if (strcmp(media_present, "1") == 0 && bs != NULL && bs->drv == NULL) { + if (bdrv_open(bs, bs->filename, 0 /* snapshot */) < 0) { + fprintf(stderr, "qemu: could not open hard disk image '%s'\n", + bs->filename); + } + bs->media_changed = 1; + } + } + } + } goto out; } diff -r 362adec0c459 -r fa6ec13addb4 tools/python/xen/xend/server/HalDaemon.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/server/HalDaemon.py Fri Jun 22 13:07:43 2007 -0600 @@ -0,0 +1,228 @@ +#!/usr/bin/env python +# -*- mode: python; -*- +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 Pat Campbell +# Copyright (C) 2007 Novell Inc. +#============================================================================ + +"""hald (Hardware Abstraction Layer Daemon) watcher for Xen management + of removable block device media. + +""" + +import gobject +import dbus +import dbus.glib +import os +import types +import sys +import signal +import traceback +from xen.xend.xenstore.xstransact import xstransact, complete +from xen.xend.xenstore.xsutil import xshandle +from xen.xend import PrettyPrint +from xen.xend import XendLogging +from xen.xend.XendLogging import log + +class HalDaemon: + """The Hald block device watcher for XEN + """ + + """Default path to the log file. """ + logfile_default = "/var/log/xen/hald.log" + + """Default level of information to be logged.""" + loglevel_default = 'INFO' + + def __init__(self): + + XendLogging.init(self.logfile_default, self.loglevel_default) + log.debug( "%s", "__init__") + + self.udi_dict = {} + self.debug = 0 + self.dbpath = "/local/domain/0/backend/vbd" + self.bus = dbus.SystemBus() + self.hal_manager_obj = self.bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') + self.hal_manager = dbus.Interface( self.hal_manager_obj, 'org.freedesktop.Hal.Manager') + self.gatherBlockDevices() + self.registerDeviceCallbacks() + + def run(self): + log.debug( "%s", "In new run" ); + try: + self.mainloop = gobject.MainLoop() + self.mainloop.run() + except KeyboardInterrupt, ex: + log.debug('Keyboard exception handler: %s', ex ) + self.mainloop.quit() + except Exception, ex: + log.debug('Generic exception handler: %s', ex ) + self.mainloop.quit() + + def __del__(self): + log.debug( "%s", "In del " ); + self.unRegisterDeviceCallbacks() + self.mainloop.quit() + + def shutdown(self): + log.debug( "%s", "In shutdown now " ); + self.unRegisterDeviceCallbacks() + self.mainloop.quit() + + def stop(self): + log.debug( "%s", "In stop now " ); + self.unRegisterDeviceCallbacks() + self.mainloop.quit() + + def gatherBlockDevices(self): + + # Get all the current devices from hal and save in a dictionary + try: + device_names = self.hal_manager.GetAllDevices() + i = 0; + for name in device_names: + #log.debug("device name, device=%s",name) + dev_obj = self.bus.get_object ('org.freedesktop.Hal', name) + dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device') + dev_properties = dev_obj.GetAllProperties(dbus_interface="org.freedesktop.Hal.Device") + if dev_properties.has_key('block.device'): + dev_str = dev_properties['block.device'] + dev_major = dev_properties['block.major'] + dev_minor = dev_properties['block.minor'] + udi_info = {} + udi_info['device'] = dev_str + udi_info['major'] = dev_major + udi_info['minor'] = dev_minor + udi_info['udi'] = name + self.udi_dict[i] = udi_info + i = i + 1 + except Exception, ex: + print >>sys.stderr, 'Exception gathering block devices:', ex + log.warn("Exception gathering block devices (%s)",ex) + + # + def registerDeviceCallbacks(self): + # setup the callbacks for when the gdl changes + self.hal_manager.connect_to_signal('DeviceAdded', self.device_added_callback) + self.hal_manager.connect_to_signal('DeviceRemoved', self.device_removed_callback) + + # + def unRegisterDeviceCallbacks(self): + # setup the callbacks for when the gdl changes + self.hal_manager.remove_signal_receiver(self.device_added_callback,'DeviceAdded') + self.hal_manager.remove_signal_receiver(self.device_removed_callback,'DeviceRemoved') + + # + def device_removed_callback(self,udi): + log.debug('UDI %s was removed',udi) + self.show_dict(self.udi_dict) + for key in self.udi_dict: + udi_info = self.udi_dict[key] + if udi_info['udi'] == udi: + device = udi_info['device'] + major = udi_info['major'] + minor = udi_info['minor'] + self.change_xenstore( "remove", device, major, minor) + + # Adds device to dictionary if not already there + def device_added_callback(self,udi): + log.debug('UDI %s was added', udi) + self.show_dict(self.udi_dict) + dev_obj = self.bus.get_object ('org.freedesktop.Hal', udi) + dev = dbus.Interface (dev_obj, 'org.freedesktop.Hal.Device') + device = dev.GetProperty ('block.device') + major = dev.GetProperty ('block.major') + minor = dev.GetProperty ('block.minor') + udi_info = {} + udi_info['device'] = device + udi_info['major'] = major + udi_info['minor'] = minor + udi_info['udi'] = udi + already = 0 + cnt = 0; + for key in self.udi_dict: + info = self.udi_dict[key] + if info['udi'] == udi: + already = 1 + break + cnt = cnt + 1 + if already == 0: + self.udi_dict[cnt] = udi_info; + log.debug('UDI %s was added, device:%s major:%s minor:%s index:%d\n', udi, device, major, minor, cnt) + self.change_xenstore( "add", device, major, minor) + + # Debug helper, shows dictionary contents + def show_dict(self,dict=None): + if self.debug == 0 : + return + if dict == None : + dict = self.udi_dict + for key in dict: + log.debug('udi_info %s udi_info:%s',key,dict[key]) + + # Set or clear xenstore media-present depending on the action argument + # for every vbd that has this block device + def change_xenstore(self,action, device, major, minor): + domains = xstransact.List(self.dbpath) + log.debug('domains: %s', domains) + for domain in domains: # for each domain + devices = xstransact.List( self.dbpath + '/' + domain) + log.debug('devices: %s',devices) + for device in devices: # for each vbd device + str = device.split('/') + vbd_type = None; + vbd_physical_device = None + vbd_media = None + vbd_device_path = self.dbpath + '/' + domain + '/' + device + listing = xstransact.List(vbd_device_path) + for entry in listing: # for each entry + item = self.dbpath + '/' + entry + value = xstransact.Read( vbd_device_path + '/' + entry) + log.debug('%s=%s',item,value) + if item.find('media-present') != -1: + vbd_media = item; + vbd_media_path = item + if item.find('physical-device') != -1: + vbd_physical_device = value; + if item.find('type') != -1: + vbd_type = value; + if vbd_type is not None and vbd_physical_device is not None and vbd_media is not None : + inode = vbd_physical_device.split(':') + imajor = inode[0] + iminor = inode[1] + log.debug("action:%s major:%s- minor:%s- imajor:%s- iminor:%s- inode: %s", + action,major,minor, imajor, iminor, inode) + if int(imajor) == int(major) and int(iminor) == int(minor): + if action == "add": + xs_dict = {'media': "1"} + xstransact.Write(vbd_device_path, 'media-present', "1" ) + log.debug("wrote xenstore media-present 1 path:%s",vbd_media_path) + else: + xstransact.Write(vbd_device_path, 'media-present', "0" ) + log.debug("wrote xenstore media 0 path:%s",vbd_media_path) + +def mylog( fmt, *args): + f = open('/tmp/haldaemon.log', 'a') + print >>f, "HalDaemon ", fmt % args + f.close() + +if __name__ == "__main__": + watcher = HalDaemon() + watcher.run() + print 'Falling off end' + + diff -r 362adec0c459 -r fa6ec13addb4 tools/python/xen/xend/server/Hald.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/python/xen/xend/server/Hald.py Fri Jun 22 13:07:43 2007 -0600 @@ -0,0 +1,113 @@ +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 Pat Campbell +# Copyright (C) 2007 Novell Inc. +#============================================================================ + +import errno +import types +import os +import sys +import time +import signal +from traceback import print_exc + +from xen.xend.XendLogging import log + +class Hald: + def __init__(self): + self.ready = False + self.running = True + + def run(self): + """Starts the HalDaemon process + """ + self.ready = True + try: + myfile = self.find("xen/xend/server/HalDaemon.py") + args = (["python", myfile ]) + self.pid = self.daemonize("python", args ) + #log.debug( "%s %s pid:%d", "Hald.py starting ", args, self.pid ) + except: + self.pid = -1 + log.debug("Unable to start HalDaemon process") + + def shutdown(self): + """Shutdown the HalDaemon process + """ + log.debug("%s pid:%d", "Hald.shutdown()", self.pid) + self.running = False + self.ready = False + if self.pid != -1: + try: + os.kill(self.pid, signal.SIGINT) + except: + print_exc() + + def daemonize(self,prog, args): + """Runs a program as a daemon with the list of arguments. Returns the PID + of the daemonized program, or returns 0 on error. + Copied from xm/create.py instead of importing to reduce coupling + """ + r, w = os.pipe() + pid = os.fork() + + if pid == 0: + os.close(r) + w = os.fdopen(w, 'w') + os.setsid() + try: + pid2 = os.fork() + except: + pid2 = None + if pid2 == 0: + os.chdir("/") + for fd in range(0, 256): + try: + os.close(fd) + except: + pass + os.open("/dev/null", os.O_RDWR) + os.dup2(0, 1) + os.dup2(0, 2) + os.execvp(prog, args) + os._exit(1) + else: + w.write(str(pid2 or 0)) + w.close() + os._exit(0) + os.close(w) + r = os.fdopen(r) + daemon_pid = int(r.read()) + r.close() + os.waitpid(pid, 0) + #log.debug( "daemon_pid: %d", daemon_pid ) + return daemon_pid + + def find(self,path, matchFunc=os.path.isfile): + """Find a module in the sys.path + From web page: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52224 + """ + for dirname in sys.path: + candidate = os.path.join(dirname, path) + if matchFunc(candidate): + return candidate + raise Error("Can't find file %s" % path) + +if __name__ == "__main__": + watcher = Hald() + watcher.run() + time.sleep(10) + watcher.shutdown() diff -r 362adec0c459 -r fa6ec13addb4 tools/python/xen/xend/server/SrvServer.py --- a/tools/python/xen/xend/server/SrvServer.py Fri Jun 22 13:02:23 2007 -0600 +++ b/tools/python/xen/xend/server/SrvServer.py Fri Jun 22 13:07:43 2007 -0600 @@ -57,6 +57,7 @@ from xen.web.SrvDir import SrvDir from SrvRoot import SrvRoot from XMLRPCServer import XMLRPCServer +from xen.xend.server.Hald import Hald xoptions = XendOptions.instance() @@ -248,6 +249,8 @@ def _loadConfig(servers, root, reload): if xoptions.get_xend_unix_xmlrpc_server(): servers.add(XMLRPCServer(XendAPI.AUTH_PAM, False)) + servers.add(Hald()) + def create(): root = SrvDir() # HG changeset patch # User plc@xxxxxxxxxxxxxxxxxxxxx # Date 1182542474 21600 # Node ID 46685041fb424de81500375183149ecb126e1a88 # Parent fa6ec13addb49f7054c364a90bbcbfae1d79fea8 Added return true to raw_is_inserted() if ioctl fails diff -r fa6ec13addb4 -r 46685041fb42 tools/ioemu/block.c --- a/tools/ioemu/block.c Fri Jun 22 13:07:43 2007 -0600 +++ b/tools/ioemu/block.c Fri Jun 22 14:01:14 2007 -0600 @@ -777,6 +777,9 @@ static int raw_is_inserted(BlockDriverSt case BDRV_TYPE_CDROM: ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT); if (ret == CDS_DISC_OK) { + return 1; + } + if (ret == -1) { // iso case return 1; } else { # HG changeset patch # User plc@xxxxxxxxxxxxxxxxxxxxx # Date 1182542925 21600 # Node ID 69fc41d0f24bbc6a428d0e5dd23225ef7aa9d6f5 # Parent 46685041fb424de81500375183149ecb126e1a88 Added if test for params diff -r 46685041fb42 -r 69fc41d0f24b tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Fri Jun 22 14:01:14 2007 -0600 +++ b/tools/ioemu/xenstore.c Fri Jun 22 14:08:45 2007 -0600 @@ -168,7 +168,8 @@ void xenstore_parse_domain_config(int do /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); - xs_watch(xsh, buf, dev); + if (pasprintf(&buf, "%s/params", bpath) != -1) + xs_watch(xsh, buf, dev); if (pasprintf(&buf, "%s/media-present", bpath) != -1) { free(media_present); media_present = xs_read(xsh, XBT_NULL, buf, &len); diff -ur a/tools/python/xen/xend/server/Hald.py b/tools/python/xen/xend/server/Hald.py --- a/tools/python/xen/xend/server/Hald.py 2007-06-28 09:24:34.000000000 -0600 +++ b/tools/python/xen/xend/server/Hald.py 2007-06-28 09:25:33.000000000 -0600 @@ -74,6 +74,8 @@ pid2 = None if pid2 == 0: os.chdir("/") + env = os.environ.copy() + env['PYTHONPATH'] = self.getpythonpath() for fd in range(0, 256): try: os.close(fd) @@ -82,7 +84,7 @@ os.open("/dev/null", os.O_RDWR) os.dup2(0, 1) os.dup2(0, 2) - os.execvp(prog, args) + os.execvpe(prog, args, env) os._exit(1) else: w.write(str(pid2 or 0)) @@ -96,6 +98,16 @@ #log.debug( "daemon_pid: %d", daemon_pid ) return daemon_pid + def getpythonpath(self): + str = " " + for p in sys.path: + if str != " ": + str = str + ":" + p + else: + if str != "": + str = p + return str + def find(self,path, matchFunc=os.path.isfile): """Find a module in the sys.path From web page: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52224