The attached patch adds a lot of error catching and reporting for adding hardware in virt-manager. The particulars are: 1) Build virtinst VirtualDisk and VirtualNics as we go through creation wizards to reuse present validation. 2) Added a few cases of using the "install_error" infrastructure if we fail when at the end of the wizard. 3) Added error checking for removing hardware in the 'details' screen. 4) A small cleanup in create.py This stuff will definitely be useful for future bug reports :) - Cole -- Cole Robinson crobinso@xxxxxxxxxx
diff -r b2718c0c023c src/virtManager/addhardware.py --- a/src/virtManager/addhardware.py Wed Nov 14 16:13:37 2007 -0500 +++ b/src/virtManager/addhardware.py Thu Nov 15 15:48:53 2007 -0500 @@ -59,6 +59,8 @@ class vmmAddHardware(gobject.GObject): self.__gobject_init__() self.config = config self.vm = vm + self._net = None + self._disk = None self.window = gtk.glade.XML(config.get_glade_dir() + "/vmm-add-hardware.glade", "vmm-add-hardware", domain="virt-manager") self.topwin = self.window.get_widget("vmm-add-hardware") self.topwin.hide() @@ -429,18 +431,8 @@ class vmmAddHardware(gobject.GObject): self.close() def add_network(self): - net = self.get_config_network() - mac = self.get_config_macaddr() - vnic = None - if net[0] == "bridge": - vnic = virtinst.VirtualNetworkInterface(macaddr=mac, type=net[0], bridge=net[1]) - elif net[0] == "network": - vnic = virtinst.VirtualNetworkInterface(macaddr=mac, type=net[0], network=net[1]) - else: - raise ValueError, "Unsupported networking type " + net[0] - - vnic.setup(self.vm.get_connection().vmm) - self.add_device(vnic.get_xml_config()) + self._net.setup(self.vm.get_connection().vmm) + self.add_device(self._net.get_xml_config()) def add_input(self): input = self.get_config_input() @@ -469,22 +461,6 @@ class vmmAddHardware(gobject.GObject): def add_storage(self): node, maxnode, device = self.get_config_disk_target() - filesize = None - disk = None - if self.get_config_disk_size() != None: - filesize = self.get_config_disk_size() / 1024.0 - try: - disk = virtinst.VirtualDisk(self.get_config_disk_image(), - filesize, - device = device, - sparse = self.is_sparse_file()) - if disk.type == virtinst.VirtualDisk.TYPE_FILE and \ - not self.vm.is_hvm() \ - and virtinst.util.is_blktap_capable(): - disk.driver_name = virtinst.VirtualDisk.DRIVER_TAP - except ValueError, e: - self._validation_error_box(_("Invalid storage address"), e.args[0]) - return used = {} for d in self.vm.get_disk_devices(): @@ -511,33 +487,30 @@ class vmmAddHardware(gobject.GObject): break if node is None: - self._validation_error_box(_("Too many virtual disks"), - _("There are no more available virtual disk device nodes")) + value = _("There are no more available virtual disk device nodes") + details = "Unable to complete install: '%s'" % value + self.install_error = _("Unable to complete install: '%s'") % value + self.install_details = details return - progWin = vmmAsyncJob(self.config, self.do_file_allocate, [disk], + progWin = vmmAsyncJob(self.config, self.do_file_allocate, [self._disk], title=_("Creating Storage File"), text=_("Allocation of disk storage may take a few minutes " + \ "to complete.")) progWin.run() if self.install_error == None: - self.add_device(disk.get_xml_config(node)) + self.add_device(self._disk.get_xml_config(node)) def add_device(self, xml): logging.debug("Adding device " + xml) try: self.vm.add_device(xml) - except: - (type, value, stacktrace) = sys.exc_info () - - # Detailed error message, in English so it can be Googled. - details = \ - "Unable to complete install '%s'" % \ - (str(type) + " " + str(value) + "\n" + \ - traceback.format_exc (stacktrace)) - - self.install_error = _("Unable to complete install: '%s'") % str(value) + except Exception, e: + details = "Unable to complete install: '%s'" % \ + "".join(traceback.format_exc()) + self.install_error = _("Unable to complete install: '%s'") \ + % str(e) self.install_details = details logging.error(details) @@ -547,16 +520,11 @@ class vmmAddHardware(gobject.GObject): logging.debug("Starting background file allocate process") disk.setup(meter) logging.debug("Allocation completed") - except: - (type, value, stacktrace) = sys.exc_info () - - # Detailed error message, in English so it can be Googled. - details = \ - "Unable to complete install '%s'" % \ - (str(type) + " " + str(value) + "\n" + \ - traceback.format_exc (stacktrace)) - - self.install_error = _("Unable to complete install: '%s'") % str(value) + except Exception, e: + details = "Unable to complete install: '%s'" % \ + "".join(traceback.format_exc()) + self.install_error = _("Unable to complete install: '%s'") \ + % str(e) self.install_details = details logging.error(details) @@ -671,28 +639,27 @@ class vmmAddHardware(gobject.GObject): _("You must specify what type of hardware to add")) return False elif page_num == PAGE_DISK: - disk = self.get_config_disk_image() - if disk == None or len(disk) == 0: + path = self.get_config_disk_image() + if path == None or len(path) == 0: self._validation_error_box(_("Storage Address Required"), \ _("You must specify a partition or a file for storage for the guest install")) return False - - if not self.window.get_widget("storage-partition").get_active(): - if os.path.isdir(disk): - self._validation_error_box(_("Storage Address Is Directory"), \ - _("You chose 'Simple File' storage for your storage method, but chose a directory instead of a file. Please enter a new filename or choose an existing file.")) - return False - + if self.window.get_widget("target-device").get_active() == -1: self._validation_error_box(_("Target Device Required"), _("You must select a target device for the disk")) return False + node, nodemax, device = self.get_config_disk_target() + if self.window.get_widget("storage-partition").get_active(): + type = virtinst.VirtualDisk.TYPE_BLOCK + else: + type = virtinst.VirtualDisk.TYPE_FILE + if not self.window.get_widget("storage-partition").get_active(): - disk = self.get_config_disk_image() size = self.get_config_disk_size() - if not os.path.exists(disk): - dir = os.path.dirname(os.path.abspath(disk)) + if not os.path.exists(path): + dir = os.path.dirname(os.path.abspath(path)) if not os.path.exists(dir): self._validation_error_box(_("Storage Path Does not exist"), _("The directory %s containing the disk image does not exist") % dir) @@ -712,22 +679,30 @@ class vmmAddHardware(gobject.GObject): _("There is not enough free space to create the disk")) return False - node, nodemax, device = self.get_config_disk_target() - if self.window.get_widget("storage-partition").get_active(): - type = virtinst.VirtualDisk.TYPE_BLOCK - else: - type = virtinst.VirtualDisk.TYPE_FILE - - d = virtinst.VirtualDisk(self.get_config_disk_image(), - self.get_config_disk_size(), - type = type, - sparse = self.is_sparse_file(), - device=device) - if d.is_conflict_disk(self.vm.get_connection().vmm) is True: + # Build disk object + filesize = self.get_config_disk_size() + if self.get_config_disk_size() != None: + filesize = self.get_config_disk_size() / 1024.0 + try: + self._disk = virtinst.VirtualDisk(self.get_config_disk_image(), + filesize, + type = type, + sparse = self.is_sparse_file(), + device=device) + if self._disk.type == virtinst.VirtualDisk.TYPE_FILE and \ + not self.vm.is_hvm() and virtinst.util.is_blktap_capable(): + disk.driver_name = virtinst.VirtualDisk.DRIVER_TAP + except ValueError, e: + self._validation_error_box(_("Invalid Storage Parameters"), \ + str(e)) + return False + + if self._disk.is_conflict_disk(self.vm.get_connection().vmm) is True: res = self._yes_no_box(_('Disk "%s" is already in use by another guest!' % disk), \ _("Do you really want to use the disk ?")) return res elif page_num == PAGE_NETWORK: + net = self.get_config_network() if self.window.get_widget("net-type-network").get_active(): if self.window.get_widget("net-network").get_active() == -1: self._validation_error_box(_("Virtual Network Required"), @@ -739,16 +714,21 @@ class vmmAddHardware(gobject.GObject): _("You must select one of the physical devices")) return False + mac = self.get_config_macaddr() if self.window.get_widget("mac-address").get_active(): - mac= self.window.get_widget("create-mac-address").get_text() - if len(mac) != 17: + + if mac is None or len(mac) == 0: self._validation_error_box(_("Invalid MAC address"), \ - _("MAC adrress must be 17 characters")) + _("No MAC address was entered. Please enter a valid MAC address.")) return False - if re.match("^([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$",mac) == None: + + try: + self._net = virtinst.VirtualNetworkInterface(macaddr=mac) + except ValueError, e: self._validation_error_box(_("Invalid MAC address"), \ - _("MAC address must be a form such as AA:BB:CC:DD:EE:FF, and MAC adrress may contain numeric and alphabet of A-F(a-f) and ':' characters only")) + str(e)) return False + hostdevs = virtinst.util.get_host_network_devices() for hostdev in hostdevs: if mac.lower() == hostdev[4]: @@ -765,13 +745,29 @@ class vmmAddHardware(gobject.GObject): vm = self.vm.get_connection().vmm.lookupByName(name) inactive_vm.append(vm) - vnic = virtinst.VirtualNetworkInterface(macaddr=mac) - if (vnic.countMACaddr(vms) - vnic.countMACaddr(inactive_vm)) > 0: + if (self._net.countMACaddr(vms) - self._net.countMACaddr(inactive_vm)) > 0: return self._validation_error_box(_('MAC address "%s" is already in use by an active guest') % mac, \ _("Please enter a different MAC address or select no fixed MAC address")) - elif vnic.countMACaddr(inactive_vm) > 0: + elif self._net.countMACaddr(inactive_vm) > 0: return self._yes_no_box(_('MAC address "%s" is already in use by another inactive guest!') % mac, \ _("Do you really want to use the MAC address ?")) + + + try: + if net[0] == "bridge": + self._net = virtinst.VirtualNetworkInterface(macaddr=mac, + type=net[0], + bridge=net[1]) + elif net[0] == "network": + self._net = virtinst.VirtualNetworkInterface(macaddr=mac, + type=net[0], + network=net[1]) + else: + raise ValueError, _("Unsupported networking type") + net[0] + except ValueError, e: + self._validation_error_box(_("Invalid Network Parameter"), \ + str(e)) + return False return True @@ -819,7 +815,6 @@ class vmmAddHardware(gobject.GObject): model.append(["%s (%s)" % (net.get_name(), _("Not bridged")), False]) return hasShared - def populate_target_device_model(self, model): model.clear() if self.vm.is_hvm(): diff -r b2718c0c023c src/virtManager/create.py --- a/src/virtManager/create.py Wed Nov 14 16:13:37 2007 -0500 +++ b/src/virtManager/create.py Thu Nov 15 15:48:53 2007 -0500 @@ -934,12 +934,6 @@ class vmmCreate(gobject.GObject): self._validation_error_box(_("Invalid MAC address"), \ _("No MAC address was entered. Please enter a valid MAC address.")) return False - try: - self._guest.mac = mac - except ValueError, e: - self._validation_error_box(_("Invalid Mac address"), \ - str(e)) - return False hostdevs = virtinst.util.get_host_network_devices() for hostdev in hostdevs: diff -r b2718c0c023c src/virtManager/details.py --- a/src/virtManager/details.py Wed Nov 14 16:13:37 2007 -0500 +++ b/src/virtManager/details.py Thu Nov 15 15:48:53 2007 -0500 @@ -557,10 +557,23 @@ class vmmDetails(gobject.GObject): path = None else: path = diskinfo[1] - vbd = virtinst.VirtualDisk(path=path, type=diskinfo[0], device=diskinfo[2]) + + try: + vbd = virtinst.VirtualDisk(path=path, + type=diskinfo[0], + device=diskinfo[2]) + except Exception, e: + dg = vmmErrorDialog(None, 0, gtk.MESSAGE_ERROR, + gtk.BUTTONS_CLOSE, + _("Error Removing Disk: %s" % str(e)), + "".join(traceback.format_exc())) + dg.run() + dg.hide() + dg.destroy() + return + xml = vbd.get_xml_config(diskinfo[3]) - - self.vm.remove_device(xml) + self.remove_device(xml) self.refresh_resources() def remove_network(self, src): @@ -571,15 +584,25 @@ class vmmDetails(gobject.GObject): netinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE) vnic = None - if netinfo[0] == "bridge": - vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], bridge=netinfo[1], macaddr=netinfo[3]) - elif netinfo[0] == "network": - vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], network=netinfo[1], macaddr=netinfo[3]) - else: - vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], macaddr=netinfo[3]) + try: + if netinfo[0] == "bridge": + vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], bridge=netinfo[1], macaddr=netinfo[3]) + elif netinfo[0] == "network": + vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], network=netinfo[1], macaddr=netinfo[3]) + else: + vnic = virtinst.VirtualNetworkInterface(type=netinfo[0], macaddr=netinfo[3]) + except ValueError, e: + dg = vmmErrorDialog(None, 0, gtk.MESSAGE_ERROR, + gtk.BUTTONS_CLOSE, + _("Error Removing Network: %s" % str(e)), + "".join(traceback.format_exc())) + dg.run() + dg.hide() + dg.destroy() + return xml = vnic.get_xml_config() - self.vm.remove_device(xml) + self.remove_device(xml) self.refresh_resources() def remove_input(self, src): @@ -590,7 +613,7 @@ class vmmDetails(gobject.GObject): inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE) xml = "<input type='%s' bus='%s'/>" % (inputinfo[0], inputinfo[1]) - self.vm.remove_device(xml) + self.remove_device(xml) self.refresh_resources() def remove_graphics(self, src): @@ -601,7 +624,7 @@ class vmmDetails(gobject.GObject): inputinfo = active[0].get_value(active[1], HW_LIST_COL_DEVICE) xml = "<graphics type='%s'/>" % inputinfo[0] - self.vm.remove_device(xml) + self.remove_device(xml) self.refresh_resources() def prepare_hw_list(self): @@ -760,12 +783,33 @@ class vmmDetails(gobject.GObject): def toggle_cdrom(self, src): if src.get_label() == gtk.STOCK_DISCONNECT: #disconnect the cdrom - self.vm.disconnect_cdrom_device(self.window.get_widget("disk-target-device").get_text()) + try: + self.vm.disconnect_cdrom_device(self.window.get_widget("disk-target-device").get_text()) + except Exception, e: + dg = vmmErrorDialog(None, 0, gtk.MESSAGE_ERROR, + gtk.BUTTONS_CLOSE, + _("Error Removing CDROM: %s" % str(e)), + "".join(traceback.format_exc())) + dg.run() + dg.hide() + dg.destroy() + return + else: # connect a new cdrom if self.choose_cd is None: self.choose_cd = vmmChooseCD(self.config, self.window.get_widget("disk-target-device").get_text()) + try: self.choose_cd.connect("cdrom-chosen", self.connect_cdrom) + except Exception, e: + dg = vmmErrorDialog(None, 0, gtk.MESSAGE_ERROR, + gtk.BUTTONS_CLOSE, + _("Error Connecting CDROM: %s" % str(e)), + "".join(traceback.format_exc())) + dg.run() + dg.hide() + dg.destroy() + return else: self.choose_cd.set_target(self.window.get_widget("disk-target-device").get_text()) self.choose_cd.show() @@ -773,4 +817,17 @@ class vmmDetails(gobject.GObject): def connect_cdrom(self, src, type, source, target): self.vm.connect_cdrom_device(type, source, target) + def remove_device(self, xml): + try: + self.vm.remove_device(xml) + except Exception, e: + dg = vmmErrorDialog(None, 0, gtk.MESSAGE_ERROR, + gtk.BUTTONS_CLOSE, + _("Error Removing Device: %s" % str(e)), + "".join(traceback.format_exc())) + dg.run() + dg.hide() + dg.destroy() + + gobject.type_register(vmmDetails)
_______________________________________________ et-mgmt-tools mailing list et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools