[PATCH] catch and report errors during hardware manipulation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]

  Powered by Linux